glReadPixels 保存到 BMP - 颜色失真

Posted

技术标签:

【中文标题】glReadPixels 保存到 BMP - 颜色失真【英文标题】:glReadPixels save to BMP - Color Dirstortion 【发布时间】:2013-12-17 09:40:06 【问题描述】:

我现在正在使用 OpenGL 和 PCL_lib,我想在背景图片上绘制一个附件。

这是我展示的 output_image:

图片来源为PCD格式(PCL lib),由OpenGL绘制

这是我保存 GL_pic 的代码:

char filename[100];
sprintf(filename, "path", _mframe_Count);   

// Set Parameter
GLint x, y, width, height;
int i;
unsigned long imageSize;
GLenum lastBuffer
glGetIntegerv( GL_VIEWPORT, mViewPort );
x = mViewPort[0];
y = mViewPort[1];
width = mViewPort[2];
height = mViewPort[3];    

BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
bmfh.bfType = 0x4D42;
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(bmfh) + sizeof(bmih);
imageSize = ((width+((4-(width%4))%4))*height*3)+2;
bmfh.bfSize = imageSize + sizeof(bmfh) + sizeof(bmih);
GLubyte *pImageData = (GLubyte *)malloc(imageSize);


// Allocate apicture buffer
if(pImageData == NULL) 

    printf("[Error] : grab_GL(), Cannot create Memory_Sapce for pImageData.\n");
    return false;


// Byte alignment (that is, no alignment)
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ROW_LENGTH,0);
glPixelStorei(GL_PACK_SKIP_ROWS,0);
glPixelStorei(GL_PACK_SKIP_PIXELS,0);
glPixelStorei(GL_PACK_SWAP_BYTES,1);
glGetIntegerv(GL_READ_BUFFER, ( GLint *)&lastBuffer);
glReadBuffer(GL_FRONT);

glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, pImageData);
pImageData[imageSize-1] = 0;
pImageData[imageSize-2] = 0;
glReadBuffer(lastBuffer);


FILE *pWritingFile = fopen(filename, "wb");
if (pWritingFile == NULL)

    free(pImageData);
    printf("[Error] : grab_GL(), Cannot open %s for writting.\n", filename);
    return false;


// BMP Structures   
bmih.biSize = sizeof(bmih);
bmih.biWidth = width;
bmih.biHeight = height;
bmih.biPlanes = 1;
bmih.biBitCount = 24;
bmih.biCompression = 0;
bmih.biSizeImage = imageSize;
bmih.biXPelsPerMeter = 2835;
bmih.biYPelsPerMeter = 2835;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;    

// BMP Compress
fwrite(&bmfh, 8, 1, pWritingFile);
fwrite(&bmfh.bfReserved2, sizeof(bmfh.bfReserved2), 1, pWritingFile); 
fwrite(&bmfh.bfOffBits, sizeof(bmfh.bfOffBits), 1, pWritingFile); 
fwrite(&bmih, sizeof(bmih), 1, pWritingFile);
fwrite(pImageData, imageSize, 1, pWritingFile);


// End The Process  
fclose(pWritingFile);
free(pImageData);    
return true;

但是当将图像保存到显示器上显示的BMP文件时,它变成:

【问题讨论】:

【参考方案1】:

看起来对磁盘的写入有点难以解释:

// BMP Compress
fwrite(&bmfh, 8, 1, pWritingFile);
fwrite(&bmfh.bfReserved2, sizeof(bmfh.bfReserved2), 1, pWritingFile); 
fwrite(&bmfh.bfOffBits, sizeof(bmfh.bfOffBits), 1, pWritingFile); 
fwrite(&bmih, sizeof(bmih), 1, pWritingFile);
fwrite(pImageData, imageSize, 1, pWritingFile);

我不明白您为什么要单独编写 bmfh 的元素,所以只需这样做以确保一切都清楚:

// BMP Compress
fwrite(&bmfh, sizeof(bmfh), 1, pWritingFile);
fwrite(&bmih, sizeof(bmih), 1, pWritingFile);
fwrite(pImageData, imageSize, 1, pWritingFile);

如果这没有区别,那么您的图像的外观就是颜色分量被反转(RGB 而不是 BGR) - 尽管 glPixelStorei(GL_PACK_SWAP_BYTES,1) 不应该影响像素数据本身,但值得尝试一下:

glPixelStorei(GL_PACK_SWAP_BYTES,1);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pImageData);

或者这个:

glPixelStorei(GL_PACK_SWAP_BYTES,0);
glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, pImageData);

【讨论】:

因为我的编辑器使用的是Vim/Linux,如果我使用fwrite(&bmfh, sizeof(bmfh ..),可能会导致遇到文件过早结束的问题。跨度> 我尝试使用 glPixelStorei(GL_PACK_SWAP_BYTES,1); glReadPixels(.., GL_RGB, ..);但它似乎仍然有颜色失真dropbox.com/s/9spewhbmm4f4ggb/renderedframes-3.bmp

以上是关于glReadPixels 保存到 BMP - 颜色失真的主要内容,如果未能解决你的问题,请参考以下文章

一种颜色的图片我保存为gif和png格式的图片,为啥颜色会有偏差呢

BMP 和 JPEG

C语言读取1位的BMP图

如何使用 OpenGL 保存 OpenGL 绘制?

osg::readPixels,glreadPixels截图,保存图片的alpha不对,总是255

glReadPixels() 设置 GL_INVALID_OPERATION 错误