Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flipping RGBA output of glReadPixels (C++ OpenGL)

Tags:

c++

opengl

I would like to flip the output image from glReadPixel. I have checked the output from glReadPixels by saving it to a file. The image is correct, however its upside down.

What I tried

int patchSize = 50;
std::vector<unsigned char> rgbdata(4*patchSize*patchSize);
glReadPixels(x-(patchSize/2), y-(patchSize/2)/2), patchSize,patchSize,GL_RGBA,GL_UNSIGNED_BYTE, &rgbdata[0]);

std::vector< unsigned char > temp_rgbdata = rgbdata; // Create a copy of the data
    rgbdata.clear(); // Reset the array
    for (int i=patchSize-1; i >= 0; i--) // Count backwards in order to flip
    {
        for( int j = 0; j < patchSize; j++) {

            rgbdata.push_back(temp_rgbdata[i*patchSize+j*4]);
            rgbdata.push_back(temp_rgbdata[i*patchSize+j*4+1]);
            rgbdata.push_back(temp_rgbdata[i*patchSize+j*4+2]);
            rgbdata.push_back(temp_rgbdata[i*patchSize+j*4+3]);

        }
    }
    temp_rgbdata.clear(); // Clear the temporary array

What is wrong

The images turns out all wrong:

Output from trying to flip image

Any help and comments are appreciated. Thank you.

Solution (by Boris)

int patchSize = 50;
std::vector<unsigned char> rgbdata(4*patchSize*patchSize);
glReadPixels(x-(patchSize/2), y-(patchSize/2)), patchSize,patchSize,GL_RGBA,GL_UNSIGNED_BYTE, &rgbdata[0]);

std::vector< unsigned char > temp_rgbdata = rgbdata; // Create a copy of the data
    rgbdata.clear(); // Reset the array
    for (int i=patchSize-1; i >= 0; i--) // Count backwards in order to flip
    {
        for( int j = 0; j < patchSize; j++) {

            rgbdata.push_back(temp_rgbdata[(i*patchSize+j)*4]);
            rgbdata.push_back(temp_rgbdata[(i*patchSize+j)*4+1]);
            rgbdata.push_back(temp_rgbdata[(i*patchSize+j)*4+2]);
            rgbdata.push_back(temp_rgbdata[(i*patchSize+j)*4+3]);

        }
    }
    temp_rgbdata.clear(); // Clear the temporary array
like image 320
Købmanden Avatar asked Dec 14 '25 23:12

Købmanden


2 Answers

Here is a full example, built ontop of Stypox's great snippet - this does the actual writing also. Of course, swapping your co-ord system is another workaround but I find 0,0 at the top left more natural.

// https://github.com/nothings/stb/blob/master/stb_image_write.h
#include "stb_image_write.h"

glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadBuffer(GL_BACK_LEFT);

std::vector<uint8_t> pixels(3 * w * h);
glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());

for(int line = 0; line != h/2; ++line) {
    std::swap_ranges(pixels.begin() + 3 * w * line,
                     pixels.begin() + 3 * w * (line+1),
                     pixels.begin() + 3 * w * (h-line-1));
}

int components = 3;
stbi_write_png("out.png", w, h, components, pixels.data(), 3 * w);
stbi_write_tga("out.tga", w, h, components, pixels.data());
like image 108
Goblinhack Avatar answered Dec 16 '25 16:12

Goblinhack


You need parentheses in all those lines:

temp_rgbdata[ (i*patchSize+j)*4 ]

By the way, you can be much more efficient by:

  1. Getting the upside down image into the temporary array (avoid a useless copy)

  2. Initialize rgbdata of final size and copy a whole line at once:

Here is how you would do:

int patchSize = 50;
std::vector<unsigned char> temp_rgbdata(4*patchSize*patchSize);
glReadPixels(x-(patchSize/2), y-(patchSize/2)),patchSize,patchSize,GL_RGBA,GL_UNSIGNED_BYTE, &temp_rgbdata[0]);

std::vector< unsigned char > rgbdata(4*patchSize*patchSize);
for (int i=0; i < patchSize; i++) // Doesn't matter the order now
    memcpy(&rgbdata[i*patchSize*4],                    // address of destination
           &temp_rgbdata[(patchSize-i-1)*patchSize*4], // address of source
           patchSize*4*sizeof(unsigned char) );        // number of bytes to copy

temp_rgbdata.clear(); // Clear the temporary array
like image 22
Boris Dalstein Avatar answered Dec 16 '25 16:12

Boris Dalstein



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!