C++ 如何在OpenGL中截取屏幕截图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5844858/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to take screenshot in OpenGL
提问by EthanHunt
How to take a screenshot of an OpenGL window in C++ and save it to file.
如何在 C++ 中截取 OpenGL 窗口的屏幕截图并将其保存到文件中。
I found the glReadPixels()
function,
but I don't know what to do next. Where I can set path to a file, for example?
我找到了该glReadPixels()
功能,但我不知道下一步该怎么做。例如,我可以在哪里设置文件路径?
If not difficult, write code, please.
如果不难,请写代码。
回答by huy
This piece of code captures the OpenGL window and export to a BMP file. You must have FreeImagelibrary to run it.
这段代码捕获 OpenGL 窗口并导出为 BMP 文件。你必须有FreeImage库才能运行它。
// Make the BYTE array, factor of 3 because it's RBG.
BYTE* pixels = new BYTE[3 * width * height];
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
// Convert to FreeImage format & save to file
FIBITMAP* image = FreeImage_ConvertFromRawBits(pixels, width, height, 3 * width, 24, 0x0000FF, 0xFF0000, 0x00FF00, false);
FreeImage_Save(FIF_BMP, image, "C:/test.bmp", 0);
// Free resources
FreeImage_Unload(image);
delete [] pixels;
回答by Dan
glReadPixelswill copy the bits into a memory buffer that you supply. You have to manually format the data (to the image format of your choice) and write it to disk after glReadPixelsreturns.
glReadPixels会将这些位复制到您提供的内存缓冲区中。您必须手动格式化数据(到您选择的图像格式)并在glReadPixels返回后将其写入磁盘。
回答by Zilchonum
Saving that data to a file is something you'll either have to do yourself or use a third-party library for - OpenGL has no such feature.
将该数据保存到文件中是您必须自己做或使用第三方库的事情 - OpenGL 没有这样的功能。
Windows .bmp is probably the easiest if you're looking to do it yourself - Wikipedia has a pretty good explanation of the file format. Otherwise you can use image saving/loading libraries: libpng, libjpeg, etc. for low-level control, or devIL(there are others, but this is my favorite, and it's an extremely versatile library that goes well with GL) for high-level "just do it" image i/o.
如果您想自己动手,Windows .bmp 可能是最简单的 - 维基百科对文件格式有很好的解释。否则,您可以使用图像保存/加载库:libpng、libjpeg 等用于低级控制,或devIL(还有其他库,但这是我最喜欢的,它是一个非常通用的库,与 GL 配合得很好)用于高级控制级别“就做吧”图像输入/输出。
回答by Rafael
A simple and quick solution.
一个简单快速的解决方案。
- Outputs a TARGA file but can easily be converted to PNG(script provided).
- No extra libraries required.
- Will work with both C and C++ (with some minor changes).
- Note:The output file should have the
tga
file extension.
- 输出 TARGA 文件,但可以轻松转换为 PNG(提供脚本)。
- 不需要额外的库。
- 将适用于 C 和 C++(有一些小的变化)。
- 注意:输出文件应具有
tga
文件扩展名。
Here is the code:
这是代码:
void saveScreenshotToFile(std::string filename, int windowWidth, int windowHeight) {
const int numberOfPixels = windowWidth * windowHeight * 3;
unsigned char pixels[numberOfPixels];
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, windowWidth, windowHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
FILE *outputFile = fopen(filename.c_str(), "w");
short header[] = {0, 2, 0, 0, 0, 0, (short) windowWidth, (short) windowHeight, 24};
fwrite(&header, sizeof(header), 1, outputFile);
fwrite(pixels, numberOfPixels, 1, outputFile);
fclose(outputFile);
printf("Finish writing to file.\n");
}
And calling the function:
并调用函数:
saveScreenshotToFile("test.tga", 1200, 900);
A bash script to convert TARGA files to PNG:
将 TARGA 文件转换为 PNG 的 bash 脚本:
for oldFileName in *.tga; do
[ -f "$oldFileName" ] || break # Break out if no .tga files found.
newFileName=${oldFileName//.tga/.png}
convert $oldFileName $newFileName
rm $oldFileName
echo "Converted $oldFileName to $newFileName"
done
回答by WhiteRivers
Generally, OpenGL don't provide functions to save image. I think the fastest and simplest way to do this is save to .PPMformat. However, this kind of format is uncompressed which means it's file size would be very large. And it can be support only by quite a few programs nowadays.
通常,OpenGL 不提供保存图像的功能。我认为最快和最简单的方法是保存到 . PPM格式。但是,这种格式是未压缩的,这意味着它的文件大小会非常大。并且现在只有相当多的程序可以支持它。
I prefer to save image to .png file which is compressed but also gives lossless image and supported by many browsers. To save the OpenGL to .png format, I first recommend the PNGwriter. It's pretty simple and easy to use. For example, to save a pixel of a image with color (R, G, B) in the position (x, y), your code will be(see "quickstart" in the PNGwriter website):
我更喜欢将图像保存为压缩的 .png 文件,但也提供无损图像并被许多浏览器支持。要将 OpenGL 保存为 .png 格式,我首先推荐PNGwriter。它非常简单且易于使用。例如,要在位置 (x, y) 中保存颜色为 (R, G, B) 的图像的像素,您的代码将是(请参阅 PNGwriter 网站中的“快速入门”):
pngwriter PNG(width, height, 1.0, fileName); // "1.0" stand for the white background
PNG.plot(x, y, R, G, B);
PNG.close();
Note that, since the PNGwriter save each pixel starting from the top-left corner of the image, while the array get from glReadPixels() start from the bottom-left of the window, your code to save the whole image might probably look like this:
请注意,由于 PNGwriter 从图像的左上角开始保存每个像素,而从 glReadPixels() 获取的数组从窗口的左下角开始,您保存整个图像的代码可能如下所示:
GLfloat* pixels = new GLfloat[nPixels];
glReadPixels(0.0, 0.0, width, height,GL_RGB, GL_FLOAT, pixels);
pngwriter PNG(width, height, 1.0, fileName);
size_t x = 1;
size_t y = 1;
double R, G, B;
for(size_t i=0; i<npixels; i++) // "i" is the index for array "pixels"
{
switch(i%3)
{
case 2:
B = static_cast<double>(pixels[i]); break;
case 1:
G = static_cast<double>(pixels[i]); break;
case 0:
R = static_cast<double>(pixels[i]);
PNG.plot(x, y, R, G, B); // set pixel to position (x, y)
if( x == width ) // Move to the next row of image
{
x=1;
y++;
}
else // To the next pixel
{ x++; }
break;
}
}
PNG.close();