无法渲染 TIFF 图像并将其添加为织物对象

Unable to render TIFF images and add it as a Fabric Object

我已阅读教程:http://fabricjs.com/articles 和有关 Fabric 对象的文档。

我能够加载 JPG 和 PNG 图像,但在我的项目中,我需要将 TIFF 图像加载到 canvas 上并能够对其应用滤镜。我可以使用 canvas 上下文渲染 TIFF 图像,但每当调用 'renderAll()' 时,它都会清除上下文,我的 TIFF 图像也会被清除。我也无法执行其他操作,如缩放、平移、亮度和对比度,因为我无法渲染它。

有人可以帮助我了解如何将 TIFF 图像转换为 Fabric 对象,以便我可以对其执行所有标准 fabric.Object 相关操作。

以下是我遵循的步骤:

  1. 要加载模拟 TIFF 图像,我将其作为数组缓冲区读取。

    public loadMockTiffImage() {
    // Create a new XMLHttpRequest object to read the mock TIFF image as ArrayBuffer
    const xhr = new XMLHttpRequest();
    
    // Configure it: GET-request for the URL
    xhr.open('GET', 'assets/tif/sample.tif', true);
    xhr.responseType = 'arraybuffer';
    xhr.timeout = 10000; // timeout in ms, 10 seconds
    
    // Send the request over the network
    xhr.send();
    
    // After the response is received, load it
    xhr.onload = () => {
      // analyze HTTP status of the response
      if (xhr.status !== 200) {
        // throw error incase status is not 200
        console.log(`Error ${xhr.status}: ${xhr.statusText}`);
      } else {
        // Show the result
        console.log(`Done, got ${xhr.response.byteLength} bytes`);
        console.log(xhr.response);
        // Add to canvas the XHR response which is of type ArrayBuffer
        this.addTiffImageOnCanvas(xhr.response);
      }
    };
    
    // Show progress of loading the bytes
    xhr.onprogress = event => {
      if (event.lengthComputable) {
        console.log(`Received ${event.loaded} of ${event.total} bytes`);
      } else {
        console.log(`Received ${event.loaded} bytes`); // no Content-Length
      }
    };
    
    // Log any network request errors
    xhr.onerror = () => {
      console.log('Request failed!');
    };
    }
    
  2. 接下来,我使用 UTIF.js 解码 ArrayBuffer 并将其转换为 ImageBitmap,以便我可以使用 canvas.drawImage() 将其渲染到 canvas 上。 如何将此 ImageBitmap/ArrayBuffer 转换为 FabricJS 对象?

    private addTiffImageOnCanvas(buffer: ArrayBuffer) {
    // Using UTIF.js to decode the array buffer and convert it to ImageBitmap
    const ifds = UTIF.decode(buffer);
    UTIF.decodeImage(buffer, ifds[0]);
    const timage = ifds[0];
    const array = new Uint8ClampedArray(UTIF.toRGBA8(timage));
    // Forming image Data
    const imageData = new ImageData(array, timage.width, timage.height);
    let ibm: ImageBitmap = null;
    const bmPromise: Promise<ImageBitmap> = createImageBitmap(imageData);
    
    bmPromise.then(bitmap => {
      ibm = bitmap;
      fabric.Image.fromObject(ibm, image => {
         // TODO: How or What should I do now?
      });
    });
    

    }

感谢您的帮助。

我没有在 fabric 的 github 仓库中找到任何能够处理 ImageBitmap 的内容。

但是,您可以很好地从 HTMLCanvasElement 创建 Fabric.Image。 因此,您必须在 canvas 上绘制此 ImageBitmap,如果我们无论如何要使用 canvas,最好在上一步完成,当您获得 ImageData:

var scene = new fabric.Canvas('fabric');
scene.setHeight(500);
scene.setWidth(500);

fetch( "https://upload.wikimedia.org/wikipedia/commons/d/d8/Example.tiff" )
  .then( (resp) => resp.arrayBuffer() )
  .then( makeFabricImageFromTiff )
  .then( (fabricImage) => scene.add( fabricImage ) );

function makeFabricImageFromTiff( buffer ) {
  // Using UTIF.js to decode the array buffer and convert it to ImageData
  const ifds = UTIF.decode( buffer );
  UTIF.decodeImage( buffer, ifds[ 0 ] );
  const timage = ifds[ 0 ];
  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
  canvas.getContext( '2d' )
    .putImageData( imageData, 0, 0 );
  // before converting it to a Fabric.Image instance
  return new fabric.Image( canvas, { left: 50, top: 50 } );
}
canvas { border: 1px solid; }
<script src="https://cdn.jsdelivr.net/gh/photopea/UTIF.js/UTIF.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.4/fabric.min.js"></script>
<canvas id="fabric"></canvas>