fourier-mellin C++实现图像之间的匹配,该怎么处理
1个回答
推荐于2016-11-30
展开全部
在MFC下自己构造一个dib类实现上述功能还是有很多现成的代码~
下面就是一个构造的dib类,但是仅仅提供了最基本的一些操作,代码来自《Visual C++数字图像处理典型算法及实现》。// dibImage.h: interface for the CdibImage class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_dibIMAGE_H__254F3D1E_BB20_40DA_AE07_E8E0219DFA8C__INCLUDED_)
#define AFX_dibIMAGE_H__254F3D1E_BB20_40DA_AE07_E8E0219DFA8C__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
DECLARE_handle(Hdib); // dib句柄
#define PALVERSION 0x300 // dib常量
/* dib宏 */
// 判断是否是Win 3.0的dib
#define IS_WIN30_dib(lpbi) ((*(LPdword)(lpbi)) == sizeof(BITMAPINFOHEADER))
// 计算矩形区域的宽度
#define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left)
// 计算矩形区域的高度
#define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top)
// 在计算图像大小时,采用公式:biSizeImage = biWidth' × biHeight。
// 是biWidth',而不是biWidth,这里的biWidth'必须是4的整倍数,表示
// 大于或等于biWidth的,离4最近的整倍数。WIDTHBYTES就是用来计算
// biWidth'
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
// dib文件头标志(字符串"BM",写dib时用到该常数)
#define dib_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
class CdibImage
{
// Constructor and Destructor ///////////////////////////////
public:
CdibImage();
virtual ~CdibImage();
// function /////////////////////////////////////////////////
public:
bool Paintdib (hdc, LPRECT, Hdib, LPRECT, CPalette* pPal);
bool CreatedibPalette(Hdib hdib, CPalette* cPal);
LPSTR FinddibBits (LPSTR lpbi);
dword dibWidth (LPSTR lpdib);
dword dibHeight (LPSTR lpdib);
WORD PaletteSize (LPSTR lpbi);
WORD dibNumColors (LPSTR lpbi);
HGLOBAL Copyhandle (HGLOBAL h);
bool Savedib (Hdib hdib, CFile& file);
Hdib ReaddibFile(CFile& file);
};
#endif // !defined(AFX_dibIMAGE_H__254F3D1E_BB20_40DA_AE07_E8E0219DFA8C__INCLUDED_)
///////////////////////////////////////////////////////////////////////
// dibImage.cpp: implementation of the CdibImage class.
// dib(Independent Bitmap) 函数:
//
// Paintdib() - 绘制dib对象
// CreatedibPalette() - 创建dib对象调色板
// FinddibBits() - 返回dib图像象素起始位置
// dibWidth() - 返回dib宽度
// dibHeight() - 返回dib高度
// PaletteSize() - 返回dib调色板大小
// dibNumColors() - 计算dib调色板颜色数目
// Copyhandle() - 拷贝内存块
//
// Savedib() - 将dib保存到指定文件中
// ReaddibFile() - 重指定文件中读取dib对象
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "dibDisplay.h"
#include "dibImage.h"
#ifdef _debug
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new debug_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CdibImage::CdibImage()
{
}
CdibImage::~CdibImage()
{
}
//////////////////////////////////////////////////////////////////////
// function
//////////////////////////////////////////////////////////////////////
/*************************************************************************
* 函数名称:
* Paintdib()
* 参数:
* hdc hdc - 输出设备DC
* LPRECT lpDCRect - 绘制矩形区域
* Hdib hdib - 指向dib对象的指针
* LPRECT lpdibRect - 要输出的dib区域
* CPalette* pPal - 指向dib对象调色板的指针
* 返回值:
* bool - 绘制成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数主要用来绘制dib对象。其中调用了Stretchdibits()或者
* SetdibitsToDevice()来绘制dib对象。输出的设备由由参数hdc指
* 定;绘制的矩形区域由参数lpDCRect指定;输出dib的区域由参数
* lpdibRect指定。
************************************************************************/
bool CdibImage::Paintdib(hdc hdc,
LPRECT lpDCRect,
Hdib hdib,
LPRECT lpdibRect,
CPalette* pPal)
{
LPSTR lpdibHdr; // BITMAPINFOHEADER指针
LPSTR lpdibBits; // dib象素指针
bool bSuccess=FALSE; // 成功标志
HPALETTE hPal=NULL; // dib调色板
HPALETTE hOldPal=NULL; // 以前的调色板
if (hdib == NULL)
{
return FALSE;
}
lpdibHdr = (LPSTR)::GlobalLock((HGLOBAL) hdib);// 锁定dib
lpdibBits = FinddibBits(lpdibHdr); // 找到dib图像象素起始位置
if (pPal != NULL) // 获取dib调色板,并选中它
{
hPal = (HPALETTE) pPal->m_hObject;
hOldPal = ::SelectPalette(hdc, hPal, TRUE); // 选中调色板
}
::SetStretchBltMode(hdc, COLORONCOLOR); // 设置显示模式
// 判断是调用Stretchdibits()还是SetdibitsToDevice()来绘制dib对象
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpdibRect)) &&
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpdibRect)))
{
// 原始大小,不用拉伸。
bSuccess = ::SetdibitsToDevice(hdc, // hdc
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpdibRect->left, // SrcX
(int)dibHeight(lpdibHdr) -
lpdibRect->top -
RECTHEIGHT(lpdibRect), // SrcY
0, // nStartScan
(WORD)dibHeight(lpdibHdr), // nNumScans
lpdibBits, // lpBits
(LPBITMAPINFO)lpdibHdr, // lpBitsInfo
dib_RGB_COLORS); // wUsage
}
else
{
// 非原始大小,拉伸。
bSuccess = ::Stretchdibits(hdc, // hdc
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpdibRect->left, // SrcX
lpdibRect->top, // SrcY
RECTWIDTH(lpdibRect), // wSrcWidth
RECTHEIGHT(lpdibRect), // wSrcHeight
lpdibBits, // lpBits
(LPBITMAPINFO)lpdibHdr, // lpBitsInfo
dib_RGB_COLORS, // wUsage
SRCCOPY); // dwROP
}
::GlobalUnlock((HGLOBAL) hdib); // 解除锁定
if (hOldPal != NULL)
{
::SelectPalette(hdc, hOldPal, TRUE); // 恢复以前的调色板
}
return bSuccess;
}
/*************************************************************************
* 函数名称:
* CreatedibPalette()
* 参数:
* Hdib hdib - 指向dib对象的指针
* CPalette* pPal - 指向dib对象调色板的指针
* 返回值:
* bool - 创建成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数按照dib创建一个逻辑调色板,从dib中读取颜色表并存到调色板中,
* 最后按照该逻辑调色板创建一个新的调色板,并返回该调色板的句柄。这样
* 可以用最好的颜色来显示dib图像。
************************************************************************/
bool CdibImage::CreatedibPalette(Hdib hdib, CPalette* pPal)
{
LPLOGPALETTE lpPal; // 指向逻辑调色板的指针
handle hLogPal; // 逻辑调色板的句柄
HPALETTE hPal = NULL; // 调色板的句柄
int i; // 循环变量
WORD wNumColors; // 颜色表中的颜色数目
LPSTR lpbi; // 指向dib的指针
LPBITMAPINFO lpbmi; // 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREINFO lpbmc; // 指向BITMAPCOREINFO结构的指针
bool bWinStyledib; // 表明是否是Win3.0 dib的标记
bool bResult = FALSE; // 创建结果
if (hdib == NULL)
{
return FALSE;
}
lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hdib); // 锁定dib
lpbmi = (LPBITMAPINFO)lpbi; // 获取指向BITMAPINFO结构的指针(Win3.0)
lpbmc = (LPBITMAPCOREINFO)lpbi; // 获取指向BITMAPCOREINFO结构的指针
wNumColors = dibNumColors(lpbi);// 获取dib中颜色表中的颜色数目
if (wNumColors != 0)
{
// 分配为逻辑调色板内存
hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
+ sizeof(PALETTEENTRY)
* wNumColors);
// 如果内存不足,退出
if (hLogPal == 0)
{
::GlobalUnlock((HGLOBAL) hdib); // 解除锁定
return FALSE;
}
lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
lpPal->palVersion = PALVERSION; // 设置版本号
lpPal->palNumEntries = (WORD)wNumColors;// 设置颜色数目
bWinStyledib = IS_WIN30_dib(lpbi); // 判断是否是WIN3.0的dib
// 读取调色板
for (i = 0; i < (int)wNumColors; i++)
{
if (bWinStyledib)
{
// 读取红色绿色蓝色分量
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
// 保留位
lpPal->palPalEntry[i].peFlags = 0;
}
else
{
// 读取红色绿色蓝色分量
lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
// 保留位
lpPal->palPalEntry[i].peFlags = 0;
}
}
bResult = pPal->CreatePalette(lpPal);// 按照逻辑调色板创建调色板,并返回指针
::GlobalUnlock((HGLOBAL) hLogPal); // 解除锁定
::GlobalFree((HGLOBAL) hLogPal); // 释放逻辑调色板
}
::GlobalUnlock((HGLOBAL) hdib); // 解除锁定
return bResult;
}
/*************************************************************************
* 函数名称:
* FinddibBits()
* 参数:
* LPSTR lpbi - 指向dib对象的指针
* 返回值:
* LPSTR - 指向dib图像象素起始位置
* 说明:
* 该函数计算dib中图像象素的起始位置,并返回指向它的指针。
************************************************************************/
LPSTR CdibImage::FinddibBits(LPSTR lpbi)
{
return (lpbi + *(LPdword)lpbi + PaletteSize(lpbi));
}
/*************************************************************************
* 函数名称:
* dibWidth()
* 参数:
* LPSTR lpbi - 指向dib对象的指针
* 返回值:
* dword - dib中图像的宽度
* 说明:
* 该函数返回dib中图像的宽度。对于Windows 3.0 dib,返回BITMAPINFOHEADER
* 中的biWidth值;对于其它返回BITMAPCOREHEADER中的bcWidth值。
************************************************************************/
dword CdibImage::dibWidth(LPSTR lpdib)
{
LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针
lpbmi = (LPBITMAPINFOHEADER)lpdib;
lpbmc = (LPBITMAPCOREHEADER)lpdib;
// 返回dib中图像的宽度
if (IS_WIN30_dib(lpdib))
{
return lpbmi->biWidth; // 对于Windows 3.0 dib,返回lpbmi->biWidth
}
else
{
return (dword)lpbmc->bcWidth; // 对于其它格式的dib,返回lpbmc->bcWidth
}
}
/*************************************************************************
* 函数名称:
* dibHeight()
* 参数:
* LPSTR lpdib - 指向dib对象的指针
* 返回值:
* dword - dib中图像的高度
* 说明:
* 该函数返回dib中图像的高度。对于Windows 3.0 dib,返回BITMAPINFOHEADER
* 中的biHeight值;对于其它返回BITMAPCOREHEADER中的bcHeight值。
************************************************************************/
dword CdibImage::dibHeight(LPSTR lpdib)
{
LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针
lpbmi = (LPBITMAPINFOHEADER)lpdib;
lpbmc = (LPBITMAPCOREHEADER)lpdib;
// 返回dib中图像的宽度
if (IS_WIN30_dib(lpdib))
{
return lpbmi->biHeight; // 对于Windows 3.0 dib,返回lpbmi->biHeight
}
else
{
return (dword)lpbmc->bcHeight; // 对于其它格式的dib,返回lpbmc->bcHeight
}
}
/*************************************************************************
* 函数名称:
* PaletteSize()
* 参数:
* LPSTR lpbi - 指向dib对象的指针
* 返回值:
* WORD - dib中调色板的大小
* 说明:
* 该函数返回dib中调色板的大小。对于Windows 3.0 dib,返回颜色数目×
* RGBQUAD的大小;对于其它返回颜色数目×RGBTRIPLE的大小。
************************************************************************/
WORD CdibImage::PaletteSize(LPSTR lpbi)
{
// 计算dib中调色板的大小
if (IS_WIN30_dib (lpbi))
{
//返回颜色数目×RGBQUAD的大小
return (WORD)(dibNumColors(lpbi) * sizeof(RGBQUAD));
}
else
{
//返回颜色数目×RGBTRIPLE的大小
return (WORD)(dibNumColors(lpbi) * sizeof(RGBTRIPLE));
}
}
/*************************************************************************
* 函数名称:
* dibNumColors()
* 参数:
* LPSTR lpbi - 指向dib对象的指针
* 返回值:
* WORD - 返回调色板中颜色的种数
* 说明:
* 该函数返回dib中调色板的颜色的种数。对于单色位图,返回2,
* 对于16色位图,返回16,对于256色位图,返回256;对于真彩色
* 位图(24位),没有调色板,返回0。
************************************************************************/
WORD CdibImage::dibNumColors(LPSTR lpbi)
{
WORD wBitCount;
// 对于Windows的dib, 实际颜色的数目可以比象素的位数要少。
// 对于这种情况,则返回一个近似的数值。
// 判断是否是WIN3.0 dib
if (IS_WIN30_dib(lpbi))
{
dword dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; // 读取dwClrUsed值
if (dwClrUsed != 0)
{
// 如果dwClrUsed(实际用到的颜色数)不为0,直接返回该值
return (WORD)dwClrUsed;
}
}
// 读取象素的位数
if (IS_WIN30_dib(lpbi))
{
wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; // 读取biBitCount值
}
else
{
wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; // 读取biBitCount值
}
// 按照象素的位数计算颜色数目
switch (wBitCount)
{
case 1:
return 2;
break;
case 4:
return 16;
break;
case 8:
return 256;
break;
default:
return 0;
break;
}
}
/*************************************************************************
* 函数名称:
* Copyhandle()
* 参数:
* HGLOBAL h - 要复制的内存区域
* 返回值:
* HGLOBAL - 复制后的新内存区域
* 说明:
* 该函数复制指定的内存区域。返回复制后的新内存区域,出错时返回0。
************************************************************************/
HGLOBAL CDibImage::Copyhandle (HGLOBAL h)
{
if (h == NULL)
{
return NULL;
}
dword dwLen = ::GlobalSize((HGLOBAL) h); // 获取指定内存区域大小
HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); // 分配新内存空间
if (hCopy != NULL) // 判断分配是否成功
{
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
void* lp = ::GlobalLock((HGLOBAL) h);
memcpy(lpCopy, lp, dwLen);
::GlobalUnlock(hCopy);
::GlobalUnlock(h);
}
return hCopy;
}
/*************************************************************************
* 函数名称:
* SaveDIB()
* 参数:
* HDIB hDib - 要保存的DIB
* CFile& file - 保存文件CFile
* 返回值:
* bool - 成功返回TRUE,否则返回FALSE或者CFileException
* 说明:
* 该函数将指定的DIB对象保存到指定的CFile中。该CFile由调用程序打开和关闭。
*************************************************************************/
bool CDibImage::SaveDIB(HDIB hDib, CFile& file)
{
BITMAPFILEHEADER bmfHdr; // Bitmap文件头
LPBITMAPINFOHEADER lpBI; // 指向BITMAPINFOHEADER的指针
dword dwDIBSize; // DIB大小
if (hDib == NULL)
{
return FALSE;
}
// 读取BITMAPINFO结构,并锁定
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if (lpBI == NULL)
{
return FALSE;
}
// 判断是否是WIN3.0 DIB
if (!IS_WIN30_DIB(lpBI))
{
// 不支持其它类型的DIB保存
::GlobalUnlock((HGLOBAL) hDib);
return FALSE;
}
////////////////////////////////////////////////////////////////////////
// 填充文件头///////////////////////////////////////////////////////////
bmfHdr.bfType = DIB_HEADER_MARKER; // 文件类型"BM"
// 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并
// 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小。
// 文件头大小+颜色表大小
// (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个dword都是该结构的大小)
dwDIBSize = *(LPdword)lpBI + PaletteSize((LPSTR)lpBI);
// 计算图像大小
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
{
// 对于RLE位图,没法计算大小,只能信任biSizeImage内的值
dwDIBSize += lpBI->biSizeImage;
}
else
{
dword dwBmBitsSize; // 象素的大小
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((dword)lpBI->biBitCount))
* lpBI->biHeight; // 大小为Width * Height
dwDIBSize += dwBmBitsSize; // 计算出DIB真正的大小
// 更新biSizeImage(很多bmp文件头中biSizeImage的值是错误的)
lpBI->biSizeImage = dwBmBitsSize;
}
// 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
// 两个保留字
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
// 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小
bmfHdr.bfOffBits = (dword)sizeof(BITMAPFILEHEADER) + lpBI->biSize
+ PaletteSize((LPSTR)lpBI);
/////////////////////////////////////////////////////////////////////////
// 尝试写文件////////////////////////////////////////////////////////////
TRY
{
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); // 写文件头
file.WriteHuge(lpBI, dwDIBSize); // 写DIB头和象素
}
catch (CFileException, e)
{
::GlobalUnlock((HGLOBAL) hDib);
THROW_LAST();
}
END_catch
::GlobalUnlock((HGLOBAL) hDib);
return TRUE;
}
/*************************************************************************
* 函数名称:
* ReadDIBFile()
* 参数:
* CFile& file - 要读取得文件文件CFile
* 返回值:
* HDIB - 成功返回DIB的句柄,否则返回NULL。
* 说明:
* 该函数将指定的文件中的DIB对象读到指定的内存区域中。除BITMAPFILEHEADER
* 外的内容都将被读入内存。
*************************************************************************/
HDIB CDibImage::ReadDIBFile(CFile& file)
{
BITMAPFILEHEADER bmfHeader;
HDIB hDIB;
LPSTR pDIB;
dword dwBitsSize;
dwBitsSize = file.GetLength(); // 获取DIB(文件)长度(字节)
// 尝试读取DIB文件头
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
{
return NULL;
}
// 判断是否是DIB对象,检查头两个字节是否是"BM"
if (bmfHeader.bfType != DIB_HEADER_MARKER)
{
return NULL;
}
// 为DIB分配内存
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
if (hDIB == 0)
{
return NULL;
}
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
dwBitsSize - sizeof(BITMAPFILEHEADER) ) // 读象素
{
::GlobalUnlock((HGLOBAL) hDIB);
::GlobalFree((HGLOBAL) hDIB);
return NULL;
}
::GlobalUnlock((HGLOBAL) hDIB);
return hDIB;
}
下面就是一个构造的dib类,但是仅仅提供了最基本的一些操作,代码来自《Visual C++数字图像处理典型算法及实现》。// dibImage.h: interface for the CdibImage class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_dibIMAGE_H__254F3D1E_BB20_40DA_AE07_E8E0219DFA8C__INCLUDED_)
#define AFX_dibIMAGE_H__254F3D1E_BB20_40DA_AE07_E8E0219DFA8C__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
DECLARE_handle(Hdib); // dib句柄
#define PALVERSION 0x300 // dib常量
/* dib宏 */
// 判断是否是Win 3.0的dib
#define IS_WIN30_dib(lpbi) ((*(LPdword)(lpbi)) == sizeof(BITMAPINFOHEADER))
// 计算矩形区域的宽度
#define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left)
// 计算矩形区域的高度
#define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top)
// 在计算图像大小时,采用公式:biSizeImage = biWidth' × biHeight。
// 是biWidth',而不是biWidth,这里的biWidth'必须是4的整倍数,表示
// 大于或等于biWidth的,离4最近的整倍数。WIDTHBYTES就是用来计算
// biWidth'
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
// dib文件头标志(字符串"BM",写dib时用到该常数)
#define dib_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
class CdibImage
{
// Constructor and Destructor ///////////////////////////////
public:
CdibImage();
virtual ~CdibImage();
// function /////////////////////////////////////////////////
public:
bool Paintdib (hdc, LPRECT, Hdib, LPRECT, CPalette* pPal);
bool CreatedibPalette(Hdib hdib, CPalette* cPal);
LPSTR FinddibBits (LPSTR lpbi);
dword dibWidth (LPSTR lpdib);
dword dibHeight (LPSTR lpdib);
WORD PaletteSize (LPSTR lpbi);
WORD dibNumColors (LPSTR lpbi);
HGLOBAL Copyhandle (HGLOBAL h);
bool Savedib (Hdib hdib, CFile& file);
Hdib ReaddibFile(CFile& file);
};
#endif // !defined(AFX_dibIMAGE_H__254F3D1E_BB20_40DA_AE07_E8E0219DFA8C__INCLUDED_)
///////////////////////////////////////////////////////////////////////
// dibImage.cpp: implementation of the CdibImage class.
// dib(Independent Bitmap) 函数:
//
// Paintdib() - 绘制dib对象
// CreatedibPalette() - 创建dib对象调色板
// FinddibBits() - 返回dib图像象素起始位置
// dibWidth() - 返回dib宽度
// dibHeight() - 返回dib高度
// PaletteSize() - 返回dib调色板大小
// dibNumColors() - 计算dib调色板颜色数目
// Copyhandle() - 拷贝内存块
//
// Savedib() - 将dib保存到指定文件中
// ReaddibFile() - 重指定文件中读取dib对象
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "dibDisplay.h"
#include "dibImage.h"
#ifdef _debug
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new debug_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CdibImage::CdibImage()
{
}
CdibImage::~CdibImage()
{
}
//////////////////////////////////////////////////////////////////////
// function
//////////////////////////////////////////////////////////////////////
/*************************************************************************
* 函数名称:
* Paintdib()
* 参数:
* hdc hdc - 输出设备DC
* LPRECT lpDCRect - 绘制矩形区域
* Hdib hdib - 指向dib对象的指针
* LPRECT lpdibRect - 要输出的dib区域
* CPalette* pPal - 指向dib对象调色板的指针
* 返回值:
* bool - 绘制成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数主要用来绘制dib对象。其中调用了Stretchdibits()或者
* SetdibitsToDevice()来绘制dib对象。输出的设备由由参数hdc指
* 定;绘制的矩形区域由参数lpDCRect指定;输出dib的区域由参数
* lpdibRect指定。
************************************************************************/
bool CdibImage::Paintdib(hdc hdc,
LPRECT lpDCRect,
Hdib hdib,
LPRECT lpdibRect,
CPalette* pPal)
{
LPSTR lpdibHdr; // BITMAPINFOHEADER指针
LPSTR lpdibBits; // dib象素指针
bool bSuccess=FALSE; // 成功标志
HPALETTE hPal=NULL; // dib调色板
HPALETTE hOldPal=NULL; // 以前的调色板
if (hdib == NULL)
{
return FALSE;
}
lpdibHdr = (LPSTR)::GlobalLock((HGLOBAL) hdib);// 锁定dib
lpdibBits = FinddibBits(lpdibHdr); // 找到dib图像象素起始位置
if (pPal != NULL) // 获取dib调色板,并选中它
{
hPal = (HPALETTE) pPal->m_hObject;
hOldPal = ::SelectPalette(hdc, hPal, TRUE); // 选中调色板
}
::SetStretchBltMode(hdc, COLORONCOLOR); // 设置显示模式
// 判断是调用Stretchdibits()还是SetdibitsToDevice()来绘制dib对象
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpdibRect)) &&
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpdibRect)))
{
// 原始大小,不用拉伸。
bSuccess = ::SetdibitsToDevice(hdc, // hdc
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpdibRect->left, // SrcX
(int)dibHeight(lpdibHdr) -
lpdibRect->top -
RECTHEIGHT(lpdibRect), // SrcY
0, // nStartScan
(WORD)dibHeight(lpdibHdr), // nNumScans
lpdibBits, // lpBits
(LPBITMAPINFO)lpdibHdr, // lpBitsInfo
dib_RGB_COLORS); // wUsage
}
else
{
// 非原始大小,拉伸。
bSuccess = ::Stretchdibits(hdc, // hdc
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpdibRect->left, // SrcX
lpdibRect->top, // SrcY
RECTWIDTH(lpdibRect), // wSrcWidth
RECTHEIGHT(lpdibRect), // wSrcHeight
lpdibBits, // lpBits
(LPBITMAPINFO)lpdibHdr, // lpBitsInfo
dib_RGB_COLORS, // wUsage
SRCCOPY); // dwROP
}
::GlobalUnlock((HGLOBAL) hdib); // 解除锁定
if (hOldPal != NULL)
{
::SelectPalette(hdc, hOldPal, TRUE); // 恢复以前的调色板
}
return bSuccess;
}
/*************************************************************************
* 函数名称:
* CreatedibPalette()
* 参数:
* Hdib hdib - 指向dib对象的指针
* CPalette* pPal - 指向dib对象调色板的指针
* 返回值:
* bool - 创建成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数按照dib创建一个逻辑调色板,从dib中读取颜色表并存到调色板中,
* 最后按照该逻辑调色板创建一个新的调色板,并返回该调色板的句柄。这样
* 可以用最好的颜色来显示dib图像。
************************************************************************/
bool CdibImage::CreatedibPalette(Hdib hdib, CPalette* pPal)
{
LPLOGPALETTE lpPal; // 指向逻辑调色板的指针
handle hLogPal; // 逻辑调色板的句柄
HPALETTE hPal = NULL; // 调色板的句柄
int i; // 循环变量
WORD wNumColors; // 颜色表中的颜色数目
LPSTR lpbi; // 指向dib的指针
LPBITMAPINFO lpbmi; // 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREINFO lpbmc; // 指向BITMAPCOREINFO结构的指针
bool bWinStyledib; // 表明是否是Win3.0 dib的标记
bool bResult = FALSE; // 创建结果
if (hdib == NULL)
{
return FALSE;
}
lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hdib); // 锁定dib
lpbmi = (LPBITMAPINFO)lpbi; // 获取指向BITMAPINFO结构的指针(Win3.0)
lpbmc = (LPBITMAPCOREINFO)lpbi; // 获取指向BITMAPCOREINFO结构的指针
wNumColors = dibNumColors(lpbi);// 获取dib中颜色表中的颜色数目
if (wNumColors != 0)
{
// 分配为逻辑调色板内存
hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
+ sizeof(PALETTEENTRY)
* wNumColors);
// 如果内存不足,退出
if (hLogPal == 0)
{
::GlobalUnlock((HGLOBAL) hdib); // 解除锁定
return FALSE;
}
lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
lpPal->palVersion = PALVERSION; // 设置版本号
lpPal->palNumEntries = (WORD)wNumColors;// 设置颜色数目
bWinStyledib = IS_WIN30_dib(lpbi); // 判断是否是WIN3.0的dib
// 读取调色板
for (i = 0; i < (int)wNumColors; i++)
{
if (bWinStyledib)
{
// 读取红色绿色蓝色分量
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
// 保留位
lpPal->palPalEntry[i].peFlags = 0;
}
else
{
// 读取红色绿色蓝色分量
lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
// 保留位
lpPal->palPalEntry[i].peFlags = 0;
}
}
bResult = pPal->CreatePalette(lpPal);// 按照逻辑调色板创建调色板,并返回指针
::GlobalUnlock((HGLOBAL) hLogPal); // 解除锁定
::GlobalFree((HGLOBAL) hLogPal); // 释放逻辑调色板
}
::GlobalUnlock((HGLOBAL) hdib); // 解除锁定
return bResult;
}
/*************************************************************************
* 函数名称:
* FinddibBits()
* 参数:
* LPSTR lpbi - 指向dib对象的指针
* 返回值:
* LPSTR - 指向dib图像象素起始位置
* 说明:
* 该函数计算dib中图像象素的起始位置,并返回指向它的指针。
************************************************************************/
LPSTR CdibImage::FinddibBits(LPSTR lpbi)
{
return (lpbi + *(LPdword)lpbi + PaletteSize(lpbi));
}
/*************************************************************************
* 函数名称:
* dibWidth()
* 参数:
* LPSTR lpbi - 指向dib对象的指针
* 返回值:
* dword - dib中图像的宽度
* 说明:
* 该函数返回dib中图像的宽度。对于Windows 3.0 dib,返回BITMAPINFOHEADER
* 中的biWidth值;对于其它返回BITMAPCOREHEADER中的bcWidth值。
************************************************************************/
dword CdibImage::dibWidth(LPSTR lpdib)
{
LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针
lpbmi = (LPBITMAPINFOHEADER)lpdib;
lpbmc = (LPBITMAPCOREHEADER)lpdib;
// 返回dib中图像的宽度
if (IS_WIN30_dib(lpdib))
{
return lpbmi->biWidth; // 对于Windows 3.0 dib,返回lpbmi->biWidth
}
else
{
return (dword)lpbmc->bcWidth; // 对于其它格式的dib,返回lpbmc->bcWidth
}
}
/*************************************************************************
* 函数名称:
* dibHeight()
* 参数:
* LPSTR lpdib - 指向dib对象的指针
* 返回值:
* dword - dib中图像的高度
* 说明:
* 该函数返回dib中图像的高度。对于Windows 3.0 dib,返回BITMAPINFOHEADER
* 中的biHeight值;对于其它返回BITMAPCOREHEADER中的bcHeight值。
************************************************************************/
dword CdibImage::dibHeight(LPSTR lpdib)
{
LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针
lpbmi = (LPBITMAPINFOHEADER)lpdib;
lpbmc = (LPBITMAPCOREHEADER)lpdib;
// 返回dib中图像的宽度
if (IS_WIN30_dib(lpdib))
{
return lpbmi->biHeight; // 对于Windows 3.0 dib,返回lpbmi->biHeight
}
else
{
return (dword)lpbmc->bcHeight; // 对于其它格式的dib,返回lpbmc->bcHeight
}
}
/*************************************************************************
* 函数名称:
* PaletteSize()
* 参数:
* LPSTR lpbi - 指向dib对象的指针
* 返回值:
* WORD - dib中调色板的大小
* 说明:
* 该函数返回dib中调色板的大小。对于Windows 3.0 dib,返回颜色数目×
* RGBQUAD的大小;对于其它返回颜色数目×RGBTRIPLE的大小。
************************************************************************/
WORD CdibImage::PaletteSize(LPSTR lpbi)
{
// 计算dib中调色板的大小
if (IS_WIN30_dib (lpbi))
{
//返回颜色数目×RGBQUAD的大小
return (WORD)(dibNumColors(lpbi) * sizeof(RGBQUAD));
}
else
{
//返回颜色数目×RGBTRIPLE的大小
return (WORD)(dibNumColors(lpbi) * sizeof(RGBTRIPLE));
}
}
/*************************************************************************
* 函数名称:
* dibNumColors()
* 参数:
* LPSTR lpbi - 指向dib对象的指针
* 返回值:
* WORD - 返回调色板中颜色的种数
* 说明:
* 该函数返回dib中调色板的颜色的种数。对于单色位图,返回2,
* 对于16色位图,返回16,对于256色位图,返回256;对于真彩色
* 位图(24位),没有调色板,返回0。
************************************************************************/
WORD CdibImage::dibNumColors(LPSTR lpbi)
{
WORD wBitCount;
// 对于Windows的dib, 实际颜色的数目可以比象素的位数要少。
// 对于这种情况,则返回一个近似的数值。
// 判断是否是WIN3.0 dib
if (IS_WIN30_dib(lpbi))
{
dword dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; // 读取dwClrUsed值
if (dwClrUsed != 0)
{
// 如果dwClrUsed(实际用到的颜色数)不为0,直接返回该值
return (WORD)dwClrUsed;
}
}
// 读取象素的位数
if (IS_WIN30_dib(lpbi))
{
wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; // 读取biBitCount值
}
else
{
wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; // 读取biBitCount值
}
// 按照象素的位数计算颜色数目
switch (wBitCount)
{
case 1:
return 2;
break;
case 4:
return 16;
break;
case 8:
return 256;
break;
default:
return 0;
break;
}
}
/*************************************************************************
* 函数名称:
* Copyhandle()
* 参数:
* HGLOBAL h - 要复制的内存区域
* 返回值:
* HGLOBAL - 复制后的新内存区域
* 说明:
* 该函数复制指定的内存区域。返回复制后的新内存区域,出错时返回0。
************************************************************************/
HGLOBAL CDibImage::Copyhandle (HGLOBAL h)
{
if (h == NULL)
{
return NULL;
}
dword dwLen = ::GlobalSize((HGLOBAL) h); // 获取指定内存区域大小
HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); // 分配新内存空间
if (hCopy != NULL) // 判断分配是否成功
{
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
void* lp = ::GlobalLock((HGLOBAL) h);
memcpy(lpCopy, lp, dwLen);
::GlobalUnlock(hCopy);
::GlobalUnlock(h);
}
return hCopy;
}
/*************************************************************************
* 函数名称:
* SaveDIB()
* 参数:
* HDIB hDib - 要保存的DIB
* CFile& file - 保存文件CFile
* 返回值:
* bool - 成功返回TRUE,否则返回FALSE或者CFileException
* 说明:
* 该函数将指定的DIB对象保存到指定的CFile中。该CFile由调用程序打开和关闭。
*************************************************************************/
bool CDibImage::SaveDIB(HDIB hDib, CFile& file)
{
BITMAPFILEHEADER bmfHdr; // Bitmap文件头
LPBITMAPINFOHEADER lpBI; // 指向BITMAPINFOHEADER的指针
dword dwDIBSize; // DIB大小
if (hDib == NULL)
{
return FALSE;
}
// 读取BITMAPINFO结构,并锁定
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if (lpBI == NULL)
{
return FALSE;
}
// 判断是否是WIN3.0 DIB
if (!IS_WIN30_DIB(lpBI))
{
// 不支持其它类型的DIB保存
::GlobalUnlock((HGLOBAL) hDib);
return FALSE;
}
////////////////////////////////////////////////////////////////////////
// 填充文件头///////////////////////////////////////////////////////////
bmfHdr.bfType = DIB_HEADER_MARKER; // 文件类型"BM"
// 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并
// 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小。
// 文件头大小+颜色表大小
// (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个dword都是该结构的大小)
dwDIBSize = *(LPdword)lpBI + PaletteSize((LPSTR)lpBI);
// 计算图像大小
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
{
// 对于RLE位图,没法计算大小,只能信任biSizeImage内的值
dwDIBSize += lpBI->biSizeImage;
}
else
{
dword dwBmBitsSize; // 象素的大小
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((dword)lpBI->biBitCount))
* lpBI->biHeight; // 大小为Width * Height
dwDIBSize += dwBmBitsSize; // 计算出DIB真正的大小
// 更新biSizeImage(很多bmp文件头中biSizeImage的值是错误的)
lpBI->biSizeImage = dwBmBitsSize;
}
// 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
// 两个保留字
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
// 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小
bmfHdr.bfOffBits = (dword)sizeof(BITMAPFILEHEADER) + lpBI->biSize
+ PaletteSize((LPSTR)lpBI);
/////////////////////////////////////////////////////////////////////////
// 尝试写文件////////////////////////////////////////////////////////////
TRY
{
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); // 写文件头
file.WriteHuge(lpBI, dwDIBSize); // 写DIB头和象素
}
catch (CFileException, e)
{
::GlobalUnlock((HGLOBAL) hDib);
THROW_LAST();
}
END_catch
::GlobalUnlock((HGLOBAL) hDib);
return TRUE;
}
/*************************************************************************
* 函数名称:
* ReadDIBFile()
* 参数:
* CFile& file - 要读取得文件文件CFile
* 返回值:
* HDIB - 成功返回DIB的句柄,否则返回NULL。
* 说明:
* 该函数将指定的文件中的DIB对象读到指定的内存区域中。除BITMAPFILEHEADER
* 外的内容都将被读入内存。
*************************************************************************/
HDIB CDibImage::ReadDIBFile(CFile& file)
{
BITMAPFILEHEADER bmfHeader;
HDIB hDIB;
LPSTR pDIB;
dword dwBitsSize;
dwBitsSize = file.GetLength(); // 获取DIB(文件)长度(字节)
// 尝试读取DIB文件头
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
{
return NULL;
}
// 判断是否是DIB对象,检查头两个字节是否是"BM"
if (bmfHeader.bfType != DIB_HEADER_MARKER)
{
return NULL;
}
// 为DIB分配内存
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
if (hDIB == 0)
{
return NULL;
}
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
dwBitsSize - sizeof(BITMAPFILEHEADER) ) // 读象素
{
::GlobalUnlock((HGLOBAL) hDIB);
::GlobalFree((HGLOBAL) hDIB);
return NULL;
}
::GlobalUnlock((HGLOBAL) hDIB);
return hDIB;
}
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询