当前位置: 首页 > 知识库问答 >
问题:

同一映像的不同ArrayBuffer(在Worker问题中创建ImageData)

方建明
2023-03-14

我试图在Worker中创建ImageData,只需将带有图像URL、宽度和高度的消息发布到Worker中。为了让它工作,我需要获取图像并获取ArrayBuffer。这样我就可以创建新的ImageData:

//worker.ts
fetch(e.data.url)
  .then( r => r.arrayBuffer() )
  .then( buffer => {
      console.log(buffer.byteLength); // 4022
      new ImageData((new Uint8ClampedArray(buffer)), e.data.width, e.data.height);
  });

我得到以下错误:输入数据字节长度不是(4*宽度)的倍数。

对于Chrome,我能够向Worker发布的不仅仅是URL,还有之前使用canvas在主线程中创建的整个ArrayBuffer,这很有效:

//main thread
const canvas = typeof OffscreenCanvas !== 'undefined' ?
   new OffscreenCanvas(img.width, img.height) :
   document.createElement('canvas'),
   ctx = canvas.getContext('2d');

ctx.drawImage(img, 0, 0, img.width, img.height);
const imageData: ImageData = ctx.getImageData(0, 0, img.width, img.height);
console.log(imageData.data.buffer.byteLength); // 106288

问题是使用Firefoxworker.postMessage()只能处理较小的消息,如URL,而不能处理整个ArrayBuffer(序列化和反序列化大消息需要很长时间)。这就是为什么我尝试只发送网址、高度、宽度和在工人本身中获取图像的方法。问题是在Worker中获取的ArrayBuffer——它比在主线程中使用画布创建的要小得多(相同的网址,不同的方法,不同的ArrayBuffer)。如果我将有相同的ArrayBuffer在工人,ImageData将被创建(不抛出错误)。

我的问题是我做错了什么,我如何创建ImageData后,使用提取/axios等获取图像。

共有1个答案

钱经赋
2023-03-14

图像数据表示绘制时将成为像素的红绿蓝和阿尔法值。

另一方面,图像文件必须具有元数据。即使图像是您可以发明的最基本的位图格式,它仍然至少需要宽度高度信息。

因此,您获取的文件不仅仅是像素的RGBA通道值,它是一个二进制数据,需要对其进行解析、可能未压缩、解码,甚至可能在访问这些RGBA通道之前进行一些颜色空间处理。

不要克隆ArrayBuffer,转移它,这不需要时间。

const worker_script = document.querySelector( '[type="worker-script"]' );
const worker_content = worker_script.textContent;
const worker_blob = new Blob( [ worker_content ], { type: 'text/javascript' } );
const worker_url = URL.createObjectURL( worker_blob );
const worker = new Worker( worker_url );

let start;
worker.onmessage = e => {
  console.log( e.data );
  console.log( 'it took ' + (performance.now() - start) + 'ms to go from main thread to worker and back to main' );
};

const img = new Image();
img.onload = e => {
  const canvas = document.createElement( 'canvas' );
  canvas.width = img.width;
  canvas.height = img.height;
  const ctx = canvas.getContext( '2d' );
  ctx.drawImage( img, 0, 0, img.width, img.height );
  const imageData= ctx.getImageData( 0, 0, img.width, img.height );
  start = performance.now();
  worker.postMessage(
    imageData,
    [ imageData.data.buffer ] // transfer the ArrayBuffer
  );
};
img.crossOrigin = "anonymous";
img.src = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png";
<script type="worker-script">
  onmessage = e => {
    const imageData = e.data;
    postMessage(
`worker received a ${ imageData.width } x ${ imageData.height } ImageData,
whose buffer's size is ${ imageData.data.buffer.byteLength }bytes`
    );
  };
</script>
 类似资料:
  • 我试图写一个机器学习算法,我试图预测输出是+50000还是-50000。在这样做时,我利用了11个字符串特征使用随机森林分类器。但是由于随机森林分类器需要以float/numbers的形式输入,所以我使用DictVectorizer将字符串特性转换为float/numbers。但是对于数据中的不同行,DictVectorizer创建了不同数量的特性(240-260)。这会导致预测模型输出的错误。一

  • 问题内容: 我们可以使用没有源映像(OS)的docker文件创建docker映像吗 我们不希望在所有应用程序docker映像中使用基本映像(centos或rhel)。我们想要将基本映像(centos或rhel)与应用程序映像分开,并在运行时将它们链接起来。可能吗? 当我 不使用 或构建docker映像时,docker抱怨:“提交前提供源映像” 我的docker文件如下所示: 问题答案: 您说过:“

  • 问题内容: 我有一个用create-react-app创建的React应用,没有弹出。我正在尝试使用网络工作者。我已经尝试过worker- loader软件包(https://github.com/webpack-contrib/worker- loader )。 如果我尝试开箱即用(- )的worker-loader ,我将收到一条错误消息,告诉我Create React App不支持Webpa

  • 我正在微服务中做一些更改,它有一个像以下这样的对象: } 我将从Json中获取我将要使用的信息。Json有一个名为的键,我想在两个不同的变量中使用这个速率,一个int-rate和一个Float-ratePPR。这里的问题是,我知道在同一个对象中不能有来自同一个Json的两个变量,但我有义务这样做,因为我不能触摸变量,所以我创建了变量,以便在需要时使用。 当我进行测试时,会出现以下错误: 属性“ra

  • 我想移除一个DIV元素的类,该元素是在调用函数时立即创建的。 问题是,我希望也是该函数的一部分。 这就是我现在拥有的功能。 我已尝试在函数中添加函数 但不管用。 也许我可以在调用函数的任何地方添加,但我想知道是否有一种方法可以在函数中实现这一点 函数是这样调用的。

  • 报告的标题由10个元素组成,如下所示: 实际上是这样的: 这和垂直照明有关吗?我已经把它搞定了。 我的jrxml文件中的片段: