图像算法:数字图像处理程序大全
SkySeraph Apr 22nd 2011 HQU
Email:zgzhaobo@gmail.com QQ:452728574
Latest Modified Date:Apr 22nd 2011 HQU
说明:几乎包括所有常用的图像处理算法,发于博客,以备查询之用...
Dib头文件
class CDibImage
{
// Constructor and Destructor ///
public:
CDibImage();
virtual ~CDibImage();
// function /
public:
// DIB(Independent Bitmap) 函数
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);
// 图像点运算函数
BOOL LinerTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, FLOAT fA, FLOAT fB);
BOOL ThresholdTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bThre);
BOOL WindowTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bLow, BYTE bUp);
BOOL GrayStretch(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bX1, BYTE bY1, BYTE bX2, BYTE bY2);
BOOL InteEqualize(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
// 图像几何变换函数
BOOL TranslationDIB1 (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, LONG lXOffset, LONG lYOffset);
BOOL TranslationDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, LONG lXOffset, LONG lYOffset);
BOOL MirrorDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bDirection);
BOOL TransposeDIB(LPSTR lpbi);
HGLOBAL ZoomDIB(LPSTR lpbi, float fXZoomRatio, float fYZoomRatio);
HGLOBAL RotateDIB(LPSTR lpbi, int iRotateAngle);
HGLOBAL RotateDIB2(LPSTR lpbi, int iRotateAngle);
unsigned char Interpolation (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, FLOAT x, FLOAT y);
// 图像正交变换函数
VOID FFT(complex<double> * TD, complex<double> * FD, int r);
VOID IFFT(complex<double> * FD, complex<double> * TD, int r);
VOID DCT(double *f, double *F, int power);
VOID IDCT(double *F, double *f, int power);
VOID WALSH(double *f, double *F, int r);
VOID IWALSH(double *F, double *f, int r);
BOOL Fourier(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL DIBDct(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL DIBWalsh(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL DIBWalsh1(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
// 图像模板变换函数
BOOL Template(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int iTempH, int iTempW, int iTempMX, int iTempMY, FLOAT * fpArray, FLOAT fCoef);
BOOL MedianFilter(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int iFilterH, int iFilterW, int iFilterMX, int iFilterMY);
unsigned char GetMedianNum(unsigned char * bArray, int iFilterLen);
BOOL GradSharp(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bThre);
BOOL ReplaceColorPal(LPSTR lpDIB, BYTE * bpColorsTable);
// 图像形态学变换函数
BOOL ErosionDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bHori , int structure[3][3]);
BOOL DilationDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bHori , int structure[3][3]);
BOOL OpenDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bHori , int structure[3][3]);
BOOL CloseDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bHori , int structure[3][3]);
BOOL ThiningDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
// 图像边缘与轮廓运算函数
BOOL RobertDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL SobelDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL PrewittDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL KirschDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL GaussDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL HoughDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL FillDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL Fill2DIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL ContourDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL TraceDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
};
Dib类/实现
CDibImage::CDibImage()
{
}
CDibImage::~CDibImage()
{
}
//
// DIB(Independent Bitmap) 函数
//
/*************************************************************************
* 函数名称:
* 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))
{
DWORD
c;
c=lpbmi->biWidth;
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;
}
//
// 图像点运算函数
//
/*************************************************************************
* 函数名称:
* LinerTrans()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* FLOAT fA - 线性变换的斜率
* FLOAT fB - 线性变换的截距
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来对图像进行灰度的线性变换操作。
************************************************************************/
BOOL
CDibImage::LinerTrans(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
FLOAT
fA,
FLOAT
fB)
{
unsigned
char
* lpSrc;
// 指向源图像的指针
LONG
i;
// 循环变量
LONG
j;
LONG
lLineBytes;
// 图像每行的字节数
FLOAT
fTemp;
// 中间变量
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
for
(i = 0; i < lHeight; i++)
// 每行
{
for
(j = 0; j < lWidth; j++)
// 每列
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
fTemp = fA * (*lpSrc) + fB;
// 线性变换
if
(fTemp > 255)
// 判断是否超出范围
{
*lpSrc = 255;
}
else
if
(fTemp < 0)
{
*lpSrc = 0;
}
else
{
*lpSrc = (unsigned
char
) (fTemp + 0.5);
// 四舍五入
}
}
}
return
TRUE;
}
/*************************************************************************
* 函数名称:
* ThresholdTrans()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* BYTE bThre - 阈值
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来对图像进行阈值变换。对于灰度值小于阈值的象素直接设置
* 灰度值为0;灰度值大于阈值的象素直接设置为255。
************************************************************************/
BOOL
CDibImage::ThresholdTrans(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
BYTE
bThre)
{
unsigned
char
* lpSrc;
// 指向源图像的指针
LONG
i;
// 循环变量
LONG
j;
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
for
(i = 0; i < lHeight; i++)
// 每行
{
for
(j = 0; j < lWidth; j++)
// 每列
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
if
((*lpSrc) < bThre)
// 判断是否小于阈值
{
*lpSrc = 0;
}
else
{
*lpSrc = 255;
}
}
}
return
TRUE;
}
/*************************************************************************
* 函数名称:
* WindowTrans()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* BYTE bLow - 窗口下限
* BYTE bUp - 窗口上限
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来对图像进行窗口变换。只有在窗口范围内的灰度保持不变,
* 小于下限的象素直接设置灰度值为0;大于上限的象素直接设置灰度值为255。
************************************************************************/
BOOL
CDibImage::WindowTrans(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
BYTE
bLow,
BYTE
bUp)
{
unsigned
char
* lpSrc;
// 指向源图像的指针
LONG
i;
// 循环变量
LONG
j;
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
for
(i = 0; i < lHeight; i++)
// 每行
{
for
(j = 0; j < lWidth; j++)
// 每列
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
if
((*lpSrc) < bLow)
// 判断是否超出范围
{
*lpSrc = 0;
}
else
if
((*lpSrc) > bUp)
{
*lpSrc = 255;
}
}
}
return
TRUE;
}
/*************************************************************************
* 函数名称:
* GrayStretch()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* BYTE bX1 - 灰度拉伸第一个点的X坐标
* BYTE bY1 - 灰度拉伸第一个点的Y坐标
* BYTE bX2 - 灰度拉伸第二个点的X坐标
* BYTE bY2 - 灰度拉伸第二个点的Y坐标
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来对图像进行灰度拉伸。
************************************************************************/
BOOL
CDibImage::GrayStretch(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
BYTE
bX1,
BYTE
bY1,
BYTE
bX2,
BYTE
bY2)
{
unsigned
char
* lpSrc;
// 指向源图像的指针
LONG
i;
// 循环变量
LONG
j;
BYTE
bMap[256];
// 灰度映射表
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
// 计算灰度映射表
for
(i = 0; i <= bX1; i++)
{
if
(bX1 > 0)
// 判断bX1是否大于0(防止分母为0)
{
bMap[i] = (
BYTE
) bY1 * i / bX1;
}
else
{
bMap[i] = 0;
}
}
for
(; i <= bX2; i++)
{
if
(bX2 != bX1)
// 判断bX1是否等于bX2(防止分母为0)
{
bMap[i] = bY1 + (
BYTE
) ((bY2 - bY1) * (i - bX1) / (bX2 - bX1));
}
else
{
bMap[i] = bY1;
}
}
for
(; i < 256; i++)
{
if
(bX2 != 255)
// 判断bX2是否等于255(防止分母为0)
{
bMap[i] = bY2 + (
BYTE
) ((255 - bY2) * (i - bX2) / (255 - bX2));
}
else
{
bMap[i] = 255;
}
}
for
(i = 0; i < lHeight; i++)
// 每行
{
for
(j = 0; j < lWidth; j++)
// 每列
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 计算新的灰度值
*lpSrc = bMap[*lpSrc];
}
}
return
TRUE;
}
/*************************************************************************
* 函数名称:
* InteEqualize()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来对图像进行直方图均衡。
************************************************************************/
BOOL
CDibImage::InteEqualize(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
unsigned
char
* lpSrc;
// 指向源图像的指针
LONG
lTemp;
// 临时变量
LONG
i;
// 循环变量
LONG
j;
BYTE
bMap[256];
// 灰度映射表
LONG
lCount[256];
// 灰度映射表
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
for
(i = 0; i < 256; i ++)
// 重置计数为0
{
lCount[i] = 0;
}
// 计算各个灰度值的计数
for
(i = 0; i < lHeight; i ++)
{
for
(j = 0; j < lWidth; j ++)
{
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * i + j;
lCount[*(lpSrc)]++;
}
}
// 计算灰度映射表
for
(i = 0; i < 256; i++)
{
lTemp = 0;
for
(j = 0; j <= i ; j++)
{
lTemp += lCount[j];
}
// 计算对应的新灰度值
bMap[i] = (
BYTE
) (lTemp * 255 / lHeight / lWidth);
}
for
(i = 0; i < lHeight; i++)
// 每行
{
for
(j = 0; j < lWidth; j++)
// 每列
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 计算新的灰度值
*lpSrc = bMap[*lpSrc];
}
}
return
TRUE;
}
//
// 图像几何变换函数
//
/*************************************************************************
* 函数名称:
* TranslationDIB1()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* LONG lXOffset - X轴平移量(象素数)
* LONG lYOffset - Y轴平移量(象素数)
* 返回值:
* BOOL - 平移成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来水平移动DIB图像。函数不会改变图像的大小,移出的部分图像
* 将截去,空白部分用白色填充。
************************************************************************/
BOOL
CDibImage::TranslationDIB1(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
LONG
lXOffset,
LONG
lYOffset)
{
LPSTR
lpSrc;
// 指向源图像的指针
LPSTR
lpDst;
// 指向要复制区域的指针
LPSTR
lpNewDIBBits;
// 指向复制图像的指针
HLOCAL
hNewDIBBits;
LONG
i;
// 象素在新DIB中的坐标
LONG
j;
LONG
i0;
// 象素在源DIB中的坐标
LONG
j0;
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
for
(i = 0; i < lHeight; i++)
// 每行
{
for
(j = 0; j < lWidth; j++)
// 每列
{
// 指向新DIB第i行,第j个象素的指针
// 注意由于DIB中图像第一行其实保存在最后一行的位置,因此lpDst
// 值不是(char *)lpNewDIBBits + lLineBytes * i + j,而是
// (char *)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j
lpDst = (
char
*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 计算该象素在源DIB中的坐标
i0 = i - lXOffset;
j0 = j - lYOffset;
// 判断是否在源图范围内
if
( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
{
// 指向源DIB第i0行,第j0个象素的指针
// 同样要注意DIB上下倒置的问题
lpSrc = (
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0;
*lpDst = *lpSrc;
// 复制象素
}
else
{
// 对于源图中没有的象素,直接赋值为255
* ((unsigned
char
*)lpDst) = 255;
}
}
}
// 复制平移后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* TranslationDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* LONG lXOffset - X轴平移量(象素数)
* LONG lYOffset - Y轴平移量(象素数)
* 返回值:
* BOOL - 平移成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来水平移动DIB图像。函数不会改变图像的大小,移出的部分图像
* 将截去,空白部分用白色填充。
************************************************************************/
BOOL
CDibImage::TranslationDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
LONG
lXOffset,
LONG
lYOffset)
{
CRect rectSrc;
// 平移后剩余图像在源图像中的位置(矩形区域)
CRect rectDst;
// 平移后剩余图像在新图像中的位置(矩形区域)
LPSTR
lpSrc;
// 指向源图像的指针
LPSTR
lpDst;
// 指向要复制区域的指针
LPSTR
lpNewDIBBits;
// 指向复制图像的指针
HLOCAL
hNewDIBBits;
BOOL
bVisible;
// 指明图像是否全部移去可视区间
LONG
i;
// 循环变量
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
bVisible = TRUE;
// 赋初值
// 计算rectSrc和rectDst的X坐标
if
(lXOffset <= -lWidth)
{
bVisible = FALSE;
// X轴方向全部移出可视区域
}
else
if
(lXOffset <= 0)
{
rectDst.left = 0;
// 移动后,有图区域左上角X坐标为0
// 移动后,有图区域右下角X坐标为lWidth - |lXOffset| = lWidth + lXOffset
rectDst.right = lWidth + lXOffset;
}
else
if
(lXOffset < lWidth)
{
rectDst.left = lXOffset;
// 移动后,有图区域左上角X坐标为lXOffset
rectDst.right = lWidth;
// 移动后,有图区域右下角X坐标为lWidth
}
else
{
bVisible = FALSE;
// X轴方向全部移出可视区域
}
// 平移后剩余图像在源图像中的X坐标
rectSrc.left = rectDst.left - lXOffset;
rectSrc.right = rectDst.right - lXOffset;
// 计算rectSrc和rectDst的Y坐标
if
(lYOffset <= -lHeight)
{
bVisible = FALSE;
// Y轴方向全部移出可视区域
}
else
if
(lYOffset <= 0)
{
rectDst.top = 0;
// 移动后,有图区域左上角Y坐标为0
// 移动后,有图区域右下角Y坐标为lHeight - |lYOffset| = lHeight + lYOffset
rectDst.bottom = lHeight + lYOffset;
}
else
if
(lYOffset < lHeight)
{
rectDst.top = lYOffset;
// 移动后,有图区域左上角Y坐标为lYOffset
rectDst.bottom = lHeight;
// 移动后,有图区域右下角Y坐标为lHeight
}
else
{
bVisible = FALSE;
// X轴方向全部移出可视区域
}
// 平移后剩余图像在源图像中的Y坐标
rectSrc.top = rectDst.top - lYOffset;
rectSrc.bottom = rectDst.bottom - lYOffset;
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (
char
*)lpNewDIBBits;
memset
(lpDst, (
BYTE
)255, lLineBytes * lHeight);
if
(bVisible)
// 如果有部分图像可见
{
// 平移图像
for
(i = 0; i < (rectSrc.bottom - rectSrc.top); i++)
{
// 要复制区域的起点,注意由于DIB图像内容是上下倒置的,第一行内容是保存
// 在最后一行,因此复制区域的起点不是lpDIBBits + lLineBytes * (i +
// rectSrc.top) + rectSrc.left,而是 lpDIBBits + lLineBytes *
// (lHeight - i - rectSrc.top - 1) + rectSrc.left。
lpSrc = (
char
*)lpDIBBits + lLineBytes * (lHeight - i - rectSrc.top
- 1) + rectSrc.left;
// 要目标区域的起点,同样注意上下倒置的问题。
lpDst = (
char
*)lpNewDIBBits + lLineBytes * (lHeight - i - rectDst.top
- 1) + rectDst.left;
// 拷贝每一行,宽度为rectSrc.right - rectSrc.left
memcpy
(lpDst, lpSrc, rectSrc.right - rectSrc.left);
}
}
// 复制平移后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* MirrorDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* BOOL bDirection - 镜像的方向,TRUE表示水平镜像,FALSE表示垂直镜像
* 返回值:
* BOOL - 镜像成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来镜像DIB图像。可以指定镜像的方式是水平还是垂直。
************************************************************************/
BOOL
CDibImage::MirrorDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
BOOL
bDirection)
{
LPSTR
lpSrc;
// 指向源图像的指针
LPSTR
lpDst;
// 指向要复制区域的指针
LPSTR
lpBits;
// 指向复制图像的指针
HLOCAL
hBits;
LONG
i;
// 循环变量
LONG
j;
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
hBits = LocalAlloc(LHND, lLineBytes);
// 暂时分配内存,以保存一行图像
if
(hBits == NULL)
{
return
FALSE;
}
lpBits = (
char
* )LocalLock(hBits);
// 判断镜像方式
if
(bDirection)
// 水平镜像
{
// 针对图像每行进行操作
for
(i = 0; i < lHeight; i++)
{
// 针对每行图像左半部分进行操作
for
(j = 0; j < lWidth / 2; j++)
{
// 指向倒数第i行,第j个象素的指针
lpSrc = (
char
*)lpDIBBits + lLineBytes * i + j;
// 指向倒数第i行,倒数第j个象素的指针
lpDst = (
char
*)lpDIBBits + lLineBytes * (i + 1) - j;
// 备份一个象素
*lpBits = *lpDst;
// 将倒数第i行,第j个象素复制到倒数第i行,倒数第j个象素
*lpDst = *lpSrc;
// 将倒数第i行,倒数第j个象素复制到倒数第i行,第j个象素
*lpSrc = *lpBits;
}
}
}
else
// 垂直镜像
{
// 针对上半图像进行操作
for
(i = 0; i < lHeight / 2; i++)
{
// 指向倒数第i行象素起点的指针
lpSrc = (
char
*)lpDIBBits + lLineBytes * i;
// 指向第i行象素起点的指针
lpDst = (
char
*)lpDIBBits + lLineBytes * (lHeight - i - 1);
// 备份一行,宽度为lWidth
memcpy
(lpBits, lpDst, lLineBytes);
// 将倒数第i行象素复制到第i行
memcpy
(lpDst, lpSrc, lLineBytes);
// 将第i行象素复制到倒数第i行
memcpy
(lpSrc, lpBits, lLineBytes);
}
}
LocalUnlock(hBits);
LocalFree(hBits);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* TransposeDIB()
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* 返回值:
* BOOL - 转置成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来转置DIB图像,即图像x、y坐标互换。函数将不会改变图像的大小,
* 但是图像的高宽将互换。
************************************************************************/
BOOL
CDibImage::TransposeDIB(
LPSTR
lpDIB)
{
LONG
lWidth;
// 图像的宽度
LONG
lHeight;
// 图像的高度
LPSTR
lpDIBBits;
// 指向源图像的指针
LPSTR
lpSrc;
// 指向源象素的指针
LPSTR
lpDst;
// 指向转置图像对应象素的指针
LPSTR
lpNewDIBBits;
// 指向转置图像的指针
HLOCAL
hNewDIBBits;
LPBITMAPINFOHEADER lpbmi;
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc;
// 指向BITMAPCOREINFO结构的指针
LONG
i;
LONG
j;
LONG
lLineBytes;
// 图像每行的字节数
LONG
lNewLineBytes;
// 新图像每行的字节数
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
lpDIBBits = FindDIBBits(lpDIB);
// 找到源DIB图像象素起始位置
lWidth = DIBWidth(lpDIB);
// 获取图像的"宽度"(4的倍数)
lHeight = DIBHeight(lpDIB);
// 获取图像的高度
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
lNewLineBytes = WIDTHBYTES(lHeight * 8);
// 计算新图像每行的字节数
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lNewLineBytes);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
for
(i = 0; i < lHeight; i++)
// 针对图像每行进行操作
{
for
(j = 0; j < lWidth; j++)
// 针对每行图像每列进行操作
{
// 指向源DIB第i行,第j个象素的指针
lpSrc = (
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 指向转置DIB第j行,第i个象素的指针
// 注意此处lWidth和lHeight是源DIB的宽度和高度,应该互换
lpDst = (
char
*)lpNewDIBBits + lNewLineBytes * (lWidth - 1 - j) + i;
// 复制象素
*lpDst = *lpSrc;
}
}
// 复制转置后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lWidth * lNewLineBytes);
// 互换DIB中图像的高宽
if
(IS_WIN30_DIB(lpDIB))
{
// 对于Windows 3.0 DIB
lpbmi->biWidth = lHeight;
lpbmi->biHeight = lWidth;
}
else
{
// 对于其它格式的DIB
lpbmc->bcWidth = (unsigned
short
) lHeight;
lpbmc->bcHeight = (unsigned
short
) lWidth;
}
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* ZoomDIB()
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* float fXZoomRatio - X轴方向缩放比率
* float fYZoomRatio - Y轴方向缩放比率
* 返回值:
* HGLOBAL - 缩放成功返回新DIB句柄,否则返回NULL。
* 说明:
* 该函数用来缩放DIB图像,返回新生成DIB的句柄。
************************************************************************/
HGLOBAL
CDibImage::ZoomDIB(
LPSTR
lpDIB,
float
fXZoomRatio,
float
fYZoomRatio)
{
LONG
lWidth;
// 源图像的宽度
LONG
lHeight;
// 源图像的高度
LONG
lNewWidth;
// 缩放后图像的宽度
LONG
lNewHeight;
// 缩放后图像的高度
LONG
lNewLineBytes;
// 缩放后图像的宽度(lNewWidth',必须是4的倍数)
LPSTR
lpDIBBits;
// 指向源图像的指针
LPSTR
lpSrc;
// 指向源象素的指针
HDIB hDIB;
// 缩放后新DIB句柄
LPSTR
lpDst;
// 指向缩放图像对应象素的指针
LPSTR
lpNewDIB;
// 指向缩放图像的指针
LPSTR
lpNewDIBBits;
LPBITMAPINFOHEADER lpbmi;
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc;
// 指向BITMAPCOREINFO结构的指针
LONG
i;
// 循环变量(象素在新DIB中的坐标)
LONG
j;
LONG
i0;
// 象素在源DIB中的坐标
LONG
j0;
LONG
lLineBytes;
// 图像每行的字节数
lpDIBBits = FindDIBBits(lpDIB);
// 找到源DIB图像象素起始位置
lWidth = DIBWidth(lpDIB);
// 获取图像的宽度
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
lHeight = DIBHeight(lpDIB);
// 获取图像的高度
// 计算缩放后的图像实际宽度
// 此处直接加0.5是由于强制类型转换时不四舍五入,而是直接截去小数部分
lNewWidth = (
LONG
) (DIBWidth(lpDIB) * fXZoomRatio + 0.5);
// 计算新图像每行的字节数
lNewLineBytes = WIDTHBYTES(lNewWidth * 8);
// 计算缩放后的图像高度
lNewHeight = (
LONG
) (lHeight * fYZoomRatio + 0.5);
// 分配内存,以保存新DIB
hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight +
*(
LPDWORD
)lpDIB + PaletteSize(lpDIB));
if
(hDIB == NULL)
{
return
NULL;
}
lpNewDIB = (
char
* )::GlobalLock((
HGLOBAL
) hDIB);
// 复制DIB信息头和调色板
memcpy
(lpNewDIB, lpDIB, *(
LPDWORD
)lpDIB + PaletteSize(lpDIB));
// 找到新DIB象素起始位置
lpNewDIBBits = FindDIBBits(lpNewDIB);
lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;
lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;
// 更新DIB中图像的高度和宽度
if
(IS_WIN30_DIB(lpNewDIB))
{
// 对于Windows 3.0 DIB
lpbmi->biWidth = lNewWidth;
lpbmi->biHeight = lNewHeight;
}
else
{
// 对于其它格式的DIB
lpbmc->bcWidth = (unsigned
short
) lNewWidth;
lpbmc->bcHeight = (unsigned
short
) lNewHeight;
}
for
(i = 0; i < lNewHeight; i++)
// 针对图像每行进行操作
{
for
(j = 0; j < lNewWidth; j++)
// 针对图像每列进行操作
{
// 指向新DIB第i行,第j个象素的指针
// 注意此处宽度和高度是新DIB的宽度和高度
lpDst = (
char
*)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j;
// 计算该象素在源DIB中的坐标
i0 = (
LONG
) (i / fYZoomRatio + 0.5);
j0 = (
LONG
) (j / fXZoomRatio + 0.5);
// 判断是否在源图范围内
if
( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
{
// 指向源DIB第i0行,第j0个象素的指针
lpSrc = (
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0;
// 复制象素
*lpDst = *lpSrc;
}
else
{
// 对于源图中没有的象素,直接赋值为255
* ((unsigned
char
*)lpDst) = 255;
}
}
}
return
hDIB;
}
/*************************************************************************
* 函数名称:
* RotateDIB()
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* int iRotateAngle - 旋转的角度(0-360度)
* 返回值:
* HGLOBAL - 旋转成功返回新DIB句柄,否则返回NULL。
* 说明:
* 该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。
* 调用该函数会自动扩大图像以显示所有的象素。函数中采用最邻近插
* 值算法进行插值。
************************************************************************/
HGLOBAL
CDibImage::RotateDIB(
LPSTR
lpDIB,
int
iRotateAngle)
{
LONG
lWidth;
// 源图像的宽度
LONG
lHeight;
// 源图像的高度
LONG
lNewWidth;
// 旋转后图像的宽度
LONG
lNewHeight;
// 旋转后图像的高度
LONG
lLineBytes;
// 图像每行的字节数
LONG
lNewLineBytes;
// 旋转后图像的宽度(lNewWidth',必须是4的倍数)
LPSTR
lpDIBBits;
// 指向源图像的指针
LPSTR
lpSrc;
// 指向源象素的指针
HDIB hDIB;
// 旋转后新DIB句柄
LPSTR
lpDst;
// 指向旋转图像对应象素的指针
LPSTR
lpNewDIB;
// 指向旋转图像的指针
LPSTR
lpNewDIBBits;
LPBITMAPINFOHEADER lpbmi;
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc;
// 指向BITMAPCOREINFO结构的指针
LONG
i;
// 循环变量(象素在新DIB中的坐标)
LONG
j;
LONG
i0;
// 象素在源DIB中的坐标
LONG
j0;
float
fRotateAngle;
// 旋转角度(弧度)
float
fSina, fCosa;
// 旋转角度的正弦和余弦
// 源图四个角的坐标(以图像中心为坐标系原点)
float
fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
// 旋转后四个角的坐标(以图像中心为坐标系原点)
float
fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
float
f1,f2;
lpDIBBits = FindDIBBits(lpDIB);
// 找到源DIB图像象素起始位置
lWidth = DIBWidth(lpDIB);
// 获取图像的"宽度"(4的倍数)
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
lHeight = DIBHeight(lpDIB);
// 获取图像的高度
// 将旋转角度从度转换到弧度
fRotateAngle = (
float
) RADIAN(iRotateAngle);
fSina = (
float
)
sin
((
double
)fRotateAngle);
// 计算旋转角度的正弦
fCosa = (
float
)
cos
((
double
)fRotateAngle);
// 计算旋转角度的余弦
// 计算原图的四个角的坐标(以图像中心为坐标系原点)
fSrcX1 = (
float
) (- (lWidth - 1) / 2);
fSrcY1 = (
float
) ( (lHeight - 1) / 2);
fSrcX2 = (
float
) ( (lWidth - 1) / 2);
fSrcY2 = (
float
) ( (lHeight - 1) / 2);
fSrcX3 = (
float
) (- (lWidth - 1) / 2);
fSrcY3 = (
float
) (- (lHeight - 1) / 2);
fSrcX4 = (
float
) ( (lWidth - 1) / 2);
fSrcY4 = (
float
) (- (lHeight - 1) / 2);
// 计算新图四个角的坐标(以图像中心为坐标系原点)
fDstX1 = fCosa * fSrcX1 + fSina * fSrcY1;
fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
fDstX2 = fCosa * fSrcX2 + fSina * fSrcY2;
fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
fDstX3 = fCosa * fSrcX3 + fSina * fSrcY3;
fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
fDstX4 = fCosa * fSrcX4 + fSina * fSrcY4;
fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;
// 计算旋转后的图像实际宽度
lNewWidth = (
LONG
)(max(
fabs
(fDstX4 - fDstX1),
fabs
(fDstX3 - fDstX2)) + 0.5);
// 计算新图像每行的字节数
lNewLineBytes = WIDTHBYTES(lNewWidth * 8);
// 计算旋转后的图像高度
lNewHeight = (
LONG
)(max(
fabs
(fDstY4 - fDstY1),
fabs
(fDstY3 - fDstY2)) + 0.5);
// 两个常数,这样不用以后每次都计算了
f1 = (
float
) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina
+ 0.5 * (lWidth - 1));
f2 = (
float
) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa
+ 0.5 * (lHeight - 1));
// 分配内存,以保存新DIB
hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight +
*(
LPDWORD
)lpDIB + PaletteSize(lpDIB));
if
(hDIB == NULL)
{
return
NULL;
}
lpNewDIB = (
char
* )::GlobalLock((
HGLOBAL
) hDIB);
// 复制DIB信息头和调色板
memcpy
(lpNewDIB, lpDIB, *(
LPDWORD
)lpDIB + PaletteSize(lpDIB));
// 找到新DIB象素起始位置
lpNewDIBBits = FindDIBBits(lpNewDIB);
lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;
lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;
// 更新DIB中图像的高度和宽度
if
(IS_WIN30_DIB(lpNewDIB))
{
// 对于Windows 3.0 DIB
lpbmi->biWidth = lNewWidth;
lpbmi->biHeight = lNewHeight;
}
else
{
// 对于其它格式的DIB
lpbmc->bcWidth = (unsigned
short
) lNewWidth;
lpbmc->bcHeight = (unsigned
short
) lNewHeight;
}
for
(i = 0; i < lNewHeight; i++)
// 针对图像每行进行操作
{
for
(j = 0; j < lNewWidth; j++)
// 针对图像每列进行操作
{
// 指向新DIB第i行,第j个象素的指针
// 注意此处宽度和高度是新DIB的宽度和高度
lpDst = (
char
*)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j;
// 计算该象素在源DIB中的坐标
i0 = (
LONG
) (-((
float
) j) * fSina + ((
float
) i) * fCosa + f2 + 0.5);
j0 = (
LONG
) ( ((
float
) j) * fCosa + ((
float
) i) * fSina + f1 + 0.5);
// 判断是否在源图范围内
if
( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
{
// 指向源DIB第i0行,第j0个象素的指针
lpSrc = (
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0;
// 复制象素
*lpDst = *lpSrc;
}
else
{
// 对于源图中没有的象素,直接赋值为255
* ((unsigned
char
*)lpDst) = 255;
}
}
}
return
hDIB;
}
/*************************************************************************
* 函数名称:
* RotateDIB2()
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* int iRotateAngle - 旋转的角度(0-360度)
* 返回值:
* HGLOBAL - 旋转成功返回新DIB句柄,否则返回NULL。
* 说明:
* 该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。
* 调用该函数会自动扩大图像以显示所有的象素。函数中采用双线性插
* 值算法进行插值。
************************************************************************/
HGLOBAL
CDibImage::RotateDIB2(
LPSTR
lpDIB,
int
iRotateAngle)
{
LONG
lWidth;
// 源图像的宽度
LONG
lHeight;
// 源图像的高度
LONG
lNewWidth;
// 旋转后图像的宽度
LONG
lNewHeight;
// 旋转后图像的高度
LONG
lNewLineBytes;
// 旋转后图像的宽度(lNewWidth',必须是4的倍数)
LPSTR
lpDIBBits;
// 指向源图像的指针
HDIB hDIB;
// 旋转后新DIB句柄
LPSTR
lpDst;
// 指向旋转图像对应象素的指针
LPSTR
lpNewDIB;
// 指向旋转图像的指针
LPSTR
lpNewDIBBits;
LPBITMAPINFOHEADER lpbmi;
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc;
// 指向BITMAPCOREINFO结构的指针
LONG
i;
// 循环变量(象素在新DIB中的坐标)
LONG
j;
FLOAT
i0;
// 象素在源DIB中的坐标
FLOAT
j0;
float
fRotateAngle;
// 旋转角度(弧度)
float
fSina, fCosa;
// 旋转角度的正弦和余弦
// 源图四个角的坐标(以图像中心为坐标系原点)
float
fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
// 旋转后四个角的坐标(以图像中心为坐标系原点)
float
fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
float
f1,f2;
lpDIBBits = FindDIBBits(lpDIB);
// 找到源DIB图像象素起始位置
lWidth = DIBWidth(lpDIB);
// 获取图像的宽度
lHeight = DIBHeight(lpDIB);
// 获取图像的高度
// 将旋转角度从度转换到弧度
fRotateAngle = (
float
) RADIAN(iRotateAngle);
fSina = (
float
)
sin
((
double
)fRotateAngle);
// 计算旋转角度的正弦
fCosa = (
float
)
cos
((
double
)fRotateAngle);
// 计算旋转角度的余弦
// 计算原图的四个角的坐标(以图像中心为坐标系原点)
fSrcX1 = (
float
) (- (lWidth - 1) / 2);
fSrcY1 = (
float
) ( (lHeight - 1) / 2);
fSrcX2 = (
float
) ( (lWidth - 1) / 2);
fSrcY2 = (
float
) ( (lHeight - 1) / 2);
fSrcX3 = (
float
) (- (lWidth - 1) / 2);
fSrcY3 = (
float
) (- (lHeight - 1) / 2);
fSrcX4 = (
float
) ( (lWidth - 1) / 2);
fSrcY4 = (
float
) (- (lHeight - 1) / 2);
// 计算新图四个角的坐标(以图像中心为坐标系原点)
fDstX1 = fCosa * fSrcX1 + fSina * fSrcY1;
fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
fDstX2 = fCosa * fSrcX2 + fSina * fSrcY2;
fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
fDstX3 = fCosa * fSrcX3 + fSina * fSrcY3;
fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
fDstX4 = fCosa * fSrcX4 + fSina * fSrcY4;
fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;
// 计算旋转后的图像实际宽度
lNewWidth = (
LONG
)(max(
fabs
(fDstX4 - fDstX1),
fabs
(fDstX3 - fDstX2)) + 0.5);
lNewLineBytes = WIDTHBYTES(lNewWidth * 8);
// 计算旋转后的图像高度
lNewHeight = (
LONG
)(max(
fabs
(fDstY4 - fDstY1),
fabs
(fDstY3 - fDstY2)) + 0.5);
f1 = (
float
) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina
+ 0.5 * (lWidth - 1));
f2 = (
float
) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa
+ 0.5 * (lHeight - 1));
// 分配内存,以保存新DIB
hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight +
*(
LPDWORD
)lpDIB + PaletteSize(lpDIB));
if
(hDIB == NULL)
{
return
NULL;
}
lpNewDIB = (
char
* )::GlobalLock((
HGLOBAL
) hDIB);
// 复制DIB信息头和调色板
memcpy
(lpNewDIB, lpDIB, *(
LPDWORD
)lpDIB + PaletteSize(lpDIB));
// 找到新DIB象素起始位置
lpNewDIBBits = FindDIBBits(lpNewDIB);
lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;
lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;
// 更新DIB中图像的高度和宽度
if
(IS_WIN30_DIB(lpNewDIB))
{
// 对于Windows 3.0 DIB
lpbmi->biWidth = lNewWidth;
lpbmi->biHeight = lNewHeight;
}
else
{
// 对于其它格式的DIB
lpbmc->bcWidth = (unsigned
short
) lNewWidth;
lpbmc->bcHeight = (unsigned
short
) lNewHeight;
}
for
(i = 0; i < lNewHeight; i++)
// 针对图像每行进行操作
{
for
(j = 0; j < lNewWidth; j++)
// 针对图像每列进行操作
{
// 指向新DIB第i行,第j个象素的指针
// 注意此处宽度和高度是新DIB的宽度和高度
lpDst = (
char
*)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j;
// 计算该象素在源DIB中的坐标
i0 = -((
float
) j) * fSina + ((
float
) i) * fCosa + f2;
j0 = ((
float
) j) * fCosa + ((
float
) i) * fSina + f1;
// 利用双线性插值算法来估算象素值
*lpDst = Interpolation (lpDIBBits, lWidth, lHeight, j0, i0);
}
}
return
hDIB;
}
/*************************************************************************
* 函数名称:
* Interpolation()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* FLOAT x - 插值元素的x坐标
* FLOAT y - 插值元素的y坐标
* 返回值:
* unsigned char - 返回插值计算结果。
* 说明:
* 该函数利用双线性插值算法来估算象素值。对于超出图像范围的象素,
* 直接返回255。
************************************************************************/
unsigned
char
CDibImage::Interpolation (
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
FLOAT
x,
FLOAT
y)
{
// 四个最临近象素的坐标(i1, j1), (i2, j1), (i1, j2), (i2, j2)
LONG
i1, i2;
LONG
j1, j2;
unsigned
char
f1, f2, f3, f4;
// 四个最临近象素值
unsigned
char
f12, f34;
// 二个插值中间值
// 定义一个值,当象素坐标相差小于改值时认为坐标相同
FLOAT
EXP;
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
EXP = (
FLOAT
) 0.0001;
// 计算四个最临近象素的坐标
i1 = (
LONG
) x;
i2 = i1 + 1;
j1 = (
LONG
) y;
j2 = j1 + 1;
// 根据不同情况分别处理
if
( (x < 0) || (x > lWidth - 1) || (y < 0) || (y > lHeight - 1))
{
return
255;
// 要计算的点不在源图范围内,直接返回255。
}
else
{
if
(
fabs
(x - lWidth + 1) <= EXP)
{
// 要计算的点在图像右边缘上
if
(
fabs
(y - lHeight + 1) <= EXP)
{
// 要计算的点正好是图像最右下角那一个象素,直接返回该点象素值
f1 = *((unsigned
char
*)lpDIBBits + lLineBytes *
(lHeight - 1 - j1) + i1);
return
f1;
}
else
{
// 在图像右边缘上且不是最后一点,直接一次插值即可
f1 = *((unsigned
char
*)lpDIBBits + lLineBytes *
(lHeight - 1 - j1) + i1);
f3 = *((unsigned
char
*)lpDIBBits + lLineBytes *
(lHeight - 1 - j1) + i2);
// 返回插值结果
return
((unsigned
char
) (f1 + (y -j1) * (f3 - f1)));
}
}
else
if
(
fabs
(y - lHeight + 1) <= EXP)
{
// 要计算的点在图像下边缘上且不是最后一点,直接一次插值即可
f1 = *((unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i1);
f2 = *((unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i1);
// 返回插值结果
return
((unsigned
char
) (f1 + (x -i1) * (f2 - f1)));
}
else
{
// 计算四个最临近象素值
f1 = *((unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i1);
f2 = *((unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i1);
f3 = *((unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i2);
f4 = *((unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i2);
// 插值1
f12 = (unsigned
char
) (f1 + (x - i1) * (f2 - f1));
// 插值2
f34 = (unsigned
char
) (f3 + (x - i1) * (f4 - f3));
// 插值3
return
((unsigned
char
) (f12 + (y -j1) * (f34 - f12)));
}
}
}
//
// 图像正交变换函数
//
/*************************************************************************
* 函数名称:
* FFT()
* 参数:
* complex<double> * TD - 指向时域数组的指针
* complex<double> * FD - 指向频域数组的指针
* r -2的幂数,即迭代次数
* 返回值:
* 无。
* 说明:
* 该函数用来实现快速付立叶变换。
************************************************************************/
VOID
CDibImage::FFT(complex<
double
> * TD, complex<
double
> * FD,
int
r)
{
LONG
count;
// 付立叶变换点数
int
i,j,k;
// 循环变量
int
bfsize,p;
double
angle;
// 角度
complex<
double
> *W,*X1,*X2,*X;
count = 1 << r;
// 计算付立叶变换点数
// 分配运算所需存储器
W =
new
complex<
double
>[count / 2];
X1 =
new
complex<
double
>[count];
X2 =
new
complex<
double
>[count];
// 计算加权系数
for
(i = 0; i < count / 2; i++)
{
angle = -i * PI * 2 / count;
W[i] = complex<
double
> (
cos
(angle),
sin
(angle));
}
// 将时域点写入X1
memcpy
(X1, TD,
sizeof
(complex<
double
>) * count);
// 采用蝶形算法进行快速付立叶变换
for
(k = 0; k < r; k++)
{
for
(j = 0; j < 1 << k; j++)
{
bfsize = 1 << (r-k);
for
(i = 0; i < bfsize / 2; i++)
{
p = j * bfsize;
X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2];
X2[i + p + bfsize / 2] = (X1[i + p] - X1[i + p + bfsize / 2])
* W[i * (1<<k)];
}
}
X = X1;
X1 = X2;
X2 = X;
}
// 重新排序
for
(j = 0; j < count; j++)
{
p = 0;
for
(i = 0; i < r; i++)
{
if
(j&(1<<i))
{
p+=1<<(r-i-1);
}
}
FD[j]=X1[p];
}
delete
W;
delete
X1;
delete
X2;
}
/*************************************************************************
* 函数名称:
* IFFT()
* 参数:
* complex<double> * FD - 指向频域值的指针
* complex<double> * TD - 指向时域值的指针
* r -2的幂数
* 返回值:
* 无。
* 说明:
* 该函数用来实现快速付立叶反变换。
************************************************************************/
VOID
CDibImage::IFFT(complex<
double
> * FD, complex<
double
> * TD,
int
r)
{
LONG
count;
// 付立叶变换点数
int
i;
// 循环变量
complex<
double
> *X;
count = 1 << r;
// 计算付立叶变换点数
X =
new
complex<
double
>[count];
// 分配运算所需存储器
memcpy
(X, FD,
sizeof
(complex<
double
>) * count);
// 将频域点写入X
// 求共轭
for
(i = 0; i < count; i++)
{
X[i] = complex<
double
> (X[i].real(), -X[i].imag());
}
FFT(X, TD, r);
// 调用快速付立叶变换
// 求时域点的共轭
for
(i = 0; i < count; i++)
{
TD[i] = complex<
double
> (TD[i].real() / count, -TD[i].imag() / count);
}
delete
X;
}
/*************************************************************************
* 函数名称:
* Fourier()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来对图像进行付立叶变换。
************************************************************************/
BOOL
CDibImage::Fourier(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
unsigned
char
* lpSrc;
// 指向源图像的指针
double
dTemp;
LONG
i;
// 循环变量
LONG
j;
LONG
w;
// 进行付立叶变换的宽度(2的整数次方)
LONG
h;
// 进行付立叶变换的高度(2的整数次方)
int
wp;
int
hp;
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 计算图像每行的字节数
// 赋初值
w = 1;
h = 1;
wp = 0;
hp = 0;
// 计算进行付立叶变换的宽度和高度(2的整数次方)
while
(w * 2 <= lWidth)
{
w *= 2;
wp++;
}
while
(h * 2 <= lHeight)
{
h *= 2;
hp++;
}
complex<
double
> *TD =
new
complex<
double
>[w * h];
complex<
double
> *FD =
new
complex<
double
>[w * h];
for
(i = 0; i < h; i++)
// 行
{
for
(j = 0; j < w; j++)
// 列
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 给时域赋值
TD[j + w * i] = complex<
double
>(*(lpSrc), 0);
}
}
for
(i = 0; i < h; i++)
{
// 对y方向进行快速付立叶变换
FFT(&TD[w * i], &FD[w * i], wp);
}
// 保存变换结果
for
(i = 0; i < h; i++)
{
for
(j = 0; j < w; j++)
{
TD[i + h * j] = FD[j + w * i];
}
}
for
(i = 0; i < w; i++)
{
// 对x方向进行快速付立叶变换
FFT(&TD[i * h], &FD[i * h], hp);
}
for
(i = 0; i < h; i++)
// 行
{
for
(j = 0; j < w; j++)
// 列
{
// 计算频谱
dTemp =
sqrt
(FD[j * h + i].real() * FD[j * h + i].real() +
FD[j * h + i].imag() * FD[j * h + i].imag()) / 100;
if
(dTemp > 255)
{
dTemp = 255;
}
// 指向DIB第(i<h/2 ? i+h/2 : i-h/2)行,第(j<w/2 ? j+w/2 : j-w/2)个
// 象素的指针,此处不直接取i和j,是为了将变换后的原点移到中心
// lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight-1-i) + j;
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes *
(lHeight - 1 - (i<h/2 ? i+h/2 : i-h/2)) + (j<w/2 ? j+w/2 : j-w/2);
// 更新源图像
* (lpSrc) = (
BYTE
)(dTemp);
}
}
delete
TD;
delete
FD;
return
TRUE;
}
/*************************************************************************
* 函数名称:
* DCT()
* 参数:
* double * f - 指向时域值的指针
* double * F - 指向频域值的指针
* r -2的幂数
* 返回值:
* 无。
* 说明:
* 该函数用来实现快速离散余弦变换。该函数利用2N点的快速付立叶变换
* 来实现离散余弦变换。
************************************************************************/
VOID
CDibImage::DCT(
double
*f,
double
*F,
int
r)
{
LONG
count;
// 离散余弦变换点数
int
i;
// 循环变量
double
dTemp;
complex<
double
> *X;
count = 1<<r;
// 计算离散余弦变换点数
X =
new
complex<
double
>[count*2];
memset
(X, 0,
sizeof
(complex<
double
>) * count * 2);
// 赋初值为0
// 将时域点写入数组X
for
(i=0;i<count;i++)
{
X[i] = complex<
double
> (f[i], 0);
}
FFT(X,X,r+1);
// 调用快速付立叶变换
dTemp = 1/
sqrt
(count);
// 调整系数
F[0] = X[0].real() * dTemp;
// 求F[0]
dTemp *=
sqrt
(2);
// 求F[u]
for
(i = 1; i < count; i++)
{
F[i]=(X[i].real() *
cos
(i*PI/(count*2)) + X[i].imag() *
sin
(i*PI/(count*2))) * dTemp;
}
delete
X;
}
/*************************************************************************
* 函数名称:
* IDCT()
* 参数:
* double * F - 指向频域值的指针
* double * f - 指向时域值的指针
* r -2的幂数
* 返回值:
* 无。
* 说明:
* 该函数用来实现快速离散余弦反变换。该函数也利用2N点的快速付立叶变换
* 来实现离散余弦反变换。
************************************************************************/
VOID
CDibImage::IDCT(
double
*F,
double
*f,
int
r)
{
LONG
count;
// 离散余弦反变换点数
int
i;
// 循环变量
double
dTemp, d0;
complex<
double
> *X;
count = 1<<r;
// 计算离散余弦变换点数
X =
new
complex<
double
>[count*2];
memset
(X, 0,
sizeof
(complex<
double
>) * count * 2);
// 赋初值为0
// 将频域变换后点写入数组X
for
(i=0;i<count;i++)
{
X[i] = complex<
double
> (F[i] *
cos
(i*PI/(count*2)), F[i] *
sin
(i*PI/(count*2)));
}
IFFT(X,X,r+1);
// 调用快速付立叶反变换
// 调整系数
dTemp =
sqrt
(2.0/count);
d0 = (
sqrt
(1.0/count) - dTemp) * F[0];
for
(i = 0; i < count; i++)
{
f[i] = d0 + X[i].real()* dTemp * 2 * count;
}
delete
X;
}
/*************************************************************************
* 函数名称:
* DIBDct()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来对图像进行离散余弦变换。
************************************************************************/
BOOL
CDibImage::DIBDct(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
unsigned
char
* lpSrc;
// 指向源图像的指针
LONG
i;
// 循环变量
LONG
j;
LONG
w;
// 进行付立叶变换的宽度(2的整数次方)
LONG
h;
// 进行付立叶变换的高度(2的整数次方)
double
dTemp;
int
wp;
int
hp;
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 赋初值
w = 1;
h = 1;
wp = 0;
hp = 0;
// 计算进行离散余弦变换的宽度和高度(2的整数次方)
while
(w * 2 <= lWidth)
{
w *= 2;
wp++;
}
while
(h * 2 <= lHeight)
{
h *= 2;
hp++;
}
double
*f =
new
double
[w * h];
double
*F =
new
double
[w * h];
for
(i = 0; i < h; i++)
// 行
{
for
(j = 0; j < w; j++)
// 列
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 给时域赋值
f[j + i * w] = *(lpSrc);
}
}
for
(i = 0; i < h; i++)
{
// 对y方向进行离散余弦变换
DCT(&f[w * i], &F[w * i], wp);
}
// 保存计算结果
for
(i = 0; i < h; i++)
{
for
(j = 0; j < w; j++)
{
f[j * h + i] = F[j + w * i];
}
}
for
(j = 0; j < w; j++)
{
// 对x方向进行离散余弦变换
DCT(&f[j * h], &F[j * h], hp);
}
for
(i = 0; i < h; i++)
// 行
{
for
(j = 0; j < w; j++)
// 列
{
dTemp =
fabs
(F[j*h+i]);
// 计算频谱
// 判断是否超过255
if
(dTemp > 255)
{
dTemp = 255;
}
// 指向DIB第y行,第x个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 更新源图像
* (lpSrc) = (
BYTE
)(dTemp);
}
}
delete
f;
delete
F;
return
TRUE;
}
/*************************************************************************
* 函数名称:
* WALSH()
* 参数:
* double * f - 指向时域值的指针
* double * F - 指向频域值的指针
* r -2的幂数
* 返回值:
* 无。
* 说明:
* 该函数用来实现快速沃尔什-哈达玛变换。
************************************************************************/
VOID
CDibImage::WALSH(
double
*f,
double
*F,
int
r)
{
LONG
count;
// 沃尔什-哈达玛变换点数
int
i,j,k;
// 循环变量
int
bfsize,p;
double
*X1,*X2,*X;
count = 1 << r;
// 计算快速沃尔什变换点数
X1 =
new
double
[count];
// 分配运算所需的数组
X2 =
new
double
[count];
// 分配运算所需的数组
memcpy
(X1, f,
sizeof
(
double
) * count);
// 将时域点写入数组X1
// 蝶形运算
for
(k = 0; k < r; k++)
{
for
(j = 0; j < 1<<k; j++)
{
bfsize = 1 << (r-k);
for
(i = 0; i < bfsize / 2; i++)
{
p = j * bfsize;
X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2];
X2[i + p + bfsize / 2] = X1[i + p] - X1[i + p + bfsize / 2];
}
}
// 互换X1和X2
X = X1;
X1 = X2;
X2 = X;
}
// 调整系数
for
(j = 0; j < count; j++)
{
p = 0;
for
(i = 0; i < r; i++)
{
if
(j & (1<<i))
{
p += 1 << (r-i-1);
}
}
F[j] = X1[p] / count;
}
delete
X1;
delete
X2;
}
/*************************************************************************
* 函数名称:
* IWALSH()
* 参数:
* double * F - 指向频域值的指针
* double * f - 指向时域值的指针
* r -2的幂数
* 返回值:
* 无。
* 说明:
* 该函数用来实现快速沃尔什-哈达玛反变换。
************************************************************************/
VOID
CDibImage::IWALSH(
double
*F,
double
*f,
int
r)
{
LONG
count;
// 变换点数
int
i;
// 循环变量
count = 1 << r;
// 计算变换点数
WALSH(F, f, r);
// 调用快速沃尔什-哈达玛变换进行反变换
for
(i = 0; i < count; i++)
// 调整系数
{
f[i] *= count;
}
}
/*************************************************************************
* 函数名称:
* DIBWalsh()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来对图像进行沃尔什-哈达玛变换。函数首先对图像每列进行一维
* 沃尔什-哈达玛变换,然后对变换结果的每行进行一维沃尔什-哈达玛变换。
************************************************************************/
BOOL
CDibImage::DIBWalsh(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
unsigned
char
* lpSrc;
// 指向源图像的指针
LONG
i,j;
// 循环变量
LONG
w;
// 进行付立叶变换的宽度(2的整数次方)
LONG
h;
// 进行付立叶变换的高度(2的整数次方)
double
dTemp;
int
wp;
int
hp;
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 赋初值
w = 1;
h = 1;
wp = 0;
hp = 0;
// 计算进行离散余弦变换的宽度和高度(2的整数次方)
while
(w * 2 <= lWidth)
{
w *= 2;
wp++;
}
while
(h * 2 <= lHeight)
{
h *= 2;
hp++;
}
double
*f =
new
double
[w * h];
double
*F =
new
double
[w * h];
for
(i = 0; i < h; i++)
// 行
{
for
(j = 0; j < w; j++)
// 列
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 给时域赋值
f[j + i * w] = *(lpSrc);
}
}
for
(i = 0; i < h; i++)
{
// 对y方向进行沃尔什-哈达玛变换
WALSH(f + w * i, F + w * i, wp);
}
// 保存计算结果
for
(i = 0; i < h; i++)
{
for
(j = 0; j < w; j++)
{
f[j * h + i] = F[j + w * i];
}
}
for
(j = 0; j < w; j++)
{
// 对x方向进行沃尔什-哈达玛变换
WALSH(f + j * h, F + j * h, hp);
}
for
(i = 0; i < h; i++)
// 行
{
for
(j = 0; j < w; j++)
// 列
{
dTemp =
fabs
(F[j * h + i] * 1000);
// 计算频谱
if
(dTemp > 255)
{
dTemp = 255;
}
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 更新源图像
* (lpSrc) = (
BYTE
)(dTemp);
}
}
delete
f;
delete
F;
return
TRUE;
}
/*************************************************************************
* 函数名称:
* DIBWalsh1()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来对图像进行沃尔什-哈达玛变换。于上面不同的是,此处是将二维
* 矩阵转换成一个列向量,然后对该列向量进行一次一维沃尔什-哈达玛变换。
************************************************************************/
BOOL
CDibImage::DIBWalsh1(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
unsigned
char
* lpSrc;
// 指向源图像的指针
LONG
i,j;
// 循环变量
LONG
w;
// 进行付立叶变换的宽度(2的整数次方)
LONG
h;
// 进行付立叶变换的高度(2的整数次方)
double
dTemp;
int
wp;
int
hp;
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 赋初值
w = 1;
h = 1;
wp = 0;
hp = 0;
// 计算进行离散余弦变换的宽度和高度(2的整数次方)
while
(w * 2 <= lWidth)
{
w *= 2;
wp++;
}
while
(h * 2 <= lHeight)
{
h *= 2;
hp++;
}
double
*f =
new
double
[w * h];
double
*F =
new
double
[w * h];
for
(i = 0; i < w; i++)
// 列
{
for
(j = 0; j < h; j++)
// 行
{
// 指向DIB第j行,第i个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - j) + i;
// 给时域赋值
f[j + i * w] = *(lpSrc);
}
}
// 调用快速沃尔什-哈达玛变换
WALSH(f, F, wp + hp);
for
(i = 0; i < w; i++)
// 列
{
for
(j = 0; j < h; j++)
// 行
{
dTemp =
fabs
(F[i * w + j] * 1000);
// 计算频谱
if
(dTemp > 255)
{
dTemp = 255;
}
// 指向DIB第j行,第i个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - j) + i;
// 更新源图像
* (lpSrc) = (
BYTE
)(dTemp);
}
}
delete
f;
delete
F;
return
TRUE;
}
//
// 图像模板变换函数
//
/*************************************************************************
* 函数名称:
* Template()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* int iTempH - 模板的高度
* int iTempW - 模板的宽度
* int iTempMX - 模板的中心元素X坐标 ( < iTempW - 1)
* int iTempMY - 模板的中心元素Y坐标 ( < iTempH - 1)
* FLOAT * fpArray - 指向模板数组的指针
* FLOAT fCoef - 模板系数
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用指定的模板(任意大小)来对图像进行操作,参数iTempH指定模板
* 的高度,参数iTempW指定模板的宽度,参数iTempMX和iTempMY指定模板的中心
* 元素坐标,参数fpArray指定模板元素,fCoef指定系数。
************************************************************************/
BOOL
CDibImage::Template(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
int
iTempH,
int
iTempW,
int
iTempMX,
int
iTempMY,
FLOAT
* fpArray,
FLOAT
fCoef)
{
LPSTR
lpNewDIBBits;
// 指向复制图像的指针
HLOCAL
hNewDIBBits;
unsigned
char
* lpSrc;
// 指向源图像的指针
unsigned
char
* lpDst;
// 指向要复制区域的指针
LONG
i,j,k,l;
// 循环变量
FLOAT
fResult;
// 计算结果
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
// 初始化图像为原始图像
memcpy
(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight);
for
(i = iTempMY; i < lHeight - iTempH + iTempMY + 1; i++)
// 行(除去边缘几行)
{
for
(j = iTempMX; j < lWidth - iTempW + iTempMX + 1; j++)
// 列(除去边缘几列)
{
// 指向新DIB第i行,第j个象素的指针
lpDst = (unsigned
char
*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
fResult = 0;
for
(k = 0; k < iTempH; k++)
{
for
(l = 0; l < iTempW; l++)
{
// 指向DIB第i - iTempMY + k行,第j - iTempMX + l个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1
- i + iTempMY - k) + j - iTempMX + l;
// 保存象素值
fResult += (* lpSrc) * fpArray[k * iTempW + l];
}
}
fResult *= fCoef;
// 乘上系数
fResult = (
FLOAT
)
fabs
(fResult);
// 取绝对值
if
(fResult > 255)
{
* lpDst = 255;
}
else
{
* lpDst = (unsigned
char
) (fResult + 0.5);
}
}
}
// 复制变换后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* MedianFilter()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* int iFilterH - 滤波器的高度
* int iFilterW - 滤波器的宽度
* int iFilterMX - 滤波器的中心元素X坐标
* int iFilterMY - 滤波器的中心元素Y坐标
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数对DIB图像进行中值滤波。
************************************************************************/
BOOL
CDibImage::MedianFilter(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
int
iFilterH,
int
iFilterW,
int
iFilterMX,
int
iFilterMY)
{
unsigned
char
* lpSrc;
// 指向源图像的指针
unsigned
char
* lpDst;
// 指向要复制区域的指针
LPSTR
lpNewDIBBits;
// 指向复制图像的指针
HLOCAL
hNewDIBBits;
unsigned
char
* aValue;
// 指向滤波器数组的指针
HLOCAL
hArray;
LONG
i,j,k,l;
// 循环变量
LONG
lLineBytes;
// 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
// 初始化图像为原始图像
memcpy
(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight);
// 暂时分配内存,以保存滤波器数组
hArray = LocalAlloc(LHND, iFilterH * iFilterW);
if
(hArray == NULL)
{
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return
FALSE;
}
aValue = (unsigned
char
* )LocalLock(hArray);
// 开始中值滤波
// 行(除去边缘几行)
for
(i = iFilterMY; i < lHeight - iFilterH + iFilterMY + 1; i++)
{
// 列(除去边缘几列)
for
(j = iFilterMX; j < lWidth - iFilterW + iFilterMX + 1; j++)
{
// 指向新DIB第i行,第j个象素的指针
lpDst = (unsigned
char
*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 读取滤波器数组
for
(k = 0; k < iFilterH; k++)
{
for
(l = 0; l < iFilterW; l++)
{
// 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1
- i + iFilterMY - k) + j - iFilterMX + l;
// 保存象素值
aValue[k * iFilterW + l] = *lpSrc;
}
}
// 获取中值
* lpDst = GetMedianNum(aValue, iFilterH * iFilterW);
}
}
// 复制变换后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
LocalUnlock(hArray);
LocalFree(hArray);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* GetMedianNum()
* 参数:
* unsigned char * bpArray - 指向要获取中值的数组指针
* int iFilterLen - 数组长度
* 返回值:
* unsigned char - 返回指定数组的中值。
* 说明:
* 该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。
************************************************************************/
unsigned
char
CDibImage::GetMedianNum(unsigned
char
* bArray,
int
iFilterLen)
{
int
i,j;
// 循环变量
unsigned
char
bTemp;
// 用冒泡法对数组进行排序
for
(j = 0; j < iFilterLen - 1; j ++)
{
for
(i = 0; i < iFilterLen - j - 1; i ++)
{
if
(bArray[i] > bArray[i + 1])
{
// 互换
bTemp = bArray[i];
bArray[i] = bArray[i + 1];
bArray[i + 1] = bTemp;
}
}
}
// 计算中值
if
((iFilterLen & 1) > 0)
{
// 数组有奇数个元素,返回中间一个元素
bTemp = bArray[(iFilterLen + 1) / 2];
}
else
{
// 数组有偶数个元素,返回中间两个元素平均值
bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
}
return
bTemp;
}
/*************************************************************************
* 函数名称:
* GradSharp()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* BYTE bThre - 阈值
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用来对图像进行梯度锐化。
************************************************************************/
BOOL
CDibImage::GradSharp(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
BYTE
bThre)
{
unsigned
char
* lpSrc;
// 指向源图像的指针
unsigned
char
* lpSrc1;
unsigned
char
* lpSrc2;
LONG
i,j;
// 循环变量
LONG
lLineBytes;
// 图像每行的字节数
BYTE
bTemp;
lLineBytes = WIDTHBYTES(lWidth * 8);
for
(i = 0; i < lHeight; i++)
// 每行
{
for
(j = 0; j < lWidth; j++)
// 每列
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 指向DIB第i+1行,第j个象素的指针
lpSrc1 = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 2 - i) + j;
// 指向DIB第i行,第j+1个象素的指针
lpSrc2 = (unsigned
char
*)lpDIBBits + lLineBytes * (lHeight - 1 - i)
+ j + 1;
bTemp =
abs
((*lpSrc)-(*lpSrc1)) +
abs
((*lpSrc)-(*lpSrc2));
// 判断是否小于阈值
if
(bTemp < 255)
{
// 判断是否大于阈值,对于小于情况,灰度值不变。
if
(bTemp >= bThre)
{
*lpSrc = bTemp;
}
}
else
{
*lpSrc = 255;
}
}
}
return
TRUE;
}
/*************************************************************************
* 函数名称:
* ReplaceColorPal()
* 参数:
* LPSTR lpDIB - 指向源DIB图像指针
* BYTE * bpColorsTable - 伪彩色编码表
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用指定的伪彩色编码表来替换图像的调试板,参数bpColorsTable
* 指向要替换的伪彩色编码表。
************************************************************************/
BOOL
CDibImage::ReplaceColorPal(
LPSTR
lpDIB,
BYTE
* bpColorsTable)
{
int
i;
// 循环变量
WORD
wNumColors;
// 颜色表中的颜色数目
LPBITMAPINFO lpbmi;
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREINFO lpbmc;
// 指向BITMAPCOREINFO结构的指针
BOOL
bWinStyleDIB;
// 表明是否是Win3.0 DIB的标记
BOOL
bResult = FALSE;
// 创建结果
lpbmi = (LPBITMAPINFO)lpDIB;
// 获取指向BITMAPINFO结构的指针(Win3.0)
lpbmc = (LPBITMAPCOREINFO)lpDIB;
// 获取指向BITMAPCOREINFO结构的指针
wNumColors = DIBNumColors(lpDIB);
// 获取DIB中颜色表中的颜色数目
if
(wNumColors == 256)
// 判断颜色数目是否是256色
{
bWinStyleDIB = IS_WIN30_DIB(lpDIB);
// 判断是否是WIN3.0的DIB
// 读取伪彩色编码,更新DIB调色板
for
(i = 0; i < (
int
)wNumColors; i++)
{
if
(bWinStyleDIB)
{
// 更新DIB调色板红色绿色蓝色分量
lpbmi->bmiColors[i].rgbRed = bpColorsTable[i * 4];
lpbmi->bmiColors[i].rgbGreen = bpColorsTable[i * 4 + 1];
lpbmi->bmiColors[i].rgbBlue = bpColorsTable[i * 4 + 2];
// 更新DIB调色板保留位
lpbmi->bmiColors[i].rgbReserved = 0;
}
else
{
// 更新DIB调色板红色绿色蓝色分量
lpbmc->bmciColors[i].rgbtRed = bpColorsTable[i * 4];
lpbmc->bmciColors[i].rgbtGreen = bpColorsTable[i * 4 + 1];
lpbmc->bmciColors[i].rgbtBlue = bpColorsTable[i * 4 + 2];
}
}
}
return
bResult;
}
//
// 图像形态学变换函数
//
/*************************************************************************
* 函数名称:
* ErosiontionDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* int nMode - 腐蚀方式:0表示水平方向,1垂直方向,2自定义结构元素。
* int structure[3][3] - 自定义的3×3结构元素。
* 返回值:
* BOOL - 腐蚀成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用于对图像进行腐蚀运算。结构元素为水平方向或垂直方向的三个点,
* 中间点位于原点;或者由用户自己定义3×3的结构元素。
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL
CDibImage::ErosionDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
int
nMode ,
int
structure[3][3])
{
LPSTR
lpSrc;
// 指向源图像的指针
LPSTR
lpDst;
// 指向缓存图像的指针
LPSTR
lpNewDIBBits;
// 指向缓存DIB图像的指针
HLOCAL
hNewDIBBits;
long
i,j,n,m;
//循环变量
unsigned
char
pixel;
//像素值
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (
char
*)lpNewDIBBits;
memset
(lpDst, (
BYTE
)255, lWidth * lHeight);
if
(nMode == 0)
{
//使用水平方向的结构元素进行腐蚀
for
(j = 0; j <lHeight; j++)
{
for
(i = 1;i <lWidth-1; i++)
{
// 由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边
// 的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成黑色
*lpDst = (unsigned
char
)0;
//如果源图像中当前点自身或者左右有一个点不是黑色,
//则将目标图像中的当前点赋成白色
for
(n = 0;n < 3;n++ )
{
pixel = *(lpSrc+n-1);
if
(pixel == 255 )
{
*lpDst = (unsigned
char
)255;
break
;
}
}
}
}
}
else
if
(nMode == 1)
{
//使用垂直方向的结构元素进行腐蚀
for
(j = 1; j <lHeight-1; j++)
{
for
(i = 0;i <lWidth; i++)
{
// 由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边
// 的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成黑色
*lpDst = (unsigned
char
)0;
//如果源图像中当前点自身或者上下有一个点不是黑色,
//则将目标图像中的当前点赋成白色
for
(n = 0;n < 3;n++ )
{
pixel = *(lpSrc+(n-1)*lWidth);
if
(pixel == 255 )
{
*lpDst = (unsigned
char
)255;
break
;
}
}
}
}
}
else
{
//使用自定义的结构元素进行腐蚀
for
(j = 1; j <lHeight-1; j++)
{
for
(i = 0;i <lWidth; i++)
{
// 由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边
// 的两列像素和最上边和最下边的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成黑色
*lpDst = (unsigned
char
)0;
//如果原图像中对应结构元素中为黑色的那些点中有一个不是黑色,
//则将目标图像中的当前点赋成白色
//注意在DIB图像中内容是上下倒置的
for
(m = 0;m < 3;m++ )
{
for
(n = 0;n < 3;n++)
{
if
( structure[m][n] == -1)
continue
;
pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1));
if
(pixel == 255 )
{
*lpDst = (unsigned
char
)255;
break
;
}
}
}
}
}
}
// 复制腐蚀后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* DilationDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* int nMode - 膨胀方式:0表示水平方向,1垂直方向,2自定义结构元素。
* int structure[3][3] - 自定义的3×3结构元素。
* 返回值:
* BOOL - 膨胀成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用于对图像进行膨胀运算。结构元素为水平方向或垂直方向的三个点,
* 中间点位于原点;或者由用户自己定义3×3的结构元素。
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL
CDibImage::DilationDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
int
nMode,
int
structure[3][3])
{
LPSTR
lpSrc;
// 指向源图像的指针
LPSTR
lpDst;
// 指向缓存图像的指针
LPSTR
lpNewDIBBits;
// 指向缓存DIB图像的指针
HLOCAL
hNewDIBBits;
long
i,j,m,n;
//循环变量
unsigned
char
pixel;
//像素值
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (
char
*)lpNewDIBBits;
memset
(lpDst, (
BYTE
)255, lWidth * lHeight);
if
(nMode == 0)
{
//使用水平方向的结构元素进行膨胀
for
(j = 0; j <lHeight; j++)
{
for
(i = 1;i <lWidth-1; i++)
{
// 由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边
// 的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && pixel != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成白色
*lpDst = (unsigned
char
)255;
//源图像中当前点自身或者左右只要有一个点是黑色,
//则将目标图像中的当前点赋成黑色
for
(n = 0;n < 3;n++ )
{
pixel = *(lpSrc+n-1);
if
(pixel == 0 )
{
*lpDst = (unsigned
char
)0;
break
;
}
}
}
}
}
else
if
(nMode == 1)
{
//使用垂直方向的结构元素进行膨胀
for
(j = 1; j <lHeight-1; j++)
{
for
(i = 0;i <lWidth; i++)
{
// 由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边
// 的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成白色
*lpDst = (unsigned
char
)255;
//源图像中当前点自身或者上下只要有一个点是黑色,
//则将目标图像中的当前点赋成黑色
for
(n = 0;n < 3;n++ )
{
pixel = *(lpSrc+(n-1)*lWidth);
if
(pixel == 0 )
{
*lpDst = (unsigned
char
)0;
break
;
}
}
}
}
}
else
{
//使用自定义的结构元素进行膨胀
for
(j = 1; j <lHeight-1; j++)
{
for
(i = 0;i <lWidth; i++)
{
// 由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边
// 的两列像素和最上边和最下边的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成白色
*lpDst = (unsigned
char
)255;
//原图像中对应结构元素中为黑色的那些点中只要有一个是黑色,
//则将目标图像中的当前点赋成黑色
//注意在DIB图像中内容是上下倒置的
for
(m = 0;m < 3;m++ )
{
for
(n = 0;n < 3;n++)
{
if
( structure[m][n] == -1)
continue
;
pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1));
if
(pixel == 0 )
{
*lpDst = (unsigned
char
)0;
break
;
}
}
}
}
}
}
// 复制膨胀后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* OpenDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* int nMode - 开运算方式:0表示水平方向,1垂直方向,2自定义结构元素。
* int structure[3][3] - 自定义的3×3结构元素。
* 返回值:
* BOOL - 开运算成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用于对图像进行开运算。结构元素为水平方向或垂直方向的三个点,
* 中间点位于原点;或者由用户自己定义3×3的结构元素。
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL
CDibImage::OpenDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
int
nMode ,
int
structure[3][3])
{
LPSTR
lpSrc;
// 指向源图像的指针
LPSTR
lpDst;
// 指向缓存图像的指针
LPSTR
lpNewDIBBits;
// 指向缓存DIB图像的指针
HLOCAL
hNewDIBBits;
long
i,j,m,n;
//循环变量
unsigned
char
pixel;
//像素值
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (
char
*)lpNewDIBBits;
memset
(lpDst, (
BYTE
)255, lWidth * lHeight);
if
(nMode == 0)
{
//使用水平方向的结构元素进行腐蚀
for
(j = 0; j <lHeight; j++)
{
for
(i = 1;i <lWidth-1; i++)
{
// 由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边
// 的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成黑色
*lpDst = (unsigned
char
)0;
//如果源图像中当前点自身或者左右有一个点不是黑色,
//则将目标图像中的当前点赋成白色
for
(n = 0;n < 3;n++ )
{
pixel = *(lpSrc+n-1);
if
(pixel == 255 )
{
*lpDst = (unsigned
char
)255;
break
;
}
}
}
}
}
else
if
(nMode == 1)
{
//使用垂直方向的结构元素进行腐蚀
for
(j = 1; j <lHeight-1; j++)
{
for
(i = 0;i <lWidth; i++)
{
// 由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边
// 的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成黑色
*lpDst = (unsigned
char
)0;
//如果源图像中当前点自身或者上下有一个点不是黑色,
//则将目标图像中的当前点赋成白色
for
(n = 0;n < 3;n++ )
{
pixel = *(lpSrc+(n-1)*lWidth);
if
(pixel == 255 )
{
*lpDst = (unsigned
char
)255;
break
;
}
}
}
}
}
else
{
//使用自定义的结构元素进行腐蚀
for
(j = 1; j <lHeight-1; j++)
{
for
(i = 0;i <lWidth; i++)
{
// 由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边
// 的两列像素和最上边和最下边的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成黑色
*lpDst = (unsigned
char
)0;
//如果原图像中对应结构元素中为黑色的那些点中有一个不是黑色,
//则将目标图像中的当前点赋成白色
//注意在DIB图像中内容是上下倒置的
for
(m = 0;m < 3;m++ )
{
for
(n = 0;n < 3;n++)
{
if
( structure[m][n] == -1)
continue
;
pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1));
if
(pixel == 255 )
{
*lpDst = (unsigned
char
)255;
break
;
}
}
}
}
}
}
// 复制腐蚀后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 重新初始化新分配的内存,设定初始值为255
//lpDst = (char *)lpNewDIBBits;
//memset(lpDst, (BYTE)255, lWidth * lHeight);
if
(nMode == 0)
{
//使用水平方向的结构元素进行膨胀
for
(j = 0; j <lHeight; j++)
{
for
(i = 1;i <lWidth-1; i++)
{
// 由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边
// 的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成白色
*lpDst = (unsigned
char
)255;
//源图像中当前点自身或者左右只要有一个点是黑色,
//则将目标图像中的当前点赋成黑色
for
(n = 0;n < 3;n++ )
{
pixel = *(lpSrc+n-1);
if
(pixel == 0 )
{
*lpDst = (unsigned
char
)0;
break
;
}
}
}
}
}
else
if
(nMode == 1)
{
//使用垂直方向的结构元素进行膨胀
for
(j = 1; j <lHeight-1; j++)
{
for
(i = 0;i <lWidth; i++)
{
// 由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边
// 的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成白色
*lpDst = (unsigned
char
)255;
//源图像中当前点自身或者上下只要有一个点是黑色,
//则将目标图像中的当前点赋成黑色
for
(n = 0;n < 3;n++ )
{
pixel = *(lpSrc+(n-1)*lWidth);
if
(pixel == 0 )
{
*lpDst = (unsigned
char
)0;
break
;
}
}
}
}
}
else
{
//使用自定义的结构元素进行膨胀
for
(j = 1; j <lHeight-1; j++)
{
for
(i = 0;i <lWidth; i++)
{
// 由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边
// 的两列像素和最上边和最下边的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//目标图像中的当前点先赋成白色
*lpDst = (unsigned
char
)255;
//原图像中对应结构元素中为黑色的那些点中只要有一个是黑色,
//则将目标图像中的当前点赋成黑色
//注意在DIB图像中内容是上下倒置的
for
(m = 0;m < 3;m++ )
{
for
(n = 0;n < 3;n++)
{
if
( structure[m][n] == -1)
continue
;
pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1));
if
(pixel == 0 )
{
*lpDst = (unsigned
char
)0;
break
;
}
}
}
}
}
}
// 复制膨胀后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* CloseDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* int nMode - 闭运算方式:0表示水平方向,1垂直方向,2自定义结构元素。
* int structure[3][3] - 自定义的3×3结构元素。
* 返回值:
* BOOL - 闭运算成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用于对图像进行开运算。结构元素为水平方向或垂直方向的三个点,
* 中间点位于原点;或者由用户自己定义3×3的结构元素。
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL
CDibImage::CloseDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight,
int
nMode ,
int
structure[3][3])
{
if
(DilationDIB(lpDIBBits, lWidth, lHeight, nMode , structure))
{
if
(ErosionDIB(lpDIBBits, lWidth, lHeight, nMode , structure))
{
return
TRUE;
}
}
return
FALSE;
}
/*************************************************************************
* 函数名称:
* ThinDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 闭运算成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用于对图像进行细化运算。要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL
CDibImage::ThiningDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
LPSTR
lpSrc;
// 指向源图像的指针
LPSTR
lpDst;
// 指向缓存图像的指针
LPSTR
lpNewDIBBits;
// 指向缓存DIB图像的指针
HLOCAL
hNewDIBBits;
BOOL
bModified;
//脏标记
long
i,j,m,n;
//循环变量
//四个条件
BOOL
bCondition1;
BOOL
bCondition2;
BOOL
bCondition3;
BOOL
bCondition4;
unsigned
char
nCount;
//计数器
unsigned
char
pixel;
//像素值
unsigned
char
neighbour[5][5];
//5×5相邻区域像素值
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (
char
*)lpNewDIBBits;
memset
(lpDst, (
BYTE
)255, lWidth * lHeight);
bModified = TRUE;
while
(bModified)
{
bModified = FALSE;
// 初始化新分配的内存,设定初始值为255
lpDst = (
char
*)lpNewDIBBits;
memset
(lpDst, (
BYTE
)255, lWidth * lHeight);
for
(j = 2; j <lHeight-2; j++)
{
for
(i = 2;i <lWidth-2; i++)
{
bCondition1 = FALSE;
bCondition2 = FALSE;
bCondition3 = FALSE;
bCondition4 = FALSE;
//由于使用5×5的结构元素,为防止越界,所以不处理外围的几行和几列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
continue
;
}
//如果源图像中当前点为白色,则跳过
else
if
(pixel == 255)
{
continue
;
}
//获得当前点相邻的5×5区域内像素值,白色用0代表,黑色用1代表
for
(m = 0;m < 5;m++ )
{
for
(n = 0;n < 5;n++)
{
neighbour[m][n] =(255 - (unsigned
char
)*(lpSrc +
((4 - m) - 2)*lWidth + n - 2 )) / 255;
}
}
//逐个判断条件。
//判断2<=NZ(P1)<=6
nCount = neighbour[1][1] + neighbour[1][2] + neighbour[1][3] \
+ neighbour[2][1] + neighbour[2][3] + \
+ neighbour[3][1] + neighbour[3][2] + neighbour[3][3];
if
( nCount >= 2 && nCount <=6)
{
bCondition1 = TRUE;
}
//判断Z0(P1)=1
nCount = 0;
if
(neighbour[1][2] == 0 && neighbour[1][1] == 1)
nCount++;
if
(neighbour[1][1] == 0 && neighbour[2][1] == 1)
nCount++;
if
(neighbour[2][1] == 0 && neighbour[3][1] == 1)
nCount++;
if
(neighbour[3][1] == 0 && neighbour[3][2] == 1)
nCount++;
if
(neighbour[3][2] == 0 && neighbour[3][3] == 1)
nCount++;
if
(neighbour[3][3] == 0 && neighbour[2][3] == 1)
nCount++;
if
(neighbour[2][3] == 0 && neighbour[1][3] == 1)
nCount++;
if
(neighbour[1][3] == 0 && neighbour[1][2] == 1)
nCount++;
if
(nCount == 1)
bCondition2 = TRUE;
//判断P2*P4*P8=0 or Z0(p2)!=1
if
(neighbour[1][2]*neighbour[2][1]*neighbour[2][3] == 0)
{
bCondition3 = TRUE;
}
else
{
nCount = 0;
if
(neighbour[0][2] == 0 && neighbour[0][1] == 1)
nCount++;
if
(neighbour[0][1] == 0 && neighbour[1][1] == 1)
nCount++;
if
(neighbour[1][1] == 0 && neighbour[2][1] == 1)
nCount++;
if
(neighbour[2][1] == 0 && neighbour[2][2] == 1)
nCount++;
if
(neighbour[2][2] == 0 && neighbour[2][3] == 1)
nCount++;
if
(neighbour[2][3] == 0 && neighbour[1][3] == 1)
nCount++;
if
(neighbour[1][3] == 0 && neighbour[0][3] == 1)
nCount++;
if
(neighbour[0][3] == 0 && neighbour[0][2] == 1)
nCount++;
if
(nCount != 1)
bCondition3 = TRUE;
}
//判断P2*P4*P6=0 or Z0(p4)!=1
if
(neighbour[1][2]*neighbour[2][1]*neighbour[3][2] == 0)
{
bCondition4 = TRUE;
}
else
{
nCount = 0;
if
(neighbour[1][1] == 0 && neighbour[1][0] == 1)
nCount++;
if
(neighbour[1][0] == 0 && neighbour[2][0] == 1)
nCount++;
if
(neighbour[2][0] == 0 && neighbour[3][0] == 1)
nCount++;
if
(neighbour[3][0] == 0 && neighbour[3][1] == 1)
nCount++;
if
(neighbour[3][1] == 0 && neighbour[3][2] == 1)
nCount++;
if
(neighbour[3][2] == 0 && neighbour[2][2] == 1)
nCount++;
if
(neighbour[2][2] == 0 && neighbour[1][2] == 1)
nCount++;
if
(neighbour[1][2] == 0 && neighbour[1][1] == 1)
nCount++;
if
(nCount != 1)
bCondition4 = TRUE;
}
if
(bCondition1 && bCondition2 && bCondition3 && bCondition4)
{
*lpDst = (unsigned
char
)255;
bModified = TRUE;
}
else
{
*lpDst = (unsigned
char
)0;
}
}
}
// 复制腐蚀后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
}
// 复制腐蚀后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return
TRUE;
}
//
// 图像边缘与轮廓运算函数
//
/*************************************************************************
* 函数名称:
* RobertDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 边缘检测成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用Robert边缘检测算子对图像进行边缘检测运算。
* 要求目标图像为灰度图像。
************************************************************************/
BOOL
CDibImage::RobertDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
WatershedSegment(lpDIBBits,lWidth,lHeight);
//ju_lei(lpDIBBits,lWidth,lHeight);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* SobelDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 边缘检测成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用Sobel边缘检测算子对图像进行边缘检测运算。
* 要求目标图像为灰度图像。
************************************************************************/
BOOL
CDibImage::SobelDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
LPSTR
lpDst1;
// 指向缓存图像的指针
LPSTR
lpDst2;
LPSTR
lpNewDIBBits1;
// 指向缓存DIB图像的指针
HLOCAL
hNewDIBBits1;
LPSTR
lpNewDIBBits2;
HLOCAL
hNewDIBBits2;
long
i,j;
// 循环变量
int
iTempH;
// 模板高度
int
iTempW;
// 模板宽度
FLOAT
fTempC;
// 模板系数
int
iTempMX;
// 模板中心元素X坐标
int
iTempMY;
// 模板中心元素Y坐标
FLOAT
aTemplate[9];
// 模板数组
// 暂时分配内存,以保存新图像
hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits1 == NULL)
{
return
FALSE;
}
lpNewDIBBits1 = (
char
* )LocalLock(hNewDIBBits1);
// 暂时分配内存,以保存新图像
hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits2 == NULL)
{
return
FALSE;
}
lpNewDIBBits2 = (
char
* )LocalLock(hNewDIBBits2);
// 拷贝源图像到缓存图像中
lpDst1 = (
char
*)lpNewDIBBits1;
memcpy
(lpNewDIBBits1, lpDIBBits, lWidth * lHeight);
lpDst2 = (
char
*)lpNewDIBBits2;
memcpy
(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
// 设置Sobel模板参数
iTempW = 3;
iTempH = 3;
fTempC = 1.0;
iTempMX = 1;
iTempMY = 1;
aTemplate[0] = -1.0;
aTemplate[1] = -2.0;
aTemplate[2] = -1.0;
aTemplate[3] = 0.0;
aTemplate[4] = 0.0;
aTemplate[5] = 0.0;
aTemplate[6] = 1.0;
aTemplate[7] = 2.0;
aTemplate[8] = 1.0;
if
(!Template(lpNewDIBBits1, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
// 设置Sobel模板参数
aTemplate[0] = -1.0;
aTemplate[1] = 0.0;
aTemplate[2] = 1.0;
aTemplate[3] = -2.0;
aTemplate[4] = 0.0;
aTemplate[5] = 2.0;
aTemplate[6] = -1.0;
aTemplate[7] = 0.0;
aTemplate[8] = 1.0;
if
(!Template(lpNewDIBBits2, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
//求两幅缓存图像的最大值
for
(j = 0; j <lHeight; j++)
{
for
(i = 0;i <lWidth-1; i++)
{
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (
char
*)lpNewDIBBits1 + lWidth * j + i;
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (
char
*)lpNewDIBBits2 + lWidth * j + i;
if
(*lpDst2 > *lpDst1)
{
*lpDst1 = *lpDst2;
}
}
}
// 复制经过模板运算后的图像到源图像
memcpy
(lpDIBBits, lpNewDIBBits1, lWidth * lHeight);
LocalUnlock(hNewDIBBits1);
LocalFree(hNewDIBBits1);
LocalUnlock(hNewDIBBits2);
LocalFree(hNewDIBBits2);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* PrewittDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 边缘检测成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用Prewitt边缘检测算子对图像进行边缘检测运算。
* 要求目标图像为灰度图像。
************************************************************************/
BOOL
CDibImage::PrewittDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
LPSTR
lpDst1;
// 指向缓存图像的指针
LPSTR
lpDst2;
LPSTR
lpNewDIBBits1;
// 指向缓存DIB图像的指针
HLOCAL
hNewDIBBits1;
LPSTR
lpNewDIBBits2;
HLOCAL
hNewDIBBits2;
long
i,j;
// 循环变量
int
iTempH;
// 模板高度
int
iTempW;
// 模板宽度
FLOAT
fTempC;
// 模板系数
int
iTempMX;
// 模板中心元素X坐标
int
iTempMY;
// 模板中心元素Y坐标
FLOAT
aTemplate[9];
// 模板数组
// 暂时分配内存,以保存新图像
hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits1 == NULL)
{
return
FALSE;
}
lpNewDIBBits1 = (
char
* )LocalLock(hNewDIBBits1);
// 暂时分配内存,以保存新图像
hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits2 == NULL)
{
return
FALSE;
}
lpNewDIBBits2 = (
char
* )LocalLock(hNewDIBBits2);
// 拷贝源图像到缓存图像中
lpDst1 = (
char
*)lpNewDIBBits1;
memcpy
(lpNewDIBBits1, lpDIBBits, lWidth * lHeight);
lpDst2 = (
char
*)lpNewDIBBits2;
memcpy
(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
// 设置Prewitt模板参数
iTempW = 3;
iTempH = 3;
fTempC = 1.0;
iTempMX = 1;
iTempMY = 1;
aTemplate[0] = -1.0;
aTemplate[1] = -1.0;
aTemplate[2] = -1.0;
aTemplate[3] = 0.0;
aTemplate[4] = 0.0;
aTemplate[5] = 0.0;
aTemplate[6] = 1.0;
aTemplate[7] = 1.0;
aTemplate[8] = 1.0;
if
(!Template(lpNewDIBBits1, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
// 设置Prewitt模板参数
aTemplate[0] = 1.0;
aTemplate[1] = 0.0;
aTemplate[2] = -1.0;
aTemplate[3] = 1.0;
aTemplate[4] = 0.0;
aTemplate[5] = -1.0;
aTemplate[6] = 1.0;
aTemplate[7] = 0.0;
aTemplate[8] = -1.0;
if
(!Template(lpNewDIBBits2, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
//求两幅缓存图像的最大值
for
(j = 0; j <lHeight; j++)
{
for
(i = 0;i <lWidth-1; i++)
{
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (
char
*)lpNewDIBBits1 + lWidth * j + i;
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (
char
*)lpNewDIBBits2 + lWidth * j + i;
if
(*lpDst2 > *lpDst1)
{
*lpDst1 = *lpDst2;
}
}
}
// 复制经过模板运算后的图像到源图像
memcpy
(lpDIBBits, lpNewDIBBits1, lWidth * lHeight);
LocalUnlock(hNewDIBBits1);
LocalFree(hNewDIBBits1);
LocalUnlock(hNewDIBBits2);
LocalFree(hNewDIBBits2);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* KirschDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 边缘检测成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用kirsch边缘检测算子对图像进行边缘检测运算。
* 要求目标图像为灰度图像。
************************************************************************/
BOOL
CDibImage::KirschDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
LPSTR
lpDst1;
// 指向缓存图像的指针
LPSTR
lpDst2;
LPSTR
lpNewDIBBits1;
// 指向缓存DIB图像的指针
HLOCAL
hNewDIBBits1;
LPSTR
lpNewDIBBits2;
HLOCAL
hNewDIBBits2;
long
i,j;
// 循环变量
int
iTempH;
// 模板高度
int
iTempW;
// 模板宽度
FLOAT
fTempC;
// 模板系数
int
iTempMX;
// 模板中心元素X坐标
int
iTempMY;
// 模板中心元素Y坐标
FLOAT
aTemplate[9];
// 模板数组
// 暂时分配内存,以保存新图像
hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits1 == NULL)
{
return
FALSE;
}
lpNewDIBBits1 = (
char
* )LocalLock(hNewDIBBits1);
// 暂时分配内存,以保存新图像
hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits2 == NULL)
{
return
FALSE;
}
lpNewDIBBits2 = (
char
* )LocalLock(hNewDIBBits2);
// 拷贝源图像到缓存图像中
lpDst1 = (
char
*)lpNewDIBBits1;
memcpy
(lpNewDIBBits1, lpDIBBits, lWidth * lHeight);
lpDst2 = (
char
*)lpNewDIBBits2;
memcpy
(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
// 设置Kirsch模板1参数
iTempW = 3;
iTempH = 3;
fTempC = 1.0;
iTempMX = 1;
iTempMY = 1;
aTemplate[0] = 5.0;
aTemplate[1] = 5.0;
aTemplate[2] = 5.0;
aTemplate[3] = -3.0;
aTemplate[4] = 0.0;
aTemplate[5] = -3.0;
aTemplate[6] = -3.0;
aTemplate[7] = -3.0;
aTemplate[8] = -3.0;
if
(!Template(lpNewDIBBits1, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
// 设置Kirsch模板2参数
aTemplate[0] = -3.0;
aTemplate[1] = 5.0;
aTemplate[2] = 5.0;
aTemplate[3] = -3.0;
aTemplate[4] = 0.0;
aTemplate[5] = 5.0;
aTemplate[6] = -3.0;
aTemplate[7] = -3.0;
aTemplate[8] = -3.0;
if
(!Template(lpNewDIBBits2, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
//求两幅缓存图像的最大值
for
(j = 0; j <lHeight; j++)
{
for
(i = 0;i <lWidth-1; i++)
{
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (
char
*)lpNewDIBBits1 + lWidth * j + i;
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (
char
*)lpNewDIBBits2 + lWidth * j + i;
if
(*lpDst2 > *lpDst1)
{
*lpDst1 = *lpDst2;
}
}
}
// 拷贝源图像到缓存图像中
memcpy
(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
// 设置Kirsch模板3参数
aTemplate[0] = -3.0;
aTemplate[1] = -3.0;
aTemplate[2] = 5.0;
aTemplate[3] = -3.0;
aTemplate[4] = 0.0;
aTemplate[5] = 5.0;
aTemplate[6] = -3.0;
aTemplate[7] = -3.0;
aTemplate[8] = 5.0;
if
(!Template(lpNewDIBBits2, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
//求两幅缓存图像的最大值
for
(j = 0; j <lHeight; j++)
{
for
(i = 0;i <lWidth-1; i++)
{
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (
char
*)lpNewDIBBits1 + lWidth * j + i;
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (
char
*)lpNewDIBBits2 + lWidth * j + i;
if
(*lpDst2 > *lpDst1)
{
*lpDst1 = *lpDst2;
}
}
}
// 拷贝源图像到缓存图像中
memcpy
(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
// 设置Kirsch模板4参数
aTemplate[0] = -3.0;
aTemplate[1] = -3.0;
aTemplate[2] = -3.0;
aTemplate[3] = -3.0;
aTemplate[4] = 0.0;
aTemplate[5] = 5.0;
aTemplate[6] = -3.0;
aTemplate[7] = 5.0;
aTemplate[8] = 5.0;
if
(!Template(lpNewDIBBits2, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
//求两幅缓存图像的最大值
for
(j = 0; j <lHeight; j++)
{
for
(i = 0;i <lWidth-1; i++)
{
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (
char
*)lpNewDIBBits1 + lWidth * j + i;
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (
char
*)lpNewDIBBits2 + lWidth * j + i;
if
(*lpDst2 > *lpDst1)
{
*lpDst1 = *lpDst2;
}
}
}
// 拷贝源图像到缓存图像中
memcpy
(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
// 设置Kirsch模板5参数
aTemplate[0] = -3.0;
aTemplate[1] = -3.0;
aTemplate[2] = -3.0;
aTemplate[3] = -3.0;
aTemplate[4] = 0.0;
aTemplate[5] = -3.0;
aTemplate[6] = 5.0;
aTemplate[7] = 5.0;
aTemplate[8] = 5.0;
if
(!Template(lpNewDIBBits2, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
// 拷贝源图像到缓存图像中
memcpy
(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
//求两幅缓存图像的最大值
for
(j = 0; j <lHeight; j++)
{
for
(i = 0;i <lWidth-1; i++)
{
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (
char
*)lpNewDIBBits1 + lWidth * j + i;
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (
char
*)lpNewDIBBits2 + lWidth * j + i;
if
(*lpDst2 > *lpDst1)
{
*lpDst1 = *lpDst2;
}
}
}
// 拷贝源图像到缓存图像中
memcpy
(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
// 设置Kirsch模板6参数
aTemplate[0] = -3.0;
aTemplate[1] = -3.0;
aTemplate[2] = -3.0;
aTemplate[3] = 5.0;
aTemplate[4] = 0.0;
aTemplate[5] = -3.0;
aTemplate[6] = 5.0;
aTemplate[7] = 5.0;
aTemplate[8] = -3.0;
if
(!Template(lpNewDIBBits2, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
//求两幅缓存图像的最大值
for
(j = 0; j <lHeight; j++)
{
for
(i = 0;i <lWidth-1; i++)
{
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (
char
*)lpNewDIBBits1 + lWidth * j + i;
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (
char
*)lpNewDIBBits2 + lWidth * j + i;
if
(*lpDst2 > *lpDst1)
{
*lpDst1 = *lpDst2;
}
}
}
// 拷贝源图像到缓存图像中
memcpy
(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
// 设置Kirsch模板7参数
aTemplate[0] = 5.0;
aTemplate[1] = -3.0;
aTemplate[2] = -3.0;
aTemplate[3] = 5.0;
aTemplate[4] = 0.0;
aTemplate[5] = -3.0;
aTemplate[6] = 5.0;
aTemplate[7] = -3.0;
aTemplate[8] = -3.0;
if
(!Template(lpNewDIBBits2, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
//求两幅缓存图像的最大值
for
(j = 0; j <lHeight; j++)
{
for
(i = 0;i <lWidth-1; i++)
{
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (
char
*)lpNewDIBBits1 + lWidth * j + i;
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (
char
*)lpNewDIBBits2 + lWidth * j + i;
if
(*lpDst2 > *lpDst1)
{
*lpDst1 = *lpDst2;
}
}
}
// 拷贝源图像到缓存图像中
memcpy
(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
// 设置Kirsch模板8参数
aTemplate[0] = 5.0;
aTemplate[1] = 5.0;
aTemplate[2] = -3.0;
aTemplate[3] = 5.0;
aTemplate[4] = 0.0;
aTemplate[5] = -3.0;
aTemplate[6] = -3.0;
aTemplate[7] = -3.0;
aTemplate[8] = -3.0;
if
(!Template(lpNewDIBBits2, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
//求两幅缓存图像的最大值
for
(j = 0; j <lHeight; j++)
{
for
(i = 0;i <lWidth-1; i++)
{
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (
char
*)lpNewDIBBits1 + lWidth * j + i;
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (
char
*)lpNewDIBBits2 + lWidth * j + i;
if
(*lpDst2 > *lpDst1)
{
*lpDst1 = *lpDst2;
}
}
}
// 复制经过模板运算后的图像到源图像
memcpy
(lpDIBBits, lpNewDIBBits1, lWidth * lHeight);
LocalUnlock(hNewDIBBits1);
LocalFree(hNewDIBBits1);
LocalUnlock(hNewDIBBits2);
LocalFree(hNewDIBBits2);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* GaussDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 边缘检测成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用高斯拉普拉斯边缘检测算子对图像进行边缘检测运算。
* 要求目标图像为灰度图像。
************************************************************************/
BOOL
CDibImage::GaussDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
LPSTR
lpDst1;
// 指向缓存图像的指针
LPSTR
lpDst2;
LPSTR
lpNewDIBBits1;
// 指向缓存DIB图像的指针
HLOCAL
hNewDIBBits1;
LPSTR
lpNewDIBBits2;
HLOCAL
hNewDIBBits2;
int
iTempH;
// 模板高度
int
iTempW;
// 模板宽度
FLOAT
fTempC;
// 模板系数
int
iTempMX;
// 模板中心元素X坐标
int
iTempMY;
// 模板中心元素Y坐标
FLOAT
aTemplate[25];
//模板数组
// 暂时分配内存,以保存新图像
hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits1 == NULL)
{
return
FALSE;
}
lpNewDIBBits1 = (
char
* )LocalLock(hNewDIBBits1);
// 暂时分配内存,以保存新图像
hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits2 == NULL)
{
return
FALSE;
}
lpNewDIBBits2 = (
char
* )LocalLock(hNewDIBBits2);
// 拷贝源图像到缓存图像中
lpDst1 = (
char
*)lpNewDIBBits1;
memcpy
(lpNewDIBBits1, lpDIBBits, lWidth * lHeight);
lpDst2 = (
char
*)lpNewDIBBits2;
memcpy
(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
// 设置Gauss模板参数
iTempW = 5;
iTempH = 5;
fTempC = 1.0;
iTempMX = 3;
iTempMY = 3;
aTemplate[0] = -2.0;
aTemplate[1] = -4.0;
aTemplate[2] = -4.0;
aTemplate[3] = -4.0;
aTemplate[4] = -2.0;
aTemplate[5] = -4.0;
aTemplate[6] = 0.0;
aTemplate[7] = 8.0;
aTemplate[8] = 0.0;
aTemplate[9] = -4.0;
aTemplate[10] = -4.0;
aTemplate[11] = 8.0;
aTemplate[12] = 24.0;
aTemplate[13] = 8.0;
aTemplate[14] = -4.0;
aTemplate[15] = -4.0;
aTemplate[16] = 0.0;
aTemplate[17] = 8.0;
aTemplate[18] = 0.0;
aTemplate[19] = -4.0;
aTemplate[20] = -2.0;
aTemplate[21] = -4.0;
aTemplate[22] = -4.0;
aTemplate[23] = -4.0;
aTemplate[24] = -2.0;
if
(!Template(lpNewDIBBits1, lWidth, lHeight,
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
{
return
FALSE;
}
// 复制经过模板运算后的图像到源图像
memcpy
(lpDIBBits, lpNewDIBBits1, lWidth * lHeight);
LocalUnlock(hNewDIBBits1);
LocalFree(hNewDIBBits1);
LocalUnlock(hNewDIBBits2);
LocalFree(hNewDIBBits2);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* HoughDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用于对检测图像中的平行直线。如果图像中有两条平行的直线,
* 则将这两条平行直线提取出来。
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL
CDibImage::HoughDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
LPSTR
lpSrc;
// 指向源图像的指针
LPSTR
lpDst;
// 指向缓存图像的指针
LPSTR
lpTrans;
// 指向变换域的指针
LONG
lLineBytes;
// 图像每行的字节数
LPSTR
lpNewDIBBits;
// 指向缓存DIB图像的指针
HLOCAL
hNewDIBBits;
LPSTR
lpTransArea;
// 指向变换域的指针
HLOCAL
hTransArea;
int
iMaxDist;
// 变换域的尺寸
int
iMaxAngleNumber;
int
iDist;
// 变换域的坐标
int
iAngleNumber;
long
i,j;
// 循环变量
unsigned
char
pixel;
// 像素值
MaxValue MaxValue1;
// 存储变换域中的两个最大值
MaxValue MaxValue2;
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (
char
*)lpNewDIBBits;
memset
(lpDst, (
BYTE
)255, lWidth * lHeight);
//计算变换域的尺寸 最大距离
iMaxDist = (
int
)
sqrt
(lWidth*lWidth + lHeight*lHeight);
//角度从0-180,每格2度
iMaxAngleNumber = 90;
//为变换域分配内存
hTransArea = LocalAlloc(LHND, lWidth * lHeight *
sizeof
(
int
));
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpTransArea = (
char
* )LocalLock(hTransArea);
// 初始化新分配的内存,设定初始值为0
lpTrans = (
char
*)lpTransArea;
memset
(lpTrans, 0, lWidth * lHeight *
sizeof
(
int
));
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
for
(j = 0; j <lHeight; j++)
{
for
(i = 0;i <lWidth; i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lLineBytes * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && *lpSrc != 0)
{
return
FALSE;
}
//如果是黑点,则在变换域的对应各点上加1
if
(pixel == 0)
{
//注意步长是2度
for
(iAngleNumber=0; iAngleNumber<iMaxAngleNumber; iAngleNumber++)
{
iDist = (
int
)
fabs
(i*
cos
(iAngleNumber*2*PI/180.0) + \
j*
sin
(iAngleNumber*2*PI/180.0));
//变换域的对应点上加1
*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber) = \
*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber) +1;
}
}
}
}
//找到变换域中的两个最大值点
MaxValue1.Value=0;
MaxValue2.Value=0;
//找到第一个最大值点
for
(iDist=0; iDist<iMaxDist;iDist++)
{
for
(iAngleNumber=0; iAngleNumber<iMaxAngleNumber; iAngleNumber++)
{
if
((
int
)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber)>MaxValue1.Value)
{
MaxValue1.Value = (
int
)*(lpTransArea+iDist*iMaxAngleNumber
+iAngleNumber);
MaxValue1.Dist = iDist;
MaxValue1.AngleNumber = iAngleNumber;
}
}
}
//将第一个最大值点附近清零
for
(iDist = -9;iDist < 10;iDist++)
{
for
(iAngleNumber=-1; iAngleNumber<2; iAngleNumber++)
{
if
(iDist+MaxValue1.Dist>=0 && iDist+MaxValue1.Dist<iMaxDist \
&& iAngleNumber+MaxValue1.AngleNumber>=0 && iAngleNumber
+MaxValue1.AngleNumber<=iMaxAngleNumber)
{
*(lpTransArea+(iDist+MaxValue1.Dist)*iMaxAngleNumber+\
(iAngleNumber+MaxValue1.AngleNumber))=0;
}
}
}
//找到第二个最大值点
for
(iDist=0; iDist<iMaxDist;iDist++)
{
for
(iAngleNumber=0; iAngleNumber<iMaxAngleNumber; iAngleNumber++)
{
if
((
int
)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber)>MaxValue2.Value)
{
MaxValue2.Value = (
int
)*(lpTransArea+iDist*iMaxAngleNumber
+iAngleNumber);
MaxValue2.Dist = iDist;
MaxValue2.AngleNumber = iAngleNumber;
}
}
}
//判断两直线是否平行
if
(
abs
(MaxValue1.AngleNumber-MaxValue2.AngleNumber)<=2)
{
//两直线平行,在缓存图像中重绘这两条直线
for
(j = 0; j <lHeight; j++)
{
for
(i = 0;i <lWidth; i++)
{
// 指向缓存图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lLineBytes * j + i;
//如果该点在某一条平行直线上,则在缓存图像上将该点赋为黑
//在第一条直线上
iDist = (
int
)
fabs
(i*
cos
(MaxValue1.AngleNumber*2*PI/180.0) + \
j*
sin
(MaxValue1.AngleNumber*2*PI/180.0));
if
(iDist == MaxValue1.Dist)
{
*lpDst = (unsigned
char
)0;
}
//在第二条直线上
iDist = (
int
)
fabs
(i*
cos
(MaxValue2.AngleNumber*2*PI/180.0) + \
j*
sin
(MaxValue2.AngleNumber*2*PI/180.0));
if
(iDist == MaxValue2.Dist)
{
*lpDst = (unsigned
char
)0;
}
}
}
}
// 复制腐蚀后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
LocalUnlock(hTransArea);
LocalFree(hTransArea);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* Fill2DIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 种子填充成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用于对图像进行种子填充运算。
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL
CDibImage::Fill2DIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
LPSTR
lpSrc;
// 指向源图像的指针
long
i;
// 循环变量
unsigned
char
pixel;
// 像素值
int
xl,xr;
// 左右边界像素位置
BOOL
bFilll,bFillr;
// 是否已填充至边界
Seed Seeds[10];
// 种子堆栈及指针
int
StackPoint;
int
iCurrentPixelx,iCurrentPixely;
// 当前像素位置
int
iBufferPixelx,iBufferPixely;
Seeds[1].Height = lHeight / 2;
// 初始化种子
Seeds[1].Width = lWidth / 2;
StackPoint = 1;
while
( StackPoint != 0)
{
//取出种子
iCurrentPixelx = Seeds[StackPoint].Width;
iCurrentPixely = Seeds[StackPoint].Height;
StackPoint--;
// if(Seed2.Height== 75)
// {
// return true;
// i++;
// }
bFilll =
true
;
bFillr =
true
;
//填充种子所在的行,保存种子像素的位置
iBufferPixelx = iCurrentPixelx;
iBufferPixely = iCurrentPixely;
//先向左填充
while
(bFilll)
{
lpSrc = (
char
*)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && pixel != 0)
{
return
FALSE;
}
//遇到边界
if
(pixel == 0)
{
bFilll =
false
;
xl=iCurrentPixelx+1;
}
else
{
*lpSrc = (unsigned
char
)0;
iCurrentPixelx--;
//防止越界
if
(iCurrentPixelx<0)
{
bFilll =
false
;
iCurrentPixelx = 0;
xl = 0;
}
}
}
//再向右填充,取回种子像素的位置
iCurrentPixelx = iBufferPixelx+1;
if
(iCurrentPixelx>lWidth)
{
bFillr =
false
;
iCurrentPixelx = lWidth;
xr = lWidth;
}
iCurrentPixely = iBufferPixely;
while
(bFillr)
{
lpSrc = (
char
*)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && pixel != 0)
return
FALSE;
//遇到边界
if
(pixel == 0)
{
bFillr =
false
;
xr=iCurrentPixelx-1;
}
else
{
*lpSrc = (unsigned
char
)0;
iCurrentPixelx++;
//防止越界
if
(iCurrentPixelx>lWidth)
{
bFillr =
false
;
iCurrentPixelx = lWidth;
xr = lWidth;
}
}
}
//上、下两条扫描线是否全为边界象素或已填充过
//先看上面的扫描线
iCurrentPixely--;
if
(iCurrentPixely < 0)
{
iCurrentPixely = 0;
}
for
(i = xr; i>= xl;i--)
{
lpSrc = (
char
*)lpDIBBits + lWidth * iCurrentPixely + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//有未填充的像素,将新的种子压入堆栈
if
(pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely;
Seeds[StackPoint].Width = i;
break
;
}
}
//再看下面的扫描线
iCurrentPixely+=2;
if
(iCurrentPixely > lHeight)
{
iCurrentPixely = lHeight;
}
for
(i = xr; i>= xl;i--)
{
lpSrc = (
char
*)lpDIBBits + lWidth * iCurrentPixely + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//有未填充的像素,将新的种子压入堆栈
if
(pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely;
Seeds[StackPoint].Width = i;
break
;
}
}
}
return
TRUE;
}
/*************************************************************************
* 函数名称:
* FillDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 种子填充成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用于对图像进行种子填充运算。
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL
CDibImage::FillDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
LPSTR
lpSrc;
// 指向源图像的指针
unsigned
char
pixel;
// 像素值
Seed *Seeds;
// 种子堆栈及指针
int
StackPoint;
int
iCurrentPixelx,iCurrentPixely;
// 当前像素位置
Seeds =
new
Seed[lWidth*lHeight];
// 初始化种子
Seeds[1].Height = lHeight / 2;
Seeds[1].Width = lWidth / 2;
StackPoint = 1;
while
( StackPoint != 0)
{
//取出种子
iCurrentPixelx = Seeds[StackPoint].Width;
iCurrentPixely = Seeds[StackPoint].Height;
StackPoint--;
lpSrc = (
char
*)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && pixel != 0)
{
return
FALSE;
}
//将当前点涂黑
*lpSrc = (unsigned
char
)0;
//判断左面的点,如果为白,则压入堆栈,注意防止越界
if
(iCurrentPixelx > 0)
{
lpSrc = (
char
*)lpDIBBits+lWidth*iCurrentPixely+iCurrentPixelx-1;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
if
(pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely;
Seeds[StackPoint].Width = iCurrentPixelx - 1;
}
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && pixel != 0)
{
return
FALSE;
}
}
//判断上面的点,如果为白,则压入堆栈,注意防止越界
if
(iCurrentPixely < lHeight - 1)
{
lpSrc = (
char
*)lpDIBBits+lWidth*(iCurrentPixely+1)+iCurrentPixelx;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
if
(pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely + 1;
Seeds[StackPoint].Width = iCurrentPixelx;
}
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && pixel != 0)
{
return
FALSE;
}
}
//判断右面的点,如果为白,则压入堆栈,注意防止越界
if
(iCurrentPixelx < lWidth - 1)
{
lpSrc = (
char
*)lpDIBBits+lWidth*iCurrentPixely+iCurrentPixelx+1;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
if
(pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely;
Seeds[StackPoint].Width = iCurrentPixelx + 1;
}
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && pixel != 0)
{
return
FALSE;
}
}
//判断下面的点,如果为白,则压入堆栈,注意防止越界
if
(iCurrentPixely > 0)
{
lpSrc = (
char
*)lpDIBBits+lWidth*(iCurrentPixely-1)+iCurrentPixelx;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
if
(pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely - 1;
Seeds[StackPoint].Width = iCurrentPixelx;
}
//目标图像中含有0和255外的其它灰度值
if
(pixel != 255 && pixel != 0)
{
return
FALSE;
}
}
}
delete
Seeds;
return
TRUE;
}
/*************************************************************************
* 函数名称:
* ContourDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用于对图像进行轮廓提取运算。
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL
CDibImage::ContourDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
LPSTR
lpSrc;
// 指向源图像的指针
LPSTR
lpDst;
// 指向缓存图像的指针
LPSTR
lpNewDIBBits;
// 指向缓存DIB图像的指针
HLOCAL
hNewDIBBits;
long
i,j;
//循环变量
unsigned
char
n,e,s,w,ne,se,nw,sw;
unsigned
char
pixel;
//像素值
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (
char
*)lpNewDIBBits;
memset
(lpDst, (
BYTE
)255, lWidth * lHeight);
for
(j = 1; j <lHeight-1; j++)
{
for
(i = 1;i <lWidth-1; i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
//目标图像中含有0和255外的其它灰度值
// if(pixel != 255 && pixel != 0)
// return FALSE;
if
(pixel == 0)
{
*lpDst = (unsigned
char
)0;
nw = (unsigned
char
)*(lpSrc + lWidth -1);
n = (unsigned
char
)*(lpSrc + lWidth );
ne = (unsigned
char
)*(lpSrc + lWidth +1);
w = (unsigned
char
)*(lpSrc -1);
e = (unsigned
char
)*(lpSrc +1);
sw = (unsigned
char
)*(lpSrc - lWidth -1);
s = (unsigned
char
)*(lpSrc - lWidth );
se = (unsigned
char
)*(lpSrc - lWidth +1);
//如果相邻的八个点都是黑点
if
(nw+n+ne+w+e+sw+s+se==0)
{
*lpDst = (unsigned
char
)255;
}
}
}
}
// 复制腐蚀后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return
TRUE;
}
/*************************************************************************
* 函数名称:
* TraceDIB()
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
* 说明:
* 该函数用于对图像进行轮廓跟踪运算。
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL
CDibImage::TraceDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
LPSTR
lpSrc;
// 指向源图像的指针
LPSTR
lpDst;
// 指向缓存图像的指针
LPSTR
lpNewDIBBits;
// 指向缓存DIB图像的指针
HLOCAL
hNewDIBBits;
LONG
lLineBytes;
// 图像每行的字节数
long
i,j;
// 循环变量
unsigned
char
pixel;
// 像素值
bool
bFindStartPoint;
// 是否找到起始点及回到起始点
bool
bFindPoint;
// 是否扫描到一个边界点
Point StartPoint,CurrentPoint;
// 起始边界点与当前边界点
//八个方向和起始扫描方向
int
Direction[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
int
BeginDirect;
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if
(hNewDIBBits == NULL)
{
return
FALSE;
}
lpNewDIBBits = (
char
* )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (
char
*)lpNewDIBBits;
memset
(lpDst, (
BYTE
)255, lLineBytes * lHeight);
//先找到最左上方的边界点
bFindStartPoint =
false
;
for
(j = 0;j < lHeight && !bFindStartPoint;j++)
{
for
(i = 0;i < lWidth && !bFindStartPoint;i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (
char
*)lpDIBBits + lLineBytes * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned
char
)*lpSrc;
if
(pixel == 0)
{
bFindStartPoint =
true
;
StartPoint.Height = j;
StartPoint.Width = i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (
char
*)lpNewDIBBits + lLineBytes * j + i;
*lpDst = (unsigned
char
)0;
}
}
}
//由于起始点是在左下方,故起始扫描沿左上方向
BeginDirect = 0;
//跟踪边界
bFindStartPoint =
false
;
//从初始点开始扫描
CurrentPoint.Height = StartPoint.Height;
CurrentPoint.Width = StartPoint.Width;
while
(!bFindStartPoint)
{
bFindPoint =
false
;
while
(!bFindPoint)
{
//沿扫描方向查看一个像素
lpSrc = (
char
*)lpDIBBits + lLineBytes * ( CurrentPoint.Height +
Direction[BeginDirect][1]) + (CurrentPoint.Width +
Direction[BeginDirect][0]);
pixel = (unsigned
char
)*lpSrc;
if
(pixel == 0)
{
bFindPoint =
true
;
CurrentPoint.Height = CurrentPoint.Height+Direction[BeginDirect][1];
CurrentPoint.Width = CurrentPoint.Width + Direction[BeginDirect][0];
if
(CurrentPoint.Height == StartPoint.Height && CurrentPoint.Width
== StartPoint.Width)
{
bFindStartPoint =
true
;
}
lpDst = (
char
*)lpNewDIBBits + lLineBytes * CurrentPoint.Height
+ CurrentPoint.Width;
*lpDst = (unsigned
char
)0;
//扫描的方向逆时针旋转两格
BeginDirect--;
if
(BeginDirect == -1)
{
BeginDirect = 7;
}
BeginDirect--;
if
(BeginDirect == -1)
{
BeginDirect = 7;
}
}
else
{
//扫描方向顺时针旋转一格
BeginDirect++;
if
(BeginDirect == 8)
{
BeginDirect = 0;
}
}
}
}
// 复制腐蚀后的图像
memcpy
(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return
TRUE;
}
|
Author: SKySeraph
Email/GTalk: zgzhaobo@gmail.com QQ:452728574
From: http://www.cnblogs.com/skyseraph/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,请尊重作者的
作者:skyseraph
出处:http://www.cnblogs.com/skyseraph/
Email/GTalk: zgzhaobo@gmail.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
融云,免费为你的App加入IM功能——让你的App“聊”起来!!
· 大众点评完成新轮8.5亿美元融资 小米腾讯参投
· 让人悚然心惊的节奏 听一听北京雾霾唱歌
· NASA推出灶神星探索网页工具
· 谷歌大开杀戒? 移除近200个Chrome恶意扩展
· 阿里的网商银行已提交验收申请 进入开业准备
» 更多新闻...
· 事件流如何提高应用程序的扩展性、可靠性和可维护性
· Web动效研究与实践
· 关于工作效率的心得分享
· 编码之道:取个好名字很重要