有没有办法在不使用画布 API 的情况下从图像文件中获取二进制数据?

Posted

技术标签:

【中文标题】有没有办法在不使用画布 API 的情况下从图像文件中获取二进制数据?【英文标题】:Is there a way to get binary data from an image file without using canvas API? 【发布时间】:2020-10-05 03:12:40 【问题描述】:

我想使用 javascript 访问和操作图像的二进制数据。据我研究,可以使用 Canvas API 来完成 - 在内存中创建画布和上下文,然后使用它们的内置方法。我想出的看起来像这样:

function fileToBase64(file: File): Promise<string> 
  return new Promise((resolve, reject) => 
    const reader = new FileReader();
    reader.onload = () => resolve(<string>reader.result);
    reader.onerror = () => reject(reader.error);
    reader.readAsDataURL(file);
  );


function base64ToImageData(base64: string): Promise<ImageData> 
  return new Promise((resolve, reject) => 
    const img = new Image();
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    img.onload = () => 
      canvas.width = img.width;
      canvas.height = img.height;
      ctx.drawImage(img, 0, 0);
      const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
      resolve(imageData);
    
    img.onerror = () => reject();
    img.src = base64;
  );

不喜欢这种方法的一点是它冗长并且可能使用了更多的资源。 所以问题是:有没有办法在不使用 canvas API 的情况下获得图像的二进制表示?

【问题讨论】:

Is there a way to get a binary representation? 认为您的意思是 ImageData 表示您以后可以操作的所有 rgba 像素数据?图像的二进制表示有很多,png、jpg、webp等 【参考方案1】:

您可以手动构造一个ImageData,但为此您需要一个 Uint8ClampedArray。为此,您还必须自己将二进制文件解码为像素数据。因此,您可能无论如何都想使用 canvas 或 offscreanCanvas

但是有一些工具可以简化使用 createImageBitmap 从 blob 获取 imageData 的方式 此 imageBitmap 包含像素数据,但您无法读取它,但至少将其绘制到画布元素会更快。

(async () => 
// just to simulate a file you would get from file input
const res = await fetch('https://httpbin.org/image/png')
const blob = await res.blob()
const file = new File([blob], 'image.png', blob)

async function getImageData (blob) 
  const bitmap = await createImageBitmap(blob)
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')

  canvas.width = bitmap.width
  canvas.height = bitmap.height

  ctx.drawImage(bitmap, 0, 0)
  return ctx.getImageData(0, 0, canvas.width, canvas.height)


getImageData(blob).then(imageData => console.log(imageData.width))

)()

但由于兼容性问题,您可能不会使用createImageBitmap,所以我建议您不要使用 FileReader 从file input -&gt; base64 -&gt; image 创建图像,而是使用带有对象 url 的指针引用从文件转到图像

const img = new Image()
img.src = URL.createObjectURL(file)

这将使用更少的资源,因为您不需要将其编码为 base64 并再次将其解码回二进制文件,它将使用更少的内存,因为它只会直接从您的磁盘加载图像

【讨论】:

以上是关于有没有办法在不使用画布 API 的情况下从图像文件中获取二进制数据?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在不使用图像选择器的情况下从照片应用程序呈现默认的 iOS 编辑视图?

有没有办法在不使用画布的情况下在 JavaScript 中合并图像?

有没有办法确定跨域图像是不是会在不绘制画布的情况下污染画布?

有没有办法在不导入 csv 的情况下从 .csv 创建 JSON?

是否有可能在不快速调用 API 的情况下从互联网获取图像?

目标 C:如何在不损失边缘质量的情况下从 JPG 图像中去除白色背景