我想从glReadPixel翻转输出图像。我已经通过将glReadPixels保存到文件来检查输出。图像是正确的,但它是颠倒的。
我尝试了什么
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
有什么问题
图像完全没错:
感谢任何帮助和评论。谢谢。
解决方案(鲍里斯)
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
答案 0 :(得分:3)
您确定要从正确的坐标系读取和写入吗?以下摘自OpenGL.org:
与具有左上角坐标系的2D渲染API相关的另一个常见缺陷是2D图像文件格式在顶部扫描线而不是底部扫描线处开始图像。 OpenGL假定图像默认从底部扫描线开始。如果您确实需要在渲染时翻转图像,则可以使用 glPixelZoom(1,-1)。
如果您保存的图像始终显示为颠倒,则可能出现问题。确保您知道(0,0)像素的位置(左上角或左下角),然后相应地调整图像算法。
答案 1 :(得分:2)
使用C ++ 17 swap_ranges
可以更简单地翻转glReadPixels
的输出而没有临时矢量。以下代码并非特定于所要求的代码,可以与x
,y
,w
和h
的任何值一起使用。
std::vector<uint8_t> pixels(3 * w * h);
glReadPixels(x, y, 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));
}
答案 2 :(得分:2)
这是一个完整的示例,建立在Stypox的摘录片段之上-这也可以完成实际的编写。当然,交换协调系统是另一种解决方法 但我发现左上角的0,0更自然。
// 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());
答案 3 :(得分:1)
您需要在所有这些行中使用括号:
temp_rgbdata[ (i*patchSize+j)*4 ]
顺便说一下,你可以通过以下方式提高效率:
将倒置的图像放入临时数组(避免无用的副本)
初始化最终尺寸的rgbdata并立即复制整行:
您将如何做:
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