当前位置:文档之家› 图像处理的源代码

图像处理的源代码

*************************************************************************
* 文件DIBPrcs.cpp用来存放有关DIB的操作函数
* 文件头存放在GlobalApi.h中
*************************************************************************
*/

#include "GlobalApi.h"
#include "stdafx.h"
#include "cdib.h"



/*************************************************************************
*
* \函数名称:
* GetSystemPalette()
*
* \输入参数:
* 无
*
* \返回值:
* HPALETTE - 系统调色板句柄
*
* \说明:
* 该函数获得当前正在使用的系统调色板的句柄
*
*************************************************************************
*/
HPALETTE GetSystemPalette()
{
// 设备上下文
HDC hDC;

// 声明调色板句柄、指针等临时变量
static HPALETTE hPal = NULL;
HANDLE hLogPal;
LPLOGPALETTE lpLogPal;

// 当前系统调色板的颜色数
int nColors;

// 获得当前系统设备上下文
hDC = GetDC(NULL);
if (!hDC)
return NULL;

// 获得当前系统调色板的颜色数目
nColors = ( 1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)));

// 给调色板分配内存
hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors *
sizeof(PALETTEENTRY));
if (!hLogPal)
return NULL;

// 得到调色板内存指针
lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);

// 设置调色板信息
lpLogPal->palVersion = 0x300;
lpLogPal->palNumEntries = nColors;

// 将系统的调色板拷贝到当前的逻辑调色板中
GetSystemPaletteEntries(hDC, 0, nColors,
(LPPALETTEENTRY)(lpLogPal->palPalEntry));

// 创建Windows调色板
hPal = CreatePalette(lpLogPal);

// 释放已分配内存并删除临时对象
GlobalUnlock(hLogPal);
GlobalFree(hLogPal);
ReleaseDC(NULL, hDC);

// 返回
return hPal;
}


/*************************************************************************
*
* \函数名称:
* CopyPalette
*
* \输入参数:
* HPALETTE hPalSrc - 需要拷贝的源调色板句柄
*
* \返回值:
* HPALETTE - 如果操作成功,则返回拷贝的调色板句柄
*
* \说明:
* 该函数将创建一个新的调色板,并从指定的调色板拷贝调色板内容
*
*************************************************************************
*/
HPALETTE CopyPalette(HPALETTE hPalSrc)
{
// 调色板指针,临时变量
PLOGPALETTE plogPal;



// 声明一个调色板句柄和一个临时句柄
HPALETTE hPalette;
HANDLE hTemp;

// 调色板表项数
int iNumEntries=0;

// 获取调色板中的表项数
iNumEntries = GetPaletteEntries(hPalSrc, 0, iNumEntries, NULL);
if (iNumEntries == 0)
return (HPALETTE) NULL;

// 分配调色板内存,得到句柄
hTemp = GlobalAlloc(GHND, sizeof(DWORD) + sizeof(PALETTEENTRY)*iNumEntries);
if (! hTemp)
return (HPALETTE) NULL;

// 得到调色板的指针
plogPal = (PLOGPALETTE)GlobalLock(hTemp);
if (! plogPal)
return (HPALETTE) NULL;

// 设置调色板的信息
plogPal->palVersion = 0x300;
plogPal->palNumEntries = (WORD) iNumEntries;

// 获取逻辑调色板中指定范围的调色板表项
GetPaletteEntries(hPalSrc, 0, iNumEntries, plogPal->palPalEntry);

// 创建一个Windows调色板
hPalette = CreatePalette(plogPal);

// 释放以分配的内存
GlobalUnlock( hTemp );
GlobalFree ( hTemp );

return hPalette;
}




/*************************************************************************
*
* \函数名称:
* ReadDIB
*
* \输入参数:
* CFile* pFile - 需要打开的DIB文件
* LPBITMAPINFOHEADER* pLpBMIH - DIB信息头指针的指针
* LPBYTE* pLpImage - DIB位图数据块指针的指针
*
* \返回值:
* BOOL - 如果操作成功,则返回TRUE
*
* \说明:
* 该函数将指定文件中的DIB文件载入,其中信息头和调色板放在*pLpBMIH中
* 图象数据存放到*pLpImage中。
*
*************************************************************************
*/
BOOL ReadDIB(CFile* pFile, LPBITMAPINFOHEADER* pLpBMIH, LPBYTE* pLpImage)
{
// 临时存放信息的变量
int nCount, nSize;
BITMAPFILEHEADER bmfh;

// 信息头指针
//LPBITMAPINFOHEADER lpBMIH;

// DIB图象数据指针
//LPBYTE lpImage;

// 进行读操作
try
{
// 读取文件头
nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
if(nCount != sizeof(BITMAPFILEHEADER)) {
throw new CException;
}

// 如果文件类型部位"BM",则返回并进行相应错误处理
if(bmfh.bfType != 0x4d42) {
throw new CException;
}

// 计算信息头加上调色板的大小,并分配相应的内存
nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
*pLpBMIH = (LPBITMAPINFOHEADER) new char[nSize];

// 读取信息头

和调色板
nCount = pFile->Read(*pLpBMIH, nSize);

// 计算图象数据大小并设置调色板指针
if((*pLpBMIH)->biSize != sizeof(BITMAPINFOHEADER)) {
TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmap\n");
throw new CException;
}

// 如果图象数据内存大小为0,则重新计算
if((*pLpBMIH)->biSizeImage == 0) {
DWORD dwBytes = ((DWORD) (*pLpBMIH)->biWidth * (*pLpBMIH)->biBitCount) / 32;
if(((DWORD) (*pLpBMIH)->biWidth * (*pLpBMIH)->biBitCount) % 32) {
dwBytes++;
}
dwBytes *= 4;
(*pLpBMIH)->biSizeImage = dwBytes * (*pLpBMIH)->biHeight;
}

// 分配图象数据内存,并从文件中读取图象数据
*pLpImage = (LPBYTE) new char[(*pLpBMIH)->biSizeImage];
nCount = pFile->Read((*pLpImage), (*pLpBMIH)->biSizeImage);
}

// 错误处理
catch(CException* pe)
{
AfxMessageBox("Read error");
pe->Delete();
return FALSE;
}

// 将指针赋值

// 返回
return TRUE;


}


/*************************************************************************
*
* \函数名称:
* MakeDIBPalette()
*
* \输入参数:
* LPVOID lpvColorTable - 颜色表指针
* LPBITMAPINFOHEADER lpBMIH - DIB信息头指针
*
* \返回值:
* HPALETTE - 如果成功,则调色板句柄
*
* \说明:
* 该函数将读取颜色表,并创建一个Windows调色板,并返回此调色板的句柄
*
************************************************************************
*/
HPALETTE MakeDIBPalette(LPVOID lpvColorTable, LPBITMAPINFOHEADER lpBMIH)
{
// 调色板句柄
HPALETTE hPalette = NULL;

// 颜色表颜色数
int nColorTableEntries;

// 设置DIB中的调色板指针
// lpvColorTable = (LPBYTE) lpBMIH + sizeof(BITMAPINFOHEADER);

// 计算调色板的表项数
if(lpBMIH->biClrUsed == 0) {
switch(lpBMIH->biBitCount) {
case 1:
nColorTableEntries = 2;
break;
case 4:
nColorTableEntries = 16;
break;
case 8:
nColorTableEntries = 256;
break;
case 16:
case 24:
case 32:
nColorTableEntries = 0;
break;
default:
break;
}
}

// 否则调色板的表项数就是用到的颜色数目
else {
nColorTableEntries

= lpBMIH->biClrUsed;
}

ASSERT((nColorTableEntries >= 0) && (nColorTableEntries <= 256));

// 如果不存在调色板,则返回FALSE
if(nColorTableEntries == 0) return FALSE;

// 给逻辑调色板分配内存
LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) +
nColorTableEntries * sizeof(PALETTEENTRY)];

// 设置逻辑调色板的信息
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = nColorTableEntries;

// 拷贝DIB中的颜色表到逻辑调色板
LPRGBQUAD pDibQuad = (LPRGBQUAD) lpvColorTable;
for(int i = 0; i < nColorTableEntries; i++) {
pLogPal->palPalEntry[i].peRed = pDibQuad->rgbRed;
pLogPal->palPalEntry[i].peGreen = pDibQuad->rgbGreen;
pLogPal->palPalEntry[i].peBlue = pDibQuad->rgbBlue;
pLogPal->palPalEntry[i].peFlags = 0;
pDibQuad++;
}

// 创建逻辑调色板
hPalette = ::CreatePalette(pLogPal);

// 删除临时变量
delete pLogPal;

// 返回调色板句柄
return hPalette;
}

/*************************************************************************
*
* \函数名称:
* PaintDIB()
*
* \输入参数:
* CDC* pDC - 指向将要接收DIB图象的设备上下文指针
* LPBITMAPINFOHEADER lpBMIH - DIB信息头指针
* LPBYTE lpImage; - DIB位图数据块地址
* CPoint origin - 显示DIB的逻辑坐标
* CSize size - 显示矩形的宽度和高度
* HPALETTE hPalette - 指向DIB的调色板句柄
*
* \返回值:
* BOOL - 如果成功,则返回TRUE
*
* \说明:
* 该函数将DIB图象进行显示
*
************************************************************************
*/
BOOL PaintDIB(CDC* pDC, LPBITMAPINFOHEADER lpBMIH, LPBYTE lpImage, CPoint origin, CSize size, HPALETTE hPalette)
{
if(lpBMIH == NULL) return FALSE;

// 如果调色板不为空,则将调色板选入设备上下文
if(hPalette != NULL) {
::SelectPalette(pDC->GetSafeHdc(), hPalette, TRUE);
}

// 设置显示模式
pDC->SetStretchBltMode(COLORONCOLOR);

// 在设备的origin位置上画出大小为size的图象
::StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y,size.cx,size.cy,
0, 0, lpBMIH->biWidth, lpBMIH->biHeight,
lpImage, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS, SRCCOPY);

// 返回
return TRUE;
}


/*************************************************************************
*
* \函数名称:
* ConvertDDBToDIB()
*
* \输入参数:
* HBITMAP hBitmap - 指向源数据的BITMAP句柄
* CDib* pDibDs

t - 指向转换目标的CDib对象指针
*
* \返回值:
* BOOL - 如果操作成功,则返回TRUE
*
* \说明:
* 该函数将源BITMAP类pDibSrc中的数据拷贝到pDibDst中,并对相应的数据成员赋值
*
*************************************************************************
*/

BOOL ConvertDDBToDIB(HBITMAP hBitmap, CDib* pDibDest, HPALETTE hPal)
{
// 声明一个BITMAP结构
BITMAP bm;

// 设备上下文
HDC hDC;

// 象素位数
WORD biBitCount;

// 调色板表项数
int nColorTableEntries;

// 如果hBitmap句柄无效,则返回
if(!hBitmap){
return FALSE;
}

// 填充图象数据到bm中,其中最后一个参数表示接收这个指定的对象的指针
if(!GetObject(hBitmap,sizeof(BITMAP),(LPBYTE)&bm)){
return FALSE;
}

// 计算象素位数
biBitCount=bm.bmPlanes*bm.bmBitsPixel;
if(biBitCount<=1)
biBitCount=1;
else if(biBitCount<=4)
biBitCount=4;
else if(biBitCount<=8)
biBitCount=8;
else
biBitCount=24;

// 计算调色板的尺寸
// 如果biClrUsed为零,则用到的颜色数为2的biBitCount次方
switch(biBitCount) {
case 1:
nColorTableEntries = 2;
break;
case 4:
nColorTableEntries = 16;
break;
case 8:
nColorTableEntries = 256;
break;
case 16:
case 24:
case 32:
nColorTableEntries = 0;
break;
default:
ASSERT(FALSE);
}
ASSERT((nColorTableEntries >= 0) && (nColorTableEntries <= 256));

// 分配DIB信息头和调色板的内存
LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) new char
[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorTableEntries];

lpBMIH->biSize = sizeof(BITMAPINFOHEADER);
lpBMIH->biWidth = bm.bmWidth;
lpBMIH->biHeight = bm.bmHeight;
lpBMIH->biPlanes = 1;
lpBMIH->biBitCount = biBitCount;
lpBMIH->biCompression = BI_RGB;
lpBMIH->biSizeImage = 0;
lpBMIH->biXPelsPerMeter = 0;
lpBMIH->biYPelsPerMeter = 0;
lpBMIH->biClrUsed = nColorTableEntries;
lpBMIH->biClrImportant = nColorTableEntries;

// 获得设备上下文句柄
hDC=GetDC(NULL);

// select and realize our palette

// 如果没有指定调色板,则从系统中获得当前的系统调色板
if(hPal==NULL){
hPal = GetSystemPalette();
}
hPal = SelectPalette(hDC, hPal, FALSE);
RealizePalette(hDC);



// 调用GetDIBits填充信息头,并获得图象数据的尺寸。注意这里图象数据指针为NULL
GetDIBits( hDC, hBitmap, 0, (UINT)lpBMIH->biHeight, NULL, (LPBITMAPINFO)lpBMIH, DIB_RGB_COLORS);

// 如果没有正确的获得图象数据尺寸,则重新计算
if( lpBMIH->biSizeImage == 0 ){
lpBMIH->biSizeImage=(((bm.bmWidth*biBitCount) + 31) / 32 * 4)*bm.bmHeight;
}

// 分配存放图象数据的内存
LPBYTE lpImage = (LPBYTE) new char[lpBMIH->biSizeImage];

// 调用GetDIBits加载图象数据,注意这里给出了图象数据指针

// 如果加载图象数据不成功,则释放已经分配的内存,并返回FALSE
if( GetDIBits( hDC, hBitmap, 0, (UINT)lpBMIH->biHeight, (LPBYTE)lpImage,
(LPBITMAPINFO)lpBMIH, DIB_RGB_COLORS) == 0 ){
//clean up and return NULL
delete []lpImage;
delete []lpBMIH;

SelectPalette( hDC, hPal, TRUE );
RealizePalette( hDC );
ReleaseDC( NULL, hDC );

return FALSE;
}

// 将指针保存在CDib对象的数据成员中
pDibDest->m_lpBMIH = lpBMIH;
pDibDest->m_lpImage = lpImage;
pDibDest->m_nBmihAlloc = pDibDest->m_nImageAlloc = pDibDest->crtAlloc;


// 删除临时变量
SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
return TRUE;
}


/*************************************************************************
*
* \函数名称:
* CopyDIB()
*
* \输入参数:
* CDib* pDibSrc - 指向源数据的CDib对象指针
* CDib* pDibDst - 指向拷贝目标的CDib对象指针
*
* \返回值:
* BOOL - 如果操作成功,则返回TRUE
*
* \说明:
* 该函数将源CDib类pDibSrc中的数据拷贝到pDibDst中,并对相应的数据成员赋值
*
*************************************************************************
*/
BOOL CopyDIB(CDib* pDibSrc, CDib* pDibDst)
{
// 将目的CDib对象清空
pDibDst->Empty();

// 计算信息头加上调色板的大小,并分配相应的内存
int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pDibSrc->m_nColorTableEntries;

pDibDst->m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSizeHdr];
pDibDst->m_nBmihAlloc = pDibDst->m_nImageAlloc = pDibDst->crtAlloc;

try{

// 拷贝信息头和调色板
memcpy(pDibDst->m_lpBMIH,pDibSrc->m_lpBMIH,nSizeHdr);


// 如果结构的长度不对,则进行错误处理
if(pDibDst->m_lpBMIH->biSize != sizeof(BITMAPINFOHEADER)) {
TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmap\n");


throw new CException;
}

// 保存图象数据内存大小到CDib对象的数据成员中
pDibDst->m_dwSizeImage = pDibDst->m_lpBMIH->biSizeImage;

// 如果图象数据内存大小为0,则重新计算
if(pDibDst->m_dwSizeImage == 0) {
DWORD dwBytes = ((DWORD) pDibDst->m_lpBMIH->biWidth * pDibDst->m_lpBMIH->biBitCount) / 32;
if(((DWORD) pDibDst->m_lpBMIH->biWidth * pDibDst->m_lpBMIH->biBitCount) % 32) {
dwBytes++;
}
dwBytes *= 4;
pDibDst->m_dwSizeImage = dwBytes * pDibDst->m_lpBMIH->biHeight;
}

// 设置DIB中的调色板指针
pDibDst->m_lpvColorTable = (LPBYTE) pDibDst->m_lpBMIH + sizeof(BITMAPINFOHEADER);

// 计算调色板的表项数
pDibDst->ComputePaletteSize(pDibDst->m_lpBMIH->biBitCount);

// 如果DIB中存在调色板,则创建一个Windows调色板
pDibDst->MakePalette();

// 分配图象数据内存,并拷贝图象数据
pDibDst->m_lpImage = (LPBYTE) new char[pDibDst->m_dwSizeImage];
memcpy(pDibDst->m_lpImage, pDibSrc->m_lpImage,pDibDst->m_dwSizeImage);
}

catch(CException* pe)
{
AfxMessageBox("Copy DIB error");
pDibDst->Empty();
pe->Delete();
return FALSE;
}

return TRUE;
}


/*************************************************************************
*
* \函数名称:
* CopyScreenToDIB
*
* \输入参数:
* LPRECT lpRect - 需要拷贝的屏幕区域
* CDib* pDibDest - 指向目标CDib对象的指针
*
* \返回值:
* BOOL - 如果操作成功,则返回TRUE
*
* \说明:
* 该函数将指定矩形位置内的屏幕内容拷贝到DIB中源CDib类pDibSrc中的数据拷贝到pDibDst中
*
*************************************************************************
*/
BOOL CopyScreenToDIB(LPRECT lpRect, CDib* pDibDest)
{
// 屏幕设备上下文和内存设备上下文句柄
HDC hScrDC, hMemDC;

// 声明BITMAP临时句柄和以前的BITMAP句柄
HBITMAP hBitmap, hOldBitmap;

// 调色板句柄
HPALETTE hPalette;

// 获取矩形区域的坐标
int nX, nY, nX2, nY2;

// DIB图象的高度和宽度
int nWidth, nHeight;

// 屏幕分辨率
int xScrn, yScrn;

// 如果给定的矩形区域为空,则不进行进一步的处理
if (IsRectEmpty(lpRect))
return FALSE;

// 得到一个屏幕设备上下文
hScrDC = CreateDC("DISPLAY", NUL

L, NULL, NULL);

// 创建与屏幕设备兼容的内存设备上下文
hMemDC = CreateCompatibleDC(hScrDC);

// 得到矩形的区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;

// 得到屏幕的分辨率,以便后面的判断处理
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);

// 判断矩形区域是否超出屏幕

if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > xScrn)
nX2 = xScrn;
if (nY2 > yScrn)
nY2 = yScrn;

// 计算DIB图象的高度和宽度
nWidth = nX2 - nX;
nHeight = nY2 - nY;

// 创建一个与屏幕设备上下文兼容的DDB位图
hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);

// 将DDB位图选入内存设备上下文
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);

// 将屏幕中指定区域的图象传输到内存设备上下文中
BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);

// 然后将以前的图象选入,并得到屏幕区域的DDB图象句柄
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);

// 将临时的设备上下文删除
DeleteDC(hScrDC);
DeleteDC(hMemDC);

// 得到当前系统调色板
hPalette = GetSystemPalette();

// 将DDB图象转换为DIB图象
pDibDest->ConvertFromDDB(hBitmap,hPalette);

// 删除临时对象
DeleteObject(hPalette);
DeleteObject(hBitmap);

return TRUE;
}

相关主题
文本预览
相关文档 最新文档