游戏开发论坛

 找回密码
 立即注册
搜索
查看: 1165|回复: 0

求助:OpenGL环境中客户区图像保存为24位位图出现的问题

[复制链接]

4

主题

10

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2006-4-5 11:15:00 | 显示全部楼层 |阅读模式
在vc 6中设置好opengl开发环境,视口的大小设置成与客户区大小一样,欲将客户区的图像保存为24位真彩色位图,源代码如下,可是存在这样的问题:
程序运行,窗口刚创建时(此时不拉动边框改变客户区大小),可以正常保存。
当最大化窗口或将最大化窗口复原,都可以正常保存。
而当人为拉动边框改变客户区大小后,保存的图像出现问题,如下:
1.图像出现错位
2.调试信息出错
  Debug Error!
  DAMAGE:after Normal block(#7711) at 0x04A40040.


调试信息如下:

源代码如下:
void CMySDOpenGLView::OnCaptureImage() //保存位图的消息函数
{
        // TODO: Add your command handler code here
        CString s("Windows Bitmap(*.bmp)|*.bmp||");
        CFileDialog fd(FALSE,"bmp",0,OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY|OFN_PATHMUSTEXIST,s);

        if(fd.DoModal()==IDOK)
        {
                BeginWaitCursor();
                int viewport[4];
                glGetIntegerv(GL_VIEWPORT,viewport);

        bool success = false;

        DWORD nFileType=0;

                if(strcmp(fd.GetFileExt(),"bmp")==0) nFileType=1;


       if(nFileType==1)
                {
               
                success=m_imagecapture.CaptureGLBufferToBMP(fd.GetPathName(),                                                                           //调用保存位图类的
                                            viewport[0],viewport[1],//函数保存位图
                                            viewport[2],viewport[3]);
                }
                else
        {
            // Invalid file extension specified.
            MessageBox("WTF? Unknown file extension specified for screen capture.\n","Error",MB_OK);
        }

        if (!success)
        {
            char errorMsg[64];

            if(nFileType == 0)
                sprintf(errorMsg, "Specified file extension is not recognized.");
            else
                sprintf(errorMsg, "Could not save image file.");

            MessageBox(errorMsg, "Error", MB_OK | MB_ICONERROR);
        }

                EndWaitCursor();
        }
}

保存位图类的定义
class CImageCapture{
public:
        CImageCapture();
        virtual ~CImageCapture();

        bool CaptureGLBufferToBMP(CString filename, int x, int y,
                                      int width, int height);
        int WriteBitmapFile(CString filename, int width, int height,
                                unsigned char *imageData);
};

CImageCapture::CImageCapture()
{

}

CImageCapture::~CImageCapture()
{

}
bool CImageCapture::CaptureGLBufferToBMP(CString filename,
                           int x, int y,
                           int width, int height)
{
        void* imageData = malloc(width*height*3);// allocate memory for the imageData
       memset(imageData, 0, width*height*3);         // clear imageData memory contents

                // read the image data from the window
       glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char*)imageData);

       
                // write the image data to a file
      WriteBitmapFile(filename, width, height, (unsigned char*)imageData);

                // free the image data memory
     free(imageData);
     return true;
}

// WriteBitmapFile()
// desc: takes image data and saves it into a 24-bit RGB .BMP file
//       with width X height dimensions
int CImageCapture::WriteBitmapFile(CString filename, int width, int height, unsigned char *imageData)
{
        FILE  *filePtr;                        // file pointer
        BITMAPFILEHEADER bitmapFileHeader;        // bitmap file header
        BITMAPINFOHEADER bitmapInfoHeader;        // bitmap info header
        unsigned int         imageIdx;         // used for swapping RGB->BGR
        unsigned char         tempRGB;         // used for swapping

        // open file for writing binary mode
        filePtr = fopen(filename, "wb");
        if (!filePtr)
                return 0;

        // define the bitmap file header
        bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(4*((width*24+31)/32) * height);
        bitmapFileHeader.bfType = 0x4D42;
        bitmapFileHeader.bfReserved1 = 0;
        bitmapFileHeader.bfReserved2 = 0;
        bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
       
        // define the bitmap information header
        bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
        bitmapInfoHeader.biPlanes = 1;
        bitmapInfoHeader.biBitCount = 24;                                                // 24-bit
        bitmapInfoHeader.biCompression = BI_RGB;                                // no compression
        bitmapInfoHeader.biSizeImage = 4*((width*24+31)/32) * height;                   // width * height * (RGB bytes)
        bitmapInfoHeader.biXPelsPerMeter = 0;
        bitmapInfoHeader.biYPelsPerMeter = 0;
        bitmapInfoHeader.biClrUsed = 0;
        bitmapInfoHeader.biClrImportant = 0;
        bitmapInfoHeader.biWidth = width;                                                // bitmap width
        bitmapInfoHeader.biHeight = height;                                                // bitmap height

        // switch the image data from RGB to BGR
        for (imageIdx = 0; imageIdx < bitmapInfoHeader.biSizeImage; imageIdx+=3)
        {
                tempRGB = imageData[imageIdx];
                imageData[imageIdx] = imageData[imageIdx + 2];
                imageData[imageIdx + 2] = tempRGB;
        }
       
        //add empty Byte to every row, if this row cannot be divided exactly by 4.
        unsigned char *imageDataAfterAdding =(unsigned char *) malloc(4*((width*24+31)/32) * height);
        memset(imageDataAfterAdding, 0, 4*((width*24+31)/32) * height);
   
        for(int k=0; k<height; k++){
                               for(int i=0; i<width*3; i++){
                imageDataAfterAdding[k*width*3+i+k*(4*((width*24+31)/32)-                                width*3)]= imageData[k*width*3+i];
                }
        }


        // write the bitmap file header
        fwrite(&bitmapFileHeader, 1, sizeof(BITMAPFILEHEADER), filePtr);

        // write the bitmap info header
        fwrite(&bitmapInfoHeader, 1, sizeof(BITMAPINFOHEADER), filePtr);

        // write the image data
        fwrite(imageDataAfterAdding, 1, bitmapInfoHeader.biSizeImage, filePtr);

        // close our file
        fclose(filePtr);
    free(imageDataAfterAdding);

return 1;
}

不知道错在什么地方,请各位高手不吝赐教,不胜感激,谢谢!

[code][/code] [em7] [em7]

sf_200645111430.doc

64.5 KB, 下载次数:

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-24 02:38

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表