位图保存下来是翻转的!!!!!!!!!!!!!!!!如何正过来 本帖最后由 qf230zhj 于 2010-08-07 17:20:21 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 SaveBitmapToFile(bitmap,(LPSTR)(LPCTSTR)str);是网上的标准公共代码 SaveBitmapToFile(bitmap,(LPSTR)(LPCTSTR)str.MakeReverse());// 楼主试试CXImage类,这个可以把buffer中的图像保存成图片的,你看看memmove(pBits,bm.bmBits,bm.bmWidthBytes*bm.bmHeight)之后,pBits里的图像是不是反的。有一个效率低一些的办法,再把图像反过来: DWORD dwRGB24BufLen = iWidth * iHeight * 3; BYTE *pTempBuf = new BYTE[dwRGB24BufLen]; if(NULL == pTempBuf) { return; } memset(pTempBuf, 0, dwRGB24BufLen * sizeof(BYTE)); DWORD dwLineData = (iWidth * 24) >> 3; for(DWORD dwLoop = 0; dwLoop < iHeight; dwLoop++) { memcpy(pTempBuf + dwLoop * dwLineData, pBits + dwRGB24BufLen - (dwLoop + 1) * dwLineData, dwLineData * sizeof(BYTE)); } memcpy(pBits, pTempBuf, dwRGB24BufLen); delete[] pTempBuf; pTempBuf = NULL; 见4楼。原因:DDB的图素位是从上到下的,DIB的图素位是从下到上的。你把SaveBitmapToFile函数里的biHeight字段改称相反的值就行了。 DIB数据在内存中就是底朝上放的。你要是想自己控制缓冲区pBits中的数据,自己颠倒过来,可以这样:BYTE *buf=new BYTE[bm.bmWidthBytes*bm.bmHeight];for(int i=0; i<bm.bmHeight; i++){ memcpy(buf+i*bm.bmWidthBytes ,pBits+(bm.bmHeight-i-1)*bm.bmWidthBytes),bm.bmWidthBytes);} int CDemoView::SaveDCToBitmap(CDC *pDC, LPRECT pRect, const char *pFileName){ int nRet; int w,h; if ( pDC == NULL ) { return -1; } if ( pRect == NULL ) { return -1; } if ( pFileName == NULL ) { return -1; } w = pRect->right - pRect->left; h = pRect->bottom - pRect->top; CBitmap bm; bm.CreateCompatibleBitmap(pDC,w,h); CDC memdc; memdc.CreateCompatibleDC(pDC); CBitmap*pOld=memdc.SelectObject(&bm); memdc.BitBlt( 0, 0, w, h, pDC, pRect->left, pRect->top, SRCCOPY ); BITMAP btm; bm.GetBitmap(&btm); DWORD size=btm.bmWidthBytes*btm.bmHeight; LPSTR lpData=(LPSTR)::GlobalAlloc(GPTR,size); ///////////////////////////////////////////// BITMAPINFOHEADER bih; bih.biBitCount=btm.bmBitsPixel; bih.biClrImportant=0; bih.biClrUsed=0; bih.biCompression=0; bih.biHeight=btm.bmHeight; bih.biPlanes=1; bih.biSize=sizeof(BITMAPINFOHEADER); bih.biSizeImage=size; bih.biWidth=btm.bmWidth; bih.biXPelsPerMeter=0; bih.biYPelsPerMeter=0; GetDIBits(memdc,bm,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS); CString name; name = pFileName;//保存文件名 BITMAPFILEHEADER bfh; bfh.bfReserved1=bfh.bfReserved2=0; bfh.bfType=((WORD)('M'<< 8)|'B'); bfh.bfSize=54+size; bfh.bfOffBits=54; CFile bf; if(bf.Open(name,CFile::modeCreate|CFile::modeWrite)) { bf.WriteHuge(&bfh,sizeof(BITMAPFILEHEADER)); bf.WriteHuge(&bih,sizeof(BITMAPINFOHEADER)); bf.WriteHuge(lpData,size); bf.Close(); nRet = 0; }else { nRet = 1; } memdc.SelectObject( pOld ); bm.DeleteObject( ); memdc.DeleteDC( ); ::GlobalFree(lpData); return nRet;}改biheight是那一个,我两个分别改了无效!!!!!!! bool CDemoView::SaveBitmapToFile(CBitmap *bitmap, LPSTR lpFileName){ HBITMAP hBitmap; HDC hDC; //设备描述表 int iBits; //当前显示分辨率下每个像素所占字节数 WORD wBitCount; //位图中每个像素所占字节数 DWORD dwPaletteSize=0, //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数 dwBmBitsSize, dwDIBSize, dwWritten; BITMAP Bitmap; //位图属性结构 BITMAPFILEHEADER bmfHdr; //位图文件头结构 BITMAPINFOHEADER bi; //位图信息头结构 LPBITMAPINFOHEADER lpbi; //指向位图信息头结构 HANDLE fh, hDib, hPal,hOldPal=NULL; //定义文件,分配内存句柄,调色板句柄 //计算位图文件每个像素所占字节数 hBitmap = (HBITMAP)*bitmap; 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 if ( iBits <= 32 ) 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, (LPBITMAPINFO ) lpbi, DIB_RGB_COLORS); //恢复调色板 if (hOldPal) { SelectPalette(hDC, (HPALETTE)hOldPal, TRUE); RealizePalette(hDC); ::ReleaseDC(NULL, hDC); } //创建位图文件 fh = CreateFile(lpFileName, 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, dwDIBSize, &dwWritten, NULL); //清除 GlobalUnlock(hDib); GlobalFree(hDib); CloseHandle(fh); return TRUE; }楼上代码贴错了,这个是正确的请问改biheight是那一个,我两个分别改了无效!!!!!!! //设置位图信息头结构 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; 注意:改称负的只能是用看图软件打开时不颠倒,里面的数据其实仍是倒得。 DIBSECTION跟bmp文件一样是倒置的。SetBitmapBits是用填充DDB位,但是你用DIB位区填充式什么意思呢?此处应该用memmove(bm.bmBits,pBits,bm.bmWidthBytes*bm.bmHeight); 如何让程序带上进度等待条? ClistCtrl有一种奇怪的状态,对CListCtrl了解的高手请进 我自己写的类,在其中建立其他类的实例就出错? 谁能帮我改正错误,最好给个例子!两天没搞定了! 请问:如何读取一个目录下的所有文件名(该目录下包含子目录) 急!关于生成新进程的问题 100分相送 在线等待 GGJJDDMM们,我想学编成,请指教,送上100分!!! 如何得到两位的月份???? COM组件中的一个对话框中含有ActiveX控件,在MFC中使用此组件弹出对话框时程序崩溃? 如何解决这个问题啊? 求个xml最简单的序列号和反序列化的实例 文件路径问题
是网上的标准公共代码
DWORD dwRGB24BufLen = iWidth * iHeight * 3;
BYTE *pTempBuf = new BYTE[dwRGB24BufLen];
if(NULL == pTempBuf)
{
return;
}
memset(pTempBuf, 0, dwRGB24BufLen * sizeof(BYTE)); DWORD dwLineData = (iWidth * 24) >> 3;
for(DWORD dwLoop = 0; dwLoop < iHeight; dwLoop++)
{
memcpy(pTempBuf + dwLoop * dwLineData, pBits + dwRGB24BufLen - (dwLoop + 1) * dwLineData, dwLineData * sizeof(BYTE));
}
memcpy(pBits, pTempBuf, dwRGB24BufLen);
delete[] pTempBuf;
pTempBuf = NULL;
原因:DDB的图素位是从上到下的,DIB的图素位是从下到上的。
你把SaveBitmapToFile函数里的biHeight字段改称相反的值就行了。
你要是想自己控制缓冲区pBits中的数据,自己颠倒过来,可以这样:
BYTE *buf=new BYTE[bm.bmWidthBytes*bm.bmHeight];
for(int i=0; i<bm.bmHeight; i++)
{
memcpy(buf+i*bm.bmWidthBytes ,pBits+(bm.bmHeight-i-1)*bm.bmWidthBytes),bm.bmWidthBytes);
}
{
int nRet;
int w,h;
if ( pDC == NULL )
{
return -1;
}
if ( pRect == NULL )
{
return -1;
}
if ( pFileName == NULL )
{
return -1;
}
w = pRect->right - pRect->left;
h = pRect->bottom - pRect->top;
CBitmap bm;
bm.CreateCompatibleBitmap(pDC,w,h);
CDC memdc;
memdc.CreateCompatibleDC(pDC);
CBitmap*pOld=memdc.SelectObject(&bm);
memdc.BitBlt( 0, 0, w, h, pDC, pRect->left, pRect->top, SRCCOPY );
BITMAP btm;
bm.GetBitmap(&btm);
DWORD size=btm.bmWidthBytes*btm.bmHeight;
LPSTR lpData=(LPSTR)::GlobalAlloc(GPTR,size);
/////////////////////////////////////////////
BITMAPINFOHEADER bih;
bih.biBitCount=btm.bmBitsPixel;
bih.biClrImportant=0;
bih.biClrUsed=0;
bih.biCompression=0;
bih.biHeight=btm.bmHeight;
bih.biPlanes=1;
bih.biSize=sizeof(BITMAPINFOHEADER);
bih.biSizeImage=size;
bih.biWidth=btm.bmWidth;
bih.biXPelsPerMeter=0;
bih.biYPelsPerMeter=0;
GetDIBits(memdc,bm,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);
CString name;
name = pFileName;//保存文件名
BITMAPFILEHEADER bfh;
bfh.bfReserved1=bfh.bfReserved2=0;
bfh.bfType=((WORD)('M'<< 8)|'B');
bfh.bfSize=54+size;
bfh.bfOffBits=54;
CFile bf;
if(bf.Open(name,CFile::modeCreate|CFile::modeWrite))
{
bf.WriteHuge(&bfh,sizeof(BITMAPFILEHEADER));
bf.WriteHuge(&bih,sizeof(BITMAPINFOHEADER));
bf.WriteHuge(lpData,size);
bf.Close();
nRet = 0;
}else
{
nRet = 1;
}
memdc.SelectObject( pOld );
bm.DeleteObject( );
memdc.DeleteDC( );
::GlobalFree(lpData);
return nRet;
}改biheight是那一个,我两个分别改了无效!!!!!!!
{
HBITMAP hBitmap;
HDC hDC; //设备描述表
int iBits; //当前显示分辨率下每个像素所占字节数
WORD wBitCount; //位图中每个像素所占字节数
DWORD dwPaletteSize=0, //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
dwBmBitsSize,
dwDIBSize, dwWritten;
BITMAP Bitmap; //位图属性结构
BITMAPFILEHEADER bmfHdr; //位图文件头结构
BITMAPINFOHEADER bi; //位图信息头结构
LPBITMAPINFOHEADER lpbi; //指向位图信息头结构
HANDLE fh, hDib, hPal,hOldPal=NULL; //定义文件,分配内存句柄,调色板句柄 //计算位图文件每个像素所占字节数
hBitmap = (HBITMAP)*bitmap;
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 if ( iBits <= 32 )
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,
(LPBITMAPINFO )
lpbi, DIB_RGB_COLORS); //恢复调色板
if (hOldPal)
{
SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
} //创建位图文件
fh = CreateFile(lpFileName, 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, dwDIBSize,
&dwWritten, NULL); //清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;
}楼上代码贴错了,这个是正确的请问改biheight是那一个,我两个分别改了无效!!!!!!!
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; 注意:改称负的只能是用看图软件打开时不颠倒,里面的数据其实仍是倒得。
SetBitmapBits是用填充DDB位,但是你用DIB位区填充式什么意思呢?
此处应该用memmove(bm.bmBits,pBits,bm.bmWidthBytes*bm.bmHeight);