您的位置:首页 > 其它

常用用图像处理算法(一)

2012-12-14 20:59 363 查看
这是以前应朋友邀请写的算法,大多数是基础的,只是由于长时间不写,显得生疏,不知道是否有用,贴出来帮给初学者参考。算法是在MFC框架下编写的,我会把主文件和相关文件相继贴出来。

一、基本实现如下功能:

1) 图像灰度图、彩色图和二值化三种格式文件的打开和存储功能;

2) 支持版面局部纠偏功能;

3) 图像去污功能;

4) 支持图像局部浓淡调整功能;

5) 支持去除图像黑白边功能;

6) 支持部分磨白功能;

7) 擦除图像功能;

8) 自动和人工二值化功能;

9) 对图像提供横、竖拆页功能,图像人工、自动拼页功能;

10) 图像进行左、右旋转,翻转及改变图像亮度操作功能;

二、主函数为CArdpsImg类

1)头文件

#pragma once

#include "api/dibapi.h"

#include "api/ImgConv.h"

#include "api/CompConnect.h"

class CArdpsImg : public CObject

{

DECLARE_SERIAL(CArdpsImg)

public:

CArdpsImg(void);

CArdpsImg &operator =(const CArdpsImg &ArdSrc);

CArdpsImg(const CArdpsImg &ArdSrc);

HANDLE LoadNonDibHandle(BOOL *bBmp, char* szImgFileName);

bool ConvertGray(int nMethod, UINT uiRWeight = 114, UINT uiGWeight = 587, UINT uiBWeight = 299 );

bool ConvertBinary(int nMethod /* = 0 */, int nTh /* = 0 */);

bool SaveNonDIB(HDIB hDib, CString strFileName, ImageType nDestFileExtType );

bool GrayEqual();

bool GrayStretch(int nMethod, BYTE x1,BYTE y1,BYTE x2,BYTE y2);

bool EliminateDirt(int nMethod, const CRect rct);

bool EliminateDirt(int nMethod, const int nCircleX, const int nCircleY, const int nRadius);

void SetDirtSize(CSize szMax, CSize szMin);

CRect* GetDirtPos( int nMethod, int *nCnt);

bool AutoEliminateDirt(int nMethod, int nMinArea);

bool AutoEliminateDirt(int nMethod, CRect *pRect, int *pFlag, const int nNum);

bool RotateImage(int iRotateAngle = 0);

bool AutoRotatelImage( RECT rtROI);

bool CutFrame();

bool SplitImage(POINT pt1, POINT pt2, CArdpsImg *pNewArd);

bool MergeImage(CArdpsImg *pSrcArd, int nMethod = 0);

bool MergeImage(CArdpsImg *pSrcArd, int nPos1, int nPos2, int nMethod = 0);

bool SaveTiff(char *szImgFileName);

bool AjustLightAndContrast(int brightness, int contrast);

bool Zoom(double fRatioX, double fRatioY);

bool AdjustBinPos( int nMethod = 0);

bool ColorEqual();

bool SaveGrayDIB(); // for debug

void Serialize(CArchive& ar);

bool IsEmpty();

bool Read(CFile *pFile);

bool Write(CFile *pFile);

bool Create(LPBYTE lpDIB);

bool Create(LPBYTE lpDIB, WORD wBitCount);

bool UpdateInternal();

void Destroy();

bool BuildBitmap();

bool BuildPalette();

bool Display(CDC* pDC, int x, int y, DWORD dwRop=SRCCOPY);

bool ConvertFormat(WORD wBitCount);

WORD GetBitCount();

LONG GetWidth();

LONG GetHeight();

LONG GetWidthBytes();

WORD GetPaletteSize();

HANDLE GetHandle();

WORD GetColorNumber();

LPBYTE GetBitsPtr();

bool Attach(HDIB hDib);

ImageType GetFileExtType(CString strExt);

CPalette* GetPalette();

private:

bool InitDIBFileHead(LPBITMAPINFOHEADER lpBI, BITMAPFILEHEADER *lpbmfHdr);

bool IntensityMean(const BYTE *pbGray, const int nImgWid, const int nImgHei, int &nIntenMean );

bool ThreshImage(const BYTE *pbImg, BYTE *pbBinary, const int nImgWid, const int nImgHei, const int nTh);

void OtsuTh( DWORD nW, DWORD nH, BYTE *lpBits, int &Th);

void ExtractComponent(Line * Li, BYTE *pMotion, UINT grayBytesPerLine, BYTE bCur ) ;

inline void add(int a,int b,char **flag,int *&stack,int **InStack, int &top,int &topin,int c,int d,component *ctail, BYTE *pMotion, UINT grayBytesPerLine, BYTE bCur );

void AnalysisComponent( Line * Li, BYTE *pbBinary, UINT unBinaryBytesPerLine, UINT minArea, const BYTE bValue);

bool AnalysisDirtPos(Line *Li, CSize maxSize, CSize minSize, int nHeight, int *nCnt);

bool ConvertBinary2Gray(const unsigned char * pbBinary, const int nWidth, const int nHeight, unsigned char *pbGray);

void SetBinary(CRect rect, BYTE *pbImg, UINT unBinaryBytesPerLine, const BYTE bValue);

int OutputNormalImageUnderAngle(BYTE *DesImg, const BYTE *SrcImage, int nWidth, int nHeight, double dk);

bool FindTopEdge(BYTE *pbOutImage, BYTE *image, RECT rtROI, int nWidth);

double DetectSkewAngle(BYTE *pbImage, RECT rtROI, int nWidth);

RECT GetEdgeImageBoundary(BYTE *pbImage, int nWidth, int nHeight);

RECT GetBinImageBoundary(BYTE *pbImage, int nWidth, int nHeight);

int FindEdgeImage(BYTE *pbOutImage, BYTE *image, RECT rtROI, int nWidth);

RECT SetRectValue(int left, int right, int top, int bottom);

bool VerticalSplit(int nX, CArdpsImg *newArt);

bool HorizntalSplit(int nY, CArdpsImg *newArt);

int CompVPrjValeSum(int *pnRamBuff, const BYTE *pInImg, int nImgWidth, int nImgHeight, int nRotAngle);

void SmoothingArray(int *pOut, int nR, const int *pIn, int nStart, int nEnd) ;

int DeleteVtlSmallLine(BYTE* pImg, BYTE* pBuf, int nWidth, int nHeight, int nTh);

HDIB ReadBinTiff(char* szImgFileName);

void Img32to24(BYTE *pbImg32, BYTE *pbImg24, int nWidth, int nHeight);

void ReversBits(BYTE *pbIn, int nWidth, int nHeight, DWORD nBitCnt);

void ReversColors(BYTE*pbIn, BYTE *pbOut, int nWidth, int nHeight);

void ReversColors(BYTE*pbIn, int nWidth, int nHeight);

void MoveBin(BYTE *pbIn, int nWidth, int nHeight, RECT rtOld, RECT rtNew, int nMethod = 0);

public:

HDIB m_hDib; //DIB handle of CDib object

HBITMAP m_hBitmap; // handle of DIBSection

CPalette* m_pPalette; //related to DIB's palette CPalette object

CBitmap* m_pBitmap; //related to DDB's CBitmap object

HDIB m_hNewDib;

// private member data

private:

// for drawing in DIB

CDC * m_pMemDC;

CBitmap* m_pBitmapTmp;

CPalette* m_pPaletteTmp;

CSize m_DirtSize;

CSize m_minDirtSize;

CRect *m_dirRect;

public:

virtual ~CArdpsImg(void);

};

2)源文件

#include "StdAfx.h"

#include "ArdpsImg.h"

#include "api/ImgConv.h"

#include "api/CompConnect.h"

#include "api/tiff/tiffio.h"

#include <stdlib.h>

#include <time.h>

#include <math.h>

#include <windowsx.h> // especially for GlobalAllocPtr

const UINT uiRWeight = 114;

const UINT uiGWeight = 587;

const UINT uiBWeight = 299;

#define PI 3.14159

//角度到弧度转化的宏

#define RADIAN(angle) ((angle)*PI/180.0)

#define EDGE_STEP 4

DWORD buf[256];

double bufi[256], varience[256];

// 5. the cos value(*65536 or * (2**16)) with angle from 0 to 180 and the step is 1

const int g_nCos[180] = {

65536, 65526, 65496, 65446, 65376, 65286, 65176, 65047, 64898, 64729,

64540, 64331, 64103, 63856, 63589, 63302, 62997, 62672, 62328, 61965,

61583, 61183, 60763, 60326, 59870, 59395, 58903, 58393, 57864, 57319,

56755, 56175, 55577, 54963, 54331, 53683, 53019, 52339, 51643, 50931,

50203, 49460, 48702, 47930, 47142, 46340, 45525, 44695, 43852, 42995,

42125, 41243, 40347, 39440, 38521, 37589, 36647, 35693, 34728, 33753,

32768, 31772, 30767, 29752, 28729, 27696, 26655, 25606, 24550, 23486,

22414, 21336, 20251, 19160, 18064, 16961, 15854, 14742, 13625, 12504,

11380, 10252, 9120, 7986, 6850, 5711, 4571, 3429, 2287, 1143,

0, -1143, -2287, -3429, -4571, -5711, -6850, -7986, -9120, -10252,

-11380, -12504, -13625, -14742, -15854, -16961, -18064, -19160, -20251, -21336,

-22414, -23486, -24550, -25606, -26655, -27696, -28729, -29752, -30767, -31772,

-32768, -33753, -34728, -35693, -36647, -37589, -38521, -39440, -40347, -41243,

-42125, -42995, -43852, -44695, -45525, -46340, -47142, -47930, -48702, -49460,

-50203, -50931, -51643, -52339, -53019, -53683, -54331, -54963, -55577, -56175,

-56755, -57319, -57864, -58393, -58903, -59395, -59870, -60326, -60763, -61183,

-61583, -61965, -62328, -62672, -62997, -63302, -63589, -63856, -64103, -64331,

-64540, -64729, -64898, -65047, -65176, -65286, -65376, -65446, -65496, -65526

};

// 6. the sin value(*65536 or * (2**16)) with angle from 0 to 180 and the step is 1

const int g_nSin[180] = {

0, 1143, 2287, 3429, 4571, 5711, 6850, 7986, 9120, 10252,

11380, 12504, 13625, 14742, 15854, 16961, 18064, 19160, 20251, 21336,

22414, 23486, 24550, 25606, 26655, 27696, 28729, 29752, 30767, 31772,

32768, 33753, 34728, 35693, 36647, 37589, 38521, 39440, 40347, 41243,

42125, 42995, 43852, 44695, 45525, 46340, 47142, 47930, 48702, 49460,

50203, 50931, 51643, 52339, 53019, 53683, 54331, 54963, 55577, 56175,

56755, 57319, 57864, 58393, 58903, 59395, 59870, 60326, 60763, 61183,

61583, 61965, 62328, 62672, 62997, 63302, 63589, 63856, 64103, 64331,

64540, 64729, 64898, 65047, 65176, 65286, 65376, 65446, 65496, 65526,

65536, 65526, 65496, 65446, 65376, 65286, 65176, 65047, 64898, 64729,

64540, 64331, 64103, 63856, 63589, 63302, 62997, 62672, 62328, 61965,

61583, 61183, 60763, 60326, 59870, 59395, 58903, 58393, 57864, 57319,

56755, 56175, 55577, 54963, 54331, 53683, 53019, 52339, 51643, 50931,

50203, 49460, 48702, 47930, 47142, 46340, 45525, 44695, 43852, 42995,

42125, 41243, 40347, 39440, 38521, 37589, 36647, 35693, 34728, 33753,

32768, 31772, 30767, 29752, 28729, 27696, 26655, 25606, 24550, 23486,

22414, 21336, 20251, 19160, 18064, 16961, 15854, 14742, 13625, 12504,

11380, 10252, 9120, 7986, 6850, 5711, 4571, 3429, 2287, 1143

};

typedef bool (*PFN_ImageConvert)(const unsigned char * pSrcData, int nSrcDataLen, ImageType itSrcImageType,

unsigned char * * ppDestData, int * pnDestDataLen, ImageType itDestImageType);

typedef bool (*PFN_ImageDelete)(unsigned char * * ppImageData);

IMPLEMENT_SERIAL(CArdpsImg, CObject, 0)

CArdpsImg::CArdpsImg(void)

{

m_hDib = NULL; //CDib对象所表示的DIB句柄

m_hBitmap = NULL; //DIB对应的DIBSECTION的句柄

m_pPalette = NULL; //和DIB相关的CPalette调色板对象

m_pBitmap = NULL; //和DIB相关的CBitmap DDB对象

m_hNewDib = NULL;

m_DirtSize.cx = 5;

m_DirtSize.cy = 5;

m_minDirtSize.cx = 2;

m_minDirtSize.cy = 2;

m_dirRect = NULL;

}

CArdpsImg::CArdpsImg(const CArdpsImg &ArdSrc)

{

if (this != &ArdSrc)

{

Destroy();

if (m_pBitmap != NULL)

{

delete m_pBitmap;

m_pBitmap = NULL;

}

if (m_pPalette != NULL)

{

delete m_pPalette;

m_pPalette = NULL;

}

if( m_dirRect )

{

delete []m_dirRect;

m_dirRect = NULL;

}

if ( m_pMemDC )

{

delete m_pMemDC;

m_pMemDC = NULL;

}

this->m_hDib = ArdSrc.m_hDib;

this->m_hNewDib = ArdSrc.m_hNewDib;

this->m_pBitmap = ArdSrc.m_pBitmap;

this->m_pPalette = ArdSrc.m_pPalette;

this->m_dirRect = ArdSrc.m_dirRect;

this->m_pMemDC = ArdSrc.m_pMemDC;

this->m_pPaletteTmp = ArdSrc.m_pPaletteTmp;

this->m_pBitmapTmp = ArdSrc.m_pBitmapTmp;

this->m_DirtSize = ArdSrc.m_DirtSize;

this->m_minDirtSize = ArdSrc.m_minDirtSize;

this->m_dirRect = ArdSrc.m_dirRect;

}

}

CArdpsImg::~CArdpsImg(void)

{

Destroy();

if (m_pBitmap != NULL)

{

delete m_pBitmap;

m_pBitmap = NULL;

}

if (m_pPalette != NULL)

{

delete m_pPalette;

m_pPalette = NULL;

}

if( m_dirRect )

{

delete []m_dirRect;

m_dirRect = NULL;

}

}

CArdpsImg & CArdpsImg::operator =(const CArdpsImg &ArdSrc)

{

if (this != &ArdSrc)

{

Destroy();

if (m_pBitmap != NULL)

{

delete m_pBitmap;

m_pBitmap = NULL;

}

if (m_pPalette != NULL)

{

delete m_pPalette;

m_pPalette = NULL;

}

if( m_dirRect )

{

delete []m_dirRect;

m_dirRect = NULL;

}

if ( m_pMemDC )

{

delete m_pMemDC;

m_pMemDC = NULL;

}

this->m_hDib = ArdSrc.m_hDib;

this->m_hNewDib = ArdSrc.m_hNewDib;

this->m_pBitmap = ArdSrc.m_pBitmap;

this->m_pPalette = ArdSrc.m_pPalette;

this->m_dirRect = ArdSrc.m_dirRect;

this->m_pMemDC = ArdSrc.m_pMemDC;

this->m_pPaletteTmp = ArdSrc.m_pPaletteTmp;

this->m_pBitmapTmp = ArdSrc.m_pBitmapTmp;

this->m_DirtSize = ArdSrc.m_DirtSize;

this->m_minDirtSize = ArdSrc.m_minDirtSize;

this->m_dirRect = ArdSrc.m_dirRect;

}

return *this;

}

void CArdpsImg::Serialize(CArchive& ar)

{

CObject::Serialize(ar);

ar.Flush();

if (ar.IsStoring())

{

Write(ar.GetFile());

}

else

{

Read(ar.GetFile());

}

}

bool CArdpsImg::Read(CFile *pFile)

{

WaitCursorBegin();

LPBITMAPINFOHEADER lpbi;

DWORD dwSize;

TRY

{

// read DIB file header

BITMAPFILEHEADER bmfHdr;

pFile->Read(&bmfHdr, sizeof(BITMAPFILEHEADER));

// is DIB file?

if (bmfHdr.bfType != DIB_HEADER_MARKER/*"BM"*/)

{

WaitCursorEnd();

return false;

}

DWORD dwLength = pFile->GetLength();

if (bmfHdr.bfSize != dwLength)

bmfHdr.bfSize = dwLength;

// read DIB buffer

dwSize = bmfHdr.bfSize - sizeof(BITMAPFILEHEADER);

lpbi = (LPBITMAPINFOHEADER)GlobalAllocPtr(GHND, dwSize);

DWORD dwCount = pFile->Read(lpbi, dwSize);

// read ok?

if (dwCount != dwSize)

{

GlobalFreePtr(lpbi);

WaitCursorEnd();

return false;

}

// Check to see that it's a Windows DIB -- an OS/2 DIB would cause

// strange problems with the rest of the DIB API since the fields

// in the header are different and the color table entries are

// smaller.

//

// If it's not a Windows DIB (e.g. if biSize is wrong), return NULL.

if (lpbi->biSize != sizeof(BITMAPINFOHEADER))

{

GlobalFreePtr(lpbi);

WaitCursorEnd();

return false;

}

// fill color num item

int nNumColors = (UINT)lpbi->biClrUsed;

if (nNumColors == 0)

{

// no color table for 24-bit, default size otherwise

if (lpbi->biBitCount != 24)

nNumColors = 1 << lpbi->biBitCount; // standard size table

}

// fill in some default values if they are zero

if (lpbi->biClrUsed == 0)

lpbi->biClrUsed = nNumColors;

if (lpbi->biSizeImage == 0)

lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) * lpbi->biHeight;

}

CATCH (CException, e)

{

GlobalFreePtr(lpbi);

WaitCursorEnd();

return false;

}

END_CATCH

// create CDib with DIB buffer

bool bSuccess = Create((LPBYTE)lpbi);

GlobalFreePtr(lpbi);

WaitCursorEnd();

return bSuccess;

}

///////////////////////////////////////////////////////////////////////

//从DIB数据块创建默认CDib对象

///////////////////////////////////////////////////////////////////////

bool CArdpsImg::Create(LPBYTE lpDIB)

{

if (lpDIB == NULL)

return false;

DWORD dwSize = DIBlockSize(lpDIB);

HDIB hDib = GlobalAlloc(GHND, dwSize);

// Check that DIB handle is valid

if (! hDib)

return false;

LPBYTE lpbi = (LPBYTE)GlobalLock(hDib);

if (! lpbi)

return false;

CopyMemory(lpbi, lpDIB, dwSize);

GlobalUnlock(hDib);

Destroy();

m_hDib = hDib;

LPBYTE ptmp = (LPBYTE) GlobalLock(m_hDib);

return UpdateInternal();

}

//*******************************************************************

// 功能:调用DIBToDIBSection函数,创建并更新DIB的DIBSECTION和DDB

//*******************************************************************

bool CArdpsImg::BuildBitmap()

{

if (m_pBitmap != NULL)

{

delete m_pBitmap;

m_pBitmap = NULL;

m_hBitmap = NULL;

}

m_hBitmap = DIBToDIBSection(m_hDib);

if (m_hBitmap == NULL)

return false;

m_pBitmap = new CBitmap;

m_pBitmap->Attach(m_hBitmap);

return true;

}

//*******************************************************************

//该函数调用CreateDIBPalette函数,创建并更新DIB调色板

//*******************************************************************

bool CArdpsImg::BuildPalette()

{

if (m_pPalette != NULL)

{

delete m_pPalette;

m_pPalette = NULL;

}

HPALETTE hPalette = CreateDIBPalette(m_hDib);

if (hPalette == NULL)

return false;

m_pPalette = new CPalette;

m_pPalette->Attach(hPalette);

return true;

}

//*******************************************************************

//UpdateInternal function 更新CDib对象所对应的调色板、DIBSECTION、DDB对象

//调用BuildPlaette 和BuildBitmap函数,重建CDib对象的,m_pPalette、m_hBitmap

//和m_pBitmap 成员数据

bool CArdpsImg::UpdateInternal()

{

BuildPalette();

return BuildBitmap();

}

void CArdpsImg::Destroy()

{

if (m_hDib != NULL)

{

DestroyDIB(m_hDib);

m_hDib = NULL;

}

if( m_hNewDib != NULL )

{

DestroyDIB(m_hNewDib);

m_hNewDib = NULL;

}

}

///////////////////////////////////////////////////////////////////////

//从DIB数据块创建CDib对象

///////////////////////////////////////////////////////////////////////

bool CArdpsImg::Create(LPBYTE lpDIB, WORD wBitCount) // bits/pixel

{

if (lpDIB == NULL)

return false;

if (! Create(lpDIB))

return false;

WORD wBits = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;

if (wBitCount == wBits)

return true;

HDIB hNewDib = ConvertDIBFormat(m_hDib, wBitCount, NULL);

if (! hNewDib)

return false;

Destroy();

m_hDib = hNewDib;

return UpdateInternal();

}

CPalette* CArdpsImg::GetPalette()

{

return m_pPalette;

}

bool CArdpsImg::Write(CFile *pFile)

{

WaitCursorBegin();

BITMAPFILEHEADER bmfHdr; // Header for Bitmap file

LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure

DWORD dwDIBSize;

// Get a pointer to the DIB memory, the first of which contains

// a BITMAPINFO structure

lpBI = (LPBITMAPINFOHEADER)GlobalLock(m_hDib);

if (!lpBI)

{

GlobalUnlock(m_hDib);

WaitCursorEnd();

return false;

}

// Check to see if we're dealing with an OS/2 DIB. If so, don't

// save it because our functions aren't written to deal with these

// DIBs.

if (lpBI->biSize != sizeof(BITMAPINFOHEADER))

{

GlobalUnlock(m_hDib);

WaitCursorEnd();

return false;

}

// Fill in the fields of the file header

// Fill in file type (first 2 bytes must be "BM" for a bitmap)

bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"

// Calculating the size of the DIB is a bit tricky (if we want to

// do it right). The easiest way to do this is to call GlobalSize()

// on our global handle, but since the size of our global memory may have

// been padded a few bytes, we may end up writing out a few too

// many bytes to the file (which may cause problems with some apps,

// like HC 3.0).

//

// So, instead let's calculate the size manually.

//

// To do this, find size of header plus size of color table. Since the

// first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains

// the size of the structure, let's use this.

// Partial Calculation

dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPBYTE)lpBI);

// Now calculate the size of the image

// It's an RLE bitmap, we can't calculate size, so trust the biSizeImage

// field

if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))

dwDIBSize += lpBI->biSizeImage;

else

{

DWORD dwBmBitsSize; // Size of Bitmap Bits only

// It's not RLE, so size is Width (DWORD aligned) * Height

dwBmBitsSize = MYWIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) *

lpBI->biHeight;

dwDIBSize += dwBmBitsSize;

// Now, since we have calculated the correct size, why don't we

// fill in the biSizeImage field (this will fix any .BMP files which

// have this field incorrect).

lpBI->biSizeImage = dwBmBitsSize;

}

// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)

bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);

bmfHdr.bfReserved1 = 0;

bmfHdr.bfReserved2 = 0;

// Now, calculate the offset the actual bitmap bits will be in

// the file -- It's the Bitmap file header plus the DIB header,

// plus the size of the color table.

bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize +

PaletteSize((LPBYTE)lpBI);

TRY

{

// Write the file header

pFile->Write(&bmfHdr, sizeof(BITMAPFILEHEADER));

// write DIB buffer

pFile->Write(lpBI, dwDIBSize);

}

CATCH (CException, e)

{

GlobalUnlock(m_hDib);

WaitCursorEnd();

return false;

}

END_CATCH

GlobalUnlock(m_hDib);

WaitCursorEnd();

return true;

}

bool CArdpsImg::IsEmpty()

{

if (m_hDib == NULL)

return true;

if (! GlobalLock(m_hDib))

return true;

GlobalUnlock(m_hDib);

return false;

}

bool CArdpsImg::Display(CDC * pDC, int x, int y, DWORD dwRop)

{

CDC MemDC;

MemDC.CreateCompatibleDC(pDC);

CBitmap* pOldBmp = MemDC.SelectObject(m_pBitmap);

CPalette* pOldPal = pDC->SelectPalette(m_pPalette, true);

pDC->RealizePalette();

bool bSuccess = pDC->BitBlt(x, y,

GetWidth(), GetHeight(),

&MemDC,

0, 0,

dwRop);

MemDC.SelectObject(pOldBmp);

pDC->SelectPalette(pOldPal, true);

return bSuccess;

}

WORD CArdpsImg::GetBitCount()

{

LPBITMAPINFOHEADER lpBI = (LPBITMAPINFOHEADER)GlobalLock(m_hDib);

if (!lpBI)

{

GlobalUnlock(m_hDib);

return 0;

}

WORD wBitCount = lpBI->biBitCount;

GlobalUnlock(m_hDib);

return wBitCount;

}

LONG CArdpsImg::GetWidth()

{

// get DIB buffer pointer

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

if (! lpDIB)

{

GlobalUnlock(m_hDib);

return 0;

}

LONG lWidth = (LONG)DIBWidth(lpDIB);

GlobalUnlock(m_hDib);

return lWidth;

}

LONG CArdpsImg::GetHeight()

{

// get DIB buffer pointer

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

if (! lpDIB)

{

GlobalUnlock(m_hDib);

return 0;

}

LONG lHeight = (LONG)DIBHeight(lpDIB);

GlobalUnlock(m_hDib);

return lHeight;

}

LONG CArdpsImg::GetWidthBytes()

{

return MYWIDTHBYTES((GetWidth())*((DWORD)GetBitCount()));

//return WIDTHBYTES((GetWidth())*((int)GetBitCount()));

}

LPBYTE CArdpsImg::GetBitsPtr()

{

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

if (! lpDIB)

{

GlobalUnlock(m_hDib);

return NULL;

}

LPBYTE lpData = FindDIBBits(lpDIB);

GlobalUnlock(m_hDib);

return lpData;

}

HANDLE CArdpsImg::GetHandle()

{

return m_hDib;

}

WORD CArdpsImg::GetColorNumber()

{

LPBYTE lpBI = (LPBYTE)GlobalLock(m_hDib);

if (! lpBI)

{

GlobalUnlock(m_hDib);

return 0;

}

WORD wColors = DIBNumColors(lpBI);

GlobalUnlock(m_hDib);

return wColors;

}

WORD CArdpsImg::GetPaletteSize()

{

LPBYTE lpBI = (LPBYTE)GlobalLock(m_hDib);

if (! lpBI)

{

GlobalUnlock(m_hDib);

return 0;

}

WORD wPalSize = PaletteSize(lpBI);

GlobalUnlock(m_hDib);

return wPalSize;

}

bool CArdpsImg::Attach(HDIB hDib)

{

if (hDib == NULL)

return false;

Destroy();

m_hDib = hDib;

return UpdateInternal();

}

bool CArdpsImg::ConvertFormat(WORD wBitCount)

{

if (IsEmpty())

return false;

if (GetBitCount() == wBitCount)

return true;

HDIB hNewDib = ConvertDIBFormat(m_hDib, wBitCount, NULL);

if (! hNewDib)

return false;

Destroy();

m_hDib = hNewDib;

return UpdateInternal();

}

/*

功能:加载其他图像格式,支持jpg、tiff格式

输入:

szImgFileName:文件名;

输出:

bBmp:加载成功,转换成DIB句柄

*/

HANDLE CArdpsImg::LoadNonDibHandle(BOOL *bBmp, char* szImgFileName)

{

*bBmp = FALSE;

char drive[_MAX_DRIVE];

char dir[_MAX_DIR];

char fname[_MAX_FNAME];

char ext[_MAX_EXT];

char szName[256];

typedef HANDLE (WINAPI * PGETDIBPROC)(HWND, char *, HANDLE);

PGETDIBPROC lpFun;

HANDLE hDib;

HINSTANCE hConvertLib = LoadLibrary("Convert.dll");

ASSERT(hConvertLib != NULL);

strcpy(szName, szImgFileName);

_splitpath(szName, drive, dir, fname, ext);

strcpy(szName, ext);

strlwr(szName);

if(strcmp(szName,".tif") == 0 || strcmp(szName, ".tiff") == 0)

{

//lpFun = (PGETDIBPROC)GetProcAddress(hConvertLib, "Tiff2HDIB");

/*hDib = LoadTiff(szImgFileName);*/

hDib = ReadBinTiff(szImgFileName);

return hDib;

}

else if(strcmp(szName,".jpg") == 0 || strcmp(szName,".jpeg") == 0 || strcmp(szName,".jpe") == 0 )

{

lpFun = (PGETDIBPROC)GetProcAddress(hConvertLib, "Jpg2HDIB");

}

else

{

if(hConvertLib)

{

FreeLibrary(hConvertLib);

}

*bBmp = TRUE;

return NULL;

}

ASSERT(lpFun != NULL);

freopen("nul", "w", stdout);

hDib = (*lpFun) ( NULL, szImgFileName, NULL);

freopen("con", "w", stdout);

if(hConvertLib)

{

FreeLibrary(hConvertLib);

}

return hDib;

}

/*

功能:BMP转换为其他图像格式

输入:

hDib:当前图像句柄;

strFileName:文件名;

nDestFileExtType:在ImgConv.h中定义

输出:

true:存储成功

*/

bool CArdpsImg::SaveNonDIB(HDIB hDib, CString strFileName, ImageType nDestFileExtType)

{

HMODULE hDll = LoadLibrary("ImgConv.dll");

if (hDll == NULL)

{

return false;

}

PFN_ImageConvert ImageConvert = (PFN_ImageConvert)GetProcAddress(hDll, "ImageConvert");

PFN_ImageDelete ImageDelete = (PFN_ImageDelete)GetProcAddress(hDll, "ImageDelete");

if (ImageConvert == NULL || ImageDelete == NULL)

{

FreeLibrary(hDll);

return false;

}

LPBITMAPINFOHEADER lpBI = (LPBITMAPINFOHEADER)GlobalLock(m_hDib);

bool bSave = false;

BITMAPFILEHEADER bmfHdr;

bool bInit = InitDIBFileHead(lpBI, &bmfHdr);

if( !bInit )

{

GlobalUnlock(m_hDib);

FreeLibrary(hDll);

return false;

}

unsigned char *pbSrc = new unsigned char [bmfHdr.bfSize];

if( !pbSrc )

{

GlobalUnlock(m_hDib);

FreeLibrary(hDll);

return false;

}

memcpy(pbSrc, &bmfHdr, sizeof(BITMAPFILEHEADER));

memcpy(pbSrc + sizeof(BITMAPFILEHEADER), lpBI, lpBI->biSizeImage * sizeof(unsigned char));

unsigned char * pDestData = NULL;

int nDestDataLen = 0;

bool bSuccess = false;

bSuccess = ImageConvert(pbSrc, bmfHdr.bfSize , imgBMP, &pDestData, &nDestDataLen, nDestFileExtType);

if( bSuccess )

{

FILE * pFile = fopen(strFileName, "wb");

if (pFile != NULL)

{

fwrite(pDestData, sizeof(unsigned char), nDestDataLen, pFile);

fclose(pFile);

ImageDelete(&pDestData);

bSave = true;

}

}

if (pbSrc)

{

delete []pbSrc;

pbSrc = NULL;

}

FreeLibrary(hDll);

GlobalUnlock(m_hDib);

return bSave;

}

bool CArdpsImg::InitDIBFileHead(LPBITMAPINFOHEADER lpBI, BITMAPFILEHEADER *lpbmfHdr )

{

if( !lpBI || !lpbmfHdr )

return false;

//BITMAPFILEHEADER bmfHdr;

lpbmfHdr->bfType = DIB_HEADER_MARKER; // "BM"

DWORD dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPBYTE)lpBI);

if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))

dwDIBSize += lpBI->biSizeImage;

else

{

DWORD dwBmBitsSize; // Size of Bitmap Bits only

// It's not RLE, so size is Width (DWORD aligned) * Height

dwBmBitsSize = MYWIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) *

lpBI->biHeight;

dwDIBSize += dwBmBitsSize;

// Now, since we have calculated the correct size, why don't we

// fill in the biSizeImage field (this will fix any .BMP files which

// have this field incorrect).

lpBI->biSizeImage = dwBmBitsSize;

}

lpbmfHdr->bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);

lpbmfHdr->bfReserved1 = 0;

lpbmfHdr->bfReserved2 = 0;

lpbmfHdr->bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize + PaletteSize((LPBYTE)lpBI);

return true;

}

ImageType CArdpsImg::GetFileExtType(CString strExt)

{

if (strExt. CompareNoCase ("bmp") == 0 || strExt.CompareNoCase("dib") == 0 )

{

return imgBMP;

}

else if (strExt.CompareNoCase("gif") == 0 )

{

return imgGIF;

}

else if (strExt.CompareNoCase("jpg") == 0 )

{

return imgJPG;

}

else if (strExt.CompareNoCase("jpeg") == 0 || strExt.CompareNoCase("jpe") == 0 )

{

return imgJPEG;

}

else if (strExt.CompareNoCase("png") == 0 )

{

return imgPNG;

}

else if (strExt.CompareNoCase("tiff") || strExt.CompareNoCase("tif"))

{

return imgTIFF;

}

else

{

return imgBMP;

}

}

/*

功能:转换为灰度图像

输入:

nMethod:二值化方法;默认为0,加权平均方法;1为最大值;

uiGWeight,uiGWeight,uiBWeight:红、绿、蓝色分量

输出:

true:灰度化成功

*/

bool CArdpsImg::ConvertGray(int nMethod, UINT uiRWeight /* = 114 */, UINT uiGWeight /* = 587 */, UINT uiBWeight /* = 229 */)

{

LPBITMAPINFOHEADER lpDIBHdr = (LPBITMAPINFOHEADER)GlobalLock(m_hDib);

//for color image

LONG nImgHei = GetHeight();

LONG nImgWid = GetWidth();

LONG nOriBytesPerLine = GetWidthBytes();

int nBitCnt = GetBitCount();

if( nBitCnt < 24 )

{

GlobalUnlock(m_hDib);

return false;

}

//for gray image

LONG nGrayBytesPerLine = MYWIDTHBYTES( nImgWid << 3 );

LONG nGrayImgSize = nGrayBytesPerLine * nImgHei;

LONG nFileSize = nGrayImgSize + lpDIBHdr->biSize + 256 * sizeof(RGBQUAD);

//allocate memory for gray image

LPBYTE lpNewDIB = new BYTE[nFileSize];

if( !lpNewDIB )

{

GlobalUnlock(m_hDib);

return false;

}

memset(lpNewDIB, 0, nFileSize*sizeof(BYTE));

LPBITMAPINFOHEADER lpNewDIBHdr = (LPBITMAPINFOHEADER)lpNewDIB;

memcpy(lpNewDIBHdr, lpDIBHdr, sizeof(BITMAPINFOHEADER));

GlobalUnlock(m_hDib);

lpNewDIBHdr->biBitCount = 8;

lpNewDIBHdr->biCompression = BI_RGB;

lpNewDIBHdr->biSizeImage = nGrayImgSize;

lpNewDIBHdr->biClrUsed = 256;

//create RGBQUARD

RGBQUAD *pNewRGBQuad = (RGBQUAD*)(lpNewDIB +sizeof(BITMAPINFOHEADER));

memset(pNewRGBQuad, 0, 256*sizeof(RGBQUAD));

for( int i = 0; i < 256; ++i )

{

pNewRGBQuad->rgbBlue = pNewRGBQuad->rgbRed =

pNewRGBQuad->rgbGreen = i;

pNewRGBQuad++;

}

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

LPBYTE lpImg = FindDIBBits(lpDIB);

LPBYTE lpNewImg = lpNewDIB + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);

LPBYTE lpOritmp = lpImg;

LPBYTE lpNewtmp = lpNewImg;

int j, k, m, n, nStep = nBitCnt >> 3;

switch (nMethod)

{

case 0:

for( j = 0, m = 0, n = 0; j < nImgHei; ++j , m += nOriBytesPerLine, n += nGrayBytesPerLine )

{

lpNewtmp = lpNewImg + n;

lpOritmp = lpImg + m;

for( k = 0; k < nImgWid; ++k, lpNewtmp ++ )

{

*lpNewtmp = BYTE(( (*lpOritmp) *uiRWeight +

*(lpOritmp + 1) * uiGWeight + *(lpOritmp + 2) * uiBWeight )/1000);

lpOritmp += nStep;

}

}

break;

case 1:

default:

for( j = 0, m = 0, n = 0; j < nImgHei; ++j , m += nOriBytesPerLine, n += nGrayBytesPerLine )

{

lpNewtmp = lpNewImg + n;

lpOritmp = lpImg + m;

for( k = 0; k < nImgWid; ++k, lpNewtmp ++ )

{

*lpNewtmp = BYTE( max(max ( (*lpOritmp), *(lpOritmp + 1) ), *(lpOritmp + 2) ));

lpOritmp += nStep;

}

}

break;

}

GlobalUnlock(m_hDib);

bool bCrate = Create(lpNewDIB);

if( lpNewDIB )

{

delete []lpNewDIB;

lpNewDIB = NULL;

}

return true;

}

/*

功能:对灰度图像进行二值化

输入:

nMethod:二值化方法;默认为0,OTSU方法;1为均值;2:为给定阈值方法

nTh:二值化阈值

输出:

true:二值化成功

*/

bool CArdpsImg::ConvertBinary(int nMethod /* = 0 */, int nTh /* = 0 */)

{

//for image

int nBitCnt = GetBitCount();

//for gray image

LONG nGrayBytesPerLine = GetWidthBytes();

if( nBitCnt > 8 )

{

bool bGray = ConvertGray(0);

if(!bGray)

{

return false;

}

//lpDIBHdr = (LPBITMAPINFOHEADER)GlobalLock(m_hDib);

}

else if( nBitCnt == 1)

{

return true;

}

LPBITMAPINFOHEADER lpDIBHdr = (LPBITMAPINFOHEADER)GlobalLock(m_hDib);

LONG nImgHei = GetHeight();

LONG nImgWid = GetWidth();

//for binary image

LONG nBinaryBytesPerLine = MYWIDTHBYTES( nImgWid );

LONG nBinaryImgSize = nBinaryBytesPerLine * nImgHei;

LONG nFileSize = nBinaryImgSize + lpDIBHdr->biSize + 2 * sizeof(RGBQUAD);

//allocate memory for binary image

LPBYTE lpNewDIB = new BYTE[nFileSize];

if( !lpNewDIB )

{

GlobalUnlock(m_hDib);

return false;

}

memset(lpNewDIB, 0, nFileSize*sizeof(BYTE));

LPBITMAPINFOHEADER lpNewDIBHdr = (LPBITMAPINFOHEADER)lpNewDIB;

memcpy(lpNewDIBHdr, lpDIBHdr, sizeof(BITMAPINFOHEADER));

GlobalUnlock(m_hDib);

lpNewDIBHdr->biBitCount = 1;

lpNewDIBHdr->biCompression = 0;

lpNewDIBHdr->biSizeImage = nBinaryImgSize;

lpNewDIBHdr->biClrUsed = 2;

lpNewDIBHdr->biXPelsPerMeter = 0;

lpNewDIBHdr->biYPelsPerMeter = 0;

//create RGBQUARD

RGBQUAD *pNewRGBQuad = (RGBQUAD*)(lpNewDIB +sizeof(BITMAPINFOHEADER));

pNewRGBQuad->rgbRed = pNewRGBQuad->rgbGreen = pNewRGBQuad->rgbBlue

= 0;

pNewRGBQuad->rgbReserved = 0;

pNewRGBQuad++;

pNewRGBQuad->rgbRed = pNewRGBQuad->rgbGreen = pNewRGBQuad->rgbBlue

= 255;

pNewRGBQuad->rgbReserved = 0;

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

LPBYTE lpImg = FindDIBBits(lpDIB);

LPBYTE lpNewImg = lpNewDIB + sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD);

LPBYTE lpOritmp = lpImg;

LPBYTE lpNewtmp = lpNewImg;

int nStep = nBitCnt >> 3;

bool bResult = false;

switch (nMethod)

{

case 1:

nTh = 0;

bResult = IntensityMean( lpImg, nImgWid, nImgHei, nTh );

break;

case 2:

bResult = true;

break;

case 0:

default:

nTh = 0;

OtsuTh(nImgWid, nImgHei, lpImg, nTh);

bResult = true;

break;

}

if( bResult )

bResult = ThreshImage(lpImg, lpNewImg, nImgWid, nImgHei, nTh);

GlobalUnlock(m_hDib);

bool bCrate = Create(lpNewDIB);

if (lpNewDIB)

{

delete []lpNewDIB;

lpNewDIB = NULL;

}

return bCrate;

}

/*

功能:利用Otsu方法计算二值化的阈值

输入:

lpBits:灰度图像内存指针

nW:图像宽度

nH:图像高度

输出:

Th:图像灰度均值

*/

void CArdpsImg:: OtsuTh( DWORD nW, DWORD nH, BYTE *lpBits, int &Th)

{

UINT i;

float bmax;

float counter1,counter2;

float mean1,mean2;

int TH, threshold, k, deta;

float sum1,sum2;

int buf[256];

memset(buf, 0, 256 * sizeof(int));

if( !GetGrayHist(lpBits, nW, nH, buf) )

return;

for ( i = 0; i < 256; i ++)

{

bufi[i] = i * buf[i];

}

deta = 10; //计算阈值的步长,以加快求解速度。

counter1 = 0;

for ( TH = 0; TH < 256; TH += deta )

{

counter1 = counter2=0;

sum1 = sum2=0.0;

for( k = 0; k <= TH; k++ )

{

counter1 += buf[k];

sum1 += bufi[k];

}

for( k = TH + 1; k < 256; k++ )

{

counter2 += buf[k];

sum2 += bufi[k];

}

if ( counter1>0 ) mean1= sum1/counter1;

else mean1=0;

if ( counter2>0 ) mean2= sum2/counter2;

else mean2=0;

varience=counter1*counter2*(mean1-mean2)*(mean1-mean2);

}

bmax=varience[0]; threshold=0;

for ( TH=0; TH<256; TH += deta )

{

if( bmax<varience)

{

bmax=varience;

threshold=TH;

}

}

Th=threshold;

}

/*

功能:计算图像的灰度均值

输入:

pbGray:灰度图像内存指针

nImgWid:图像宽度

nImgHei:图像高度

输出:

nIntenMean:图像灰度均值

*/

bool CArdpsImg::IntensityMean(const BYTE *pbGray, const int nImgWid, const int nImgHei, int &nIntenMean )

{

if( pbGray == NULL || nImgHei <= 0 || nImgWid <= 0 )

return false;

int nSum = 0;

nIntenMean = 0;

for( int i = 0; i < nImgHei * nImgWid; i++ )

{

nSum += *pbGray ++;

}

nIntenMean = BYTE(nSum /((nImgHei * nImgWid) + 1));

return true;

}

bool CArdpsImg::ThreshImage(const BYTE *pbImg, BYTE *pbBinary, const int nImgWid, const int nImgHei, const int nTh )

{

if( pbImg == NULL || pbBinary== NULL )

return false;

LONG nGrayPerLine = MYWIDTHBYTES(nImgWid << 3);

LONG nBinaryPerLine = MYWIDTHBYTES(nImgWid);

const BYTE *pbIn = pbImg;

BYTE *pbOut = pbBinary;

BYTE tmp = 0;

for( int i = 0, m = 0, n = 0; i < nImgHei; ++i )

{

pbIn = pbImg + m;

pbOut = pbBinary + n;

for(int j = 0; j < nImgWid/8; ++j )

{

tmp = 0;

if( *pbIn > nTh )

tmp = tmp | 128;

++pbIn;

if( *pbIn > nTh )

tmp = tmp | 64;

++pbIn;

if( *pbIn > nTh )

tmp = tmp | 32;

++pbIn;

if( *pbIn > nTh )

tmp = tmp | 16;

++pbIn;

if( *pbIn > nTh )

tmp = tmp | 8;

++pbIn;

if( *pbIn > nTh )

tmp = tmp | 4;

++pbIn;

if( *pbIn > nTh )

tmp = tmp | 2;

++pbIn;

if( *pbIn > nTh )

tmp = tmp | 1;

++pbIn;

*pbOut ++ = tmp;

}

tmp = 0;

for( int k = 0; k < nImgWid % 8; k++, pbIn++ )

{

if( *pbIn > nTh )

{

tmp += 1;

}

tmp = tmp << 1;

}

*pbOut = tmp << (8 - nImgWid % 8 - 1);

m += nGrayPerLine;

n += nBinaryPerLine;

}

return true;

}

/******************************************************************

功能:灰度图像的均衡化,使得像素在灰度阶上尽量均匀

输入:

当前图像的内存句柄

输出:

灰度成功返回true

******************************************************************/

bool CArdpsImg::GrayEqual()

{

if(IsEmpty())

return false;

if( !GrayEqualize(m_hDib))

return false;

return UpdateInternal();

}

/****************************************************************************

功能:对灰度图像进行拉伸

输入:

nMethod:灰度图像内存指针。

(x1,y1):拉伸曲线的第一点坐标

(x2,y2):拉伸曲线的第二点坐标

*(255,255)

*

* (x2,y2)

*

*

*

*(x1,y1)

*

*(0,0)

nMethod = 0:根据直方图自动计算第一点和第二点坐标,阈值取累积直方图的10%~90%。

nMethod = 1:根据输入的坐标进行计算

输出:

操作成功返回True。

**********************************************************************************/

bool CArdpsImg::GrayStretch(int nMethod, BYTE x1 = 0 , BYTE y1 = 0 , BYTE x2 = 255, BYTE y2 = 255 )

{

if(IsEmpty())

return false;

if(!GrayStretchDIB(nMethod, m_hDib, x1, y1, x2, y2) )

return false;

return UpdateInternal();

}

/*******************************************************************

功能:去除矩形区域二值化图像的污点

输入:

nMethod = 0:去污,选中区域如果为白色占主要部分则变成黑色

否则相反。

nMethod = 1 :磨白,把选中的区域变成白色

nMethod = 2:填充,把选中的区域变成黑色

rct:选中的处理区域

输出:

去除成功

*******************************************************************/

bool CArdpsImg::EliminateDirt(int nMethod, const CRect rct)

{

if ( rct.IsRectEmpty() || IsEmpty() )

return false;

// Convert the physical coordinate into imaging coordinate

if( GetBitCount() > 1 )

return false;

if(!EliminateDirtDIB(nMethod, m_hDib, rct) )

return false;

return UpdateInternal();

}

/*******************************************************************

功能:去除圆形区域二值化图像的污点

输入:

nMethod = 0:去污,选中区域如果为白色占主要部分则变成黑色

否则相反。

nMethod = 1 :磨白,把选中的区域变成白色

nMethod = 2:填充,把选中的区域变成黑色

rct:选中的处理区域

输出:

去除成功

*******************************************************************/

bool CArdpsImg::EliminateDirt(int nMethod, const int nCircleX, const int nCircleY, const int nRadius)

{

if( IsEmpty() || nCircleX < 0 || nCircleY < 0 || nRadius < 0 )

return false;

if( GetBitCount() > 1 )

return false;

if(!EliminateDirtDIB(nMethod, m_hDib, nCircleX, nCircleY, nRadius) )

return false;

return UpdateInternal();

}

/******************************************************************

功能:设置污点的大小

输入:

sz,污点大小,小于sz为污点

******************************************************************/

void CArdpsImg::SetDirtSize(CSize szMax, CSize szMin)

{

m_DirtSize = szMax;

m_minDirtSize = szMin;

}

/******************************************************************

功能:自动去除图像中的小于一定面积的污点

输入:

nMethod,去除0黑色污点,1去除白色污点

nMinArea,污点的最大面积,小于该污点的像素区域将被作为污点

输出:

去除成功返回true

******************************************************************/

bool CArdpsImg::AutoEliminateDirt(int nMethod, int nMinArea)

{

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

if( !lpDIB)

return false;

LPBYTE lpBinImg = FindDIBBits(lpDIB);

if( !lpBinImg )

{

GlobalUnlock(m_hDib);

return false;

}

bool bSuccess = true;

LONG nImgHei = GetHeight();

LONG nImgWid = GetWidth();

int nBitCnt = DIBBitCount(lpDIB);

if( nBitCnt != 1 )

{

GlobalUnlock(m_hDib);

return false;

}

LONG nBinBytesPerLine = MYWIDTHBYTES(nImgWid * nBitCnt);

//for gray image

LONG nGrayBytesPerLine = MYWIDTHBYTES( nImgWid << 3 );

LONG nGrayImgSize = nGrayBytesPerLine * nImgHei;

BYTE *pbGrayImg = new BYTE[nGrayImgSize];

if( !pbGrayImg )

{

GlobalUnlock(m_hDib);

return false;

}

bSuccess = ConvertBinary2Gray(lpBinImg, nImgWid, nImgHei, pbGrayImg );

//SaveTo8bit_BMP(pbGrayImg, nImgWid, nImgHei, "d:\\testgray.bmp", 8);

if( !bSuccess )

{

delete []pbGrayImg;

pbGrayImg = NULL;

GlobalUnlock(m_hDib);

return false;

}

Line *Li = new Line;

if( !Li )

{

delete []pbGrayImg;

pbGrayImg = NULL;

GlobalUnlock(m_hDib);

return false;

}

Li->StartY = 3;

Li->StartX = 3;

Li->EndX = nImgWid - 3;

Li->EndY = nImgHei - 3;

Li->cp = NULL;

BYTE bCur;

if( nMethod == 0 ) //黑色为背景

{

bCur = 0;

}

else

{

bCur = 255;

}

ExtractComponent(Li, pbGrayImg, nGrayBytesPerLine, bCur );

AnalysisComponent(Li, pbGrayImg, nGrayBytesPerLine, nMinArea, 255- bCur);

// SaveTo8bit_BMP(pbGrayImg, nImgWid, nImgHei, "d:\\testcom.bmp", 8);

ThreshImage(pbGrayImg, lpBinImg, nImgWid, nImgHei, 128);

if( pbGrayImg )

{

delete []pbGrayImg;

pbGrayImg = NULL;

}

if( Li )

{

delete Li;

Li = NULL;

}

GlobalUnlock(m_hDib);

return UpdateInternal();

}

bool CArdpsImg::AutoEliminateDirt(int nMethod, CRect *pRect, int *pFlag, const int nNum)

{

if( !pRect || !pFlag )

return false;

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

if( !lpDIB)

return false;

LPBYTE lpBinImg = FindDIBBits(lpDIB);

if( !lpBinImg )

{

GlobalUnlock(m_hDib);

return false;

}

bool bSuccess = true;

LONG nImgHei = GetHeight();

LONG nImgWid = GetWidth();

int nBitCnt = DIBBitCount(lpDIB);

if( nBitCnt != 1 )

{

GlobalUnlock(m_hDib);

return false;

}

LONG nBinBytesPerLine = MYWIDTHBYTES(nImgWid * nBitCnt);

//for gray image

LONG nGrayBytesPerLine = MYWIDTHBYTES( nImgWid << 3 );

LONG nGrayImgSize = nGrayBytesPerLine * nImgHei;

BYTE *pbGrayImg = new BYTE[nGrayImgSize];

if( !pbGrayImg )

{

GlobalUnlock(m_hDib);

return false;

}

bSuccess = ConvertBinary2Gray(lpBinImg, nImgWid, nImgHei, pbGrayImg );

if( !bSuccess )

{

delete []pbGrayImg;

pbGrayImg = NULL;

GlobalUnlock(m_hDib);

return false;

}

BYTE bCur;

if( nMethod == 0 ) //黑色为背景

{

bCur = 0;

}

else

{

bCur = 255;

}

CRect tmpRt;

for( int i = 0; i < nNum; i++ )

{

if (pFlag[i] == 1)

{

tmpRt.top = nImgHei - 1 - pRect[i].bottom;

tmpRt.bottom = nImgHei - 1 - pRect[i].top;

tmpRt.left = pRect[i].left;

tmpRt.right = pRect[i].right;

SetBinary(tmpRt, pbGrayImg, nGrayBytesPerLine, 255-bCur);

}

}

ThreshImage(pbGrayImg, lpBinImg, nImgWid, nImgHei, 128);

if( pbGrayImg )

{

delete []pbGrayImg;

pbGrayImg = NULL;

}

GlobalUnlock(m_hDib);

return UpdateInternal();

}

/******************************************************************

功能:以原有图像中心为原点,给定的角度旋转图像

输入:

iRotateAngle,指定旋转的度数,正值为向右旋转,反之向右旋转

输出:

旋转成功返回true

******************************************************************/

bool CArdpsImg::RotateImage(int iRotateAngle /* = 0 */)\

{

// 源图像的宽度和高度

LONG lWidth;

LONG lHeight;

// 旋转后图像的宽度和高度

LONG lNewWidth;

LONG lNewHeight;

// 图像每行的字节数

LONG lLineBytes;

// 旋转后图像的宽度(lNewWidth',必须是4的倍数)

LONG lNewLineBytes;

// 指向源图像的指针

LPBYTE lpDIBBits;

// 指向源象素的指针

LPBYTE lpSrc;

// 旋转后新DIB句柄

HDIB hDIB;

// 指向旋转图像对应象素的指针

LPBYTE lpDst;

// 指向旋转图像的指针

LPBYTE lpNewDIB;

LPBYTE lpNewDIBBits;

// 指向BITMAPINFO结构的指针(Win3.0)

LPBITMAPINFOHEADER lpbmi;

// 指向BITMAPCOREINFO结构的指针

LPBITMAPCOREHEADER lpbmc;

// 旋转角度(弧度)

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;

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

// 找到源DIB图像象素起始位置

lpDIBBits = FindDIBBits(lpDIB);

// 获取图像的"宽度"(4的倍数)

lWidth = DIBWidth(lpDIB);

WORD dwBitCnt = DIBBitCount(lpDIB);

if (dwBitCnt != 8 && dwBitCnt != 24 && dwBitCnt != 1 )

{

GlobalUnlock(m_hDib);

return false;

}

// 获取图像的高度

lHeight = DIBHeight(lpDIB);

LPBYTE pBin2Gray = NULL;

int lBin2GrayLineBytes = MYWIDTHBYTES(lWidth * 8);

if( dwBitCnt == 1)

{

pBin2Gray = new BYTE[lBin2GrayLineBytes * lHeight];

if( !pBin2Gray )

{

GlobalUnlock(m_hDib);

return false;

}

memset(pBin2Gray, 0, lBin2GrayLineBytes * lHeight);

ConvertBinary2Gray(lpDIBBits, lWidth, lHeight, pBin2Gray);

lpDIBBits = pBin2Gray;

}

// 计算图像每行的字节数

lLineBytes = MYWIDTHBYTES(lWidth * dwBitCnt);

// 将旋转角度从度转换到弧度

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 - 0.5;

fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1 - 0.5;

fDstX2 = fCosa * fSrcX2 + fSina * fSrcY2 - 0.5;

fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2 + 0.5;

fDstX3 = fCosa * fSrcX3 + fSina * fSrcY3 + 0.5;

fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3 - 0.5;

fDstX4 = fCosa * fSrcX4 + fSina * fSrcY4 + 0.5;

fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4 + 0.5;

// 计算旋转后的图像实际宽度

lNewWidth = (LONG) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);

// 计算旋转后的图像高度

lNewHeight = (LONG) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) ) + 0.5);

if( iRotateAngle == 90 || iRotateAngle == 270 )

{

lNewHeight = lWidth;

lNewWidth = lHeight;

}

else if( iRotateAngle == 0 || iRotateAngle == 360 || iRotateAngle == 180 )

{

lNewHeight = lHeight;

lNewWidth = lWidth;

}

lNewLineBytes = MYWIDTHBYTES(lNewWidth * dwBitCnt);

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)

{

GlobalUnlock(m_hDib);

return false;

}

// 锁定内存

lpNewDIB = (LPBYTE)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;

}

LPBYTE pNewGray = NULL;

if( dwBitCnt == 1 )

{

lNewLineBytes = MYWIDTHBYTES(lNewWidth * 8);

lLineBytes = lBin2GrayLineBytes;

pNewGray = new BYTE[lNewLineBytes * lNewHeight];

if( !pNewGray )

{

GlobalUnlock(m_hDib);

if( pBin2Gray )

delete []pBin2Gray;

pBin2Gray = NULL;

GlobalUnlock(hDIB);

GlobalFree(hDIB);

hDIB = NULL;

return false;

}

lpNewDIBBits = pNewGray;

}

LONG i, j, m, i0, j0;

for(i = 0, m = lNewLineBytes*(lNewHeight-1); i < lNewHeight; i++, m -= lNewLineBytes )

{

lpDst = lpNewDIBBits + m;

for(j = 0; j < lNewWidth; 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个象素的指针

if( dwBitCnt == 8 || dwBitCnt == 1 )

{

lpSrc = lpDIBBits + lLineBytes *( lHeight - 1 -i0 )+ j0;

// 复制象素

*lpDst ++= *lpSrc;

}

else if( dwBitCnt == 24 )

{

lpSrc = lpDIBBits + lLineBytes *( lHeight - 1 -i0 )+ j0 * 3;

*lpDst ++ = *lpSrc;

lpSrc++;

*lpDst ++ = *lpSrc;

lpSrc++;

*lpDst ++ = *lpSrc;

}

}

else

{

// 对于源图中没有的象素,直接赋值为255

if( dwBitCnt == 8 || dwBitCnt == 1)

{

* lpDst ++ = 255;

}

else if (dwBitCnt == 24)

{

*lpDst ++ = 255;

*lpDst ++ = 255;

*lpDst ++ = 255;

}

}

}

}

if( dwBitCnt == 1 )

{

lpNewDIBBits = FindDIBBits(lpNewDIB);

ThreshImage(pNewGray, lpNewDIBBits, lNewWidth,lNewHeight, 10);

if( pNewGray )

delete []pNewGray;

pNewGray = NULL;

if( pBin2Gray )

delete []pBin2Gray;

pBin2Gray = NULL;

}

GlobalUnlock(m_hDib);

GlobalFree(m_hDib);

m_hDib = hDIB;

return UpdateInternal();

}

/******************************************************************

功能:以原有灰度图像中心为原点,自动检测角度并旋转图像

倾斜角度范围-10——+10度

输入:

rtROI,给定的区域,用于检测文档的倾斜角度.输入区域为bottom = 0 或者right = 0,则设为图像区域

输出:

旋转成功返回true

******************************************************************/

bool CArdpsImg::AutoRotatelImage(RECT rtROI)

{

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

LONG lWidth = DIBWidth(lpDIB);

LONG lHeight = DIBHeight(lpDIB);

if( rtROI.bottom > lHeight || rtROI.right > lWidth )

{

GlobalUnlock(m_hDib);

return false;

}

if( rtROI.left < EDGE_STEP )

rtROI.left = EDGE_STEP;

if( rtROI.right >= lWidth - EDGE_STEP )

rtROI.right = lWidth - EDGE_STEP - 1;

if (rtROI.top < EDGE_STEP )

rtROI.top = EDGE_STEP;

if( rtROI.bottom >= lHeight - EDGE_STEP )

rtROI.bottom = lHeight - 1 - EDGE_STEP;

if( rtROI.bottom == 0 )

rtROI.bottom = lHeight-EDGE_STEP;

if(rtROI.right == 0)

rtROI.right = lWidth - EDGE_STEP;

LPBYTE lpDIBBits = FindDIBBits(lpDIB);

WORD dwBitCnt = DIBBitCount(lpDIB);

if( dwBitCnt != 8 )

{

GlobalUnlock(m_hDib);

return false;

}

LONG lLineBytes = MYWIDTHBYTES(lWidth * dwBitCnt);

BYTE * pbOutImage = new BYTE[lLineBytes * lHeight];

if( !pbOutImage )

{

GlobalUnlock(m_hDib);

return false;

}

memset(pbOutImage, 0, lLineBytes * lHeight* sizeof(BYTE));

BYTE *pbTmp = new BYTE[lLineBytes * lHeight];

if( !pbTmp )

{

GlobalUnlock(m_hDib);

delete []pbOutImage;

pbOutImage = NULL;

}

memset(pbTmp, 0, lLineBytes * lHeight* sizeof(BYTE));

bool bSuccess = FindTopEdge(pbOutImage, lpDIBBits, rtROI, lLineBytes);

//SaveTo8bit_BMP(lpDIBBits, lWidth, lHeight, "edgegray.bmp", 8);

//SaveTo8bit_BMP(pbOutImage, lWidth, lHeight, "edge0.bmp", 8);

DeleteVtlSmallLine(pbOutImage, pbTmp, lLineBytes, lHeight, 5);

//SaveTo8bit_BMP(pbOutImage, lWidth, lHeight, "edge1.bmp", 8);

double dK;

if( bSuccess )

{

dK = DetectSkewAngle(pbOutImage, rtROI, lLineBytes);

bSuccess = RotateImage(dK);

}

if( pbOutImage )

{

delete []pbOutImage;

pbOutImage = NULL;

}

if( pbTmp )

{

delete []pbTmp;

pbTmp = NULL;

}

GlobalUnlock(m_hDib);

if( bSuccess )

return UpdateInternal();

else

return bSuccess;

}

/******************************************************************

功能:自动去除灰度图像的黑白边

输入:

输出:

去除成功返回true

******************************************************************/

bool CArdpsImg::CutFrame()

{

BYTE * pbOut = NULL;

bool bSuccess = false;

LPBITMAPINFOHEADER lpbmi = NULL;

LPBITMAPCOREHEADER lpbmc = NULL;

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

LONG lWidth = DIBWidth(lpDIB);

LONG lHeight = DIBHeight(lpDIB);

LPBYTE lpDIBBits = FindDIBBits(lpDIB);

WORD dwBitCnt = DIBBitCount(lpDIB);

if( dwBitCnt != 8 )

{

goto CleanUp;

}

RECT rect;

rect = SetRectValue(0, 0, 0, 0);

LONG lLineBytes = MYWIDTHBYTES(lWidth << 3);

LONG lImgBytes = lLineBytes * lHeight;

pbOut = new BYTE[lImgBytes];

if( !pbOut )

{

goto CleanUp;

}

memset(pbOut, 0, lImgBytes * sizeof(BYTE));

rect = SetRectValue(4, lWidth - 4, 4, lHeight - 4);

if (FindEdgeImage(pbOut, lpDIBBits, rect, lWidth) < 0)

{

goto CleanUp;

}

rect = GetEdgeImageBoundary(pbOut, lWidth, lHeight);

RECT rtPhy;

rtPhy = rect;

rtPhy.bottom = lHeight - 1 - rect.top;

rtPhy.top = lHeight - 1 - rect.bottom;

HDIB hDIB = CropDIB(m_hDib, &rtPhy);

if( hDIB == NULL )

goto CleanUp;

bSuccess = true;

CleanUp:

if( pbOut )

{

delete []pbOut;

pbOut = NULL;

}

GlobalUnlock(m_hDib);

GlobalFree(m_hDib);

m_hDib = hDIB;

if( bSuccess )

return UpdateInternal();

else

return bSuccess;

}

/******************************************************************

功能:将图像拆页为两幅图像

输入:

pt1,pt2:给定的拆分的线的任意两点坐标

pNewArd:返回CArdpsImg对象,拆分后的下、右半幅图像句柄存于该对象中

输出:

拆分成功返回true

******************************************************************/

bool CArdpsImg::SplitImage(POINT pt1, POINT pt2, CArdpsImg *pNewArd)

{

bool bSuccess = false;

if( pNewArd == NULL )

return bSuccess;

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

LONG lWidth = DIBWidth(lpDIB);

LONG lHeight = DIBHeight(lpDIB);

int nx, ny;

nx = abs(pt1.x - pt2.x) ;

ny = abs(pt1.y - pt2.y) >lHeight - 1 ? lHeight - 1 : abs(pt1.y - pt2.y) ;

RECT rtROI, rtROI2;

if( nx < ny )

{

nx = (pt1.x + pt2.x + 0.5)/2 > lWidth - 1 ? lWidth - 1 : (pt1.x + pt2.x + 0.5)/2; //垂直分割

rtROI = SetRectValue(0, nx -1, 0, lHeight - 1);

rtROI2 = SetRectValue(nx, lWidth -1, 0, lHeight - 1);

}

else

{

ny = (pt1.y + pt2.y + 0.5) / 2 > lHeight - 1 ? lHeight - 1 : (pt1.y + pt2.y + 0.5) / 2 ;

rtROI = SetRectValue(0, lWidth - 1, 0, ny - 1);

rtROI2 = SetRectValue(0, lWidth - 1, ny, lHeight - 1);

}

HDIB hDib1, hDib2;

hDib1 = CropDIB(m_hDib, &rtROI );

hDib2 = CropDIB(m_hDib, &rtROI2);

GlobalUnlock(m_hDib);

GlobalFree(m_hDib);

m_hDib = hDib1;

pNewArd->m_hDib = hDib2;

return true;

}

/******************************************************************

功能:将两幅图像合并为一幅图像

输入:

pSrcArd:输入的CArdpsImg对象,图像的句柄存于该对象中

nMethod:0:上下合并,Src位于合并后的下半幅;1:上下合并,Src位于合并后的上半幅

2:左右合并,Src位于合并后的右半幅;3:左右合并,Src位于合并后的左半幅

输出:

拆分成功返回true

******************************************************************/

bool CArdpsImg::MergeImage(CArdpsImg *pSrcArd, int nMethod /* = 0 */)

{

bool bSuccess = false;

if( pSrcArd == NULL )

return bSuccess;

//当前图像

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

LONG lWidth = DIBWidth(lpDIB);

LONG lHeight = DIBHeight(lpDIB);

WORD bitCnt = DIBBitCount(lpDIB);

LONG lBytePerLine = MYWIDTHBYTES(lWidth * bitCnt);

LPBYTE lpDIBBits = FindDIBBits(lpDIB);

//欲合并的图像

LPBYTE lpSrcDIB = (LPBYTE)GlobalLock(pSrcArd->m_hDib);

LONG lSrcWidth = DIBWidth(lpSrcDIB);

LONG lSrcHeight = DIBHeight(lpSrcDIB);

WORD bitSrcCnt = DIBBitCount(lpSrcDIB);

LONG lSrcBytePerLine = MYWIDTHBYTES(lSrcWidth * bitSrcCnt);

if( bitCnt != bitSrcCnt || bitCnt < 8 )

goto CleanUp;

LPBYTE lpSrcDIBBits = FindDIBBits(lpSrcDIB);

LONG lDstWidth, lDstHeight, lDstBytesPerLine, i, j, k;

HDIB hDIB = NULL;

LPBYTE lpDstDIB, lpDstDIBBits;

lpDstDIB = lpDstDIBBits = NULL;

switch (nMethod)

{

case 0:

case 1:

lDstHeight = lSrcHeight + lHeight;

lDstWidth = max(lWidth, lSrcWidth);

break;

case 2:

case 3:

default:

lDstHeight = max(lSrcHeight, lHeight);

lDstWidth = lWidth + lSrcWidth;

}

lDstBytesPerLine = MYWIDTHBYTES(lDstWidth*bitCnt);

// 分配内存,以保存新DIB

hDIB = (HDIB) ::GlobalAlloc(GHND, lDstBytesPerLine * lDstHeight + *(LPDWORD)lpDIB + ::PaletteSize(lpDIB));

if( hDIB == NULL )

goto CleanUp;

lpDstDIB = (LPBYTE)GlobalLock(hDIB);

// 获取指针

LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)lpDstDIB;

LPBITMAPCOREHEADER lpbmc = (LPBITMAPCOREHEADER)lpDstDIB;

// 复制DIB信息头和调色板

memcpy(lpDstDIB, lpDIB, *(LPDWORD)lpDIB + PaletteSize(lpDIB));

lpDstDIBBits = lpDstDIB + *(LPDWORD)lpDIB + ::PaletteSize(lpDIB);

memset(lpDstDIBBits, 255, lDstBytesPerLine * lDstHeight * sizeof(BYTE));

switch (nMethod)

{

case 0: //上下结构,Src位于图像的下半部分

for( i = 0, j = 0, k = 0; i < lSrcHeight; i++, j += lDstBytesPerLine, k += lSrcBytePerLine )

{

memcpy(lpDstDIBBits + j, lpSrcDIBBits + k, lSrcBytePerLine);

}

for( i = lSrcHeight, j = i * lDstBytesPerLine, k = 0; i < lDstHeight; i++, j += lDstBytesPerLine, k += lBytePerLine )

{

memcpy(lpDstDIBBits + j, lpDIBBits + k, lBytePerLine );

}

break;

case 1: //上下结构,当前图像位于合并后图像的下半部分

for( i = 0, j = 0, k = 0; i < lHeight; i++, j += lDstBytesPerLine, k += lBytePerLine )

{

memcpy(lpDstDIBBits + j, lpDIBBits + k, lBytePerLine);

}

for( i = lHeight, j = i * lDstBytesPerLine, k = 0; i < lDstHeight; i++, j += lDstBytesPerLine, k += lSrcBytePerLine )

{

memcpy(lpDstDIBBits + j, lpSrcDIBBits + k, lSrcBytePerLine );

}

break;

case 2: //左右结构,Src图像位于合并后图像的右半部分

for( i = 0, j = 0, k = 0; i < lHeight; i++, j += lDstBytesPerLine, k += lBytePerLine)

{

memcpy(lpDstDIBBits + j, lpDIBBits + k, lBytePerLine);

}

for( i = 0, j = lBytePerLine, k = 0; i < lSrcHeight; i++, j += lDstBytesPerLine, k += lSrcBytePerLine )

{

memcpy(lpDstDIBBits + j, lpSrcDIBBits + k, lSrcBytePerLine);

}

break;

case 3: //左右结构,当前图像位于合并后图像的右半部分

default:

for( i = lSrcHeight - 1, j = i * lDstBytesPerLine, k = i * lSrcBytePerLine; i >= 0; i--, j -= lDstBytesPerLine, k -= lSrcBytePerLine)

{

memcpy(lpDstDIBBits + j, lpSrcDIBBits + k, lSrcBytePerLine);

}

for( i = lHeight - 1, j = i * lDstBytesPerLine + lSrcBytePerLine, k = i * lBytePerLine; i >= 0; i--, j -= lDstBytesPerLine, k -= lBytePerLine )

{

memcpy(lpDstDIBBits + j, lpDIBBits + k, lBytePerLine);

}

break;

}

// 更新DIB中图像的高度和宽度

if (IS_WIN30_DIB(lpDIB))

{

// 对于Windows 3.0 DIB

lpbmi->biWidth = lDstWidth;

lpbmi->biHeight = lDstHeight;

}

else

{

// 对于其它格式的DIB

lpbmc->bcWidth = (unsigned short) lDstWidth;

lpbmc->bcHeight = (unsigned short) lDstHeight;

}

bSuccess = true;

CleanUp:

GlobalUnlock(m_hDib);

GlobalFree(m_hDib);

GlobalUnlock(pSrcArd->m_hDib);

if( bSuccess && hDIB != NULL )

m_hDib = hDIB;

if( bSuccess )

return UpdateInternal();

else

return bSuccess;

}

/******************************************************************

功能:将两幅图像合并为一幅图像

输入:

pSrcArd:输入的CArdpsImg对象,图像的句柄存于该对象中

nPos1: 当前图像的合并坐标;

nPos2 输入的CArdpsImg对象,合并图像的坐标

nMethod:0:上下合并,取当前图像的下部,pSrcArd图像的上部

1:左右合并,取当前图像的右部,pSrcArd图像的下部

输出:

当前图像为合并后的图像,合并成功返回true

******************************************************************/

bool CArdpsImg::MergeImage(CArdpsImg *pSrcArd, int nPos1, int nPos2, int nMethod /* = 0 */)

{

bool bSuccess = false;

if( pSrcArd == NULL )

return bSuccess;

//当前图像

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

LONG lWidth = DIBWidth(lpDIB);

LONG lHeight = DIBHeight(lpDIB);

WORD bitCnt = DIBBitCount(lpDIB);

LONG lBytePerLine = MYWIDTHBYTES(lWidth * bitCnt);

LPBYTE lpDIBBits = FindDIBBits(lpDIB);

//欲合并的图像

LPBYTE lpSrcDIB = (LPBYTE)GlobalLock(pSrcArd->m_hDib);

LONG lSrcWidth = DIBWidth(lpSrcDIB);

LONG lSrcHeight = DIBHeight(lpSrcDIB);

WORD bitSrcCnt = DIBBitCount(lpSrcDIB);

LONG lSrcBytePerLine = MYWIDTHBYTES(lSrcWidth * bitSrcCnt);

if( bitCnt != bitSrcCnt || bitCnt < 8 )

goto CleanUp;

LPBYTE lpSrcDIBBits = FindDIBBits(lpSrcDIB);

LONG lDstWidth, lDstHeight, lDstBytesPerLine, i, j, k;

HDIB hDIB = NULL;

LPBYTE lpDstDIB, lpDstDIBBits;

lpDstDIB = lpDstDIBBits = NULL;

nPos1 -= 1;

nPos2 -= 1;

switch (nMethod)

{

case 0:

if( nPos1 >= lHeight )

nPos1 = lHeight - 1;

if( nPos1 < 0 )

nPos1 = 0;

if( nPos2 >= lSrcHeight )

nPos2 = lSrcHeight - 1;

if( nPos2 < 0 )

nPos2 = 0;

lDstHeight = nPos2 + lHeight - nPos1;

lDstWidth = max(lWidth, lSrcWidth);

break;

case 1:

if (nPos1 >= lWidth )

nPos1 = lWidth - 1;

if( nPos1 < 0 )

nPos1 = 0;

if( nPos2 >= lSrcWidth )

nPos2 = lSrcWidth - 1;

if( nPos2 < 0 )

nPos2 = 0;

lDstHeight = max(lSrcHeight, lHeight);

lDstWidth = lWidth - nPos1 + nPos2;

}

lDstBytesPerLine = MYWIDTHBYTES(lDstWidth*bitCnt);

// 分配内存,以保存新DIB

hDIB = (HDIB) ::GlobalAlloc(GHND, lDstBytesPerLine * lDstHeight + *(LPDWORD)lpDIB + ::PaletteSize(lpDIB));

if( hDIB == NULL )

goto CleanUp;

lpDstDIB = (LPBYTE)GlobalLock(hDIB);

// 获取指针

LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)lpDstDIB;

LPBITMAPCOREHEADER lpbmc = (LPBITMAPCOREHEADER)lpDstDIB;

// 复制DIB信息头和调色板

memcpy(lpDstDIB, lpDIB, *(LPDWORD)lpDIB + PaletteSize(lpDIB));

lpDstDIBBits = lpDstDIB + *(LPDWORD)lpDIB + ::PaletteSize(lpDIB);

memset(lpDstDIBBits, 255, lDstBytesPerLine * lDstHeight * sizeof(BYTE));

int nLength = 0;

switch (nMethod)

{

case 0: //上下结构,当前图像位于合并图像的下半部分

for( i = 0, j = 0, k = 0; i < lHeight - nPos1; i++, j += lDstBytesPerLine, k += lBytePerLine )

{

memcpy(lpDstDIBBits + j, lpDIBBits + k, lBytePerLine);

}

for( i = lSrcHeight - nPos2 , k = i * lSrcBytePerLine; i < lSrcHeight; i++, j += lDstBytesPerLine, k += lSrcBytePerLine )

{

memcpy(lpDstDIBBits + j, lpSrcDIBBits + k, lSrcBytePerLine );

}

break;

case 1: //左右结构,当前图像位于合并后图像的右半部分

nLength = nPos2 * bitCnt / 8;

for( i = 0, k = 0, j = 0; i < lSrcHeight; i++, k += lSrcBytePerLine, j += lDstBytesPerLine )

{

memcpy(lpDstDIBBits + j, lpSrcDIBBits + k, nLength);

}

nLength = (lWidth - nPos1) * bitCnt / 8;

for( i = 0, k = nPos1 * bitCnt / 8, j = nPos2 * bitCnt / 8; i < lHeight; i++, k+= lBytePerLine, j += lDstBytesPerLine )

{

memcpy(lpDstDIBBits + j, lpDIBBits + k, nLength);

}

break;

}

// 更新DIB中图像的高度和宽度

if (IS_WIN30_DIB(lpDIB))

{

// 对于Windows 3.0 DIB

lpbmi->biWidth = lDstWidth;

lpbmi->biHeight = lDstHeight;

}

else

{

// 对于其它格式的DIB

lpbmc->bcWidth = (unsigned short) lDstWidth;

lpbmc->bcHeight = (unsigned short) lDstHeight;

}

bSuccess = true;

CleanUp:

GlobalUnlock(m_hDib);

GlobalFree(m_hDib);

GlobalUnlock(pSrcArd->m_hDib);

if( bSuccess && hDIB != NULL )

m_hDib = hDIB;

if( bSuccess )

return UpdateInternal();

else

return bSuccess;

}

////////////////////////////////////////////////////////////////////////////////

/**

* Changes the brightness and the contrast of the image. Apply a look up table to the image.

* \ * \param brightness: can be from -255 to 255, if brightness is negative, the image becomes dark.

* \param contrast: can be from -100 to 100, the neutral value is 0.

* \return true if everything is ok

*/

bool CArdpsImg::AjustLightAndContrast(int brightness, int contrast)

{

if (!m_hDib) return false;

float c=(100 + contrast)/100.0f;

brightness+=128;

long i;

BYTE cTable[256]; //<nipper>

for ( i=0;i<256;i++) {

cTable[i] = (BYTE)max(0,min(255,(int)((i-128)*c + brightness + 0.5f)));

}

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

if( lpDIB == NULL )

return false;

LONG lWidth = DIBWidth(lpDIB);

LONG lHeight = DIBHeight(lpDIB);

WORD bitCnt = DIBBitCount(lpDIB);

LONG lBytePerLine = MYWIDTHBYTES(lWidth * bitCnt);

LPBYTE lpDIBBits = FindDIBBits(lpDIB);

RGBQUAD *pRgb =(RGBQUAD *)( lpDIB + 40);

if (bitCnt == 8)

{

for( i = 0; i < 256; i++)

{

pRgb[i].rgbBlue = pRgb[i].rgbRed = pRgb[i].rgbGreen = cTable[i];

}

}

else if( bitCnt == 24)

{

for( i = 0; i < lBytePerLine * lHeight; i++)

{

*lpDIBBits++ = cTable[*lpDIBBits];

}

}

else

{

GlobalUnlock(m_hDib);

return false;

}

GlobalUnlock(m_hDib);

return UpdateInternal();

}

/******************************************************************

功能:自动分析边框,并进行调整,不改变图像的大小

输入:

nMethod:0:从水平,垂直两个方向上进行调整。

1:水平调整

2:垂直调整

输出:

调整后的图像,成功返回true

******************************************************************/

bool CArdpsImg::AdjustBinPos(int nMethod /* = 0 */)

{

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

if( lpDIB == NULL )

return false;

LONG lWidth = DIBWidth(lpDIB);

LONG lHeight = DIBHeight(lpDIB);

WORD bitCnt = DIBBitCount(lpDIB);

LONG lBytePerLine = MYWIDTHBYTES(lWidth * bitCnt);

LPBYTE lpDIBBits = FindDIBBits(lpDIB);

if( bitCnt != 1 )

{

GlobalUnlock(m_hDib);

return false;

}

//for gray image

LONG nGrayBytesPerLine = MYWIDTHBYTES( lWidth << 3 );

LONG nGrayImgSize = nGrayBytesPerLine * lHeight;

BYTE *pbGrayImg = new BYTE[nGrayImgSize];

if( !pbGrayImg )

{

GlobalUnlock(m_hDib);

return false;

}

bool bSuccess = ConvertBinary2Gray(lpDIBBits, lWidth, lHeight, pbGrayImg );

if( !bSuccess )

{

GlobalUnlock(m_hDib);

delete []pbGrayImg;

pbGrayImg = NULL;

return false;

}

RECT rtImg = GetBinImageBoundary(pbGrayImg, lWidth, lHeight);

RECT rtNew;

rtNew.left = (rtImg.left + lWidth - rtImg.right )/2;

rtNew.right = lWidth - rtNew.left -1;

rtNew.top = (rtImg.top + lHeight - rtImg.bottom)/2;

rtNew.bottom = lHeight - rtNew.top - 1;

MoveBin(pbGrayImg, lWidth, lHeight, rtImg, rtNew, nMethod );

bSuccess = ThreshImage(pbGrayImg, lpDIBBits, lWidth, lHeight, 10);

if( pbGrayImg )

delete []pbGrayImg;

pbGrayImg = NULL;

GlobalUnlock(m_hDib);

return UpdateInternal();

}

/******************************************************************

功能:彩色图像色阶调整

输入:

输出:

调整后的图像,成功返回true

******************************************************************/

bool CArdpsImg::ColorEqual()

{

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

if( lpDIB == NULL )

return false;

LONG lWidth = DIBWidth(lpDIB);

LONG lHeight = DIBHeight(lpDIB);

WORD bitCnt = DIBBitCount(lpDIB);

LONG lBytePerLine = MYWIDTHBYTES(lWidth * bitCnt);

LPBYTE lpDIBBits = FindDIBBits(lpDIB);

if( bitCnt != 24 )

{

GlobalUnlock(m_hDib);

return false;

}

int nHist[256];

long long nCulHist[256];

long long nConver[256];

memset(nHist, 0, 256 * sizeof(int));

memset(nCulHist, 0, 256 * sizeof( long long ));

memset(nConver, 0, 256 * sizeof(long long ));

long i, j, m, newValue;

LPBYTE pSrc = NULL;

for( i = 0, m = 0; i < lHeight; i++, m += lBytePerLine )

{

pSrc = lpDIBBits + m;

for( j = 0; j < lWidth; j++)

{

newValue = (*pSrc) * uiBWeight + uiGWeight * (*(pSrc + 1)) + uiRWeight * (*(pSrc + 2));

newValue /= 1000;

nHist[newValue]++;

pSrc += 3;

}

}

long long nTotal = lHeight * lWidth;

nCulHist[0] = nHist[0];

nConver[0] = nHist[0] * 255 / nTotal;

for( i = 1; i < 256; i++ )

{

nCulHist[i] = nCulHist[i - 1] + nHist[i];

nConver[i] = nCulHist[i] * 255 / nTotal;

}

for( i = 0, m = 0; i < lHeight; i++, m += lBytePerLine )

{

pSrc = lpDIBBits + m;

for( j = 0; j < lWidth; j++)

{

*pSrc = nConver[*pSrc];

pSrc++;

*pSrc = nConver[*pSrc];

pSrc++;

*pSrc = nConver[*pSrc];

pSrc++;

}

}

GlobalUnlock(m_hDib);

return UpdateInternal();

}

bool CArdpsImg::Zoom(double fRatioX, double fRatioY)

{

int nWidth = (int)(fRatioX * (double)GetWidth());

int nHeight = (int)(fRatioY * (double)GetHeight());

HDIB hNewDib = ChangeDIBSize(m_hDib, nWidth, nHeight);

if (! hNewDib)

return false;

// set to m_hDib

Destroy();

m_hDib = hNewDib;

// return

return UpdateInternal();

}

//连通域提取

void CArdpsImg::ExtractComponent(Line * Li, BYTE *pbBinary, UINT grayBytesPerLine, BYTE bCur ) //连通域提取

{

if( Li == NULL || pbBinary == NULL )

return;

int * stack = NULL;

int * InStack[10];

int top, topin;

top = topin = 0;

CPoint temp;

component *ctail =NULL;

component *chead =new component;

InStack[topin] = new int[COMP_NUM];

if( InStack[topin] == NULL )

return;

stack = InStack[topin];

char **flag=new char*[Li->EndY-Li->StartY+1];

if( *flag == NULL )

{

delete []InStack[topin];

InStack[topin] = NULL;

return;

}

int i, j, k;

for(i = 0; i <= Li->EndY - Li->StartY; i++) //寻找连通体

{

flag[i]=new char[Li->EndX - Li->StartX + 1];

for(j = 0; j <= Li->EndX - Li->StartX; j++)

{

flag[i][j]=0;

}

}

for(j = Li->StartX; j <= Li->EndX; j++) //寻找连通体

{

for( i = Li->StartY, k = Li->StartY * grayBytesPerLine; i <= Li->EndY; i++, k += grayBytesPerLine)

{

if(flag[i-Li->StartY][j-Li->StartX] == 0 && pbBinary[k + j] == bCur )

{

stack[top++]=i;

stack[top++]=j;

flag[i - Li->StartY][j - Li->StartX] = 1;

if(ctail!=NULL)

{

component *cp = new component;

ctail->cnext = cp;

ctail = cp;

}

else

{

ctail = chead;

}

ctail->bound =CRect(j,i,j,i);

ctail->count =1;

while(top != 0)

{

temp.x = stack[--top];

temp.y = stack[--top];

if(top == 0 && topin != 0)

{

stack = InStack[topin-1];

delete []InStack[topin--];

top = COMP_NUM;

}

if(temp.x - 1 >= Li->StartX)

add(temp.x-1, temp.y, flag, stack, InStack, top, topin,

Li->StartX, Li->StartY, ctail, pbBinary, grayBytesPerLine, bCur );

if(temp.x+1 <= Li->EndX)

add(temp.x+1, temp.y, flag, stack, InStack, top, topin,

Li->StartX, Li->StartY, ctail, pbBinary, grayBytesPerLine, bCur);

if(temp.y-1 >= Li->StartY)

add(temp.x, temp.y-1, flag, stack, InStack, top, topin,

Li->StartX, Li->StartY, ctail, pbBinary, grayBytesPerLine, bCur);

if(temp.y+1 <= Li->EndY)

add(temp.x, temp.y+1, flag, stack, InStack, top, topin,

Li->StartX, Li->StartY, ctail, pbBinary, grayBytesPerLine, bCur);

if((temp.x-1 >= Li->StartX) && (temp.y - 1 >= Li->StartY))

add(temp.x-1, temp.y-1, flag, stack, InStack, top, topin,

Li->StartX, Li->StartY, ctail, pbBinary, grayBytesPerLine, bCur);

if((temp.x+1 <= Li->EndX) && (temp.y-1 >= Li->StartY))

add(temp.x+1, temp.y-1, flag, stack, InStack, top, topin,

Li->StartX, Li->StartY, ctail, pbBinary, grayBytesPerLine, bCur);

if((temp.x-1 >= Li->StartX) && (temp.y+1 <= Li->EndY))

add(temp.x-1, temp.y+1, flag, stack, InStack, top, topin,

Li->StartX, Li->StartY, ctail, pbBinary, grayBytesPerLine, bCur);

if((temp.x+1 <= Li->EndX) && (temp.y+1 <= Li->EndY))

add(temp.x+1, temp.y+1, flag, stack, InStack, top, topin,

Li->StartX, Li->StartY, ctail, pbBinary, grayBytesPerLine, bCur);

}

}

}

} //end for

Li->cp = chead;

delete []stack;

for(i = 0; i <= Li->EndY-Li->StartY; i++)

delete []flag[i];

delete []flag;

}

void CArdpsImg::add(int a,int b,char **flag,int *&stack,int **InStack,

int &top,int &topin,int c,int d,component *ctail, BYTE *pMotion, UINT grayBytesPerLine, BYTE bCur )

{

if((flag[b-d][a-c] == 0 ) && pMotion[b * grayBytesPerLine + a] == bCur )

{

flag[b-d][a-c] = 1;

if(top == COMP_NUM)

{

if(topin == 9)

{

return;

}

InStack[++topin]=new int[COMP_NUM];

stack=InStack[topin];

top=0;

}

stack[top++]=b;

stack[top++]=a;

ctail->count++;

if(ctail->bound.bottom < b) //连通体边界

ctail->bound.bottom = b;

if(ctail->bound.top > b)

ctail->bound.top = b;

if(ctail->bound.left > a)

ctail->bound.left = a;

if(ctail->bound.right < a)

ctail->bound.right = a;

}

}

void CArdpsImg::AnalysisComponent( Line * Li, BYTE *pbBinary, UINT unBinaryBytesPerLine, UINT minArea, const BYTE bValue)

{

if( Li == NULL || pbBinary == NULL )

return;

component *cp1= Li->cp;

component *cp2;

int area;//, nCnt = 0;

while( cp1 != NULL )

{

area = cp1->bound.Height() * cp1->bound.Width();

if( area < minArea && area > 0 )

{

SetBinary(cp1->bound, pbBinary, unBinaryBytesPerLine, bValue);

}

cp2 = cp1;

cp1 = cp1->cnext;

delete cp2;

}

Li->cp = NULL;

}

CRect* CArdpsImg::GetDirtPos(int nMethod, int *nCnt)

{

*nCnt = 0;

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

if( !lpDIB)

return m_dirRect;

LPBYTE lpBinImg = FindDIBBits(lpDIB);

if( !lpBinImg )

{

GlobalUnlock(m_hDib);

return m_dirRect;

}

bool bSuccess = true;

LONG nImgHei = GetHeight();

LONG nImgWid = GetWidth();

int nBitCnt = DIBBitCount(lpDIB);

if( nBitCnt != 1 )

{

GlobalUnlock(m_hDib);

return m_dirRect;

}

LONG nBinBytesPerLine = MYWIDTHBYTES(nImgWid * nBitCnt);

//for gray image

LONG nGrayBytesPerLine = MYWIDTHBYTES( nImgWid << 3 );

LONG nGrayImgSize = nGrayBytesPerLine * nImgHei;

BYTE *pbGrayImg = new BYTE[nGrayImgSize];

if( !pbGrayImg )

{

GlobalUnlock(m_hDib);

return m_dirRect;

}

bSuccess = ConvertBinary2Gray(lpBinImg, nImgWid, nImgHei, pbGrayImg );

//SaveTo8bit_BMP(pbGrayImg, nImgWid, nImgHei, "d:\\testgray.bmp", 8);

if( !bSuccess )

{

delete []pbGrayImg;

pbGrayImg = NULL;

GlobalUnlock(m_hDib);

return m_dirRect;

}

Line *Li = new Line;

if( !Li )

{

delete []pbGrayImg;

pbGrayImg = NULL;

GlobalUnlock(m_hDib);

return m_dirRect;

}

Li->StartY = 3;

Li->StartX = 3;

Li->EndX = nImgWid - 3;

Li->EndY = nImgHei - 3;

Li->cp = NULL;

BYTE bCur;

if( nMethod == 0 ) //黑色为背景

{

bCur = 0;

}

else

{

bCur = 255;

}

ExtractComponent(Li, pbGrayImg, nGrayBytesPerLine, bCur );

AnalysisDirtPos(Li, m_DirtSize, m_minDirtSize, nImgHei, nCnt);

if( pbGrayImg )

{

delete []pbGrayImg;

pbGrayImg = NULL;

}

if( Li )

{

delete Li;

Li = NULL;

}

GlobalUnlock(m_hDib);

return m_dirRect;

}

bool CArdpsImg::AnalysisDirtPos(Line *Li, CSize maxSize, CSize minSize, int nHeight, int *nCnt)

{

if( Li == NULL || nCnt == NULL )

return false;

component *cp1= Li->cp;

component *cp2;

int area;//, nCnt = 0;

int minArea = minSize.cx * minSize.cy;

int maxArea = maxSize.cx * maxSize.cy;

*nCnt = 0;

while(cp1 != NULL )

{

cp1 = cp1->cnext;

(*nCnt)++;

}

if( m_dirRect )

{

delete []m_dirRect;

m_dirRect = NULL;

}

m_dirRect = new CRect[(*nCnt)];

if( m_dirRect == NULL )

return false;

cp1= Li->cp;

*nCnt = 0;

while( cp1 != NULL )

{

area = cp1->bound.Height() * cp1->bound.Width();

if( area <= maxArea && area >= minArea )

{

m_dirRect[*nCnt].top = nHeight - 1 - cp1->bound.bottom;

m_dirRect[*nCnt].bottom = nHeight - 1 - cp1->bound.top;

m_dirRect[*nCnt].left = cp1->bound.left;

m_dirRect[*nCnt].right = cp1->bound.right;

(*nCnt)++;

}

cp2 = cp1;

cp1 = cp1->cnext;

delete cp2;

}

Li->cp = NULL;

return true;

}

void CArdpsImg::SetBinary(CRect rect, BYTE *pbImg, UINT unBinaryBytesPerLine, const BYTE bValue)

{

if( pbImg == NULL )

return;

LONG i, j, m;

for( i = rect.top, m = rect.top * unBinaryBytesPerLine; i <= rect.bottom; i++, m += unBinaryBytesPerLine )

{

for( j = rect.left; j <= rect.right; j++ )

{

*(pbImg + m + j) = bValue;

}

}

}

bool CArdpsImg::ConvertBinary2Gray(const unsigned char * pbBinary, const int nWidth, const int nHeight, unsigned char *pbGray)

{

if( pbBinary == NULL || pbGray == NULL || nWidth < 1 || nHeight < 1)

return false;

LONG nBinaryBytesPerLine = MYWIDTHBYTES(nWidth);

LONG nGrayBytesPerLine = MYWIDTHBYTES(nWidth << 3);

LONG i, j, k, m;

const unsigned char * pbIn = pbBinary;

unsigned char * pbOut = pbGray;

memset( pbGray, 0, nHeight * nGrayBytesPerLine * sizeof( unsigned char));

BYTE btmp = 0;

for( i = 0, k = 0, m = 0; i < nHeight; i++, k += nGrayBytesPerLine, m += nBinaryBytesPerLine )

{

pbIn = pbBinary + m;

pbOut = pbGray + k;

for( j = 0; j < (nWidth + 7)/8; j++, pbIn++)

{

btmp = *pbIn;

btmp = btmp & 128 ;

if( btmp == 128)

*pbOut = 255;

pbOut ++;

btmp = *pbIn;

btmp = btmp & 64 ;

if( btmp == 64)

*pbOut = 255;

pbOut ++;

btmp = *pbIn;

btmp = btmp & 32 ;

if( btmp == 32)

*pbOut = 255;

pbOut ++;

btmp = *pbIn;

btmp = btmp & 16 ;

if( btmp == 16)

*pbOut = 255;

pbOut ++;

btmp = *pbIn;

btmp = btmp & 8 ;

if( btmp == 8)

*pbOut = 255;

pbOut ++;

btmp = *pbIn;

btmp = btmp & 4 ;

if( btmp == 4)

*pbOut = 255;

pbOut ++;

btmp = *pbIn;

btmp = btmp & 2 ;

if( btmp == 2)

*pbOut = 255;

pbOut ++;

btmp = *pbIn;

btmp = btmp & 1;

if( btmp == 1)

*pbOut = 255;

pbOut ++;

}

}

return true;

}

bool CArdpsImg::FindTopEdge(BYTE *pbOutImage, BYTE *image, RECT rtROI, int nWidth)

{

if( pbOutImage == NULL || image == NULL )

return false;

BYTE *pbIn1, *pbIn2;

pbIn2 = pbIn1 = NULL;

int i, j;

int gd, n = 0, k = 0;

int d;

gd = n = 0;

pbIn1 = image + (rtROI.top + EDGE_STEP) * nWidth + rtROI.left;

for (i = rtROI.top + EDGE_STEP; i < rtROI.bottom; i++, pbIn1 += nWidth)

{

pbIn2 = pbIn1;

for (j = rtROI.left; j < rtROI.right; j++, pbIn2++)

{

d = pbIn2[-EDGE_STEP * nWidth] - pbIn2[0];

if (d > 20)

{

gd += d;

n++;

}

}

}

if (n > 0)

{

gd = gd / n;

}

pbIn1 = image + rtROI.top * nWidth + rtROI.left;

for (i = rtROI.top; i < rtROI.bottom; i++, pbIn1 += nWidth)

{

pbIn2 = pbIn1;

for (j = rtROI.left; j < rtROI.right; j++, pbIn2++)

{

n = (int)(pbIn2 - image);

pbOutImage
= 0;

if (j > EDGE_STEP)

{

d = pbIn2[nWidth - EDGE_STEP] - pbIn2[0];

if (d > gd)

{

pbOutImage
= 255;

}

}

}

}

for (i = rtROI.top; i < rtROI.bottom; i++)

{

for (j = rtROI.right; j > rtROI.left; j--)

{

if (pbOutImage[i * nWidth + j] <= pbOutImage[i * nWidth + j - 1])

{

pbOutImage[i * nWidth + j] = 0;

}

}

}

return true;

}

double CArdpsImg::DetectSkewAngle(BYTE *pbImage, RECT rtROI, int nWidth)

{

double dK = 0.0;

int i;

int nValeSum, nValeMax, angle;

int *pnRamBuff = NULL;

pnRamBuff = new int[nWidth * 2];

if (pnRamBuff == NULL)

{

return 0.0;

}

angle = nValeMax = 0;

for (i = -10; i <= 10; i ++)

{

nValeSum = CompVPrjValeSum(pnRamBuff, pbImage, nWidth, rtROI.bottom, i);

if(nValeSum>nValeMax)

{

nValeMax = nValeSum;

angle = i;

}

}

dK = angle;// * 3.14159265 / 180;

if( pnRamBuff)

{

delete []pnRamBuff;

pnRamBuff = NULL;

}

return dK;

}

// compute all vale sum

int CArdpsImg::CompVPrjValeSum(int *pnRamBuff, const BYTE *pInImg, int nImgWidth, int nImgHeight, int nRotAngle)

{

if( pnRamBuff == NULL || pInImg == NULL )

return 0;

int nValeSum = 0;

int i, j;

int *nVprj = pnRamBuff, *nPlot = NULL;

int nPrjLen;

int nPrjOffset;

int nPx;

int nSin, nCos;

const BYTE *pb = NULL;

if((nRotAngle >= 0) && (nRotAngle <= 90))

{

nSin = g_nSin[nRotAngle];

nCos = g_nCos[nRotAngle];

}

else if ((nRotAngle < 0)&&(nRotAngle > -90))

{

nSin = -g_nSin[-nRotAngle];

nCos = g_nCos[-nRotAngle];

}

// compute max project length

i = nSin > 0 ? nSin : -nSin;

nPrjLen = nImgWidth*nCos+nImgHeight*i+32768;

nPrjLen = nPrjLen>>16;

if (nPrjLen>nImgWidth)

{

nPrjLen = nImgWidth;

}

if (nSin<0)

{

nPrjOffset = -nImgHeight*nSin+32768;

nPrjOffset = nPrjOffset>>16;

}

else

{

nPrjOffset = 0;

}

memset(nVprj, 0, nPrjLen * 2 * sizeof(int));

nPlot = nVprj + nPrjLen;

pb = pInImg;

for (i = 0; i < nImgHeight; i++)

{

for (j = 0; j < nImgWidth; j++, pb++)

{

if (*pb < 8)

continue;

nPx = j * nCos + i * nSin + 32768;

nPx = (nPx >> 16) + nPrjOffset;

if((nPx < nPrjLen) && (nPx>=0))

{

nVprj[nPx] += *pb;

}

}

}

SmoothingArray(nPlot, 1, nVprj, 0, nPrjLen);

nValeSum = 0;

for(i = 0; i < nPrjLen; i++)

{

if (nPlot[i]==0)

{

nValeSum++;

}

}

return nValeSum;

}

//--------------------------------------------------------------------

// NAME: SmoothingArray

// PARAMS: int *pIn, input array

// int *pOut, output array

// int nR, smooth radius

// int nStart, int nEnd, the begin and end of smoothing

// RETURN: NULL

// FUNCTION: Smoothing one-dimentional array

//---------------------------------------------------------------------

void CArdpsImg::SmoothingArray(int *pOut, int nR, const int *pIn, int nStart, int nEnd)

{

if( pIn == NULL || pOut == NULL )

return;

int i, nSum, nCount;

int beg, end;

nSum = 0;

// the len is less than nR

if (nEnd - nStart <= nR + 1)

{

nCount = nEnd - nStart;

if (nCount <= 0)

{

pOut[nStart] = pIn[nStart];

return;

}

nSum = 0;

for (i = nStart; i < nEnd; i ++)

{

nSum += pIn[i];

}

nSum = (nSum + (nCount >> 1)) / nCount;

for (i = nStart; i < nEnd; i ++)

{

pOut[i] = nSum;

}

return;

}

// first nR len

beg = nStart;

end = nStart + nR;

if (end > nEnd) end = nEnd;

for (i = beg; i < end; i ++)

{

nSum += pIn[i];

}

nCount = end - beg;

// from start to start + nR, maybe less than start + nR

if (end >= nEnd-nR)

end = nEnd - nR - 1;

for (i = nStart; i <= end; i ++)

{

nSum += pIn[i + nR];

nCount ++;

pOut[i] = (nSum + (nCount >> 1)) / nCount;

}

// from start+nR to end - nR

end = nEnd - nR;

for (; i < end; i ++)

{

nSum += pIn[i + nR] - pIn[i - nR - 1];

pOut[i] = (nSum + nCount / 2) / nCount;

}

// from end-nR to start + nR

end = nStart + nR + 1;

if (end > nEnd) end = nEnd;

for (; i < end; i++)

{

pOut[i] = (nSum + nCount / 2) / nCount;

}

// the last nR

beg = i;

if (beg < nStart + nR + 1) beg = nStart + nR + 1;

for (i = beg; i < nEnd; i ++)

{

nCount --;

nSum -= pIn[i - nR - 1];

pOut[i] = (nSum + nCount / 2) / nCount;

}

return;

}

//-------------------------------------------------------

// delete short vertical stroke

//-------------------------------------------------------

int CArdpsImg::DeleteVtlSmallLine(BYTE* pImg, BYTE* pBuf, int nWidth, int nHeight, int nTh)

{

if( pImg == NULL || pBuf == NULL )

return 0;

int i, j, nTop, nBtm, nLen;

int top, btm;

BYTE *pIn, *pIn1, *pb, *pb1;

pb = pb1 = pIn = pIn1 = NULL;

int hr = 0;

top = 0;

btm = nHeight;

LONG nBytesPerLine = MYWIDTHBYTES(nWidth * 8);

memset(pBuf, 0, nBytesPerLine * nHeight);

pIn = pImg + top * nBytesPerLine;

pb = pBuf + top * nBytesPerLine;

for (i = top; i < btm; i++)

{

for (j = 0; j < nWidth; j++, pIn++, pb++)

{

if (*pIn == 0)

{

continue;

}

nTop = i-1;

pIn1 = pIn - nBytesPerLine;

pb1 = pb - nBytesPerLine;

for (; nTop >= 0 && *pIn1 != 0; nTop--, pIn1 -= nBytesPerLine, pb1 -= nBytesPerLine)

{

*pb1 = *pIn1;

*pIn = 0;

}

nTop++;

nBtm = i+1;

pIn1 = pIn + nBytesPerLine;

pb1 = pb + nBytesPerLine;

for (; nBtm < nHeight && *pIn1 != 0; nBtm++, pIn1 += nBytesPerLine, pb1 += nBytesPerLine)

{

*pb1 = *pIn1;

*pIn1 = 0;

}

nBtm --;

nLen = nBtm - nTop + 1;

if (nLen < nTh)

{

pb1 = pBuf + nTop * nBytesPerLine + j;

for (; nTop <= nBtm; nTop++, pb1 += nBytesPerLine)

{

*pb1 = 0;

}

}

}

}

memcpy(pImg, pBuf, nBytesPerLine*nHeight);

return 0;

}

RECT CArdpsImg::GetEdgeImageBoundary(BYTE *pbImage, int nWidth, int nHeight)

{

RECT rect;

BYTE *pbIn1, *pbIn2;

LONG i, j, m;

LONG n, d;

int *pnProjX = NULL, *pnProjY = NULL;

rect = SetRectValue(0, 0, 0, 0);

if( pbImage == NULL )

return rect;

LONG nBytesPerLine = MYWIDTHBYTES(nWidth<< 3);

pnProjX = new int [nWidth + nHeight];

if (pnProjX == NULL)

{

return rect;

}

pnProjY = pnProjX + nWidth;

memset(pnProjX, 0, (nWidth + nHeight) * sizeof(int));

for (i = 0, m = 0; i < nHeight; i++, m+= nBytesPerLine )

{

pnProjY[i] = 0;

pbIn1 = pbImage + m;

for (j = 0; j < nWidth; j++, pbIn1++)

{

pnProjY[i] += pbIn1[0];

}

}

pbIn1 = pbImage;

for (i = 0; i < nWidth; i++, pbIn1++)

{

pbIn2 = pbIn1;

pnProjX[i] = 0;

for (j = 0; j < nHeight; j++, pbIn2 += nBytesPerLine)

{

pnProjX[i] += pbIn2[0];

}

}

d = n = 0;

for (i = 0; i < nHeight; i++)

{

d += pnProjY[i];

n++;

}

d = d / (4 * n);

rect.top = 0;

for (i = 0; i < nHeight; i++)

{

if (pnProjY[i] > d)

{

rect.top = i;

break;

}

}

rect.top = rect.top > 1 ? (rect.top - 1) : rect.top;

rect.bottom = nHeight - 1;

for (i = nHeight - 1; i >= 0; i--)

{

if (pnProjY[i] > d)

{

rect.bottom = i;

break;

}

}

rect.bottom = rect.bottom < (nHeight - 2) ? (rect.bottom + 1) : rect.bottom;

d = n = 0;

for (i = 0; i < nWidth; i++)

{

d += pnProjX[i];

n++;

}

d = d / (4 * n);

rect.left = 0;

for (i = 0; i < nWidth; i++)

{

if (pnProjX[i] > d)

{

rect.left = i;

break;

}

}

rect.left = rect.left > 0 ? (rect.left - 1) : rect.left;

rect.right = nWidth - 1;

for (i = nWidth - 1; i >= 0; i--)

{

if (pnProjX[i] > d)

{

rect.right = i;

break;

}

}

rect.right = rect.right < (nWidth - 2) ? (rect.right + 1) : rect.right;

if (pnProjX != NULL)

{

delete []pnProjX;

pnProjX = NULL;

}

return rect;

}

void CArdpsImg::MoveBin(BYTE *pbIn, int nWidth, int nHeight, RECT rtOld, RECT rtNew, int nMethod)

{

if( !pbIn )

return;

LONG lBytesPerLine = MYWIDTHBYTES(nWidth << 3);

LONG lImgSize = lBytesPerLine * nHeight;

BYTE *pbOut = new BYTE[lImgSize];

if( pbOut == NULL )

return;

memset(pbOut, 255, lImgSize * sizeof(BYTE));

LONG i, j, m, n;

BYTE *pbTmpIn = NULL;

switch (nMethod)

{

case 1: //水平调整

j = rtOld.right - rtOld.left + 1;

for (i = 0, m = 0; i < nHeight; i++, m += lBytesPerLine )

{

memcpy(pbOut + rtNew.left+ m, pbIn + rtOld.left + m, j * sizeof(BYTE) );

}

break;

case 2: //垂直调整

//i = rtOld.bottom - rtOld.top + 1;

i = rtNew.top * lBytesPerLine;

for( j = rtOld.top, m = j * lBytesPerLine; j <= rtOld.bottom; j++, m += lBytesPerLine)

{

memcpy(pbOut + i, pbIn + m, lBytesPerLine);

i += lBytesPerLine;

}

break;

case 0: //垂直和水平调整

default:

i = rtNew.top * lBytesPerLine + rtNew.left;

m = rtOld.top *lBytesPerLine + rtOld.left;

n = rtOld.right - rtOld.left + 1;

for( j = rtOld.top; j <= rtOld.bottom; j++)

{

memcpy(pbOut + i, pbIn + m, n * sizeof(BYTE));

i += lBytesPerLine;

m += lBytesPerLine;

}

break;

}

memcpy( pbIn, pbOut, lImgSize * sizeof(BYTE));

if( pbOut )

delete[]pbOut;

pbOut = NULL;

}

RECT CArdpsImg::GetBinImageBoundary(BYTE *pbImage, int nWidth, int nHeight)

{

RECT rect;

BYTE *pbIn1, *pbIn2;

LONG i, j, m;

LONG n, d;

int *pnProjX = NULL, *pnProjY = NULL;

rect = SetRectValue(0, 0, 0, 0);

if( pbImage == NULL )

return rect;

LONG nBytesPerLine = MYWIDTHBYTES(nWidth<< 3);

pnProjX = new int [nWidth + nHeight];

if (pnProjX == NULL)

{

return rect;

}

pnProjY = pnProjX + nWidth;

memset(pnProjX, 0, (nWidth + nHeight) * sizeof(int));

for (i = 0, m = 0; i < nHeight; i++, m+= nBytesPerLine )

{

pnProjY[i] = 0;

pbIn1 = pbImage + m;

for (j = 0; j < nWidth; j++, pbIn1++)

{

pnProjY[i] += 255- pbIn1[0];

}

pnProjY[i] /= 255;

}

pbIn1 = pbImage;

for (i = 0; i < nWidth; i++, pbIn1++)

{

pbIn2 = pbIn1;

pnProjX[i] = 0;

for (j = 0; j < nHeight; j++, pbIn2 += nBytesPerLine)

{

pnProjX[i] += 255- pbIn2[0];

}

pnProjX[i] /= 255;

}

d = n = 0;

for (i = 0; i < nHeight; i++)

{

d += pnProjY[i];

n++;

}

d = d / (4 * n);

rect.top = 0;

for (i = 0; i < nHeight; i++)

{

if (pnProjY[i] > d)

{

rect.top = i;

break;

}

}

rect.top = rect.top > 1 ? (rect.top - 1) : rect.top;

rect.bottom = nHeight - 1;

for (i = nHeight - 1; i >= 0; i--)

{

if (pnProjY[i] > d)

{

rect.bottom = i;

break;

}

}

rect.bottom = rect.bottom < (nHeight - 2) ? (rect.bottom + 1) : rect.bottom;

d = n = 0;

for (i = 0; i < nWidth; i++)

{

d += pnProjX[i];

n++;

}

d = d / (4 * n);

rect.left = 0;

for (i = 0; i < nWidth; i++)

{

if (pnProjX[i] > d)

{

rect.left = i;

break;

}

}

rect.left = rect.left > 0 ? (rect.left - 1) : rect.left;

rect.right = nWidth - 1;

for (i = nWidth - 1; i >= 0; i--)

{

if (pnProjX[i] > d)

{

rect.right = i;

break;

}

}

rect.right = rect.right < (nWidth - 2) ? (rect.right + 1) : rect.right;

if (pnProjX != NULL)

{

delete []pnProjX;

pnProjX = NULL;

}

return rect;

}

RECT CArdpsImg::SetRectValue(int left, int right, int top, int bottom)

{

RECT rect;

rect.left = left;

rect.right = right;

rect.top = top;

rect.bottom = bottom;

return rect;

}

int CArdpsImg::FindEdgeImage(BYTE *pbOutImage, BYTE *image, RECT rtROI, int nWidth)

{

if( pbOutImage == NULL || image == NULL )

return -1;

BYTE *pbIn1, *pbIn2;

int i, j, d;

int gd, n = 0, k = 0;

pbIn2 = pbIn1 = NULL;

int nBytesPerLine = MYWIDTHBYTES(nWidth << 3);

gd = n = 0;

pbIn1 = image + rtROI.top * nBytesPerLine + rtROI.left;

for (i = rtROI.top; i < rtROI.bottom; i++, pbIn1 += nBytesPerLine)

{

pbIn2 = pbIn1 + EDGE_STEP;

for (j = rtROI.left + EDGE_STEP; j < rtROI.right; j++, pbIn2++)

{

d = pbIn2[-EDGE_STEP] - pbIn2[0];

if (d < 10)

{

continue;

}

gd += d;

n++;

}

}

if (n < 100)

{

return -1;

}

gd = gd / n;

pbIn1 = image + rtROI.top * nBytesPerLine + rtROI.left;

for (i = rtROI.top; i < rtROI.bottom; i++, pbIn1 += nBytesPerLine)

{

pbIn2 = pbIn1;

for (j = rtROI.left; j < rtROI.right; j++, pbIn2++)

{

n = (int)(pbIn2 - image);

pbOutImage
= 0;

if (j > EDGE_STEP)

{

d = pbIn2[-EDGE_STEP] - pbIn2[0];

if (d > gd)

{

pbOutImage
= d;

}

}

if (j < nWidth - EDGE_STEP - 1)

{

d = pbIn2[EDGE_STEP] - pbIn2[0];

if (d > gd && d > pbOutImage[i * nBytesPerLine + j])

{

pbOutImage
= d;

}

}

}

}

return 0;

}

HDIB CArdpsImg::ReadBinTiff(char* szImgFileName)

{

TIFF *image = NULL;

uint32 height, buffsize, bytesPerLine, nImgWidth, nPalleteSize, nFileSize;

uint32 row, k, i;

HDIB hDIB = NULL;

// Open the TIFF image

image = TIFFOpen(szImgFileName, "r");

if( image == NULL )

return hDIB;

TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height);

TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &nImgWidth);

uint16 bitspersample=1;

uint16 samplesperpixel=1;

TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);

TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample);

//for debug

uint16 compression = 0;

TIFFGetField(image, TIFFTAG_COMPRESSION, &compression);

uint16 photmeric = 0;

TIFFGetField(image, TIFFTAG_PHOTOMETRIC, &photmeric);

uint16 bitsperpixel = bitspersample * samplesperpixel;

if( bitsperpixel == 1)

nPalleteSize = 2;

else if( bitsperpixel == 8 )

nPalleteSize = 256;

else if( bitsperpixel == 16)

return hDIB;

else

nPalleteSize = 0;

buffsize = TIFFScanlineSize(image);

uint32 buffTotalSize = buffsize * height;

BYTE * pbOriImg = new BYTE[buffTotalSize];

if( pbOriImg == NULL )

{

TIFFClose(image);

return hDIB;

}

for (row = 0 , k = (height - 1) * buffsize; row < height; row++ , k -= buffsize )

TIFFReadScanline(image, (void*)(pbOriImg + k), row);

TIFFClose(image);

/*TIFF *newImg = TIFFOpen("d:\\testread.tif", "w");

TIFFSetField(newImg, TIFFTAG_IMAGELENGTH, height);

TIFFSetField(newImg, TIFFTAG_IMAGEWIDTH, nImgWidth);

TIFFSetField(newImg, TIFFTAG_SAMPLESPERPIXEL,samplesperpixel);

TIFFSetField(newImg, TIFFTAG_BITSPERSAMPLE, bitspersample);

TIFFSetField(newImg, TIFFTAG_COMPRESSION, compression);

TIFFSetField(newImg, TIFFTAG_PHOTOMETRIC, photmeric);

for (row = 0 , k = (height - 1) * buffsize; row < height; row++ , k -= buffsize )

TIFFWriteScanline(newImg, (void*)(pbOriImg + k), row);*/

//TIFFClose(newImg);

if( bitsperpixel == 32 )

bytesPerLine = MYWIDTHBYTES(nImgWidth * 24);

else

bytesPerLine = MYWIDTHBYTES(nImgWidth * bitsperpixel);

buffTotalSize = bytesPerLine * height;

nFileSize = buffTotalSize + nPalleteSize * sizeof(RGBQUAD) + sizeof(BITMAPINFOHEADER);

hDIB = (HDIB)GlobalAlloc(GHND, nFileSize);

if( hDIB == NULL )

{

delete []pbOriImg;

pbOriImg = NULL;

return hDIB;

}

LPBYTE lpNewDIB = (LPBYTE)GlobalLock(hDIB);

memset( lpNewDIB, 0, nFileSize * sizeof(BYTE));

LPBITMAPINFOHEADER pInfo = (LPBITMAPINFOHEADER) lpNewDIB;

pInfo->biSize = sizeof(BITMAPINFOHEADER);

pInfo->biWidth = nImgWidth;

pInfo->biHeight = height;

pInfo->biCompression = BI_RGB;

pInfo->biClrUsed = 0;

pInfo->biClrImportant = 0;

pInfo->biPlanes = 1;

pInfo->biSizeImage = buffTotalSize;

pInfo->biXPelsPerMeter = 0;

pInfo->biYPelsPerMeter = 0;

if( bitsperpixel == 32 )

pInfo->biBitCount = 24;

else

pInfo->biBitCount = bitsperpixel;

RGBQUAD *pNewRGBQuad = (RGBQUAD *)( lpNewDIB + sizeof(BITMAPINFOHEADER));

if( bitsperpixel == 1 )

{

pNewRGBQuad->rgbRed = pNewRGBQuad->rgbGreen = pNewRGBQuad->rgbBlue = 0;

pNewRGBQuad->rgbReserved = 0;

pNewRGBQuad ++;

pNewRGBQuad->rgbRed = pNewRGBQuad->rgbGreen = pNewRGBQuad->rgbBlue = 255;

pNewRGBQuad->rgbReserved = 0;

}

else

{

for( int i = 0; i < nPalleteSize; i++, pNewRGBQuad++ )

{

pNewRGBQuad->rgbRed = pNewRGBQuad->rgbGreen = pNewRGBQuad->rgbBlue = i;

pNewRGBQuad->rgbReserved = 0;

}

}

BYTE *pbNewImg = lpNewDIB + sizeof(BITMAPINFOHEADER) + nPalleteSize * sizeof(RGBQUAD) ;

if (bitsperpixel == 32)

{

Img32to24(pbOriImg, pbNewImg, nImgWidth, height);

}

else if (bitsperpixel == 24)

{

ReversColors(pbOriImg, pbNewImg, nImgWidth, height);

}

else

{

for( i = 0, k = 0, row = 0; i < height; i++, k += bytesPerLine, row += buffsize )

{

memcpy(pbNewImg + k, pbOriImg + row, buffsize * sizeof(BYTE));

}

}

if( pbOriImg )

delete []pbOriImg;

pbOriImg = NULL;

return hDIB;

}

void CArdpsImg::Img32to24(BYTE *pbImg32, BYTE *pbImg24, int nWidth, int nHeight)

{

if( pbImg32 == NULL || pbImg24 == NULL )

return;

int i, j, m, n;

LONG nBytesLine24 = MYWIDTHBYTES(nWidth * 24);

BYTE *pbIn = pbImg32;

BYTE *pbOut = pbImg24;

for( i = 0, m = 0, n = 0; i < nHeight; i++, m += nWidth * 4, n += nBytesLine24 )

{

pbIn = pbImg32 + m;

pbOut = pbImg24 + n;

for( j = 0; j < nWidth; j++ )

{

*pbOut = *(pbIn + 2);

*(pbOut + 1) = *(pbIn + 1);

*(pbOut + 2) = *(pbIn);

pbIn += 4;

pbOut += 3;

}

}

}

void CArdpsImg::ReversColors(BYTE*pbIn, BYTE *pbOut, int nWidth, int nHeight)

{

if( pbIn == NULL || pbOut == NULL )

return;

int i, j,n, m;

LONG nBytesLine24 = MYWIDTHBYTES(nWidth * 24);

BYTE *ptmp = pbIn;

BYTE *ptmp2 = pbOut;

for( i = 0, n = 0, m = 0; i < nHeight; i++, n += nBytesLine24, m += nWidth * 3 )

{

ptmp = pbIn + m;

ptmp2 = pbOut + n;

for( j = 0; j < nWidth; j++ )

{

*ptmp2 = *(ptmp + 2);

*(ptmp2 + 1) = *(ptmp + 1);

*(ptmp2 + 2) = *(ptmp);

ptmp2 += 3;

ptmp += 3;

}

}

}

void CArdpsImg::ReversColors(BYTE*pbIn, int nWidth, int nHeight)

{

if( pbIn == NULL )

return;

int i, j, m;

LONG nBytesLine24 = MYWIDTHBYTES(nWidth * 24);

BYTE *ptmp = pbIn;

BYTE bValue = 0;

for( i = 0, m = 0; i < nHeight; i++, m += nBytesLine24 )

{

ptmp = pbIn + m;

for( j = 0; j < nWidth; j++ )

{

bValue = *(ptmp + 2);

*(ptmp + 2) = *(ptmp);

*ptmp = bValue;

ptmp += 3;

}

}

}

bool CArdpsImg::SaveTiff(char *szImgFileName)

{

if( szImgFileName == NULL )

return false;

LPBYTE lpDIB = (LPBYTE) GlobalLock(m_hDib);

if( lpDIB == NULL )

return false;

LPBYTE lpBinImg = FindDIBBits(lpDIB);

if( !lpBinImg )

{

GlobalUnlock(m_hDib);

return false;

}

uint16 samplesperpixel, bitspersample, photometric, compression;

LONG nImgHei = GetHeight();

LONG nImgWid = GetWidth();

WORD nBitCnt = DIBBitCount(lpDIB);

if( nBitCnt == 1)

{

samplesperpixel = 1;

bitspersample = 1;

photometric = PHOTOMETRIC_MINISBLACK;

compression = COMPRESSION_CCITTFAX4;

ReversBits(lpBinImg, nImgWid, nImgHei, nBitCnt);

}

else if (nBitCnt == 8)

{

samplesperpixel = 1;

bitspersample = 8;

photometric = 1;

compression = COMPRESSION_LZW;

}

else if (nBitCnt == 24)

{

samplesperpixel = 3;

bitspersample = 8;

photometric = 2;

compression = COMPRESSION_JPEG;

//compression = COMPRESSION_DEFLATE;

ReversColors(lpBinImg, nImgWid, nImgHei);

}

else

{

GlobalUnlock(m_hDib);

return false;

}

TIFF * newImg = TIFFOpen(szImgFileName, "w");

if( newImg == NULL )

{

GlobalUnlock(m_hDib);

return false;

}

TIFFSetField(newImg, TIFFTAG_IMAGELENGTH, nImgHei);

TIFFSetField(newImg, TIFFTAG_IMAGEWIDTH, nImgWid);

TIFFSetField(newImg, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);

TIFFSetField(newImg, TIFFTAG_BITSPERSAMPLE,bitspersample);

TIFFSetField(newImg, TIFFTAG_PHOTOMETRIC, photometric);

//if(nBitCnt != 24 ) 只能由程序读取,去掉该注释可以被通用程序读取,压缩比变小。

TIFFSetField(newImg, TIFFTAG_COMPRESSION, compression);

TIFFSetField(newImg, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);

uint32 row, buffsize, k;

buffsize = MYWIDTHBYTES(nImgWid * bitspersample * samplesperpixel );

for (row = 0 , k = (nImgHei - 1) * buffsize; row < nImgHei; row++ , k -= buffsize )

TIFFWriteScanline(newImg, (void*)(lpBinImg + k), row, 0);

TIFFClose(newImg);

GlobalUnlock(m_hDib);

return true;

}

void CArdpsImg::ReversBits(BYTE *pbIn, int nWidth, int nHeight, DWORD nBitCnt)

{

int nBytesPerLine = MYWIDTHBYTES(nBitCnt * nWidth );

BYTE *ptmp = pbIn;

for( int i = 0; i < nBytesPerLine * nHeight; i++, ptmp++ )

{

*ptmp = 255- (*ptmp);

}

}

bool CArdpsImg::SaveGrayDIB()

{

LPBITMAPINFOHEADER lpDIBHdr = (LPBITMAPINFOHEADER)GlobalLock(m_hDib);

//for color image

LONG nImgHei = GetHeight();

LONG nImgWid = GetWidth();

//for gray image

LONG nGrayBytesPerLine = MYWIDTHBYTES( nImgWid << 3 );

LONG nGrayImgSize = nGrayBytesPerLine * nImgHei;

LONG nFileSize = nGrayImgSize + lpDIBHdr->biSize + 256 * sizeof(RGBQUAD);

//allocate memory for gray image

LPBYTE lpNewDIB = new BYTE[nFileSize];

if( !lpNewDIB )

return false;

memset(lpNewDIB, 0, nFileSize*sizeof(BYTE));

LPBITMAPINFOHEADER lpNewDIBHdr = (LPBITMAPINFOHEADER)lpNewDIB;

memcpy(lpNewDIBHdr, lpDIBHdr, sizeof(BITMAPINFOHEADER));

GlobalUnlock(m_hDib);

lpNewDIBHdr->biBitCount = 8;

lpNewDIBHdr->biCompression = BI_RGB;

lpNewDIBHdr->biSizeImage = nGrayImgSize;

lpNewDIBHdr->biClrUsed = 256;

lpNewDIBHdr->biXPelsPerMeter = 2952;

lpNewDIBHdr->biYPelsPerMeter = 2952;

//create RGBQUARD

RGBQUAD *pNewRGBQuad = (RGBQUAD*)(lpNewDIB +sizeof(BITMAPINFOHEADER));

memset(pNewRGBQuad, 0, 256*sizeof(RGBQUAD));

for( int i = 0; i < 256; ++i )

{

pNewRGBQuad->rgbBlue = pNewRGBQuad->rgbRed =

pNewRGBQuad->rgbGreen = i;

pNewRGBQuad++;

}

LPBYTE lpDIB = (LPBYTE)GlobalLock(m_hDib);

LPBYTE lpSrcImg = FindDIBBits(lpDIB);

LPBYTE lpNewImg = lpNewDIB + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);

bool bConvert = ConvertBinary2Gray(lpSrcImg, nImgWid, nImgHei, lpNewImg);

GlobalUnlock(m_hDib);

bool bCrate = Create(lpNewDIB);

if( lpNewDIB )

delete []lpNewDIB;

lpNewDIB = NULL;

return true;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: