最近OpenGL程序中需要用到将当前屏幕图像保存为jpg文件,在网上查了很多资料,大部分都是保存为bmp文件,很难找到保存为jpg文件的说明与示例,通过查找资料以及自己的试验将其总结如下:
将当前屏幕图像保存为bmp文件
//抓取窗口中的像素
void grab()
{
FILE* pDummyFile;
FILE* pWritingFile;
GLubyte* pPixelData;
GLubyte BMP_Header[BMP_Header_Length];
GLint i, j;
GLint PixelDataLength;
// 计算像素数据的实际长度
i = WIN_WIDTH * 3; // 得到每一行的像素数据长度
while( i%4 != 0 ) // 补充数据,直到 i是的倍数
++i; // 本来还有更快的算法,
// 但这里仅追求直观,对速度没有太高要求
PixelDataLength = i * WIN_HEIGHT;
// 分配内存和打开文件
pPixelData = (GLubyte*)malloc(PixelDataLength);
if( pPixelData == 0 )
exit(0);
pDummyFile = fopen("whole.bmp", "rb");//从一个正确的bmp文件中读取前54个字节,修改其中的宽度和高度信息,就可以得到新的文件头
if( pDummyFile == 0 )
exit(0);
pWritingFile = fopen("test.bmp", "wb");
if( pWritingFile == 0 )
exit(0);
// 读取像素
// GL_UNPACK_ALIGNMENT指定OPenGL如何从数据缓冲区中解包图像数据
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glReadPixels(0, 0, WIN_WIDTH, WIN_HEIGHT, GL_BGR_EXT, GL_UNSIGNED_BYTE, pPixelData);
// 把 whole.bmp 的文件头复制为新文件的文件头
fread(BMP_Header, sizeof(BMP_Header), 1, pDummyFile);
fwrite(BMP_Header, sizeof(BMP_Header), 1, pWritingFile);
fseek(pWritingFile, 0x0012, SEEK_SET);
i = WIN_WIDTH;
j = WIN_HEIGHT;
fwrite(&i, sizeof(i), 1, pWritingFile);
fwrite(&j, sizeof(j), 1, pWritingFile);
fseek(pWritingFile, 0, SEEK_END);
fwrite(pPixelData, PixelDataLength, 1, pWritingFile);
// 释放内存和关闭文件
fclose(pDummyFile);
fclose(pWritingFile);
free(pPixelData);
}
void grab()
{
unsigned char *mpixels =new unsigned char[WIDTH * HEIGHT * 4];//WIDTH和HEIGHT为所要保存的屏幕图像的宽度与高度
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, mpixels);
glReadBuffer(GL_BACK);
for(int i=0; i<(int)WIDTH*HEIGHT*4; i+=4)
{
mpixels[i] ^= mpixels[i+2] ^= mpixels[i] ^= mpixels[i+2];
}
FIBITMAP* bitmap =FreeImage_Allocate(WIDTH, HEIGHT, 32, 8, 8, 8);
for(int y = 0 ;y < FreeImage_GetHeight(bitmap); y++)
{
BYTE *bits = FreeImage_GetScanLine(bitmap, y);
for(int x = 0; x < FreeImage_GetWidth(bitmap); x++)
{
bits[0] = mpixels[(y*WIDTH+x)*4+0];
bits[1] = mpixels[(y*WIDTH+x)*4+1];
bits[2] = mpixels[(y*WIDTH+x)*4+2];
bits[3] = 255;
bits += 4;
}
}
bool bSuccess = FreeImage_Save(FIF_PNG, bitmap, "test.png", PNG_DEFAULT);
FreeImage_Unload(bitmap);
}
将当前屏幕图像保存为jpg文件
void grab()
{
unsigned char *mpixels = new unsigned char[WIDTH * HEIGHT * 3];
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, mpixels);
glReadBuffer(GL_BACK);
for(int i = 0; i < (int)WIDTH*HEIGHT*3; i += 3)
{
mpixels[i] ^= mpixels[i+2] ^= mpixels[i] ^= mpixels[i+2];
}
FIBITMAP* bitmap = FreeImage_Allocate(WIDTH, HEIGHT, 24, 8, 8, 8);
for(int y = 0 ; y < FreeImage_GetHeight(bitmap); y++)
{
BYTE *bits = FreeImage_GetScanLine(bitmap, y);
for(int x = 0 ; x < FreeImage_GetWidth(bitmap); x++)
{
bits[0] = mpixels[(y*WIDTH+x) * 3 + 0];
bits[1] = mpixels[(y*WIDTH+x) * 3 + 1];
bits[2] = mpixels[(y*WIDTH+x) * 3 + 2];
bits += 3;
}
}
FreeImage_Save(FIF_JPEG, bitmap, "test.jpg", JPEG_DEFAULT);
FreeImage_Unload(bitmap);
}