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:

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
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());
You need parentheses in all those lines:
temp_rgbdata[ (i*patchSize+j)*4 ]
By the way, you can be much more efficient by:
Getting the upside down image into the temporary array (avoid a useless copy)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With