Search code examples
iosopengl-esglreadpixels

Converting RGBA to ARGB (glReadPixels -> AVAssetWriter)


I want to record images, rendered with OpenGL, into a movie-file with the help of AVAssetWriter. The problem arises, that the only way to access pixels from an OpenGL framebuffer is by using glReadPixels, which only supports the RGBA-pixel format on iOS. But AVAssetWriter doesn't support this format. Here I can either use ARGB or BGRA. As the alpha-values can be ignored, I came to the conclusion, that the fastest way to convert RGBA to ARGB would be to give glReadPixels the buffer shifted by one byte:

UInt8 *buffer = malloc(width*height*4+1);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer+1);

The problem is, that the glReadPixels call leads to a EXC_BAD_ACCESS crash. If I don't shift the buffer by one byte, it works perfectly (but obviously with wrong colors in the video-file). What's the problem here?


Solution

  • I came to the conclusion, that the fastest way to convert RGBA to ARGB would be to give glReadPixels the buffer shifted by one byte

    This will however shift your alpha values by 1 pixel as well. Here's another suggestion:

    Render the picture to a texture (using a FBO with that texture as color attachment). Next render that texture to another framebuffer, with a swizzling fragment shader:

    #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
    }