问题描述
我有一个YUV-NV12格式的图像数据的字节缓冲区。当我尝试将其转换为RGB时,会得到带有拉伸颜色(色度)层的输出,如下图所示。
我遵循了出色的answer,该指南指导将YUV-NV21转换为RGB。由于NV-12只是具有翻转的U和V数据的NV-21,所以我唯一要做的更改是替换片段着色器中的u
和v
值。
顶点着色器:
precision mediump float;
uniform mat4 uMVPMatrix;
attribute vec4 vPosition;
attribute vec4 vTextureCoordinate;
varying vec2 position;
void main()
{
gl_Position = uMVPMatrix * vPosition;
position = vTextureCoordinate.xy;
}
片段着色器:
precision mediump float;
varying vec2 position;
uniform sampler2D uTextureY;
uniform sampler2D uTextureUV;
void main()
{
float y,u,v;
y = texture2D(uTextureY,position).r;
u = texture2D(uTextureUV,position).a - 0.5;
v = texture2D(uTextureUV,position).r - 0.5;
float r,g,b;
r = y + 1.13983 * v;
g = y - 0.39465 * u - 0.58060 * v;
b = y + 2.03211 * u;
gl_FragColor = vec4(r,b,1.0);
}
将图像数据分割并放入2个ByteBuffer
和mYBuffer
的{{1}}中。 mUVBuffer
只是一个mSourceImage
,其中包含图像数据作为Buffer
数据。
byte
生成纹理:
ByteBuffer bb = (ByteBuffer) mSourceImage;
if (bb == null) {
return;
}
int size = mWidth * mHeight;
bb.position(0).limit(size);
mYBuffer = bb.slice();
bb.position(size).limit(bb.remaining());
mUVBuffer = bb.slice();
将缓冲区数据传递给纹理:
GLES20.glGenTextures(2,mTexture,0);
for(int i = 0; i < 2; i++) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,mTexture[i]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE);
}
我不知道为什么得到这样的输出。任何帮助将不胜感激。
解决方法
没关系,这是我的代码中的一个小错误。
拆分字节缓冲区时,我将bb.position(size).limit(bb.remaining())
用于UV缓冲区。由于某些原因,bb.remaining()
在获得一些帧后变为0(这实际上是相机预览)。因此,我将其更改为bb.position(size).limit(size + size / 2)
。
也是我通过阅读this做出的假设,
我唯一要做的更改是替换片段着色器中的u和v值
似乎是错误的。可以观察到GL20.GL_LUMINANCE_ALPHA
总是将U
字节放入纹理的A分量,并将V
字节放入R,G,B分量(您可以使用其中任何一个)。因此,无需在片段着色器中交换u
和v
值(我已经使用正确的片段着色器代码编辑了问题)。
我将继续提出问题,希望这对以后的人有所帮助。