从HTML画布提取的ArrayBuffer与使用UTIF解码并加载到ArrayBuffer的ArrayBuffer不同

问题描述 投票:0回答:1

我的目标是将TIFF图像加载到HTML画布上。前端接收到TIFF图像的ArrayBuffer,我能够利用UTIF解码ArrayBuffer并将其呈现在HTML画布上。但是,另一个功能要求我导出画布内容。为此,我再次使用UTIF将其编码回ArrayBuffer,然后将其传递到后端服务器上使用。

我的实际情况是:

  1. 将TIFF图像加载到画布上。
  2. 在画布上添加其他对象。例如。圆,笔触,三角形等(在下面的代码中忽略)
  3. 将画布内容导出为TIFF图像。

添加ArrayBuffer的代码:

private _addArrayBufferAsImageOnCanvas(buffer: ArrayBuffer, meta?: {}) {
    console.log(buffer); // 8 MB input
    // Using UTIF.js to decode the array buffer and convert it to ImageData
    const ifds = UTIF.decode(buffer);
    const timage = ifds[0];
    UTIF.decodeImage(buffer, timage);
    const array = new Uint8ClampedArray(UTIF.toRGBA8(timage));
    // Forming image Data
    const imageData = new ImageData(array, timage.width, timage.height);
    // a temporary canvas element
    const canvas = document.createElement('canvas');
    canvas.width = timage.width;
    canvas.height = timage.height;
    // on which we draw the ImageData
    const ctx = canvas.getContext('2d');
    ctx.putImageData(imageData, 0, 0);
    // Get the image data
    const outImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    // and use UTIF to encode the image 
    const binaryTiffImage = UTIF.encodeImage(outImageData.data, outImageData.width, outImageData.height);
    // 
    console.log(binaryTiffImage); // 16 MB output
  }

作为输入参数的buffer的大小/字节长度是从画布中提取的binaryTiffImage的大小/字节长度的一半。 (8MB输入,16MB输出)

是因为UTIF编码不会压缩数组吗? (https://github.com/photopea/UTIF.js/blob/master/README.md#utifencodeimagergba-w-h-metadata

有没有一种方法可以从加载画布时获得与画布完全相同的ArrayBuffer?

javascript typescript canvas tiff arraybuffer
1个回答
0
投票

对于比输入大两倍的输出,是的,压缩可能是最大的问题。

但是,即使压缩图像数据,也无法从正在执行的操作中获得完全相同的文件。

首先,压缩器将需要使用与最初使用的设置完全相同的设置,这可能会或可能不会,但是无论如何都不简单。

然后,您将丢失原始TIFF文件中的所有元数据。您的过程仅提取原始位图数据,但是所有可能嵌入此TIFF中的信息(EXIF,jpeg预览等)都将丢失。

不仅丢失了元数据,而且丢失了颜色配置文件和颜色深度,您的代码将原来在TIFF中的内容转换为sRGB @ 32Bits(24bits + alpha)。

[如果您的图像数据使用的是像JPEG这样的松散压缩(虽然很少见,那是可能的,那么您可以通过将凝聚的数据转换为现在的单个像素来创建新数据。


但是,即使您正在使用未经压缩的32bits原始像素数据(已经具有sRGB颜色配置文件并能够放回所有原始元数据,您仍然会遇到一个大问题:

2D canvas API松散:

const ctx = document.createElement('canvas').getContext('2d');
ctx.canvas.width = ctx.canvas.height = 50;

const input = new Uint8ClampedArray(50 * 50 * 4);
crypto.getRandomValues(input); // fill with noise

const input_img = new ImageData( input, 50, 50 );
ctx.putImageData(input_img, 0, 0);
const output = ctx.getImageData(0, 0, 50, 50).data;

const are_different = input.some( (input_value, index) => output[ index ] !== input_value );

console.log( 'input and output are', are_different ? 'different' : 'same' );
// check from your browser's dev-tools
console.table( [input, output] );

公平地说,由于这是由于Alpha预乘而引起的,如果仅只有完全不透明的像素,则不会发生这种情况,但是所有这些点只会加起来。

© www.soinside.com 2019 - 2024. All rights reserved.