Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 786
Dominik Seibold Avatar asked Oct 30 '25 01:10

Dominik Seibold


2 Answers

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
}
like image 111
datenwolf Avatar answered Nov 01 '25 23:11

datenwolf


What happens if you put an extra 128 bytes of slack on the end of your buffer? It might be that OpenGL is trying to fill 4/8/16/etc bytes at a time for performance, and has a bug when the buffer is non-aligned or something. It wouldn't be the first time a performance optimization in OpenGL had issues on an edge case :)

like image 23
StilesCrisis Avatar answered Nov 01 '25 21:11

StilesCrisis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!