OpenGL导出渲染的图像到外部文件中

需要配置Freeimage库

  • 首先下载好FreeImage
  • 找打dist目录下的x32目录,将.h文件放在包含目录下;将lib文件放在库目录下,将dll放在运行目录下

保存渲染结果到png格式的图像:

void grab(const char * fileName)
{
	unsigned char *mpixels = new unsigned char[SCR_WIDTH * SCR_HEIGHT * 4];//WIDTH和HEIGHT为所要保存的屏幕图像的宽度与高度
	glReadBuffer(GL_FRONT);
	glReadPixels(0, 0, SCR_WIDTH, SCR_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, mpixels);
	glReadBuffer(GL_BACK);
	for (int i = 0; i < (int)SCR_WIDTH*SCR_HEIGHT * 4; i += 4)
	{
		mpixels[i] ^= mpixels[i + 2] ^= mpixels[i] ^= mpixels[i + 2];
	}
	FIBITMAP* bitmap = FreeImage_Allocate(SCR_WIDTH, SCR_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*SCR_WIDTH + x) * 4 + 0];
			bits[1] = mpixels[(y*SCR_WIDTH + x) * 4 + 1];
			bits[2] = mpixels[(y*SCR_WIDTH + x) * 4 + 2];
			bits[3] = 255;
			bits += 4;
		}

	}
	bool bSuccess = FreeImage_Save(FIF_PNG, bitmap, fileName, PNG_DEFAULT);
	FreeImage_Unload(bitmap);
}

保存渲染结果到bmp格式图像中

//抓取窗口中的像素
void grab()
{
	FILE* pDummyFile;
	FILE* pWritingFile;
	GLubyte* pPixelData;
	GLubyte BMP_Header[BMP_Header_Length];
	GLint i, j;
	GLint PixelDataLength;
	// 计算像素数据的实际长度
	i = SCR_WIDTH * 3; // 得到每一行的像素数据长度
	while (i % 4 != 0) // 补充数据,直到 i是的倍数
		++i; // 本来还有更快的算法,
	// 但这里仅追求直观,对速度没有太高要求
	PixelDataLength = i * SCR_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, SCR_WIDTH, SCR_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 = SCR_WIDTH;
	j = SCR_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);
}

不使用FreeImage库保存渲染结果到bitmap图像的实现(存在bug):

void saveSceneImage(const char * fileName)
{
	GLint ViewPort[4];
	glGetIntegerv(GL_VIEWPORT, ViewPort);
	GLsizei ColorChannel = 3;
	GLsizei bufferSize = ViewPort[2] * ViewPort[3] * sizeof(GLubyte)*ColorChannel;
	GLubyte * ImgData = (GLubyte*)malloc(bufferSize);

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glReadPixels(ViewPort[0], ViewPort[1], ViewPort[2], ViewPort[3], GL_BGR, GL_UNSIGNED_BYTE, ImgData);

	FILE * saveTxt = NULL;
	saveTxt = fopen("F:\\life\\image\\saveImage.txt", "w");
	if (!saveTxt)
	{
		cout << "Cannot save the RGB value!" << endl;
		getchar();
	}
	for (int i = 0; i < bufferSize / 3; i++)
	{
		fprintf(saveTxt, "%d  %d  %d\n", ImgData[3 * i], ImgData[3 * i], ImgData[3 * i]);
	}

	BITMAPFILEHEADER hdr;
	BITMAPINFOHEADER infoHdr;

	infoHdr.biSize = sizeof(BITMAPINFOHEADER);
	infoHdr.biWidth = ViewPort[2];
	infoHdr.biHeight = ViewPort[3];
	infoHdr.biPlanes = 1;
	infoHdr.biBitCount = 24;
	infoHdr.biCompression = 0;
	infoHdr.biSizeImage = ViewPort[2] * ViewPort[3] * 3;
	infoHdr.biXPelsPerMeter = 0;
	infoHdr.biYPelsPerMeter = 0;
	infoHdr.biClrUsed = 0;
	infoHdr.biClrImportant = 0;

	hdr.bfType = 0x4D42;
	hdr.bfReserved1 = 0;
	hdr.bfReserved2 = 0;
	hdr.bfOffBits = 54;
	hdr.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + ViewPort[2] * ViewPort[3] * 3);
	FILE *fid = NULL;
	if (!(fid = fopen(fileName, "wb+")))
	{
		cout << "Cannot load bmp image format!" << endl;
		getchar();
	}
	fwrite(&hdr, 1, sizeof(BITMAPFILEHEADER), fid);
	fwrite(&infoHdr, 1, sizeof(BITMAPINFOHEADER), fid);
	fwrite(ImgData, 1, ViewPort[2] * ViewPort[2] * 3, fid);
	fclose(fid);
	free(ImgData);
	cout << "Finished!!!" << endl;
}
posted @ 2021-01-01 11:17  Garrett_Wale  阅读(331)  评论(0编辑  收藏  举报