主頁 > 軟體工程 > 急!急!急! 求一份將基于MFC渲染的OpenGL場景保存為JPG等圖片格式的全代碼

急!急!急! 求一份將基于MFC渲染的OpenGL場景保存為JPG等圖片格式的全代碼

2020-10-05 02:25:23 軟體工程

如題,先有基于MFC渲染的一個OpenGL場景,需要保存成圖片,需要做成想平時各種軟體狗保存時那樣,可以在保存時彈出檔案對話框,自主選擇路徑和檔案名和格式等,求有好心的大神提供一份完整的代碼,小弟感激不盡!!

uj5u.com熱心網友回復:

求好心的大神給一個代碼,最近都要崩潰了,網上各種零零亂亂的說的挺多的,不太懂   現在時間來不及了,只好求一個完整的代碼,我的郵箱[email protected]

uj5u.com熱心網友回復:

參考
保存為 bmp 的

//
bool ScreenShot(const char* filename)
{
GLenum lastBuffer;
GLbyte* pBits = 0; // data
unsigned long lImageSize;
GLint iViewport[4]; // view

glGetIntegerv(GL_VIEWPORT, iViewport);
lImageSize = iViewport[2] * iViewport[3] * 3;

pBits = (GLbyte*)new unsigned char[lImageSize];
if (!pBits) return false;

// 從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);
//
glGetIntegerv(GL_READ_BUFFER, (GLint*)&lastBuffer);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, iViewport[2], iViewport[3], GL_BGR_EXT, GL_UNSIGNED_BYTE, pBits);
glReadBuffer(lastBuffer);

if (writeBMP(filename,(unsigned char*)pBits,iViewport[2],iViewport[3])) return true;

return false;
}
///////////////////////////////////////////////////
// save
void CxxxxDlg::OnButton2() 
{
// TODO: Add your control notification handler code here
if(ScreenShot("Gl.bmp")) AfxMessageBox("Gl.bmp saved");
}

uj5u.com熱心網友回復:

學習了!

uj5u.com熱心網友回復:

參考 2 樓 schlafenhamster 的回復:
參考
保存為 bmp 的

//
bool ScreenShot(const char* filename)
{
GLenum lastBuffer;
GLbyte* pBits = 0; // data
unsigned long lImageSize;
GLint iViewport[4]; // view

glGetIntegerv(GL_VIEWPORT, iViewport);
lImageSize = iViewport[2] * iViewport[3] * 3;

pBits = (GLbyte*)new unsigned char[lImageSize];
if (!pBits) return false;

// 從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);
//
glGetIntegerv(GL_READ_BUFFER, (GLint*)&lastBuffer);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, iViewport[2], iViewport[3], GL_BGR_EXT, GL_UNSIGNED_BYTE, pBits);
glReadBuffer(lastBuffer);

if (writeBMP(filename,(unsigned char*)pBits,iViewport[2],iViewport[3])) return true;

return false;
}
///////////////////////////////////////////////////
// save
void CxxxxDlg::OnButton2() 
{
// TODO: Add your control notification handler code here
if(ScreenShot("Gl.bmp")) AfxMessageBox("Gl.bmp saved");
}


writeBMP是什么東東

uj5u.com熱心網友回復:


bool writeBMP(const char filename[], unsigned char* data, unsigned int w, unsigned int h)
{
/** 創建位圖檔案資訊和位圖檔案頭結構 */
BITMAPFILEHEADER header;
BITMAPINFOHEADER bitmapInfoHeader;
/** 填充BITMAPFILEHEADER */
header.bfType = 0x4d42;// 'BM'
header.bfSize = w*h*3 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
header.bfReserved1 = 0;
header.bfReserved2 = 0;
header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
/** 寫入位圖檔案頭資訊 */
CFile out_file;
out_file.Open(filename,CFile::modeCreate | CFile::modeWrite);
out_file.Write((char*)&header, sizeof(BITMAPFILEHEADER));
/** 填充BITMAPINFOHEADER */
bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfoHeader.biWidth = w;
bitmapInfoHeader.biHeight = h;
bitmapInfoHeader.biPlanes = 1;
bitmapInfoHeader.biBitCount = 24;
bitmapInfoHeader.biCompression = BI_RGB; // BI_RLE4 BI_RLE8
bitmapInfoHeader.biSizeImage = w * h * 3; // 當壓縮型別為BI_RGB是也可以設定為0
bitmapInfoHeader.biXPelsPerMeter = 0;
bitmapInfoHeader.biYPelsPerMeter = 0;
bitmapInfoHeader.biClrUsed = 0;
bitmapInfoHeader.biClrImportant = 0;
/** 寫入位圖檔案資訊 */
out_file.Write((char*)&bitmapInfoHeader, sizeof(BITMAPINFOHEADER));
/** 將指標移到資料開始位置 */
out_file.Seek(header.bfOffBits,CFile::begin);
/** 寫入影像資料 */
out_file.Write((char*)data, bitmapInfoHeader.biSizeImage);
out_file.Close();
delete [] data;
return true;
}

uj5u.com熱心網友回復:

參考 5 樓 schlafenhamster 的回復:

bool writeBMP(const char filename[], unsigned char* data, unsigned int w, unsigned int h)
{
/** 創建位圖檔案資訊和位圖檔案頭結構 */
BITMAPFILEHEADER header;
BITMAPINFOHEADER bitmapInfoHeader;
/** 填充BITMAPFILEHEADER */
header.bfType = 0x4d42;// 'BM'
header.bfSize = w*h*3 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
header.bfReserved1 = 0;
header.bfReserved2 = 0;
header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
/** 寫入位圖檔案頭資訊 */
CFile out_file;
out_file.Open(filename,CFile::modeCreate | CFile::modeWrite);
out_file.Write((char*)&header, sizeof(BITMAPFILEHEADER));
/** 填充BITMAPINFOHEADER */
bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfoHeader.biWidth = w;
bitmapInfoHeader.biHeight = h;
bitmapInfoHeader.biPlanes = 1;
bitmapInfoHeader.biBitCount = 24;
bitmapInfoHeader.biCompression = BI_RGB; // BI_RLE4 BI_RLE8
bitmapInfoHeader.biSizeImage = w * h * 3; // 當壓縮型別為BI_RGB是也可以設定為0
bitmapInfoHeader.biXPelsPerMeter = 0;
bitmapInfoHeader.biYPelsPerMeter = 0;
bitmapInfoHeader.biClrUsed = 0;
bitmapInfoHeader.biClrImportant = 0;
/** 寫入位圖檔案資訊 */
out_file.Write((char*)&bitmapInfoHeader, sizeof(BITMAPINFOHEADER));
/** 將指標移到資料開始位置 */
out_file.Seek(header.bfOffBits,CFile::begin);
/** 寫入影像資料 */
out_file.Write((char*)data, bitmapInfoHeader.biSizeImage);
out_file.Close();
delete [] data;
return true;
}

不太懂你這個函式   out_file.Open(filename,CFile::modeCreate | CFile::modeWrite); 第一個引數報錯,我強制轉換后 程式可以運行,但是不知道保存在哪的,而且我想要想GDI里面呼叫DoModal那樣保存的時候彈出對話框,選擇路徑和檔案名, 還請您費費心,謝謝了

uj5u.com熱心網友回復:

///////////////////////////////////////////////////
// save
void CxxxxDlg::OnButton2() 
{
// TODO: Add your control notification handler code here
if(ScreenShot("Gl.bmp")) AfxMessageBox("Gl.bmp saved");
}

uj5u.com熱心網友回復:

filename 就是 save 后 檔案名。
如果 是 Unicode 版本,要 使用 
ScreenShot(L"Gl.bmp");

uj5u.com熱心網友回復:

參考 7 樓 schlafenhamster 的回復:
///////////////////////////////////////////////////
// save
void CxxxxDlg::OnButton2() 
{
// TODO: Add your control notification handler code here
if(ScreenShot("Gl.bmp")) AfxMessageBox("Gl.bmp saved");
}

我的代碼,前面一個加了有錯,后面不加有錯,我用的是VC2010旗艦版,一般情況雙引號的字串都是要加L的,但是這個加了有錯。
if(ScreenShot("Gl.bmp")) AfxMessageBox(L"Gl.bmp saved");
這個是后面函式的錯誤:
error C2664: “BOOL CFile::Open(LPCTSTR,UINT,CFileException *)”: 不能將引數 1 從“const char []”轉換為“LPCTSTR”,代碼什么都沒改。

uj5u.com熱心網友回復:

writeBMP(const char filename[], 這里 要 改 WCHAR 

uj5u.com熱心網友回復:

參考 10 樓 schlafenhamster 的回復:
writeBMP(const char filename[], 這里 要 改 WCHAR 

我都不好意思再問了,又出問題了,保存后的圖片打開顯示圖片錯誤,這是為什么?又給你添麻煩了

uj5u.com熱心網友回復:

"保存后的圖片打開顯示圖片錯誤"
用 “畫圖” 打開看看。

用通用的方法(與 GL 無關) 截圖 是

//
HBITMAP CopyScreenToBitmap(CRect &Rect,HWND hwnd) 
{  
HDC      hScrDC, hMemDC;      
HBITMAP  hOldBitmap,hBitmap;  
int      xScrn, yScrn;        
// to screen coordinates. 
MapWindowPoints(hwnd,NULL,(POINT *)&Rect,2);
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); 
hMemDC = CreateCompatibleDC(hScrDC); 
//
xScrn = GetDeviceCaps(hScrDC, HORZRES); 
yScrn = GetDeviceCaps(hScrDC, VERTRES); 
//
if (Rect.left < 0)  Rect.left = 0; 
if (Rect.top < 0)   Rect.top  = 0; 
if (Rect.right  > xScrn)  Rect.right = xScrn; 
if (Rect.bottom > yScrn) Rect.bottom = yScrn; 
//
hBitmap = CreateCompatibleBitmap(hScrDC, Rect.Width(),Rect.Height()); 
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); 
BitBlt(hMemDC,0,0,Rect.Width(),Rect.Height(),hScrDC,Rect.left,Rect.top,SRCCOPY); 
hBitmap =(HBITMAP)SelectObject(hMemDC,hOldBitmap); 
//
DeleteDC(hScrDC); 
DeleteDC(hMemDC); 
//
return hBitmap; 
}      
/////// 
BOOL SaveBitmapToFile(HBITMAP hBitmap, LPCSTR lpszFileName) 

HDC hDC; //設備描述表 
int iBits; //當前顯示解析度下每個像素所占位元組數 
WORD wBitCount; //位圖中每個像素所占位元組數 
//定義調色板大小, 位圖中像素位元組大小 , 位圖檔案大小 , 寫入檔案位元組數 
DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten; 
BITMAP Bitmap; //位圖屬性結構 
BITMAPFILEHEADER bmfHdr; //位圖檔案頭結構 
BITMAPINFOHEADER bi;//位圖資訊頭結構 
LPBITMAPINFOHEADER lpbi; //指向位圖資訊頭結構 
HANDLE fh, hDib, hPal; 
HPALETTE hOldPal=NULL;//定義檔案,分配記憶體句柄,調色板句柄 

//計算位圖檔案每個像素所占位元組數 
hDC = CreateDC("DISPLAY",NULL,NULL,NULL); 
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); //?
DeleteDC(hDC); 
if (iBits <= 1)       wBitCount = 1; 
else if (iBits <= 4)  wBitCount = 4; 
else if (iBits <= 8)  wBitCount = 8; 
else if (iBits <= 24) wBitCount = 24; 
else               wBitCount = 32; 
//計算調色板大小 
if (wBitCount <= 8) dwPaletteSize=(1 << wBitCount)*sizeof(RGBQUAD); 

//設定位圖資訊頭結構 
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap); 
bi.biSize = sizeof(BITMAPINFOHEADER); 
bi.biWidth = Bitmap.bmWidth; 
bi.biHeight = Bitmap.bmHeight; 
bi.biPlanes = 1; 
bi.biBitCount = wBitCount; 
bi.biCompression = BI_RGB; 
bi.biSizeImage = 0; 
bi.biXPelsPerMeter = 0; 
bi.biYPelsPerMeter = 0; 
bi.biClrUsed = 0; 
bi.biClrImportant = 0; 

dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight; 
//為位圖內容分配記憶體 
hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER)); 
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
*lpbi = bi; 
// 處理調色板 
hPal = GetStockObject(DEFAULT_PALETTE); 
if (hPal) 

hDC = ::GetDC(NULL); 
hOldPal=SelectPalette(hDC,(HPALETTE)hPal,FALSE); 
RealizePalette(hDC); 

// 獲取該調色板下新的像素值 
GetDIBits(hDC,hBitmap,0,(UINT)Bitmap.bmHeight,(LPSTR)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize, (BITMAPINFO *)lpbi,DIB_RGB_COLORS); 
//恢復調色板 
if (hOldPal) 

SelectPalette(hDC, hOldPal, TRUE); 
RealizePalette(hDC); 
::ReleaseDC(NULL, hDC); 

//創建位圖檔案 
fh=CreateFile(lpszFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 
if (fh==INVALID_HANDLE_VALUE) return FALSE; 
// 設定位圖檔案頭 
bmfHdr.bfType = 0x4D42; // "BM" 
dwDIBSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize; 
bmfHdr.bfSize = dwDIBSize; 
bmfHdr.bfReserved1 = 0; 
bmfHdr.bfReserved2 = 0; 
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize; 
// 寫入位圖檔案頭 
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 
// 寫入位圖檔案其余內容 
WriteFile(fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize , &dwWritten, NULL); 
//清除 
GlobalUnlock(hDib); 
GlobalFree(hDib); 
CloseHandle(fh);
return TRUE; 
}

呼叫
void CxxxxDlg::OnButton2() 
{
// TODO: Add your control notification handler code here
CRect rc;
GetClientRect(rc);
if(SaveBitmapToFile(CopyScreenToBitmap(rc,m_hWnd),"tmpGl.bmp"))
AfxMessageBox("tmpGl.bmp saved");
}

uj5u.com熱心網友回復:

參考 12 樓 schlafenhamster 的回復:
"保存后的圖片打開顯示圖片錯誤"
用 “畫圖” 打開看看。

用通用的方法(與 GL 無關) 截圖 是

//
HBITMAP CopyScreenToBitmap(CRect &Rect,HWND hwnd) 
{  
HDC      hScrDC, hMemDC;      
HBITMAP  hOldBitmap,hBitmap;  
int      xScrn, yScrn;        
// to screen coordinates. 
MapWindowPoints(hwnd,NULL,(POINT *)&Rect,2);
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); 
hMemDC = CreateCompatibleDC(hScrDC); 
//
xScrn = GetDeviceCaps(hScrDC, HORZRES); 
yScrn = GetDeviceCaps(hScrDC, VERTRES); 
//
if (Rect.left < 0)  Rect.left = 0; 
if (Rect.top < 0)   Rect.top  = 0; 
if (Rect.right  > xScrn)  Rect.right = xScrn; 
if (Rect.bottom > yScrn) Rect.bottom = yScrn; 
//
hBitmap = CreateCompatibleBitmap(hScrDC, Rect.Width(),Rect.Height()); 
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); 
BitBlt(hMemDC,0,0,Rect.Width(),Rect.Height(),hScrDC,Rect.left,Rect.top,SRCCOPY); 
hBitmap =(HBITMAP)SelectObject(hMemDC,hOldBitmap); 
//
DeleteDC(hScrDC); 
DeleteDC(hMemDC); 
//
return hBitmap; 
}      
/////// 
BOOL SaveBitmapToFile(HBITMAP hBitmap, LPCSTR lpszFileName) 

HDC hDC; //設備描述表 
int iBits; //當前顯示解析度下每個像素所占位元組數 
WORD wBitCount; //位圖中每個像素所占位元組數 
//定義調色板大小, 位圖中像素位元組大小 , 位圖檔案大小 , 寫入檔案位元組數 
DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten; 
BITMAP Bitmap; //位圖屬性結構 
BITMAPFILEHEADER bmfHdr; //位圖檔案頭結構 
BITMAPINFOHEADER bi;//位圖資訊頭結構 
LPBITMAPINFOHEADER lpbi; //指向位圖資訊頭結構 
HANDLE fh, hDib, hPal; 
HPALETTE hOldPal=NULL;//定義檔案,分配記憶體句柄,調色板句柄 

//計算位圖檔案每個像素所占位元組數 
hDC = CreateDC("DISPLAY",NULL,NULL,NULL); 
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); //?
DeleteDC(hDC); 
if (iBits <= 1)       wBitCount = 1; 
else if (iBits <= 4)  wBitCount = 4; 
else if (iBits <= 8)  wBitCount = 8; 
else if (iBits <= 24) wBitCount = 24; 
else               wBitCount = 32; 
//計算調色板大小 
if (wBitCount <= 8) dwPaletteSize=(1 << wBitCount)*sizeof(RGBQUAD); 

//設定位圖資訊頭結構 
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap); 
bi.biSize = sizeof(BITMAPINFOHEADER); 
bi.biWidth = Bitmap.bmWidth; 
bi.biHeight = Bitmap.bmHeight; 
bi.biPlanes = 1; 
bi.biBitCount = wBitCount; 
bi.biCompression = BI_RGB; 
bi.biSizeImage = 0; 
bi.biXPelsPerMeter = 0; 
bi.biYPelsPerMeter = 0; 
bi.biClrUsed = 0; 
bi.biClrImportant = 0; 

dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight; 
//為位圖內容分配記憶體 
hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER)); 
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
*lpbi = bi; 
// 處理調色板 
hPal = GetStockObject(DEFAULT_PALETTE); 
if (hPal) 

hDC = ::GetDC(NULL); 
hOldPal=SelectPalette(hDC,(HPALETTE)hPal,FALSE); 
RealizePalette(hDC); 

// 獲取該調色板下新的像素值 
GetDIBits(hDC,hBitmap,0,(UINT)Bitmap.bmHeight,(LPSTR)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize, (BITMAPINFO *)lpbi,DIB_RGB_COLORS); 
//恢復調色板 
if (hOldPal) 

SelectPalette(hDC, hOldPal, TRUE); 
RealizePalette(hDC); 
::ReleaseDC(NULL, hDC); 

//創建位圖檔案 
fh=CreateFile(lpszFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 
if (fh==INVALID_HANDLE_VALUE) return FALSE; 
// 設定位圖檔案頭 
bmfHdr.bfType = 0x4D42; // "BM" 
dwDIBSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize; 
bmfHdr.bfSize = dwDIBSize; 
bmfHdr.bfReserved1 = 0; 
bmfHdr.bfReserved2 = 0; 
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize; 
// 寫入位圖檔案頭 
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 
// 寫入位圖檔案其余內容 
WriteFile(fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize , &dwWritten, NULL); 
//清除 
GlobalUnlock(hDib); 
GlobalFree(hDib); 
CloseHandle(fh);
return TRUE; 
}

呼叫
void CxxxxDlg::OnButton2() 
{
// TODO: Add your control notification handler code here
CRect rc;
GetClientRect(rc);
if(SaveBitmapToFile(CopyScreenToBitmap(rc,m_hWnd),"tmpGl.bmp"))
AfxMessageBox("tmpGl.bmp saved");
}

這個函式和我要的差距有點大,他會把覆寫在這個區域上的圖形也截進去,之前那個函式我發現所保存的圖片不能一般的圖片瀏覽器或者畫圖打開,但是可以用VC打開,圖形是沒有錯的,估計就是格式有錯。

uj5u.com熱心網友回復:

前一個方法 在 vc6 win7 上 的 “畫圖“ 打開是沒問題的 !

uj5u.com熱心網友回復:

據說bmp每行像素資料的位元組數必須是4的倍數,不足需要補1到3個0:
bool writeBMP(const char filename[], unsigned char* data, unsigned int w, unsigned int h) {
    /** 創建位圖檔案資訊和位圖檔案頭結構 */
    BITMAPFILEHEADER header;
    BITMAPINFOHEADER bitmapInfoHeader;
    /** 填充BITMAPFILEHEADER */
    header.bfType = 0x4d42;// 'BM'
    int alinepixelsbytescount=(w*3+31)/32*4;
    header.bfSize = alinepixelsbytescount*h + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    header.bfReserved1 = 0;
    header.bfReserved2 = 0;
    header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    /** 寫入位圖檔案頭資訊 */
    CFile out_file;
    out_file.Open(filename,CFile::modeCreate | CFile::modeWrite);
    out_file.Write((char*)&header, sizeof(BITMAPFILEHEADER));
    /** 填充BITMAPINFOHEADER */
    bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
    bitmapInfoHeader.biWidth = w;
    bitmapInfoHeader.biHeight = h;
    bitmapInfoHeader.biPlanes = 1;
    bitmapInfoHeader.biBitCount = 24;
    bitmapInfoHeader.biCompression = BI_RGB; // BI_RLE4 BI_RLE8
    bitmapInfoHeader.biSizeImage = alinepixelsbytescount*h ; // 當壓縮型別為BI_RGB是也可以設定為0
    bitmapInfoHeader.biXPelsPerMeter = 0;
    bitmapInfoHeader.biYPelsPerMeter = 0;
    bitmapInfoHeader.biClrUsed = 0;
    bitmapInfoHeader.biClrImportant = 0;
    /** 寫入位圖檔案資訊 */
    out_file.Write((char*)&bitmapInfoHeader, sizeof(BITMAPINFOHEADER));
    /** 將指標移到資料開始位置 */
    out_file.Seek(header.bfOffBits,CFile::begin);
    /** 寫入影像資料 */
    int y;
    unsigned char *alinepixels=new unsigned char[alinepixelsbytescount];
    memset(alinepixels+alinepixelsbytescount-4,0,4);
    for (y=0;y<h;y++) {
        memcpy(alinepixels,data+y*w);
        out_file.Write((char*)alinepixels, alinepixelsbytescount);
    }
    out_file.Close();
    delete [] alinepixels;
    delete [] data;
    return true;
}

uj5u.com熱心網友回復:

有一句
dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight; 

uj5u.com熱心網友回復:

前一種
header.bfSize = h*(w*3+31)/32*4 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 
// header.bfSize = w*h*3 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

uj5u.com熱心網友回復:

糾正15樓代碼第7行
 int alinepixelsbytescount=(w*3+31)/32*4;
應改為
 int alinepixelsbytescount=(w*3+3)/4*4;

uj5u.com熱心網友回復:

參考 18 樓 zhao4zhong1 的回復:
糾正15樓代碼第7行
 int alinepixelsbytescount=(w*3+31)/32*4;
應改為
 int alinepixelsbytescount=(w*3+3)/4*4;


還是不太對啊  保存的圖片使得原來的圖的左邊有一小塊變到右邊去了就像“12345”變成了“”23451這樣的,圖形還有一點形變。。。

uj5u.com熱心網友回復:

1.看看
lImageSize = iViewport[2] * iViewport[3] * 3;// = w*h*3
這句有沒有問題
2. 把視窗 w 設定為 4的倍數

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/156104.html

標籤:界面

上一篇:關于windows media player 控制元件的用法

下一篇:畫貝塞爾曲線和曲面問題

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more