【问题标题】:Image to Uint8Array in Javascript [duplicate]Javascript中的图像到Uint8Array [重复]
【发布时间】:2019-01-22 23:16:00
【问题描述】:

我有一个需要转换为 Uint8Array 的图像。

例如:

var image = new Image();
image.src="image13.jpg";

现在我需要将这个 image 变量转换为 Uint8Array。 JS中有什么函数可以实现这个功能吗?

【问题讨论】:

  • @david 嗨,大卫,感谢您指出其他类似的问题。但是我们处理的变量的类型是不同的。
  • @Learner 你指出的问题与我在这里问的完全相反。
  • 抱歉没睡,早上起来了,如果相反,你能把它倒过来吗? :D

标签: javascript arrays image


【解决方案1】:

您可以使用Canvas API 来检索图像数据:

  1. 使用canvas.toBlob()blob.arrayBuffer()检索各种图像格式(PNG、JPEG等)的二进制形式的数据:
async function imageToUint8Array(image, context) {
  context.width = image.width;
  context.height = image.height;
  context.drawImage(image, 0, 0);
  const blob = await context.canvas.toBlob(
    callback,
    "image/jpeg" // the MIME type of the image format
    1 // quality (in the range 0..1)
  );
  return new Uint8Array(await blob.arrayBuffer());
}

function toBlob(canvas, type = "image/png", quality = 1) {
  return new Promise((resolve) => canvas.toBlob(blob => resolve(blob)))
}

async function imageToUint8Array(image, context) {
  context.width = image.width;
  context.height = image.height;
  context.drawImage(image, 0, 0);
  const blob = await toBlob(context.canvas, "image/png");
  return new Uint8Array(await blob.arrayBuffer());
}

const image = new Image();
// stackoverflow logo
image.src = `data:image/png;base64,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`;

const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");

image.onload = async() => console.log(await imageToUint8Array(image, context));
  1. 使用canvas.getImageData()检索原始图像像素:
function imageToUint8Array(image, context) {
  context.width = image.width;
  context.height = image.height;
  context.drawImage(image, 0, 0);
  // `getImageData().data` is a `Uint8ClampedArray`, which differs from `Uint8Array` only in
  // how data is treated when values are being *set*, so it is valid to perform the conversion
  // into a `Uint8Array`.
  return new Uint8Array(context.getImageData(0, 0, image.width, image.height).data.buffer);
}

function imageToUint8Array(image, context) {
  context.width = image.width;
  context.height = image.height;
  context.drawImage(image, 0, 0);
  // `getImageData().data` is a `Uint8ClampedArray`, which differs from `Uint8Array` only in
  // how data is treated when values are being *set*, so it is valid to perform the conversion
  // into a `Uint8Array`.
  return new Uint8Array(context.getImageData(0, 0, image.width, image.height).data.buffer);
}

const image = new Image();
// stackoverflow logo
image.src = `data:image/png;base64,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`;

const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");

image.onload = async() => console.log(imageToUint8Array(image, context));

【讨论】:

  • "没有额外的处理"天哪...下一个电话在上面画了一些新的东西。此外,您的第一个 sn-p 确实创建了一个全新的图像,它“看起来”相同,但不会是实际图像的数据。见stackoverflow.com/a/42916772/3702797
  • 不确定你的意思。将图像绘制到画布上后,不会进行任何处理。它创建一个新图像这一事实并不重要,因为我们只关心图像的内容,所以只要它看起来相同,就足够了。
  • 是的,当您调用 ctx.getImageData() 时,会进行大量处理:必须将存储在 GPU 缓冲区中的位图移动到 CPU,从那里每个像素都必须移动在存储在 ImageData 的缓冲区中之前,被读取并未乘以 RGBA。这实际上是 canvas API 中最慢的操作之一。是的,您现在正在生成具有更多编码伪像的新更大图像确实很重要。
  • 我想你一定误解了我的意思。您所描述的是数据存储方式的结果。当然,它必须被读取、解包和序列化为 JS 对象。我的意思是它不会另外转换为 PNG/JPEG/等除此之外。这就是我写额外处理的原因。仅当您尝试表示完全相同的图像时,额外的伪影才有意义。 OP的问题在这方面有点含糊。
  • "没有额外的处理,所以这个方法是完全同步的。"这句话清楚地说明了这个方法是同步的因为没有额外的处理。这不是真的,由于其他原因它是同步的。并且“没有额外处理”与您的第一段形成对比,第一段说“必须处理数据,这可能需要很长时间,并且不应该阻塞主线程。”这里也必须处理数据,不同的处理但仍然是一个处理,仍然“可能需要很长时间”并且还可能“阻塞主线程”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-15
  • 2021-08-30
  • 2022-01-09
  • 2012-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多