为什么编码为 Base64 的图像数据会使用错误的值解码回来?

发布于 2025-01-09 02:15:29 字数 1014 浏览 5 评论 0原文

我正在尝试将数组转换为 base64 字符串。然后又回来了。我制作了一个简单的示例,其中的示例数组如下所示: [0, 1, 2, 3, 0, 1, 2, 3] 并使用 .toDataURL()< 进行转换/code> 在画布中。但由于某种原因,当我读回 Base64 字符串并将其应用到画布时,它返回不同的图像数据[0, 0, 0, 3, 0, 0, 0, 3 ]

为什么会出现这种情况?

例子:

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

const array = new Uint8ClampedArray([0, 1, 2, 3, 0, 1, 2, 3]);
const initialImageData = new ImageData(array, 2, 1);

ctx.putImageData(initialImageData, 0, 0);
const dataURL = canvas.toDataURL();

console.log(dataURL); // data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAYAAAD0In+KAAAAAXNSR0IArs4c6QAAAA9JREFUGFdjZGBgYGYAAgAAIQAFoFclWQAAAABJRU5ErkJggg==

const img = new Image();
img.onload = () => {
    canvas.width = 2;
    canvas.height = 1;
    ctx.drawImage(img, 0, 0);
    const imageData = ctx.getImageData(0, 0, 2, 1);
    console.log(imageData.data); // [0, 0, 0, 3, 0, 0, 0, 3]
}
img.src = dataURL;

I'm trying to convert an array into a base64 string. And then back again. I've made a simple example with a sample array looking like this: [0, 1, 2, 3, 0, 1, 2, 3] and converting with .toDataURL() in canvas. But by some reason, when I read base64 string back and apply it to the canvas it returns a different image data: [0, 0, 0, 3, 0, 0, 0, 3].

Why this happens?

Example:

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

const array = new Uint8ClampedArray([0, 1, 2, 3, 0, 1, 2, 3]);
const initialImageData = new ImageData(array, 2, 1);

ctx.putImageData(initialImageData, 0, 0);
const dataURL = canvas.toDataURL();

console.log(dataURL); // data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAYAAAD0In+KAAAAAXNSR0IArs4c6QAAAA9JREFUGFdjZGBgYGYAAgAAIQAFoFclWQAAAABJRU5ErkJggg==

const img = new Image();
img.onload = () => {
    canvas.width = 2;
    canvas.height = 1;
    ctx.drawImage(img, 0, 0);
    const imageData = ctx.getImageData(0, 0, 2, 1);
    console.log(imageData.data); // [0, 0, 0, 3, 0, 0, 0, 3]
}
img.src = dataURL;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酒中人 2025-01-16 02:15:30

看起来您已经被 这个陷阱所困扰Canvas实现

警告:由于与预乘 Alpha 颜色值之间的转换存在损耗性质,刚刚使用 putImageData() 设置的像素可能会作为不同值返回到等效的 getImageData()。

(强调我的)

您传入的 Uint8ClampedArray 格式为 [r, g, b, a] ,Alpha (a) 组件为极其重要。在您的测试中,您提供了 3 的 Alpha,浏览器似乎选择将其他像素“优化”为 0

尝试使用 a 的完全不透明度值,一切正常:

const array = new Uint8ClampedArray([0, 1, 2, 255, 0, 1, 2, 255]);

...

console.log(imageData.data); // [0, 1, 2, 255, 0, 1, 2, 255]

Looks like you've been caught by this gotcha in the Canvas implementation:

Warning: Due to the lossy nature of converting to and from premultiplied alpha color values, pixels that have just been set using putImageData() might be returned to an equivalent getImageData() as different values.

(emphasis mine)

The Uint8ClampedArray you pass in is in format [r, g, b, a] and the Alpha (a) component is extremely important. In your test you've supplied an Alpha of 3 and it appears the browser is choosing to "optimize" the other pixels to 0.

Try a full-opacity value of a and it all works fine:

const array = new Uint8ClampedArray([0, 1, 2, 255, 0, 1, 2, 255]);

...

console.log(imageData.data); // [0, 1, 2, 255, 0, 1, 2, 255]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文