www.pudn.com > try2LPR-1.0.rar > LPRProcess.cpp


/* 
* Copyright (c) 2003, try2it.com 
* All rights reserved. 
* 
* This program is free software; you can redistribute it and/or modify it under 
* the terms of the GNU General Public License as published by the Free Software 
* Foundation; either version 2 of the License, or (at your option) any later 
* version. 
*  
* This program is distributed in the hope that it will be useful, but WITHOUT 
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
* details. 
*  
* You should have received a copy of the GNU General Public License along with 
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple 
* Place - Suite 330, Boston, MA 02111-1307, USA. 
* 
* 文件名称:LPRHelper.cpp 
* 文件标识:LPR-02-05 
* 摘要:牌照识别的图像处理部分 
* 
* 当前版本:1.0 
* 作者:try2it.com 
* 开始日期:2003年09月28日 
* 完成日期:2003年09月30日 
*/ 
#include "stdafx.h" 
#include  
#include  
#include  
#include  
#include "../include/types.h" 
#include "LPRHelper.h" 
#include "LPRProcess.h" 
 
/*------------------------------------------------------------------ 
* 以下声明全局变量 
------------------------------------------------------------------*/ 
int g_LPHeight = 80;        
int g_LPWidth = 220;      
int g_LPAccurateHeight = 40;  
int g_BYDiff = 10;         
int g_BWDiff = 20;        
int g_BlackLP = 80;        
int g_WhiteLP = 220;       
int g_BYLP = 60;          
int g_Threshold = 160;     
int g_Threshold_HLP = 100;  
int g_LeftOffset = 0;       
int g_RightOffset = 0;     
int g_TopOffset = 0;        
int g_BottomOffset = 0;   
 
int InteEqualize(PGrayImg pDestImg, PGrayImg pSrcImg) 
{ 
	int res = 0; 
	int HistoGram[256]; 
	int bMap[256]; 
 
	int Temp, i, j; 
	TGrayImg TempImg; 
 
	res = CalHistoGram(HistoGram, pSrcImg); 
	if (res == 0) 
		return 0; 
 
	res = GrayImg_Malloc(&TempImg, pSrcImg->Width, pSrcImg->Height); 
	if (res == 0) 
		return 0; 
	 
    for (i=0; i<256; i++) 
    { 
		Temp = 0; 
        for (j=0; j<=i; j++) 
			Temp = Temp + HistoGram[j]; 
 
        bMap[i] = (int)(Temp*255.0/pSrcImg->Height/pSrcImg->Width+0.5); 
	} 
 
    for (i=0; iHeight; i++) 
		for (j=0; jWidth; j++) 
        { 
			*(TempImg.pImg+i*TempImg.Width+j) = (BYTE)bMap[*(pSrcImg->pImg+i*pSrcImg->Width+j)]; 
		} 
 
	pDestImg->Width = TempImg.Width; 
	pDestImg->Height = TempImg.Height; 
 
	if (pDestImg->pImg)  
	{ 
		pDestImg->pImg = NULL; 
	} 
 
	pDestImg->pImg = TempImg.pImg; 
 
	return res; 
} 
 
int CalHistoGram(int HistoGram[], PGrayImg pSrcImg) 
{ 
	int i, j; 
	 
	for (i=0; i<256; i++) HistoGram[i] = 0; 
 
	for (i=0; iHeight; i++) 
		for (j=0; jWidth; j++) 
			HistoGram[*(pSrcImg->pImg+i*pSrcImg->Width+j)]++; 
 
	return 1; 
} 
 
int MedianFilter(PGrayImg pDestImg, PGrayImg pSrcImg, int iFilterH,  
				               int iFilterW, int iFilterMX, int iFilterMY) 
{ 
	int i, j, l, k; 
	int res = 0; 
	BYTE *aValue; 
 
	TGrayImg TempImg; 
 
	res = GrayImg_Malloc(&TempImg, pSrcImg->Width, pSrcImg->Height); 
	if (res == 0) 
		return 0; 
 
	aValue = (BYTE*)malloc(iFilterH * iFilterW); 
	if (aValue == NULL) 
		return 0; 
 
	for (i=iFilterMY; i<=TempImg.Height-iFilterH+iFilterMY; i++) 
		for (j=iFilterMX; j<=TempImg.Width-iFilterW+iFilterMX; j++) 
		{ 
			for (k=0; kpImg+(i-iFilterMY+k)*TempImg.Width+j-iFilterMX+1); 
				} 
			*(TempImg.pImg+i*TempImg.Width+j) = GetMedianNum(aValue, iFilterH*iFilterW); 
		} 
 
	if (aValue!=NULL) 
		free(aValue); 
 
	for (i=0; ipImg+i*pSrcImg->Width+j); 
 
	for (i=0; ipImg+i*pSrcImg->Width+j); 
 
	for (i=0; ipImg+i*pSrcImg->Width+j); 
 
	for (i=TempImg.Height-iFilterH+iFilterMY+1; ipImg+i*pSrcImg->Width+j); 
 
	pDestImg->Width = TempImg.Width; 
	pDestImg->Height = TempImg.Height; 
	if (pDestImg->pImg) 
	{ 
		pDestImg->pImg = NULL; 
	} 
	pDestImg->pImg = TempImg.pImg; 
 
	return res; 
} 
 
BYTE GetMedianNum(BYTE *aValue, int iLength) 
{ 
	int i, j; 
	BYTE tmp; 
 
	for (j=1; j (*(aValue+i+1))) 
			{ 
				tmp = *(aValue+i); 
				*(aValue+i) = *(aValue+i+1); 
				*(aValue+i+1) = tmp; 
			} 
		} 
 
	if ((iLength & 1) > 0) 
	{ 
		tmp = *(aValue+(iLength+1)/2); 
	} 
	else 
	{ 
		tmp = (*(aValue+iLength/2) + *(aValue+iLength/2+1))/2; 
	} 
 
	return tmp; 
} 
 
int GetLPPos(RECT *lpRect, PGrayImg pSrcImg) 
{ 
	int res = 0; 
	static int TemplateArr[9] = {1,0,-1,    
                                 2,0,-2, 
								 1,0,-1}; 
	static int TemplateArr1[9] = {1,1,1,    
		                          1,0,1, 
								  1,1,1}; 
 
	TGrayImg EdgeImg;           
	TGrayImg TwoImg;           
	TGrayImg HLPImg, HLPImg1, HLPImg2;  
 
	int StartYPos=0;            
	int UpYPos=0, DownYPos=0;   
	int LeftXPos=0, RightXPos=0;  
	int Threshold;             
 
	RECT Rect; 
 
	int *pHProject = NULL;       
	int *pVProject = NULL;     
 
	BOOL flag; 
 
	res = Template(&EdgeImg, pSrcImg, TemplateArr, 3 ,1); 
	if (res == 0) 
		return 0; 
 
	StartYPos = EdgeImg.Height - 1; 
	Threshold = g_Threshold; 
 
	pHProject = (int*)malloc(pSrcImg->Height*sizeof(int)); 
	if (NULL == pHProject) 
		return 0; 
 
	flag = TRUE; 
	while(flag) 
	{ 
		res = TwoPixelCarImg(&TwoImg, &EdgeImg, Threshold); 
		if (0 == res) 
			return 0; 
 
		res = ProjectImg(pHProject, &TwoImg, H_FILTER); 
		if (0 == res) 
			return 0; 
 
		res = ProjectFilter(pHProject, TwoImg.Height, H_FILTER); 
		if (0 == res) 
			return 0; 
 
		res = GetLPYPos(pHProject, TwoImg.Height, &StartYPos, &UpYPos, &DownYPos); 
		if (0 == res) 
		{ 
			Threshold -= 10; 
			if (Threshold < 50) 
			{ 
				return 0; 
			} 
		} 
		else 
		{ 
			flag = FALSE; 
		} 
 
	} 
	 
	LeftXPos = 0; 
	RightXPos = pSrcImg->Width - 1; 
	Rect.left = LeftXPos; 
	Rect.top = UpYPos; 
	Rect.right = RightXPos; 
	Rect.bottom = DownYPos; 
 
	res = GetSubImg(&HLPImg1, &EdgeImg, Rect); 
	if (0 == res) 
		return 0; 
 
//////////////////////////////////////////////////////////////////////////////////////////// 
	res = Template(&HLPImg2, &HLPImg1, TemplateArr1, 3, 1.0/8.0); 
	if (0 == res) 
		return 0; 
 
	res = TwoPixelCarImg(&HLPImg, &HLPImg2, g_Threshold_HLP); 
	if (0 == res) 
		return 0; 
 
	GrayImg_Free(&HLPImg1); 
	GrayImg_Free(&HLPImg2); 
 
	pVProject = (int*)malloc(pSrcImg->Width*sizeof(int)); 
	if (NULL == pVProject) 
		return 0; 
 
	res = ProjectImg(pVProject, &HLPImg, V_FILTER); 
	if (0 == res) 
		return 0; 
 
	res = ProjectFilter(pVProject, pSrcImg->Width, V_FILTER, g_LPAccurateHeight); 
	if (0 == res) 
		return 0; 
 
	flag = TRUE; 
	while(flag) 
	{ 
		res = GetLPXPos(pVProject, pSrcImg->Width, &LeftXPos, &RightXPos); 
		if (0 == res) 
		{ 
			res = GetLPYPos(pHProject, pSrcImg->Height, &StartYPos, &UpYPos, &DownYPos); 
			if (0 == res) 
			{ 
				StartYPos = pSrcImg->Height - 1; 
				res = GetLPYPos(pHProject, pSrcImg->Height, &StartYPos, &UpYPos, &DownYPos); 
				if (0 == res) 
					return 0; 
				else  
				{ 
					res = GetLPXPos(pVProject, pSrcImg->Width, &LeftXPos, &RightXPos); 
					if (0 == res) 
						return 0; 
					else 
					{ 
						RightXPos += (int)(g_LPWidth * 0.8 + 0.5); 
						flag = FALSE; 
					} 
				} 
			} 
		} 
		else 
		{ 
			if (RightXPos - LeftXPos < 0.6 * g_LPWidth) 
			{ 
				res = GetLPYPos(pHProject, pSrcImg->Height, &StartYPos, &UpYPos, &DownYPos); 
				if (0 == res) 
				{ 
					StartYPos = pSrcImg->Height - 1; 
					res = GetLPYPos(pHProject, pSrcImg->Height, &StartYPos, &UpYPos, &DownYPos); 
					if (0 == res) 
						return 0; 
					else  
					{ 
						res = GetLPXPos(pVProject, pSrcImg->Width, &LeftXPos, &RightXPos); 
						if (0 == res) 
							return 0; 
						else 
						{ 
						   RightXPos += (int)(g_LPWidth * 0.8 + 0.5); 
						   flag = FALSE; 
						} 
					} 
				} 
			} 
			else 
				flag = FALSE; 
		} 
	} 
 
	if (pHProject!=NULL) 
	{ 
		free(pHProject); 
		pHProject = NULL; 
	} 
 
	if (pVProject!=NULL) 
	{ 
		free(pVProject); 
		pVProject = NULL; 
	} 
 
	lpRect->left = LeftXPos; 
	lpRect->right = RightXPos; 
	lpRect->top = UpYPos; 
	lpRect->bottom = DownYPos; 
	 
	GrayImg_Free(&HLPImg); 
	GrayImg_Free(&TwoImg); 
	GrayImg_Free(&EdgeImg); 
 
	return 1; 
} 
 
int GetLPYPos(int *pProject, int PrjLen, int *pStartYPos, int *pUpYPos, int *pDownYPos) 
{ 
	int y, Temp; 
	BOOL Flag; 
 
	Flag = TRUE; 
	*pDownYPos = 0; 
	*pUpYPos = 0; 
	*(pProject+PrjLen-1) = 0; 
 
	for (y=*pStartYPos; y>=0; y--) 
	{ 
		if ((*(pProject+y)!=0) && Flag) 
		{ 
			*pDownYPos = y; 
			Flag = FALSE; 
		} 
		if ((*(pProject+y) == 0) && (!Flag)) 
		{ 
		   *pUpYPos = y; 
		   break; 
		} 
	} 
 
	*pStartYPos = *pUpYPos; 
 
	if (*pDownYPos <= *pUpYPos) 
	{ 
		*pStartYPos = PrjLen-1; 
		return 0; 
	} 
 
	Temp = *pDownYPos - *pUpYPos; 
	if (Temp < g_LPHeight) 
	{ 
	  *pDownYPos = *pDownYPos + (int)((g_LPHeight - Temp) * 0.6 + 0.5); 
	  if (*pDownYPos > PrjLen - 1) 
		   *pDownYPos = PrjLen - 1; 
 
	  *pUpYPos = *pUpYPos - (int)((g_LPHeight - Temp) * 0.4 + 0.5); 
 
	  if (*pUpYPos < 0) 
		   *pUpYPos = 0; 
	} 
 
	if (Temp > g_LPHeight * 1.5) 
	{ 
		*pDownYPos = *pDownYPos + (int)(g_LPHeight * 0.125 + 0.5); 
 
		if (*pDownYPos > PrjLen - 1) 
		   *pDownYPos = PrjLen - 1; 
 
		*pUpYPos = *pDownYPos - g_LPHeight; 
 
		*pUpYPos = *pUpYPos - (int)(g_LPHeight * 0.15 + 0.5); 
 
		if (*pUpYPos < 0) 
			*pUpYPos = 0; 
	} 
 
	return 1; 
} 
 
int GetLPXPos(int *pProject, int PrjLen, int *pLeftXPos, int *pRightXPos) 
{ 
	int x, Temp; 
	int TempLeft, TempRight; 
	BOOL flag; 
 
	flag = TRUE; 
	Temp = 0; 
 
	*pLeftXPos = 0;  
	*pRightXPos = 0; 
 
	*(pProject+PrjLen-1) = 0; 
 
	for (x=0; xWidth, pSrcImg->Height); 
	if (res == 0) 
		return 0; 
 
	for (x=TemplateN/2; xHeight-TemplateN/2; x++) 
		for (y=TemplateN/2; yWidth-TemplateN/2; y++) 
		{ 
			temp = 0; 
			for (i=-TemplateN/2; i<=TemplateN/2; i++) 
				for (j=-TemplateN/2; j<=TemplateN/2; j++) 
					temp = temp + *(pSrcImg->pImg+(x+i)*pSrcImg->Width+(y+j)) * 
		                 TemplateArr[(i+TemplateN/2)*TemplateN+j+TemplateN/2]; 
 
			temp = (int)(abs(temp) * Coef + 0.5); 
 
			if (temp > 255) 
				temp = 255; 
 
			*(TempImg.pImg+x*TempImg.Width+y) = temp; 
		} 
	 
	for (x=0; xHeight; x++) 
		for (y=0; yHeight; x++) 
		for (y=pSrcImg->Width-TemplateN/2; yWidth; y++) 
			*(TempImg.pImg+x*TempImg.Width+y) = 0; 
 
	for (x=0; xWidth; y++) 
			*(TempImg.pImg+x*TempImg.Width+y) = 0; 
 
	for (x=pSrcImg->Height-TemplateN/2; xHeight; x++) 
		for (y=0; yWidth; y++) 
			*(TempImg.pImg+x*TempImg.Width+y) = 0; 
 
	pDestImg->Width = TempImg.Width; 
	pDestImg->Height = TempImg.Height; 
	pDestImg->pImg = TempImg.pImg; 
 
	return 1; 
} 
 
int ProjectImg(int *pProject, PGrayImg pSrcImg,  TPrjType PrjType) 
{ 
	int i, j; 
 
	switch (PrjType) 
	{ 
	case H_FILTER: 
 
		for (i=0; iHeight; i++) 
			*(pProject+i) = 0; 
 
		for (i=0; iHeight; i++) 
			for (j=0; jWidth; j++) 
				*(pProject+i) += *(pSrcImg->pImg+i*pSrcImg->Width+j); 
 
		*(pProject+pSrcImg->Height-1) = 0; 
 
		break; 
 
	case V_FILTER: 
 
		for (i=0; iWidth; i++) 
			*(pProject+i) = 0; 
 
		for (i=0; iHeight; i++) 
			for (j=0; jWidth; j++) 
				*(pProject+j) += *(pSrcImg->pImg+i*pSrcImg->Width+j); 
 
		*(pProject+pSrcImg->Width-1) = 0; 
 
		break; 
 
	default: 
		return 0; 
	} 
	return 1; 
} 
 
int ProjectFilter(int *pProject, int PrjLen, TPrjType PrjType, int LPAccurateHeight) 
{ 
	int i, j, p; 
	int Temp, Temp1; 
	BOOL Flag1, Flag2; 
	int avg, CharID; 
	int TempLeft[100], TempRight[100]; 
	int TempWidth[100], MergeID[100]; 
 
	*(pProject + PrjLen - 1) = 0; 
 
	switch (PrjType) 
	{ 
	case H_FILTER:   
		for (i=0; i (int)(g_LPWidth*1.5+0.5)) 
				{ 
					for (j=Temp; j (int)(4.6 * LPAccurateHeight + 0.5)) 
		{ 
			Flag2 = TRUE; Flag1 = TRUE; 
			for (i=0; i<=(int)((PrjLen-1)/3.0); i++) 
			{ 
				if ((*(pProject+i) != 0) && Flag1) 
				{ 
					Flag1 = FALSE; 
				} 
				 
				if ((*(pProject+i) == 0) && (!Flag1)) 
				{ 
					Temp1 = i;          
					Flag1 = TRUE; 
					Flag2 = FALSE; 
				} 
 
		        if ((*(pProject+i) != 0) && (!Flag2)) 
				{ 
					if (i-Temp1 > (int)(0.6*LPAccurateHeight+0.5)) 
					{ 
						for (j=i-1; j>=0; j--) 
							*(pProject+j) = 0; 
					} 
					Flag2 = TRUE; 
				} 
			} 
 
			Flag1 = TRUE; 
			CharID = 0; 
			for (i=0; i<=(int)((PrjLen-1)/2.0); i++) 
			{ 
				if ((*(pProject+i) != 0) && Flag1) 
				{ 
					TempLeft[CharID] = i; 
					Flag1 = FALSE; 
				} 
 
				if ((*(pProject+i) == 0) && (!Flag1)) 
				{ 
					TempRight[CharID] = i; 
					TempWidth[CharID] = TempRight[CharID] - TempLeft[CharID]; 
					CharID++; 
					if (CharID > 100) 
					{ 
						return 0; 
					} 
 
					Flag1 = TRUE; 
				} 
			} 
 
			j = 0; 
			for (i=0; i=(int)(0.35*LPAccurateHeight+0.5))) 
				{ 
					 if (j > 1) 
					 { 
						for (p=TempLeft[MergeID[0]]; p<=TempRight[MergeID[j-1]]; p++) 
						{ 
						   *(pProject+p) = (int)(0.5 * LPAccurateHeight + 0.5) * 255; 
						} 
					 } 
					 j = 0; 
				} 
			} 
		} 
 
		Flag1 = TRUE; 
		for (i=0; iWidth, pSrcImg->Height); 
	if (res == 0) 
		return 0; 
 
	for (i=0; iHeight; i++) 
		for (j=0; jWidth; j++) 
		{ 
			if (*(pSrcImg->pImg+i*pSrcImg->Width+j) > Threshold) 
				*(TempImg.pImg+TempImg.Width*i+j) = 255; 
			else 
				*(TempImg.pImg+TempImg.Width*i+j) = 0; 
		} 
 
	pDestImg->Width = TempImg.Width; 
	pDestImg->Height = TempImg.Height; 
	pDestImg->pImg = TempImg.pImg; 
 
	return 1; 
} 
 
int GetSubImg(PGrayImg pDestImg, PGrayImg pSrcImg, RECT Rect) 
{ 
	int i, j; 
	int res = 0; 
	TGrayImg TempImg; 
 
	int Left=0, Right=0, Top=0, Bottom=0; 
 
	res = GrayImg_Malloc(&TempImg, Rect.right-Rect.left+1, Rect.bottom-Rect.top+1); 
	if (0 == res) 
		return 0; 
 
	for (i=Rect.top; i<=Rect.bottom; i++) 
		for (j=Rect.left; j<=Rect.right; j++) 
		{ 
			if ((i>=0 && iHeight) && (j>=0 && jWidth)) 
				*(TempImg.pImg+(i-Rect.top)*TempImg.Width+(j-Rect.left)) = *(pSrcImg->pImg+i*pSrcImg->Width+j); 
			else 
				*(TempImg.pImg+(i-Rect.top)*TempImg.Width+(j-Rect.left)) = 0; 
		} 
 
	pDestImg->Width = TempImg.Width; 
	pDestImg->Height = TempImg.Height; 
	pDestImg->pImg = TempImg.pImg; 
 
	return 1; 
} 
 
int GetSubColorImg(PColorImg pDestImg, PColorImg pSrcImg, RECT Rect) 
{ 
	int i, j; 
	int res = 0; 
	TColorImg TempImg; 
 
	res = ColorImg_Malloc(&TempImg, Rect.right-Rect.left+1, Rect.bottom-Rect.top+1); 
	if (0 == res) 
		return 0; 
 
	for (i=Rect.top; i<=Rect.bottom; i++) 
		for (j=Rect.left; j<=Rect.right; j++) 
		{ 
			if ((i>=0 && iHeight) && (j>=0 && jWidth)) 
			{ 
				*(TempImg.pRImg+(i-Rect.top)*TempImg.Width+(j-Rect.left)) = *(pSrcImg->pRImg+i*pSrcImg->Width+j); 
				*(TempImg.pGImg+(i-Rect.top)*TempImg.Width+(j-Rect.left)) = *(pSrcImg->pGImg+i*pSrcImg->Width+j); 
				*(TempImg.pBImg+(i-Rect.top)*TempImg.Width+(j-Rect.left)) = *(pSrcImg->pBImg+i*pSrcImg->Width+j); 
				*(TempImg.pYImg+(i-Rect.top)*TempImg.Width+(j-Rect.left)) = *(pSrcImg->pYImg+i*pSrcImg->Width+j); 
			} 
			else 
			{ 
				*(TempImg.pRImg+(i-Rect.top)*TempImg.Width+(j-Rect.left)) = 0; 
				*(TempImg.pGImg+(i-Rect.top)*TempImg.Width+(j-Rect.left)) = 0; 
				*(TempImg.pBImg+(i-Rect.top)*TempImg.Width+(j-Rect.left)) = 0; 
				*(TempImg.pYImg+(i-Rect.top)*TempImg.Width+(j-Rect.left)) = 0; 
			} 
		} 
	TempImg.BitCount = pSrcImg->BitCount; 
 
	pDestImg->Width = TempImg.Width; 
	pDestImg->Height = TempImg.Height; 
	pDestImg->pRImg = TempImg.pRImg; 
	pDestImg->pGImg = TempImg.pGImg; 
	pDestImg->pBImg = TempImg.pBImg; 
	pDestImg->pYImg = TempImg.pYImg; 
	pDestImg->BitCount = TempImg.BitCount; 
 
	return 1; 
} 
 
int RecoLPColor(TColorID *pLPColorID, PColorImg pSrcImg) 
{ 
	int i, j; 
	int ACount[4]; 
	int Temp; 
	BYTE R, G, B; 
 
	ACount[LP_BLACK] = 0; 
	ACount[LP_BLUE] = 0;  
	ACount[LP_YELLOW] = 0;  
	ACount[LP_WHITE] = 0; 
 
	for (i=(int)(0.15*pSrcImg->Height+0.5); i<(int)(pSrcImg->Height-0.15*pSrcImg->Height+0.5); i++) 
		for (j=(int)(0.15*pSrcImg->Width+0.5); j<(int)(pSrcImg->Width-0.15*pSrcImg->Width+0.5); j++) 
		{ 
			R = *(pSrcImg->pRImg+i*pSrcImg->Width+j); 
			G = *(pSrcImg->pGImg+i*pSrcImg->Width+j); 
			B = *(pSrcImg->pBImg+i*pSrcImg->Width+j); 
 
			if ((B-G>g_BYDiff) && (B-R>g_BYDiff) && (B>g_BYLP)) 
				  ACount[LP_BLUE]++; 
 
			if ((R-B>g_BYDiff) && (G-B>g_BYDiff) && (R>g_BYLP) && (G>g_BYLP)) 
				  ACount[LP_YELLOW]++; 
 
			if ((Bg_WhiteLP)&&(G>g_WhiteLP)&&(B>g_WhiteLP)&&(abs(G-B)Height-1; 
 
	res = Template(&EdgeImg, pSrcImg, TempArray1, 3, 1); 
	if (0 == res) 
		return 0; 
 
	res = Template(&TempImg1, &EdgeImg, TempArray, 3, 1.0/8.0); 
	if (0 == res) 
		return 0; 
 
	res = TwoPixelCarImg(&TempImg, &TempImg1, g_Threshold_HLP); 
	if (0 == res) 
		return 0; 
 
	pProject = (int*)malloc(pSrcImg->Height*sizeof(int)); 
	if (pProject == NULL) 
		return 0; 
 
	res = ProjectImg(pProject, &TempImg, H_FILTER); 
	if (0 == res) 
		return 0; 
 
	for (i=0; iHeight; i++) 
		if (*(pProject+i) < int(0.25*pSrcImg->Height)) 
			*(pProject+i) = 0; 
 
	for (i=pSrcImg->Height/2; i>=0; i--) 
	{ 
		if (*(pProject+i) == 0) 
		{ 
			Top = i; 
			break; 
		} 
	} 
	for (i=pSrcImg->Height/2; iHeight; i++) 
	{ 
		if (*(pProject+i) == 0) 
		{ 
			Bottom = i; 
			break; 
		} 
	} 
 
	if (pProject) 
		free(pProject); 
 
	GrayImg_Free(&EdgeImg); 
	GrayImg_Free(&TempImg1); 
	GrayImg_Free(&TempImg); 
 
	*pThreshold = 50; 
 
	res = GrayImg_Malloc(&TempImg, pSrcImg->Width, pSrcImg->Height); 
	if (res == 0) 
		return 0; 
 
	StopFlag1 = FALSE; 
    StopFlag2 = FALSE; 
 
	while(TRUE) 
	{ 
		BlackPixelCount = 0; 
		WhitePixelCount = 0; 
 
		for (i=0; iHeight; i++) 
			for (j=0; jWidth; j++) 
			{ 
				if (*(pSrcImg->pImg+i*pSrcImg->Width+j) > *pThreshold) 
				{ 
					if (i>=Top && i<=Bottom) 
						WhitePixelCount++; 
					*(TempImg.pImg+i*TempImg.Width+j) = 255; 
				} 
				else 
				{ 
					if (i>=Top && i<=Bottom) 
						BlackPixelCount++; 
					*(TempImg.pImg+i*TempImg.Width+j) = 0; 
				} 
			} 
 
		if ((BlackPixelCount<=(int)(MaxBlackRatio*(BlackPixelCount+WhitePixelCount)+0.5)) 
		    && (BlackPixelCount>=(int)(MinBlackRatio*(BlackPixelCount+WhitePixelCount)+0.5))) 
			break; 
 
		if (BlackPixelCount>(int)(MaxBlackRatio*(BlackPixelCount+WhitePixelCount)+0.5)) 
		{ 
			StopFlag1 = TRUE; 
			*pThreshold -= 5; 
			if (StopFlag2) 
				break; 
		} 
 
		if (BlackPixelCount < (int)(MinBlackRatio*(BlackPixelCount+WhitePixelCount)+0.5)) 
		{ 
			StopFlag2 = TRUE; 
			*pThreshold += 5; 
			if (StopFlag1) 
				break; 
		} 
	} 
 
	pDestImg->Width = TempImg.Width; 
	pDestImg->Height = TempImg.Height; 
	pDestImg->pImg = TempImg.pImg; 
 
	return 1; 
} 
 
int Invert(PGrayImg pDestImg, PGrayImg pSrcImg) 
{ 
	int i, j; 
	int res = 0; 
	TGrayImg TempImg; 
 
	res = GrayImg_Malloc(&TempImg, pSrcImg->Width, pSrcImg->Height); 
	if (0 == res) 
		return 0; 
 
	for (i=0; iHeight; i++) 
		for (j=0; jWidth; j++) 
		{ 
			*(TempImg.pImg+i*TempImg.Width+j) = 255 - *(pSrcImg->pImg+i*pSrcImg->Width+j); 
		} 
 
	pDestImg->Width = TempImg.Width; 
	pDestImg->Height = TempImg.Height; 
	pDestImg->pImg = TempImg.pImg; 
 
	return 1; 
} 
 
int RectifyLP(PGrayImg pDestImg, PGrayImg pSrcImg, PGrayImg pModelImg) 
{ 
	int i, j; 
	int res = 0; 
	TAngle Angle; 
 
	double RectifyAngle; 
	int iAngle; 
 
	TGrayImg TempImg1, TempImg2; 
	TGrayImg RowDiffImg; 
     
	res = Diff(&RowDiffImg, pModelImg, H_FILTER); 
	if (0 == res) 
		return 0; 
 
	res = HoughTrans(&Angle, &RowDiffImg, V_FILTER); 
	if (0 == res) 
		return 0; 
 
	res = GrayImg_Free(&RowDiffImg); 
	if (0 == res) 
		return 0; 
 
	res = Diff(&RowDiffImg, pModelImg, V_FILTER); 
	if (0 == res) 
		return 0; 
 
	res = HoughTrans(&Angle, &RowDiffImg, H_FILTER); 
	if (0 == res) 
		return 0; 
 
	res = GrayImg_Free(&RowDiffImg); 
	if (0 == res) 
		return 0; 
 
	res = GrayImg_Malloc(&TempImg1, pSrcImg->Width, pSrcImg->Height); 
	if (0 == res) 
		return 0; 
 
	for (i=0; iHeight; i++) 
		for (j=0; jWidth; j++) 
			*(TempImg1.pImg+i*TempImg1.Width+j) = 0; 
 
	if (fabs(Angle.HAngle+90) != 90.0)  
		RectifyAngle = -(Angle.HAngle + 90.0)/180.0*PI; 
 
	for (i=0; iWidth; i++) 
		for (j=0; jHeight; j++) 
		{ 
			if (i*tan(RectifyAngle) < 0.0) 
				iAngle = (int)(i*tan(RectifyAngle)-0.5); 
			else 
				iAngle = (int)(i*tan(RectifyAngle)+0.5); 
			 
			if ((j-iAngle >= 0) && (j-iAngle < pSrcImg->Height)) 
				*(TempImg1.pImg+j*TempImg1.Width+i) = *(pSrcImg->pImg+(j-iAngle)*pSrcImg->Width+i); 
		} 
 
	res = GrayImg_Malloc(&TempImg2, pSrcImg->Width, pSrcImg->Height); 
	if (0 == res) 
		return 0; 
 
	for (i=0; iHeight; i++) 
		for (j=0; jWidth; j++) 
			*(TempImg2.pImg+i*TempImg2.Width+j) = 0; 
 
	if (fabs(Angle.VAngle) != 90.0) 
		RectifyAngle = Angle.VAngle/180.0*PI; 
 
	for (i=0; i= 0) && (j-iAngle < TempImg1.Width)) 
				*(TempImg2.pImg+i*TempImg2.Width+j) = *(TempImg1.pImg+i*TempImg1.Width+j-iAngle); 
		} 
 
	res = GrayImg_Free(&TempImg1); 
	if (0 == res) 
		return 0; 
 
	pDestImg->Width = TempImg2.Width; 
	pDestImg->Height = TempImg2.Height; 
	pDestImg->pImg = TempImg2.pImg; 
 
	return 1; 
 
} 
 
int Diff(PGrayImg pDestImg, PGrayImg pSrcImg, TPrjType PrjType) 
{ 
	int i, j; 
	int Temp; 
	int res = 0; 
	TGrayImg TempImg; 
 
	res = GrayImg_Malloc(&TempImg, pSrcImg->Width, pSrcImg->Height); 
	if (res == 0) 
		return 0; 
 
	switch(PrjType) 
	{ 
	 
	case H_FILTER:   
 
		for (i=0; iHeight; i++) 
			*(TempImg.pImg+i*TempImg.Width+0) = 0; 
 
		for (i=0; iHeight; i++) 
			for (j=1; jWidth; j++) 
			{ 
				Temp = abs(*(pSrcImg->pImg+i*pSrcImg->Width+j)-*(pSrcImg->pImg+i*pSrcImg->Width+j-1)); 
				if (Temp > 80) 
					Temp = 255; 
				else 
					Temp = 0; 
 
				*(TempImg.pImg+i*TempImg.Width+j) = Temp; 
			} 
 
		break; 
 
	case V_FILTER:  
 
		for (j=0; jWidth; j++) 
			*(TempImg.pImg+0+j) = 0; 
 
		for (j=0; jWidth; j++) 
			for (i=1; iHeight; i++) 
			{ 
				Temp = abs(*(pSrcImg->pImg+i*pSrcImg->Width+j)-*(pSrcImg->pImg+(i-1)*pSrcImg->Width+j)); 
				 
				if (Temp > 80) 
					 Temp = 255; 
				else 
					 Temp = 0; 
 
				*(TempImg.pImg+i*TempImg.Width+j) = Temp; 
			} 
		break; 
 
	default: 
		return 0; 
	} 
 
	pDestImg->Width = TempImg.Width; 
	pDestImg->Height = TempImg.Height; 
	pDestImg->pImg = TempImg.pImg; 
 
	return 1; 
} 
 
int HoughTrans(PAngle pAngle, PGrayImg pSrcImg, TPrjType PrjType) 
{ 
	int i, j, p, o, Max, Tempo; 
	int *H; 
	int HWidth, HHeight; 
	double temp; 
 
	o = -90; p = 0; 
 
	HHeight = 4 * pSrcImg->Width + 1; 
	HWidth = 181; 
    H = (int*)malloc(HWidth*HHeight*sizeof(int)); 
	if (NULL == H) 
		return 0; 
 
	for (i=-(HHeight/2); i<=(HHeight/2); i++) 
		for (j=-(HWidth/2); j<=(HWidth/2); j++) 
			*(H+(i+HHeight/2)*HWidth+j+HWidth/2) = 0; 
 
	switch (PrjType) 
	{ 
	case H_FILTER:  
 
		for (i=0; iHeight; i++) 
			for (j=0; jWidth; j++) 
			{ 
				if (*(pSrcImg->pImg+i*pSrcImg->Width+j) == 255) 
				{ 
					for (o=-10; o<=10; o++) 
					{ 
						if (o >= 0) 
							Tempo = o + 80; 
						else 
							Tempo = o - 80; 
 
						temp = j*cos(Tempo*PI/180.0)+i*sin(Tempo*PI/180.0); 
						if (temp < 0.0) 
							p = (int)(temp-0.5); 
						else 
							p = (int)(temp+0.5); 
 
						if ((p+HHeight/2 >= 0) && (p + HHeight/2 < HHeight)) 
							 (*(H+(p+HHeight/2)*HWidth+Tempo+HWidth/2))++; 
					} 
				} 
			} 
		Max = 0; 
		for (i=-HHeight/2; i<=HHeight/2; i++) 
			for (j=-10; j<=10; j++) 
			{ 
				if (j >= 0) 
					Tempo = j + 80; 
				else 
					Tempo = j - 80; 
 
				if (Max<*(H+(i+HHeight/2)*HWidth+Tempo+HWidth/2)) 
				{ 
					Max = *(H+(i+HHeight/2)*HWidth+Tempo+HWidth/2); 
					o = Tempo;    
					p = i;      
				} 
			} 
		pAngle->HAngle = o; 
 
		break; 
 
	case V_FILTER:  
 
		for (i=0; iHeight; i++) 
			for (j=0; jWidth; j++) 
			{ 
				if (*(pSrcImg->pImg+i*pSrcImg->Width+j) == 255) 
				{ 
 
					for (o=-10; o<=10; o++) 
					{ 
						temp = j*cos(o*PI/180.0)+i*sin(o*PI/180.0); 
						if (temp < 0.0) 
							p = (int)(temp-0.5); 
						else 
							p = (int)(temp+0.5); 
 
						if ((p+HHeight/2 >= 0) && (p+HHeight/2 < HHeight)) 
							(*(H+(p+HHeight/2)*HWidth+o+HWidth/2))++; 
					} 
				} 
			} 
 
		Max = 0; 
 
		for (i=-HHeight/2; i<=HHeight/2; i++) 
			for (j=-10; j<=10; j++) 
			{ 
				if (Max < *(H+(i+HHeight/2)*HWidth+j+HWidth/2)) 
				{ 
					Max = *(H+(i+HHeight/2)*HWidth+j+HWidth/2); 
					o = j;   
					p = i;      
				} 
			} 
		pAngle->VAngle = o; 
		break; 
	default: 
		if (H) 
			free(H); 
		return 0; 
	} 
 
	if (H) 
	{ 
		free(H); 
		H = NULL; 
	} 
 
	return 1; 
} 
 
int GetLPAccuratePos(RECT *lpRect, PGrayImg pSrcImg) 
{ 
	int res = 0; 
 
	TGrayImg DiffImg; 
	TGrayImg LPImg; 
 
	int UpYPos, DownYPos, LeftXPos, RightXPos; 
	int *pHProject, *pVProject; 
 
	res = Diff(&DiffImg, pSrcImg, H_FILTER); 
	if (0 == res) 
		return 0; 
 
	pHProject = (int*)malloc(pSrcImg->Height*sizeof(int)); 
 
	res = ProjectImg(pHProject, &DiffImg, H_FILTER); 
	if (0 == res) 
		return 0; 
 
	res = ProjectFilter(pHProject, pSrcImg->Height, IH_FILTER); 
	if (0 == res) 
		return 0; 
 
	res = GetLPAccurateYPos(pHProject, pSrcImg->Height, &UpYPos, &DownYPos); 
	if (0 == res) 
		return 0; 
 
	lpRect->left = 0; 
	lpRect->right = pSrcImg->Width - 1; 
	lpRect->top = UpYPos; 
	lpRect->bottom = DownYPos; 
 
	res = GetSubImg(&LPImg, pSrcImg, *lpRect); 
	if (0 == res) 
		return 0; 
 
	res = GrayImg_Free(&DiffImg); 
	if (0 == res) 
		return 0; 
 
	pVProject = (int*)malloc(LPImg.Width*sizeof(int)); 
 
	res = ProjectImg(pVProject, &LPImg, V_FILTER); 
	if (0 == res) 
		return 0; 
 
	res = ProjectFilter(pVProject, LPImg.Width, IV_FILTER, DownYPos - UpYPos); 
	if (0 == res) 
		return 0; 
 
	res = GetLPAccurateXPos(pVProject, LPImg.Width, DownYPos - UpYPos, &LeftXPos, &RightXPos); 
	if (0 == res) 
		return 0; 
 
	if (pHProject != NULL) 
	{ 
		free(pHProject); 
		pHProject = NULL; 
	} 
	if (pVProject != NULL) 
	{ 
		free(pVProject); 
		pVProject = NULL; 
	} 
	 
	res = GrayImg_Free(&LPImg); 
	if (0 == res) 
		return 0; 
 
	lpRect->top = UpYPos; 
	lpRect->bottom = DownYPos; 
	lpRect->left = LeftXPos; 
	lpRect->right = RightXPos; 
 
	return 1; 
} 
 
int GetLPAccurateXPos(int *pProject, int PrjLen, int LPHeight, int *pLeftXPos, int *pRightXPos) 
{ 
 
	int i, j, k; 
	int TempLeft, TempRight; 
	int TempPos[101], Code[101]; 
	BOOL Flag1, Flag2; 
 
	*pLeftXPos = 0;  
	*pRightXPos = 0; 
 
	for (i=0; i PrjLen-1) 
		*pRightXPos = PrjLen - 1; 
	else 
		*pRightXPos = (int)(4.4 * LPHeight + 0.5) + (*pLeftXPos); 
 
	if (*(pProject+(*pRightXPos)) != 0) 
	{ 
		for (i=(*pRightXPos); i (int)(4.0*LPHeight+0.5)) 
	{ 
		Flag2 = TRUE; 
		Flag1 = TRUE; 
		j = 0;  
		k = 0; 
		for (i=(*pLeftXPos); i 100) 
				{ 
					return 0; 
				} 
 
				TempLeft = i;   
				Flag1 = TRUE; 
				Flag2 = FALSE; 
			} 
 
			if ((*(pProject+i) != 0) && (!Flag2)) 
			{ 
				TempRight = i;  
				if (TempRight-TempLeft < (int)(0.25*LPHeight+0.5)) 
					 Code[k] = 0; 
				else 
					 Code[k] = 1; 
				k++; 
 
				if (k > 100) 
					return 0; 
 
				Flag2 = TRUE; 
			} 
		} 
 
		for (i=0; i<=j-2; i++) 
		{ 
			if (Code[i] == 0) 
			{ 
				if (Code[i+1] == 1) 
				{ 
					if (TempPos[i]-(int)(0.45*LPHeight+0.5) > 0) 
						*pLeftXPos = TempPos[i]-(int)(0.45*LPHeight+0.5); 
					else 
						*pLeftXPos = 0; 
 
					break; 
				} 
			} 
		} 
 
		if ((int)(4.4*LPHeight+0.5)+(*pLeftXPos) < PrjLen-1) 
			*pRightXPos = (int)(4.4*LPHeight+0.5)+(*pLeftXPos); 
		else 
			*pRightXPos = PrjLen - 1; 
 
		if (*(pProject+(*pRightXPos)) != 0) 
		{ 
			for (i=(*pRightXPos); iWidth*sizeof(int)); 
 
	res = OutLineProject(pOutLineProject, pSrcImg); 
	if (0 == res) 
		return 0; 
 
	res = OutLineProjectFilter(pOutLineProject, pSrcImg->Width, pSrcImg->Height); 
	if (0 == res) 
		return 0; 
 
	Flag = TRUE; 
	CharID = 0; 
	*(pOutLineProject+pSrcImg->Width-1) = 0; 
 
	for (i=0; iWidth; i++) 
	{ 
		if ((*(pOutLineProject+i) != 0) && Flag) 
		{ 
			LPCharRect[CharID].left = i; 
			LPCharRect[CharID].top = 0; 
			LPCharRect[CharID].bottom = pSrcImg->Height - 1; 
			Flag = FALSE; 
			avg = 0; 
		} 
 
		if ((*(pOutLineProject+i) == 0) && (!Flag)) 
		{ 
			LPCharRect[CharID].right = i; 
 
			for (j=LPCharRect[CharID].left; j<=LPCharRect[CharID].right; j++) 
			{ 
				avg += *(pOutLineProject+j); 
			} 
 
			avg = (int)(avg*1.0/(LPCharRect[CharID].right-LPCharRect[CharID].left)+0.5); 
 
			if (!((LPCharRect[CharID].right-LPCharRect[CharID].left<(int)(0.2*pSrcImg->Height+0.5)) && (avg < (int)(0.5*pSrcImg->Height+0.5)))) 
			{ 
				if (LPCharRect[CharID].right-LPCharRect[CharID].left > (int)(0.05*pSrcImg->Height+0.5)) 
				{ 
					if (LPCharRect[CharID].right-LPCharRect[CharID].left < (int)(0.25*pSrcImg->Height+0.5)) 
					{ 
						avg = 0; 
						for (x=0; xHeight; x++) 
							for (y=LPCharRect[CharID].left; y<=LPCharRect[CharID].right; y++) 
							{ 
								if (*(pSrcImg->pImg+x*pSrcImg->Width+y) == 255) 
									avg++; 
							} 
						if (1.0*avg/(LPCharRect[CharID].right-LPCharRect[CharID].left)/pSrcImg->Height > 0.6) 
							CharID++; 
					} 
					else 
						CharID++; 
				} 
			}  
 
			if (CharID > MAX_LPCHAR_CURRENT_COUNT-1) 
				break; 
 
			Flag = TRUE; 
		} 
	} 
 
	Flag = TRUE;  
    Flag1 = TRUE; 
	k = 0; 
 
	if (LPCharRect[CharID-1].right-LPCharRect[0].left < (int)(4.3*pSrcImg->Height+0.5)) 
	{ 
		for (i=0; iWidth; i++) 
		{ 
			if ((*(pOutLineProject+i) != 0) && Flag1) 
				Flag1 = FALSE; 
 
			if ((*(pOutLineProject+i) == 0) && (!Flag1)) 
			{ 
				TempLeft = i;     
				Flag1 = TRUE; 
				Flag = FALSE; 
			} 
 
			if ((*(pOutLineProject+i) != 0) && (!Flag)) 
			{ 
				TempRight = i;    
 
				if (TempRight-TempLeft < (int)(0.26*pSrcImg->Height+0.5)) 
					Code[k] = 0; 
				else 
					Code[k] = 1; 
 
				k++; 
 
				if (k > 100) 
					return 0; 
 
				Flag = TRUE; 
			} 
		} 
 
		if (Code[0] != 0) 
		{ 
			if (CharID > MAX_LPCHAR_CURRENT_COUNT-1)  
				CharID--; 
		} 
		else  
		{ 
			if ((Code[1] == 1) && (CharID < MAX_LPCHAR_CURRENT_COUNT)) 
				CharID++; 
		} 
	} 
 
	for (i=CharID-1; i>=1; i--) 
	{ 
		if (LPCharRect[i].right-LPCharRect[i].left < (int)(0.2*pSrcImg->Height+0.5)) 
		{ 
		   if (LPCharRect[i].left-LPCharRect[i-1].right < (int)(0.22*pSrcImg->Height+0.5)) 
			   CharID--; 
		} 
		else 
		   break; 
	} 
 
	if (LPCharRect[CharID-1].right-LPCharRect[CharID-1].left > (int)(0.5*pSrcImg->Height+0.5)) 
	{ 
	 
		if (LPCharRect[CharID-1].left+(int)(0.5*pSrcImg->Height+0.5)Width-1) 
		{ 
			LPCharRect[CharID-1].right = LPCharRect[CharID-1].left+(int)(0.5*pSrcImg->Height+0.5); 
		} 
		else 
			LPCharRect[CharID-1].right = pSrcImg->Width - 1; 
	} 
 
	*pCharCount = CharID; 
 
	if (pOutLineProject != NULL) 
	{ 
		free(pOutLineProject); 
		pOutLineProject = NULL; 
	} 
 
	return 1; 
} 
 
int OutLineProject(int *pProject, PGrayImg pSrcImg) 
{ 
	int i, j, HighP, LowP; 
 
	for (j=0; jWidth; j++) 
	{ 
		HighP = pSrcImg->Height; 
		LowP = pSrcImg->Height; 
 
		for (i=0; iHeight; i++) 
		{ 
			if (*(pSrcImg->pImg+i*pSrcImg->Width+j) > 0) 
			{ 
				HighP = i; 
				break; 
			} 
		} 
 
		for (i=pSrcImg->Height-1; i>=0; i--) 
		{ 
		   if (*(pSrcImg->pImg+i*pSrcImg->Width+j) > 0) 
		   { 
				LowP = i; 
				break; 
		   } 
		} 
 
		*(pProject+j) = LowP - HighP; 
	} 
 
	*(pProject+pSrcImg->Width-1) = 0; 
 
	return 1; 
} 
 
int OutLineProjectFilter(int *pProject, int PrjLen, int LPHeight) 
{ 
 
	int i, CharID, j; 
	int Temp; 
	int MergeID[101], TempWidth[101]; 
	RECT LPCharRect[101]; 
	BOOL Flag; 
 
	*(pProject+PrjLen-1) = 0; 
	Flag = TRUE; 
 
	for (i=0; i *(pProject+i+1)) && (!Flag)) 
		   Flag = TRUE; 
	} 
 
	Flag = TRUE; 
	CharID = 0; 
 
	for (i=0; i 100) 
				return 0; 
 
			Flag = TRUE; 
		} 
	} 
 
	j = 0; 
	for (i=0; i=(int)(0.4*LPHeight+0.5))) 
		{ 
			switch (j) 
			{ 
			case 1: 
				if (MergeID[0] < CharID - 1) 
				{ 
					if (1 == IsChar(LPCharRect[MergeID[0]].left, LPCharRect[MergeID[0]+1].right, LPHeight)) 
						if (LPCharRect[MergeID[0]+1].left-LPCharRect[MergeID[0]].right <= 4) 
							*(pProject+LPCharRect[MergeID[0]].right+1) = 20; 
				} 
 
				if (MergeID[0] > 0) 
				{ 
					if (1 == IsChar(LPCharRect[MergeID[0]-1].left, LPCharRect[MergeID[0]].right, LPHeight)) 
						if (LPCharRect[MergeID[0]].left - LPCharRect[MergeID[0] - 1].right <= 4) 
							*(pProject+LPCharRect[MergeID[0]].right+1) = 20; 
				} 
				break; 
 
			case 2: 
				Merge2(pProject, PrjLen, LPCharRect, MergeID, 0, 1, LPHeight); 
				break; 
 
			case 3: 
				Merge3(pProject, PrjLen, LPCharRect, MergeID, 0, 2, LPHeight); 
				break; 
 
			case 4: 
				Merge4(pProject, PrjLen, LPCharRect, MergeID, 0, 3, LPHeight); 
				break; 
 
			case 5: 
				Merge5(pProject, PrjLen, LPCharRect, MergeID, 0, 4, LPHeight); 
				break; 
 
			case 6: 
			case 7: 
			case 8: 
			case 9: 
			case 10: 
			case 11: 
				Merge6(pProject, PrjLen, LPCharRect, MergeID, 0, 5, LPHeight); 
				break; 
			} 
 
			j = 0; 
		} 
	} 
	return 1; 
} 
 
int Merge2(int *pProject, int PrjLen, RECT LPCharRect[],  
		        int MergeID[], int StartID, int EndID, int CharHeight) 
{ 
 
	int p; 
	BOOL Flag; 
 
	if (1 == IsChar(LPCharRect[MergeID[StartID]].left, LPCharRect[MergeID[EndID]].right, CharHeight)) 
	{ 
		Flag = TRUE; 
		for (p=StartID; p(int)(0.15*CharHeight+0.5)) 
				Flag = FALSE; 
		} 
 
		if (Flag) 
		{ 
			for (p=LPCharRect[MergeID[StartID]].left; p<=LPCharRect[MergeID[EndID]].right; p++) 
				*(pProject+p) = (int)(CharHeight * 0.8 + 0.5); 
		} 
		else 
			return 0; 
	} 
	else 
		return 0; 
 
	return 1; 
} 
 
int Merge3(int *pProject, int PrjLen, RECT LPCharRect[],  
		        int MergeID[], int StartID, int EndID, int CharHeight) 
{ 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID, CharHeight)) 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 1, CharHeight)) 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 1, EndID, CharHeight)) 
		return 0; 
	return 1; 
} 
 
int Merge4(int *pProject, int PrjLen, RECT LPCharRect[],  
		        int MergeID[], int StartID, int EndID, int CharHeight) 
{ 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID, CharHeight)) 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 1, CharHeight)) 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 1, EndID, CharHeight)) 
	if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 2, CharHeight)) 
		Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 2, EndID, CharHeight); 
	else 
	{ 
		if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 1, EndID - 1, CharHeight)) 
		if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 2, EndID, CharHeight)) 
		   return 0; 
	} 
 
	return 1; 
} 
 
int Merge5(int *pProject, int PrjLen, RECT LPCharRect[],  
		        int MergeID[], int StartID, int EndID, int CharHeight) 
{ 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID, CharHeight)) 
 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 1, CharHeight)) 
 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 1, EndID, CharHeight)) 
 
	if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 2, CharHeight)) 
		Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 3, EndID, CharHeight); 
	else 
	{ 
		if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 1, EndID - 1, CharHeight)) 
		if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 2, EndID, CharHeight)) 
			Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 3, CharHeight); 
		else 
		{ 
			if  (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 3, CharHeight)) 
				Merge3(pProject, PrjLen, LPCharRect, MergeID, StartID + 2, EndID, CharHeight); 
			else 
			{ 
				if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 1, EndID - 2, CharHeight)) 
					Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 3, EndID, CharHeight); 
				else 
				{ 
					if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 2, EndID - 1, CharHeight)) 
						Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 3, CharHeight); 
					else 
					{ 
						if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 3, EndID, CharHeight)) 
						if (0 == Merge3(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 2, CharHeight)) 
							return 0; 
					} 
				} 
			} 
		} 
	} 
 
	return 1; 
} 
 
int Merge6(int *pProject, int PrjLen, RECT LPCharRect[],  
		        int MergeID[], int StartID, int EndID, int CharHeight) 
{ 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID, CharHeight)) 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 1, CharHeight)) 
	if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 1, EndID, CharHeight)) 
	if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 2, CharHeight)) 
		Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 4, EndID, CharHeight); 
	else 
	{ 
		if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 1, EndID - 1, CharHeight)) 
		if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 2, EndID, CharHeight)) 
			Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 4, CharHeight); 
		else 
		{ 
			if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 3, CharHeight)) 
				Merge3(pProject, PrjLen, LPCharRect, MergeID, StartID + 3, EndID, CharHeight); 
			else 
			{ 
				if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 1, EndID - 2, CharHeight)) 
					Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 4, EndID, CharHeight); 
				else 
				{ 
					if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 2, EndID - 1, CharHeight)) 
						Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 4, CharHeight); 
					else 
					{ 
						if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 3, EndID, CharHeight)) 
							Merge3(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 3, CharHeight); 
						else 
						{ 
							if  (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 4, CharHeight)) 
								Merge4(pProject, PrjLen, LPCharRect, MergeID, StartID + 2, EndID, CharHeight); 
							else 
							{ 
								if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 1, EndID - 3, CharHeight)) 
									Merge3(pProject, PrjLen, LPCharRect, MergeID, StartID + 3, EndID, CharHeight); 
								else 
								{ 
									if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 2, EndID - 2, CharHeight)) 
									{ 
										Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 4, CharHeight); 
										Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 4, EndID, CharHeight); 
									} 
									else 
									{ 
										if  (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 3, EndID - 1, CharHeight)) 
											Merge3(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 3, CharHeight); 
										else 
										{ 
											if (1 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID + 4, EndID, CharHeight)) 
												if (0 == Merge2(pProject, PrjLen, LPCharRect, MergeID, StartID, EndID - 2, CharHeight)) 
													return 0; 
									   } 
									} 
								} 
							} 
						} 
					} 
				} 
			} 
		} 
	} 
	return 1; 
} 
 
int Merge7(int *pProject, int PrjLen, RECT LPCharRect[],  
		        int MergeID[], int StartID, int EndID, int CharHeight) 
{ 
	return 1; 
} 
 
int Merge8(int *pProject, int PrjLen, RECT LPCharRect[],  
		        int MergeID[], int StartID, int EndID, int CharHeight) 
{ 
	return 1; 
} 
 
int IsChar(int CharLeft, int CharRight, int CharHeight) 
{ 
	int res = 0; 
 
	if ((CharRight-CharLeft>(int)(0.30*CharHeight+0.5)) && (CharRight-CharLeft<(int)(0.6*CharHeight+0.5))) 
		res = 1; 
	else 
		res = 0; 
 
	return res; 
} 
 
int ReadParam(char *szFileName) 
{ 
	_finddata_t fileinfo; 
	long lres; 
 
	lres = _findfirst(szFileName, &fileinfo); 
 
	if (-1 != lres) 
	{ 
		g_LPHeight = GetPrivateProfileInt("GDCLPRINI", "LPHeight", 80, szFileName); 
		g_LPWidth = GetPrivateProfileInt("GDCLPRINI", "LPWidth", 220, szFileName);        
		g_LPAccurateHeight = GetPrivateProfileInt("GDCLPRINI", "LPAccurateHeight", 40, szFileName);;  
		g_Threshold = GetPrivateProfileInt("GDCLPRINI", "Threshold", 160, szFileName);       
		g_Threshold_HLP = GetPrivateProfileInt("GDCLPRINT", "Threshold_HLP", 100, szFileName); 
		g_LeftOffset = GetPrivateProfileInt("GDCLPRINI", "LeftOffset", 0, szFileName);       
		g_RightOffset = GetPrivateProfileInt("GDCLPRINI", "RightOffset", 0, szFileName);      
		g_TopOffset = GetPrivateProfileInt("GDCLPRINI", "TopOffset", 0, szFileName);        
		g_BottomOffset = GetPrivateProfileInt("GDCLPRINI", "BottomOffset", 0, szFileName);     
	} 
 
	return 1; 
} 
 
int SaveParam(int LPHeight,       
			  int LPWidth,         
              int LPAccurateHeight, 
              int Threshold,        
			  int Threshold_HLP,     
              int LeftOffset,        
              int RightOffset,       
              int TopOffset,         
              int BottomOffset,    
			  char *szFileName) 
{ 
	char str[255]; 
 
	sprintf(str, "%d", LPHeight); 
	WritePrivateProfileString("GDCLPRINI", "LPHeight", str, szFileName); 
 
	sprintf(str, "%d", LPWidth); 
	WritePrivateProfileString("GDCLPRINI", "LPWidth", str, szFileName); 
 
	sprintf(str, "%d", LPAccurateHeight); 
	WritePrivateProfileString("GDCLPRINI", "LPAccurateHeight", str, szFileName); 
 
	sprintf(str, "%d", Threshold); 
	WritePrivateProfileString("GDCLPRINI", "Threshold", str, szFileName); 
 
	sprintf(str, "%d", Threshold_HLP); 
	WritePrivateProfileString("GDCLPRINI", "Threshold_HLP", str, szFileName); 
 
	sprintf(str, "%d", LeftOffset); 
	WritePrivateProfileString("GDCLPRINI", "LeftOffset", str, szFileName); 
 
	sprintf(str, "%d", RightOffset); 
	WritePrivateProfileString("GDCLPRINI", "RightOffset", str, szFileName); 
 
	sprintf(str, "%d", TopOffset); 
	WritePrivateProfileString("GDCLPRINI", "TopOffset", str, szFileName); 
 
	sprintf(str, "%d", BottomOffset); 
	WritePrivateProfileString("GDCLPRINI", "BottomOffset", str, szFileName); 
 
	return 1; 
} 
 
RECT GetManualCutRect(int *pLeftOffset, int *pRightOffset, int *pTopOffset, int *pBottomOffset, int OriWidth, int OriHeight) 
{ 
	RECT CutRect; 
 
	*pLeftOffset = g_LeftOffset; 
	*pRightOffset = g_RightOffset; 
	*pTopOffset = g_TopOffset; 
	*pBottomOffset = g_BottomOffset; 
 
	CutRect.left = g_LeftOffset; 
	CutRect.top = g_TopOffset; 
	CutRect.right = OriWidth - g_RightOffset - 1; 
	CutRect.bottom = OriHeight - g_BottomOffset - 1; 
 
	return CutRect; 
}