javascript - html 图像的奇怪压缩

标签 javascript html image compression webgl

我想使用从 WebGL 中的服务器检索的 base64 编码的 png。 为此,我将编码后的 png 加载到 html Image 对象中。 对于我的应用程序,我需要 png 数据绝对无损,但是着色器检索到的像素值在不同的浏览器中是不同的...... (如果我将图像加载到 Canvas 中并使用 getImageData,则检索到的像素值在不同浏览器中也会有所不同)。 一定会发生一些奇怪的像素值过滤/压缩,但我不知道如何以及为什么。有人熟悉这个问题吗?

从服务器加载图像:

var htmlImage = new Image();
htmlImage.src = BASE64_STRING_FROM_SERVER

将图像加载到着色器中:

ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGB, ctx.RGB, ctx.UNSIGNED_BYTE, 
htmlImage); 

尝试使用 Canvas 读取像素值(不同浏览器的值不同):

var canvas = document.createElement('canvas');
canvas.width = htmlImage.width;
canvas.height = htmlImage.height;
canvas.getContext('2d').drawImage(htmlImage, 0, 0, htmlImage.width, 
htmlImage.height);

// This data is different in, for example, the latest version of Chrome and Firefox
var pixelData = canvas.getContext('2d').getImageData(0, 0, 
htmlImage.width, htmlImage.height).data;   

最佳答案

正如@Sergiu 指出的,默认情况下,浏览器可能会对图像应用颜色校正、 Gamma 校正、颜色配置文件或其他任何内容。

在 WebGL 中,您可以将其关闭。在将图像上传到纹理之前,使用 gl.UNPACK_COLORSPACE_CONVERSION_WEBGL 调用 gl.pixelStorei 并将其传递给 gl_NONE,如下所示

gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);

这将告诉浏览器不要应用色彩空间、 Gamma 等。这对于 WebGL 很重要,因为许多 3D 应用程序使用纹理来传递图像以外的内容。示例包括法线贴图、高度贴图、环境光遮挡贴图、发光贴图、镜面贴图和许多其他类型的数据。

默认设置为

gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.BROWSER_DEFAULT_WEBGL);

请注意,这可能仅在直接从图像获取数据时有效,而不是在通过 2d Canvas 传递图像时有效。

请注意,如果您通过将 WebGL Canvas 绘制到 2D Canvas 中来获取数据,那么一切都将失败。如果没有别的,2D Canvas 使用预乘 alpha,因此如果 alpha < 255,将数据复制到 2D Canvas 中或从 2D Canvas 中复制出来总是有损的。如果您希望数据返回时不受 2D Canvas 所做的任何影响,请使用 gl.readPixels .

请注意,此方法的一个潜在问题是速度。浏览器可能会假设当您下载图像时它最终会显示。它无法提前知道它将在纹理中使用。因此,您创建一个图像标签,设置 src 属性,浏览器下载图像,解压缩它,准备显示,然后发出加载事件,然后将该图像上传到纹理 UNPACK_COLORSPACE_CONVERSION_WEBGL = NONE.如果浏览器没有保留尚未应用色彩空间转换的版本,则此时浏览器可能必须重新解压缩它。这不太可能是一个明显的速度问题,但也不是零。

为了解决这个问题,浏览器添加了 ImageBitmap api 。该 API 解决了一些问题。

  1. 它可以在 Web Worker 中使用,因为它不是像 Image 那样的 DOM 元素

  2. 您可以向其传递一个子矩形,这样您就不必先获取整个图像,然后才能最终获取某些部分

  3. 您可以在开始避免上述问题之前告诉它是否应用色彩空间校正。

遗憾的是,截至 2018/12 年,只有 Chrome 完全支持它。 Firefox 有部分支持。 Safari 没有。

关于javascript - html 图像的奇怪压缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53704198/

相关文章:

javascript - Canvas 矩形背景图像

javascript - 使用 AngularJS 基于来自另一个字段的输入的数据将选项填充到选择中

java - 如何从我的网站触发桌面应用程序?

java - 从资源加载图像无法读取输入文件

html - 显示来自 facebook 图表的图像出现在顶部的边缘。为什么?

javascript - 如何在 react 路由器中的每次路由更改时监听窗口负载?

javascript - 在 HTML5 中设置透明颜色

jQuery 将元素移动到同级不起作用

JavaScript "copy"HTML 表单

css 图像在另一个网站背景之上