我目前正在阅读Opengl的超级明星。我遇到了本书中显示的一些源代码的问题。该代码特别是用于获取当前场景的屏幕截图的代码。这是提供的代码:
GLint gltWriteTGA(const char *szFileName)
{
FILE *pFile; // File pointer
TGAHEADER tgaHeader; // TGA file header
unsigned long lImageSize; // Size in bytes of image
GLbyte *pBits = NULL; // Pointer to bits
GLint iViewport[4]; // Viewport in pixels
GLenum lastBuffer; // Storage for the current read buffer setting
// Get the viewport dimensions
glGetIntegerv(GL_VIEWPORT, iViewport);
// How big is the image going to be (targas are tightly packed)
lImageSize = iViewport[2] * 3 * iViewport[3];
// Allocate block. If this doesn't work, go home
pBits = new GLbyte[lImageSize];
if(pBits == NULL)
return 0;
// Read bits from color buffer
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
// Get the current read buffer setting and save it. Switch to
// the front buffer and do the read operation. Finally, restore
// the read buffer state
glGetIntegerv(GL_READ_BUFFER, &lastBuffer);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, iViewport[2], iViewport[3], GL_BGR_EXT, GL_UNSIGNED_BYTE, pBits);
glReadBuffer(lastBuffer);
// Initialize the Targa header
tgaHeader.identsize = 0;
tgaHeader.colorMapType = 0;
tgaHeader.imageType = 2;
tgaHeader.colorMapStart = 0;
tgaHeader.colorMapLength = 0;
tgaHeader.colorMapBits = 0;
tgaHeader.xstart = 0;
tgaHeader.ystart = 0;
tgaHeader.width = iViewport[2];
tgaHeader.height = iViewport[3];
tgaHeader.bits = 24;
tgaHeader.descriptor = 0;
// Attempt to open the file
pFile = fopen(szFileName, "wb");
if(pFile == NULL)
{
free(pBits); // Free buffer and return error
return 0;
}
// Write the header
fwrite(&tgaHeader, sizeof(TGAHEADER), 1, pFile);
// Write the image data
fwrite(pBits, lImageSize, 1, pFile);
// Free temporary buffer and close the file
free(pBits);
fclose(pFile);
// Success!
return 1;
}
代码的问题在于它会喷出一个大小正确的文件,但包含某种垃圾数据。它不会生成可打开的.tga文件。另一个问题是“glGetIntegerv”函数采用GLint这一事实,但上面的源代码为它提供了一个GLenum。
答案 0 :(得分:0)
当我使用我在互联网上找到的TGA_Header尝试它时,它首先失败了,因为colorMapStart和colorMapLength是应该短路的字节。 以下是应该有效的修改代码:
struct TGA_Header
{
GLbyte identsize;
GLbyte colorMapType;
GLbyte imageType;
// Color map specifications
GLshort colorMapStart;
GLshort colorMapLength;
GLbyte colorMapBits;
//image specification
GLshort xstart;
GLshort ystart;
GLshort width;
GLshort height;
GLbyte bits;
GLbyte descriptor;
}__attribute__((packed));
GLint gltWriteTGA(const char *szFileName)
{
FILE *pFile; // File pointer
struct TGA_Header tgaHeader; // TGA file header
unsigned long lImageSize; // Size in bytes of image
GLint iViewport[4]; // Viewport in pixels
GLint lastBuffer; // Storage for the current read buffer setting
// Get the viewport dimensions
glGetIntegerv(GL_VIEWPORT, iViewport);
// How big is the image going to be (targas are tightly packed)
lImageSize = iViewport[2] * 3 * iViewport[3];
// Allocate block. If this doesn't work, go home
GLbyte pBits[lImageSize];
if(pBits == NULL)
return 0;
// Read bits from color buffer
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
// Get the current read buffer setting and save it. Switch to
// the front buffer and do the read operation. Finally, restore
// the read buffer state
glGetIntegerv(GL_READ_BUFFER, &lastBuffer);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, iViewport[2], iViewport[3], GL_BGR_EXT, GL_UNSIGNED_BYTE, pBits);
glReadBuffer(lastBuffer);
// Initialize the Targa header
tgaHeader.identsize = 0;
tgaHeader.colorMapType = 0;
tgaHeader.imageType = 2;
tgaHeader.colorMapStart = 0;
tgaHeader.colorMapLength = 0;
tgaHeader.colorMapBits = 0;
tgaHeader.xstart = 0;
tgaHeader.ystart = 0;
tgaHeader.width = iViewport[2];
tgaHeader.height = iViewport[3];
tgaHeader.bits = 24;
tgaHeader.descriptor = 0;
// Attempt to open the file
pFile = fopen(szFileName, "wb");
if(pFile == NULL)
{
return 0;
}
// Write the header
fwrite(&tgaHeader, sizeof(tgaHeader), 1, pFile);
// Write the image data
fwrite(pBits, lImageSize, 1, pFile);
fclose(pFile);
// Success!
return 1;
}