将RGBA转换为ARGB(glReadPixels - > AVAssetWriter)

Dom*_*old 3 opengl-es glreadpixels ios

我希望借助于将使用OpenGL渲染的图像记录到电影文件中AVAssetWriter.问题出现了,从OpenGL帧缓冲区访问像素的唯一方法是使用glReadPixels,它只支持iOS上的RGBA像素格式.但AVAssetWriter不支持这种格式.在这里,我可以使用ARGB或BGRA.由于可以忽略alpha值,我得出结论,将RGBA转换为ARGB的最快方法是给glReadPixels缓冲移位一个字节:

UInt8 *buffer = malloc(width*height*4+1);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer+1);
Run Code Online (Sandbox Code Playgroud)

问题是,glReadPixels呼叫会导致EXC_BAD_ACCESS崩溃.如果我不将缓冲区移动一个字节,它可以很好地工作(但显然在视频文件中有错误的颜色).这有什么问题?

dat*_*olf 5

我得出结论,将RGBA转换为ARGB的最快方法是给glReadPixels缓冲移位一个字节

但是,这也会将您的alpha值移动1个像素.这是另一个建议:

将图片渲染为纹理(使用具有该纹理的FBO作为颜色附件).接下来将纹理渲染到另一个帧缓冲区,使用一个混合片段着色器:

#version ...
uniform sampler2D image;
uniform vec2 image_dim;
void main() 
{
    // we want to address texel centers by absolute fragment coordinates, this
    // requires a bit of work (OpenGL-ES SL doesn't provide texelFetch function).
    gl_FragColor.rgba = 
        texture2D(image, vec2( (2*gl_FragCoord.x + 1)/(2*image_dim.y), 
                               (2*gl_FragCoord.y + 1)/(2*image_dim.y) )
        ).argb; // this swizzles RGBA into ARGB order if read into a RGBA buffer
}
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一句.我刚刚发现了一些非常有趣的东西:AVAssetWriter在指定BGRA而不是ARGB时对视频的编码速度更快(!).所以整个问题实际上是关于转换RGBA-> BGRA而不是RGBA-> ARGB,这种像素调配技术绝对是强制性的,因为我提出的单字节移位技术无法转换RGBA-> BGRA! (2认同)