如何由已有的真彩色图象数据生成新的图象文件并显示它?
解决方案 »
- 我用m_lstMain.SetItemState(0,LVIS_SELECTED,LVIS_SELECTED);怎么也选不中CListCtrl的行呢?
- windows 服务程序怎么打开窗口程序
- ACCESS
- 求制作3D Activex的方法.
- 如何在SDI中的view中嵌入一个对话框?
- 有关GINA的几个严重问题!!!急
- 获得了当前IE的IHTMLDocument2接口如何获取当前浏览网页的HTML代码?
- 关于于内存泄漏的问题:在什么情况下会发生内存泄漏,(CButton*)getdlgitem()会吗?
- 在单文档下能实现打印吗?(在线)
- \r的含义~~~~~~?
- ADO的try-catch总是得到“未指定的错误”
- 关于下载的问题
BOOL SaveFile(HDC hdc, HBITMAP hBitmap, CString strFileName)
{
HDC hDC;
int iBits;
WORD wBitCount;
DWORD dwPaletteSize=0;
DWORD dwBmBitsSize, dwDIBSize, dwWritten;
BITMAP Bitmap;
BITMAPFILEHEADER bmfHdr;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
HANDLE hFile, hDib, hPal,hOldPal=NULL;
try
{
int ilength = strFileName.Find(":\\");
ilength = strFileName.Find("\\",ilength+2);
while(ilength !=-1)
{
CString strDirectory =strFileName.Left(ilength);
CFileFind FileFind;
if(!FileFind.FindFile(strDirectory,0))
if(!CreateDirectory(strDirectory,NULL))
{
::MessageBeep(MB_ICONHAND);
// MessageBox("フォルダクリエートに失敗しました。", "情報", MB_OK + MB_APPLMODAL + MB_ICONEXCLAMATION);
}
else
return FALSE;
ilength = strFileName.Find("\\",ilength+1);
}
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);
// CClientDC dc(this);
GetDIBits(hdc, hBitmap, 0, (UINT) Bitmap.bmHeight,(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
+dwPaletteSize,(BITMAPINFO *)lpbi, DIB_RGB_COLORS);
hFile = CreateFile(strFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
bmfHdr.bfType = 0x4D42;
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(hFile, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
WriteFile(hFile, (LPSTR)lpbi, dwDIBSize,&dwWritten, NULL);
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(hFile);
}
catch(...)
{
return FALSE;
}
return TRUE;
}
void main{
HBITMAP hBitmap
CClientDC dc(this);
hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),FileName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_DEFAULTSIZE); if(hBitmap==NULL)
{
::MessageBeep(MB_ICONHAND);
MessageBox("画像が見つかりません。", "情報", MB_OK + MB_ICONSTOP + MB_SYSTEMMODAL);
return -1;
}
if(SaveFile(dc,hBitmap,FileName))
{
return 0;
}
}
{
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;
//计算调色板大小
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;
}
BITMAPFILEHEADER bmfHdr;
// 指向BITMAPINFOHEADER结构的指针
LPBITMAPINFOHEADER lpbmiHdr;
// DIB大小
DWORD dwDIBSize;
// 如果DIB为空,返回FALSE
if(m_hBmp==NULL) return FALSE; // 读取BITMAPINFO结构,并锁定
lpbmiHdr=(LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)m_hBmp);
if(lpbmiHdr==NULL)
{
GlobalFree((HGLOBAL)m_hBmp);
m_hBmp=NULL;
return FALSE;
} // 默认保存WIN32位图格式,以下保存代码
// 填充位图文件头
// 文件类型"BM"
bmfHdr.bfType=BITMAP_FILE_MARKER;
// 计算DIB大小最简单的方法是调用GlobalSize()函数。但是全局内存大小并不是
// DIB真正的大小(总是多几个字节),因此需要计算DIB的真正大小。 // 文件头大小+颜色表大小
dwDIBSize=lpbmiHdr->biSize+RasterImagePaletteSize(); // 计算图象大小
if((lpbmiHdr->biCompression==BI_RLE8)||(lpbmiHdr->biCompression==BI_RLE4))
{
// 对于RLE压缩的位图,没法计算大小,只能信任biSizeImage的值
dwDIBSize+=lpbmiHdr->biSizeImage;
}
else
{
// 图象象素大小
DWORD dwBitsSize;
// 大小Width*Height
dwBitsSize=WIDTHBYTES((lpbmiHdr->biWidth)*(lpbmiHdr->biBitCount))*lpbmiHdr->biHeight;
// 计算DIB真正的大小
dwDIBSize+=dwBitsSize;
// 更新biSizeImage(很多位图文件头中biSizeImage的值是错误的)
lpbmiHdr->biSizeImage=dwBitsSize;
}
// 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小
bmfHdr.bfSize=dwDIBSize+sizeof(BITMAPFILEHEADER); // 填充保留字
bmfHdr.bfReserved1=0;
bmfHdr.bfReserved2=0; // 计算偏移量bfOffBits,等于:位图文件头大小+位图信息头大小+颜色表大小
// sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADR)+sizeof(PALETTE)
bmfHdr.bfOffBits=(DWORD)(sizeof(BITMAPFILEHEADER)+lpbmiHdr->biSize+RasterImagePaletteSize()); // 尝试写文件
TRY
{
// 写位图文件头
pFile->Write(&bmfHdr,sizeof(BITMAPFILEHEADER));
// 写DIB头(位图信息头+调色板)和象素
pFile->WriteHuge(lpbmiHdr,dwDIBSize);
}
CATCH(CFileException,e)
{
// 解除锁定
GlobalUnlock((HGLOBAL)m_hBmp);
// 异常
CString eMsg;
eMsg.Format("保存文件出错,原因:%s",e->m_cause);
AfxMessageBox(eMsg,MB_ICONERROR);
e->Delete();
}
END_CATCH
// 解除锁定
GlobalUnlock((HGLOBAL)m_hBmp);
// 返回TRUE
return TRUE;
}
{
// ASSERT(m_hBmp!=NULL);
// 如果DIB为空,返回FALSE
if(m_hBmp==NULL) return FALSE;
// 1.生成PCXHEAD结构
PCXHEAD pcxHdr;
ZeroMemory(&pcxHdr, sizeof(PCXHEAD));
// 指向BITMAPINFOHEADER结构的指针
LPBITMAPINFOHEADER lpbmiHdr;
// 读取DIB句柄BITMAPINFOHEADER内容
lpbmiHdr=(LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)m_hBmp);
if(lpbmiHdr==NULL)
{
GlobalFree((HGLOBAL)m_hBmp);
m_hBmp=NULL;
return FALSE;
}
// 翻译为PCX头结构,以下转换代码
// 填充PCX文件头
// 文件类型"0x0a"
pcxHdr.PcxFlag=(BYTE)PCXHEAD_MARKER;
pcxHdr.Version=5;
pcxHdr.Encoding=1;
pcxHdr.XMin=pcxHdr.YMin=0;
// 参考当前图象句柄
pcxHdr.XMax=(WORD)(lpbmiHdr->biWidth-1);
pcxHdr.YMax=(WORD)(-1*lpbmiHdr->biHeight-1);
pcxHdr.HRes=(WORD)lpbmiHdr->biXPelsPerMeter;
pcxHdr.VRes=(WORD)lpbmiHdr->biYPelsPerMeter;
if(RasterImagePaletteSize()!=0)
{
// 有调色板情况下
pcxHdr.BitPlane=1;
pcxHdr.BitPerPixel=(BYTE)lpbmiHdr->biBitCount;
}
else
{
// 无调色板情况下
if(RasterImageNumBits()==24)
{
pcxHdr.BitPlane=3;
pcxHdr.BitPerPixel=8;
}
else
{
AfxMessageBox("Unknow error!", MB_ICONERROR);
return FALSE;
}
}
// BytePerLine必须是四字节的整数倍?
// 查看过了,不是。
pcxHdr.BytePerLine=(WORD)lpbmiHdr->biWidth;
pcxHdr.PaletteType=(RasterImageNumBits()!=1)? 2: 1;
pFile->Write(&pcxHdr, sizeof(PCXHEAD));
const LONG clScanLineSize = WIDTHBYTES((pcxHdr.BitPlane)*(pcxHdr.BytePerLine)*8);
LPBYTE ppcxBits=(LPBYTE)lpbmiHdr+sizeof(BITMAPINFOHEADER)+RasterImagePaletteSize();
// 写PCXHEAD结束
//----------------------------------------
// RLE压缩-------------> 已经包含8、24bit图象
// 最坏情况下申请2倍的缓冲,相邻都不重复,并且都大于0xc0
LPBYTE ppcxImg=new BYTE[2*pcxHdr.BitPlane*pcxHdr.BytePerLine]; // 存放临时扫描行
UINT rec(0); // 计数器,写如PCX文件字节数
for( int iY=0; iY<=pcxHdr.YMax; iY++ )
{
// ☆RLE编码,最大重复<=63☆
ZeroMemory(ppcxImg,2*pcxHdr.BitPlane*pcxHdr.BytePerLine);
rec=PackPCXLine(&pcxHdr, ppcxBits, ppcxImg);
// DIB 扫描行递增
ppcxBits+=clScanLineSize;
pFile->Write(ppcxImg,rec);
}
delete []ppcxImg;
// 写图象数据结束
//----------------
// 如果是256色,写调色板数据
// 注意还原=>去除RGBQUAD结构中rgbReserved字段
if(pcxHdr.BitPlane==1&&pcxHdr.BitPerPixel==8) // 256 色图象
{
// 256色8bit,1plane
BYTE palFlg=0x0c;
pFile->Write(&palFlg,1);
// 调色板地址
LPBYTE lpPal=(LPBYTE)lpbmiHdr+sizeof(BITMAPINFOHEADER);
RGBQUAD *prgbQuad;
for( UINT npal=0; npal<256; npal++)
{
prgbQuad=(RGBQUAD*)lpPal;
pFile->Write(&(prgbQuad->rgbRed),1);
pFile->Write(&(prgbQuad->rgbGreen),1);
pFile->Write(&(prgbQuad->rgbBlue),1);
lpPal+=sizeof(RGBQUAD);
}
}
GlobalUnlock((HGLOBAL)m_hBmp);
return TRUE;
}
情况是这样的:一幅真彩色图象,由于纵向上R,G,B通道存在错位,导致同一物体的图象的R,G,B分量没有重合在一起,现在想纠正这种纵向错位,由原始图象,根据错位的偏移量将三个通道分量的数据重组,由此生成一幅真实的图象。请问各位高手,怎样实现它呢?