WebGL:将 8 位灰度图像加载到纹理时图像无效
WebGL: Invalid Image when loading 8-bit grayscale image to texture
我正在尝试将从我的服务器下载的 8 位灰度 JPG 渲染到纹理中以使用 WebGL 进行渲染。
// Pretend for the sake of example that I have passed in an argument
// 'img' that is an Image object that I used to download the jpg.
// See the EDIT below for how this happens...
// ...also presume that I have set up my WebGL context and assigned it
// to the variable 'gl':
// const gl = canvas.getContext('experimental-webgl');
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Set the parameters so we can render any size image.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
// Upload the image into the texture.
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, gl.LUMINANCE, gl.UNSIGNED_BYTE, img);
这时候WebGL打了我一巴掌,抢了我的午餐钱:
WebGL: INVALID_VALUE: texImage2D: invalid image
然后我要问:你想要 WebGL 什么?为什么你不开心???
我可能遗漏了一些基本的东西,但互联网上充斥着无法回答我的问题的 WebGL 内容。有没有 WebGL 专家可以给点建议?
图片如下:
编辑:
以下是有关如何获取图像的更多详细信息。 注意:这样做的原因是我需要一个可以洗牌、取消和重新启动的下载队列,令人作呕。因此使用 fetch、blob 和对象 URL .整个事情是深度缩放图像查看器的一部分,它应该有效地只加载视口中可见的图像块(通常会随时变化)。无论如何,这是我获取图像的方式:
// Take care of vendor prefixes:
window.URL = window.URL || window.webkitURL;
// This is where we'll assign our final product
const imageTag = new Image();
imageTag.onerror = (err) => {
console.error('IMG ERROR:', err);
};
imageTag.onload = () => {
// Once the image tag has loaded the blob data, clean up our object url:
window.URL.revokeObjectURL(imageTag.src);
// imageTag is now passed into the code above as 'img'
};
// Grab the image data as a blob
fetch(`<url_of_image>`)
.then(res => res.blob())
.then(blob => {
// When we get the image data, wrap it in an object url and assign
// it to src. The onload event won't fire until the next tick.
imageTag.src = window.URL.createObjectURL(blob);
});
我应该指出,我最初是使用 canvas2D API 渲染的,并且它能够使用 drawImage()
方法很好地绘制图像。所以我很确定图像对象加载正常。我实现 WebGL 渲染器的原因是打开通往更大性能增强的大门。
感谢观看!
通过 Chromium 代码库搜索错误消息字符串并查看 revokeObjectURL
参考,它似乎是罪魁祸首。 image URL 表示的图像内容简单地得到 "freed" 到早。解决方案是在 调用 texImage2D
.
之后调用 revokeObjectURL
好的党员们,我想通了(至少是一种方法)。
我永远无法开始工作的原始流程是:
- 以 blob 形式获取图像数据
- 使用 ObjectURL 可以将 blob 传递到
src
属性上的图像标签
- 将图像标签传递到
texImage2D
(旧方法签名)
对我有用的新流程是:
- 获取图像数据作为数组缓冲区
- 使用jpeg-js
将jpg数据解码为Uint8Array
- 将 Uint8Array 传递给
texImage2D
(新方法签名)
看起来像这样:
// I am using the decode() method from jpeg-js. Passing true as a second parameter
// causes the data to be returned wrapped in a Uint8Array. Even though the data
// was one channel going in, it's going to come out with all four (RGBA) channels.
import { decode } from 'jpeg-js';
// Like before, please presume a global gl variable to be my WebGL context.
const gl = '<my-webgl-context-that-I-set-up-elsewhere>';
fetch(`<url_of_image>`)
.then(res => res.arrayBuffer())
.then(buffer => {
// When we get the image data, it's still encoded. We need to decode it
// before we've got pixel data. We want it as a Uint8Array which will make
// texImage2D() happy.
const pixels = decode(buffer, true);
// Set up a new texture where we'll capture and keep the image data
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Set the parameters so we can render any size image.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
// Upload the image into the texture:
// Here we are telling WebGL how many bytes each pixel will be (I think
// think the default is 4, but I thought that this step was important to show).
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
// jpeg-js is kind enough to provide the dimensions of the image data in its
// returned value. Since jpeg-js returns the data with all 4 channels, we use
// gl.RGBA here.
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixels.width, pixels.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels.data);
// Ready to draw!
});
希望这对以后的人有用。感谢所有贡献思想和想法的人,感谢 jpeg-js 上的合作者!
我正在尝试将从我的服务器下载的 8 位灰度 JPG 渲染到纹理中以使用 WebGL 进行渲染。
// Pretend for the sake of example that I have passed in an argument
// 'img' that is an Image object that I used to download the jpg.
// See the EDIT below for how this happens...
// ...also presume that I have set up my WebGL context and assigned it
// to the variable 'gl':
// const gl = canvas.getContext('experimental-webgl');
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Set the parameters so we can render any size image.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
// Upload the image into the texture.
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, gl.LUMINANCE, gl.UNSIGNED_BYTE, img);
这时候WebGL打了我一巴掌,抢了我的午餐钱:
WebGL: INVALID_VALUE: texImage2D: invalid image
然后我要问:你想要 WebGL 什么?为什么你不开心???
我可能遗漏了一些基本的东西,但互联网上充斥着无法回答我的问题的 WebGL 内容。有没有 WebGL 专家可以给点建议?
图片如下:
编辑:
以下是有关如何获取图像的更多详细信息。 注意:这样做的原因是我需要一个可以洗牌、取消和重新启动的下载队列,令人作呕。因此使用 fetch、blob 和对象 URL .整个事情是深度缩放图像查看器的一部分,它应该有效地只加载视口中可见的图像块(通常会随时变化)。无论如何,这是我获取图像的方式:
// Take care of vendor prefixes:
window.URL = window.URL || window.webkitURL;
// This is where we'll assign our final product
const imageTag = new Image();
imageTag.onerror = (err) => {
console.error('IMG ERROR:', err);
};
imageTag.onload = () => {
// Once the image tag has loaded the blob data, clean up our object url:
window.URL.revokeObjectURL(imageTag.src);
// imageTag is now passed into the code above as 'img'
};
// Grab the image data as a blob
fetch(`<url_of_image>`)
.then(res => res.blob())
.then(blob => {
// When we get the image data, wrap it in an object url and assign
// it to src. The onload event won't fire until the next tick.
imageTag.src = window.URL.createObjectURL(blob);
});
我应该指出,我最初是使用 canvas2D API 渲染的,并且它能够使用 drawImage()
方法很好地绘制图像。所以我很确定图像对象加载正常。我实现 WebGL 渲染器的原因是打开通往更大性能增强的大门。
感谢观看!
通过 Chromium 代码库搜索错误消息字符串并查看 revokeObjectURL
参考,它似乎是罪魁祸首。 image URL 表示的图像内容简单地得到 "freed" 到早。解决方案是在 调用 texImage2D
.
revokeObjectURL
好的党员们,我想通了(至少是一种方法)。
我永远无法开始工作的原始流程是:
- 以 blob 形式获取图像数据
- 使用 ObjectURL 可以将 blob 传递到
src
属性上的图像标签 - 将图像标签传递到
texImage2D
(旧方法签名)
对我有用的新流程是:
- 获取图像数据作为数组缓冲区
- 使用jpeg-js 将jpg数据解码为Uint8Array
- 将 Uint8Array 传递给
texImage2D
(新方法签名)
看起来像这样:
// I am using the decode() method from jpeg-js. Passing true as a second parameter
// causes the data to be returned wrapped in a Uint8Array. Even though the data
// was one channel going in, it's going to come out with all four (RGBA) channels.
import { decode } from 'jpeg-js';
// Like before, please presume a global gl variable to be my WebGL context.
const gl = '<my-webgl-context-that-I-set-up-elsewhere>';
fetch(`<url_of_image>`)
.then(res => res.arrayBuffer())
.then(buffer => {
// When we get the image data, it's still encoded. We need to decode it
// before we've got pixel data. We want it as a Uint8Array which will make
// texImage2D() happy.
const pixels = decode(buffer, true);
// Set up a new texture where we'll capture and keep the image data
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Set the parameters so we can render any size image.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
// Upload the image into the texture:
// Here we are telling WebGL how many bytes each pixel will be (I think
// think the default is 4, but I thought that this step was important to show).
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
// jpeg-js is kind enough to provide the dimensions of the image data in its
// returned value. Since jpeg-js returns the data with all 4 channels, we use
// gl.RGBA here.
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixels.width, pixels.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels.data);
// Ready to draw!
});
希望这对以后的人有用。感谢所有贡献思想和想法的人,感谢 jpeg-js 上的合作者!