#ifdef PC_SIM
#include <mem.h>
#endif
#ifdef TARGET_PC
#include <mem.h>
#endif
#include <math.h>
#include "PrintMatching.h"
#include "cpb_module.h"
//---------------------------------------------------------------------------
int CurrentPrintPixelCnt;

#ifdef PC_SIM
unsigned char ExtractPrintData[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
unsigned char ErasePrintImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
#endif

#pragma DATA_ALIGN(8)
#pragma DATA_SECTION(".sdram")
short tempPrintMatchingData[PRINT_DATA_SIZE][2];

#pragma DATA_ALIGN(8)
#pragma DATA_SECTION(".sdram")
short tempExpansionPrintMatchingData[PRINT_DATA_SIZE][2];

#pragma DATA_ALIGN(8)
#pragma DATA_SECTION(".sdram")
short RotationPrintLabelData[THREED_PRINT_MAX_LABEL_COUNT][4000][2];

#pragma DATA_ALIGN(8)
#pragma DATA_SECTION(".sdram")
short transForm_Position_SmallPrintCoreData[4][3000][2]; // 48k

//---------------------------------------------------------------------------
void PrintMatching(int cameraIndex)
{
	if (TabletCharacter.shape == ROUND || TabletCharacter.shape == SQUARE || TabletCharacter.shape == HEXA || TabletCharacter.shape == TRIANGLE)
	{
		PrintMatchingForEachCase(CASE1, cameraIndex);
	}
	else if (TabletCharacter.shape == OBLONG || TabletCharacter.shape == OVAL)
	{
		if (TabletCharacter.discriminationDisplay_kind == PRINT || TabletGradeData.ETC_AdjustPrintAreaSW) // TEST 등급
		{
			PrintMatchingForEachCase(CASE1, cameraIndex);
		}
		else
		{
			PrintMatchingForEachCase(CASE2, cameraIndex);
		}
	}
	else if (TabletCharacter.shape == ETC)
	{
		if (TabletCharacter.symmetric_line_count == ASYMMETRY_TABLET)
			PrintMatchingForEachCase(CASE1, cameraIndex);
		else
		{
			if (TabletCharacter.arrangeInfo == ARRANGE)
			{
				if (TabletCharacter.discriminationDisplay_kind == PRINT)
				{
					PrintMatchingForEachCase(CASE1, cameraIndex);
				}
				else
				{
					PrintMatchingForEachCase(CASE2, cameraIndex);
				}
			}
			else
				PrintMatchingForEachCase(CASE1, cameraIndex);
		}
	}
}
//---------------------------------------------------------------------------
void PrintMatchingForEachCase(int option, int cameraIndex)
{

	memset(PrintLabelArea, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
	memset(PrintLabelAvgColor, 0, sizeof(int) * THREED_PRINT_MAX_LABEL_COUNT);

	BlurredEngraveSW = 0;
	CurrentPrintPixelCnt = 0;

	ExtractBrightPixelNeighborPrint(cameraIndex); // 5.3ms 정도 소요.

#ifdef PC_SIM
	memset(ErasePrintImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
#endif

	if (option == CASE1)
	{
		// 정렬되지 않아서 회전각도가 매우 큰 정제의 경우.
		PrintMatchingForHighRotationCase(cameraIndex); // 작은 정제의 경우에도 11ms 이상 소요된다.
	}
	else if (option == CASE2)
	{
		// 장방형 각인이나 정렬된 각인의 경우. 심플하게 처리한다.
		PrintMatchingForLowRotationCase(cameraIndex); // 7ms 정도 소요.
	}
}
//---------------------------------------------------------------------------
void PrintMatchingForHighRotationCase(int cameraIndex)
{
	int x, y, i, j;
	int r, m, n, k;
	int alpha;
	int addStep;

	int printNumber;
	int printDataCount;
	int expansion_printDataCount;
	short (*position_printData)[2];
	short (*expansion_position_printData)[2];

	int constantShiftX_Case[2], constantShiftY_Case[2];
	int constantShiftAddress_Case[2];

	int maxValue;

	int angleRangeLimitSW;

	int step;

	int startR, endR;

	int ValidForwardRotationStartAngle;
	int ValidForwardRotationEndAngle;

	int tr;
	int tempAddress;
	int tempAddress2;

	int matchingValue;
	int matchingValueArray[50];

	int printAddStep;

	unsigned char *extractedPrintData;
	unsigned char *tempPrintArea1;
	unsigned char *tempPrintArea2;

	int tempRotateAngleArray[2];
	int constantShiftX, constantShiftY;

	int machingMaxValue[2];
	int shiftX[2], shiftY[2];
	int rotationAngle[2];

	int tempX, tempY;
	int rotateX, rotateY;
	int printMatchingRangeAngle;
	int printMatchingRangeX;
	int shiftXStep;

	int temp_r;
	int stX, edX, stY, edY;
	int maskSize;

	int printMatchingResultShiftX[2];
	int printMatchingResultShiftY[2];
	int printMatchingResultAngle[2];
	int printMatchingCount[2];
	int printMatchingMaxValue[2];	

	unsigned int standardMaxValue[2];

	int shiftXByTotion;
	int shiftYByTotion;

	int printAreaMask;

	standardMaxValue[0] = 0;
	standardMaxValue[1] = 0;

	printAreaMask = TabletGradeData.front_unInspectionIntensity_ForPrint;

	stX = tabletAreaInfo[AREA_INFO_ST_X_ADDRESS];
	edX = tabletAreaInfo[AREA_INFO_END_X_ADDRESS];
	stY = tabletAreaInfo[AREA_INFO_ST_Y_ADDRESS];
	edY = tabletAreaInfo[AREA_INFO_END_Y_ADDRESS];

	if (stX < 10)
		stX = 10;
	if (edX > MAX_IMAGE_WIDTH - 10)
		edX = MAX_IMAGE_WIDTH - 10;
	if (stY < 10)
		stY = 10;
	if (edY > MAX_IMAGE_HEIGHT - 10)
		edY = MAX_IMAGE_HEIGHT - 10;

	tempPrintArea1 = AdjustThreeD_Data;
	tempPrintArea2 = RotationThreeDImage;

	if (TabletCharacter.discriminationDisplay_kind == PRINT)
		extractedPrintData = DarkPixelNeighborPrint2;
	else
		extractedPrintData = DarkPixelNeighborPrint;

	int RealTabletLength = TabletCharacter.length * TabletSetupData.cameraZoom[0] / 100;
	if (TabletCharacter.shape == ROUND && TabletCharacter.discriminationDisplay_kind == STAMP && RealTabletLength > 1100) // 11mm
	{
		printMatchingRangeX = 21;
		shiftXStep = 3;
	}
	else
	{
		printMatchingRangeX = 8;
		shiftXStep = 2;
	}

	printMatchingRangeAngle = 12;

	angleRangeLimitSW = 0;
	if (TabletGradeData.ETC_EngraveMatchingOption_ReflectedTabletShape)
	{
		angleRangeLimitSW = 1;

		int limitedAngleSearchRange = 24;

		ValidForwardRotationStartAngle = ETCShape_ForwardProtoRotationAngle - limitedAngleSearchRange;
		ValidForwardRotationEndAngle = ETCShape_ForwardProtoRotationAngle + limitedAngleSearchRange;
	}

	if (angleRangeLimitSW)
	{
		printMatchingRangeAngle = 4;
	}

	printAddStep = 3;
	if (TabletGradeData.ETC_EngraveMatchingOption_LightEngrave)
	{
		printAddStep = 1;
	}

	// 정렬되지 않아서 회전각도가 매우 큰 정제의 경우.
	// 두가지 인쇄 타입을 돌면서 매칭 결과를 구함.
	// PC에서 대략 5ms 이상 소요된다.
	for (printNumber = 0; printNumber <= 1; printNumber++)
	{
		int (*matchingDataAddress)[1500];
		int matchingDataCount;

		if (printNumber == 0)
		{
			matchingDataAddress = detailedCorePrintRotationAddress1;
			matchingDataCount = SmallPrintCoreData1Count;

			printDataCount = TabletSetupData.printData1Count;
			expansion_printDataCount = TabletSetupData.expansion_printData1Count;
			position_printData = TabletSetupData.position_printData1;
			expansion_position_printData = TabletSetupData.expansion_position_printData1;
		}
		else
		{
			matchingDataAddress = detailedCorePrintRotationAddress2;
			matchingDataCount = SmallPrintCoreData2Count;

			printDataCount = TabletSetupData.printData2Count;
			expansion_printDataCount = TabletSetupData.expansion_printData2Count;
			position_printData = TabletSetupData.position_printData2;
			expansion_position_printData = TabletSetupData.expansion_position_printData2;
		}

		if (TabletCharacter.discriminationDisplay_kind == PRINT)
		{
			constantShiftX_Case[printNumber] = TabletMatchingResult.PrintCenterX;
			constantShiftY_Case[printNumber] = TabletMatchingResult.PrintCenterY;
			constantShiftAddress_Case[printNumber] = constantShiftY_Case[printNumber] * MAX_IMAGE_WIDTH + constantShiftX_Case[printNumber];
		}
		else
		{
			constantShiftX_Case[printNumber] = TabletMatchingResult.AdjustCenterXInImage;
			constantShiftY_Case[printNumber] = TabletMatchingResult.AdjustCenterYInImage;
			constantShiftAddress_Case[printNumber] = constantShiftY_Case[printNumber] * MAX_IMAGE_WIDTH + constantShiftX_Case[printNumber];
		}

		maxValue = -1;

		if (angleRangeLimitSW == 0)
		{
			step = 8;
		}
		else
		{
			step = 4;
		}

		if (angleRangeLimitSW == 0)
		{
			startR = 0;
			endR = 720;
		}
		else
		{
			startR = ValidForwardRotationStartAngle;
			endR = ValidForwardRotationEndAngle;
		}

		for (r = startR; r < endR; r += step)
		{
			tr = r;
			if (tr >= 720)
			{
				tr -= 720;
			}
			else if (tr < 0)
			{
				tr += 720;
			}

			memset(matchingValueArray, 0, sizeof(int) * 35);

			for (m = 0; m < matchingDataCount; m += printAddStep)
			{
				tempAddress = matchingDataAddress[tr][m] + constantShiftAddress_Case[printNumber];

				matchingValueArray[0] += (extractedPrintData[tempAddress]);

				matchingValueArray[1] += (extractedPrintData[tempAddress - 3]);
				matchingValueArray[2] += (extractedPrintData[tempAddress - 6]);
				matchingValueArray[3] += (extractedPrintData[tempAddress - 9]);
				matchingValueArray[4] += (extractedPrintData[tempAddress - 12]);
				matchingValueArray[5] += (extractedPrintData[tempAddress + 3]);
				matchingValueArray[6] += (extractedPrintData[tempAddress + 6]);
				matchingValueArray[7] += (extractedPrintData[tempAddress + 9]);
				matchingValueArray[8] += (extractedPrintData[tempAddress + 12]);

				matchingValueArray[9] += (extractedPrintData[tempAddress - 3 * MAX_IMAGE_WIDTH]);
				matchingValueArray[10] += (extractedPrintData[tempAddress - 6 * MAX_IMAGE_WIDTH]);
				matchingValueArray[11] += (extractedPrintData[tempAddress - 9 * MAX_IMAGE_WIDTH]);
				matchingValueArray[12] += (extractedPrintData[tempAddress - 12 * MAX_IMAGE_WIDTH]);
				matchingValueArray[13] += (extractedPrintData[tempAddress + 3 * MAX_IMAGE_WIDTH]);
				matchingValueArray[14] += (extractedPrintData[tempAddress + 6 * MAX_IMAGE_WIDTH]);
				matchingValueArray[15] += (extractedPrintData[tempAddress + 9 * MAX_IMAGE_WIDTH]);
				matchingValueArray[16] += (extractedPrintData[tempAddress + 12 * MAX_IMAGE_WIDTH]);

				matchingValueArray[17] += (extractedPrintData[tempAddress - 3 - 3 * MAX_IMAGE_WIDTH]);
				matchingValueArray[18] += (extractedPrintData[tempAddress - 6 - 6 * MAX_IMAGE_WIDTH]);
				matchingValueArray[19] += (extractedPrintData[tempAddress - 9 - 9 * MAX_IMAGE_WIDTH]);
				matchingValueArray[20] += (extractedPrintData[tempAddress - 12 - 12 * MAX_IMAGE_WIDTH]);
				matchingValueArray[21] += (extractedPrintData[tempAddress + 3 + 3 * MAX_IMAGE_WIDTH]);
				matchingValueArray[22] += (extractedPrintData[tempAddress + 6 + 6 * MAX_IMAGE_WIDTH]);
				matchingValueArray[23] += (extractedPrintData[tempAddress + 9 + 9 * MAX_IMAGE_WIDTH]);
				matchingValueArray[24] += (extractedPrintData[tempAddress + 12 + 12 * MAX_IMAGE_WIDTH]);

				matchingValueArray[25] += (extractedPrintData[tempAddress + 3 - 3 * MAX_IMAGE_WIDTH]);
				matchingValueArray[26] += (extractedPrintData[tempAddress + 6 - 6 * MAX_IMAGE_WIDTH]);
				matchingValueArray[27] += (extractedPrintData[tempAddress + 9 - 9 * MAX_IMAGE_WIDTH]);
				matchingValueArray[28] += (extractedPrintData[tempAddress + 12 - 12 * MAX_IMAGE_WIDTH]);
				matchingValueArray[29] += (extractedPrintData[tempAddress - 3 + 3 * MAX_IMAGE_WIDTH]);
				matchingValueArray[30] += (extractedPrintData[tempAddress - 6 + 6 * MAX_IMAGE_WIDTH]);
				matchingValueArray[31] += (extractedPrintData[tempAddress - 9 + 9 * MAX_IMAGE_WIDTH]);
				matchingValueArray[32] += (extractedPrintData[tempAddress - 12 + 12 * MAX_IMAGE_WIDTH]);
			}

			for (i = 0; i < 35; i++)
			{
				if (matchingValueArray[i] > maxValue)
				{
					maxValue = matchingValueArray[i];
					tempRotateAngleArray[printNumber] = r;
				}
			}
		}

		if (TabletCharacter.discriminationDisplay_kind == PRINT)
		{
			constantShiftX = TabletMatchingResult.PrintCenterX;
			constantShiftY = TabletMatchingResult.PrintCenterY;
		}
		else
		{
			constantShiftX = TabletMatchingResult.AdjustCenterXInImage;
			constantShiftY = TabletMatchingResult.AdjustCenterYInImage;
		}

		if (angleRangeLimitSW == 0)
		{
			step = 4;
		}
		else
		{
			step = 2;
		}

		machingMaxValue[0] = machingMaxValue[1] = 0;
		shiftX[0] = shiftX[1] = 0;
		shiftY[0] = shiftY[1] = 0;
		rotationAngle[0] = rotationAngle[1] = 0;

		// 인쇄 방향을 구하기 위하여 180도를 회전시켜서 매칭을 구함.
		for (int directionNumber = 0; directionNumber <= 1; directionNumber++)
		{
			int angleAdd;
			unsigned char *tempPrintArea;
			if (directionNumber == 0)
			{
				angleAdd = 0;
				tempPrintArea = tempPrintArea1;
			}
			else
			{
				angleAdd = 360;
				tempPrintArea = tempPrintArea2;
			}

			maxValue = -1;
			for (r = tempRotateAngleArray[printNumber] + angleAdd - printMatchingRangeAngle; r <= tempRotateAngleArray[printNumber] + angleAdd + printMatchingRangeAngle; r += step)
			{
				temp_r = r;
				if (temp_r >= 720)
				{
					temp_r -= 720;
				}
				else if (temp_r < 0)
				{
					temp_r += 720;
				}

				int cosValue = CosData[temp_r];
				int sinValue = SinData[temp_r];						

				for (m = 0; m < printDataCount; m += HIGH_ROTATION_PRINT_ADD_M)
				{
					tempX = position_printData[m][0];
					tempY = position_printData[m][1];

					rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX;
					rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY;

					tempPrintMatchingData[m][0] = rotateX;
					tempPrintMatchingData[m][1] = rotateY;
				}

				if (TabletCharacter.discriminationDisplay_kind == STAMP && !TabletGradeData.ETC_ApplyWhiteEngraveAlgorithm)
				{
					for (m = 0; m < expansion_printDataCount; m += HIGH_ROTATION_PRINT_ADD_M)
					{
						tempX = expansion_position_printData[m][0];
						tempY = expansion_position_printData[m][1];

						rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX;
						rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY;

						tempExpansionPrintMatchingData[m][0] = rotateX;
						tempExpansionPrintMatchingData[m][1] = rotateY;
					}
				}

				for (j = -printMatchingRangeX; j <= printMatchingRangeX; j += shiftXStep)
				{
					memset(matchingValueArray, 0, sizeof(int) * 15);

					for (m = 0; m < printDataCount; m += HIGH_ROTATION_PRINT_ADD_M)
					{
						rotateX = tempPrintMatchingData[m][0];
						rotateY = tempPrintMatchingData[m][1];

						tempAddress = MAX_IMAGE_WIDTH * rotateY + rotateX;
						tempAddress = tempAddress + j;

						matchingValueArray[0] += (extractedPrintData[tempAddress - 8960]);
						matchingValueArray[1] += (extractedPrintData[tempAddress - 7680]);
						matchingValueArray[2] += (extractedPrintData[tempAddress - 6400]);
						matchingValueArray[3] += (extractedPrintData[tempAddress - 5120]);
						matchingValueArray[4] += (extractedPrintData[tempAddress - 3840]);
						matchingValueArray[5] += (extractedPrintData[tempAddress - 2560]);
						matchingValueArray[6] += (extractedPrintData[tempAddress - 1280]);
						matchingValueArray[7] += (extractedPrintData[tempAddress]);
						matchingValueArray[8] += (extractedPrintData[tempAddress + 1280]);
						matchingValueArray[9] += (extractedPrintData[tempAddress + 2560]);
						matchingValueArray[10] += (extractedPrintData[tempAddress + 3840]);
						matchingValueArray[11] += (extractedPrintData[tempAddress + 5120]);
						matchingValueArray[12] += (extractedPrintData[tempAddress + 6400]);
						matchingValueArray[13] += (extractedPrintData[tempAddress + 7680]);
						matchingValueArray[14] += (extractedPrintData[tempAddress + 8960]);
					}

					if (TabletCharacter.discriminationDisplay_kind == STAMP && !TabletGradeData.ETC_ApplyWhiteEngraveAlgorithm)
					{
						for (m = 0; m < expansion_printDataCount; m += HIGH_ROTATION_PRINT_ADD_M)
						{
							rotateX = tempExpansionPrintMatchingData[m][0];
							rotateY = tempExpansionPrintMatchingData[m][1];

							tempAddress = MAX_IMAGE_WIDTH * rotateY + rotateX;
							tempAddress = tempAddress + j;

							matchingValueArray[0] += (BrightPixelNeighborPrint[tempAddress - 8960]);
							matchingValueArray[1] += (BrightPixelNeighborPrint[tempAddress - 7680]);
							matchingValueArray[2] += (BrightPixelNeighborPrint[tempAddress - 6400]);
							matchingValueArray[3] += (BrightPixelNeighborPrint[tempAddress - 5120]);
							matchingValueArray[4] += (BrightPixelNeighborPrint[tempAddress - 3840]);
							matchingValueArray[5] += (BrightPixelNeighborPrint[tempAddress - 2560]);
							matchingValueArray[6] += (BrightPixelNeighborPrint[tempAddress - 1280]);
							matchingValueArray[7] += (BrightPixelNeighborPrint[tempAddress]);
							matchingValueArray[8] += (BrightPixelNeighborPrint[tempAddress + 1280]);
							matchingValueArray[9] += (BrightPixelNeighborPrint[tempAddress + 2560]);
							matchingValueArray[10] += (BrightPixelNeighborPrint[tempAddress + 3840]);
							matchingValueArray[11] += (BrightPixelNeighborPrint[tempAddress + 5120]);
							matchingValueArray[12] += (BrightPixelNeighborPrint[tempAddress + 6400]);
							matchingValueArray[13] += (BrightPixelNeighborPrint[tempAddress + 7680]);
							matchingValueArray[14] += (BrightPixelNeighborPrint[tempAddress + 8960]);
						}
					}

					for (i = 0; i < 15; i++)
					{
						if (matchingValueArray[i] > maxValue)
						{
							maxValue = matchingValueArray[i];

							machingMaxValue[directionNumber] = maxValue;
							shiftX[directionNumber] = j;
							shiftY[directionNumber] = (i - 7) * 2;
							rotationAngle[directionNumber] = temp_r;
						}
					}
				}
			}

			int cosValue = CosData[rotationAngle[directionNumber]];
			int sinValue = SinData[rotationAngle[directionNumber]];
			int shiftXValue = shiftX[directionNumber];
			int shiftYValue = shiftY[directionNumber];

			maskSize = 3;
			memset(tempPrintArea, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
			if (!(TabletCharacter.discriminationDisplay_kind == PRINT || (TabletCharacter.discriminationDisplay_kind == STAMP && TabletGradeData.ETC_ApplyWhiteEngraveAlgorithm)))
			{
				for (m = 0; m < expansion_printDataCount; m += 2)
				{
					tempX = expansion_position_printData[m][0];
					tempY = expansion_position_printData[m][1];

					rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX + shiftXValue;
					rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY + shiftYValue;

					for (y = rotateY - 1; y <= rotateY + 1; y++)
					{
						for (x = rotateX - 1; x <= rotateX + 1; x++)
						{
							tempPrintArea[MAX_IMAGE_WIDTH * y + x] = 0x0F;
						}
					}
				}

				maskSize = 1;
			}

			for (m = 0; m < printDataCount; m += 2)
			{
				tempX = position_printData[m][0];
				tempY = position_printData[m][1];

				rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX + shiftXValue;
				rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY + shiftYValue;

				for (y = rotateY - maskSize; y <= rotateY + maskSize; y++)
				{
					for (x = rotateX - maskSize; x <= rotateX + maskSize; x++)
					{
						tempAddress = MAX_IMAGE_WIDTH * y + x;
						if ((tempPrintArea[tempAddress] & 0xF0) == 0)
						{
							tempPrintArea[tempAddress] |= 0xF0;
						}
					}
				}
			}				
		}

		// 인쇄의 방향에 따라 중요한 차이가 나는 점의 개수를 계산
		int printDirectionMatchingCount[2];
		int exclusiveMatchingCount[2];
		int eraseCount[2];
		printDirectionMatchingCount[0] = printDirectionMatchingCount[1] = 0;
		exclusiveMatchingCount[0] = exclusiveMatchingCount[1] = 0;
		eraseCount[0] = eraseCount[1] = 0;

		if (!(TabletCharacter.discriminationDisplay_kind == PRINT || (TabletCharacter.discriminationDisplay_kind == STAMP && TabletGradeData.ETC_ApplyWhiteEngraveAlgorithm)))
		{
			for (y = stY; y < edY; y++)
			{
				for (x = stX; x < edX; x++)
				{
					tempAddress = MAX_IMAGE_WIDTH * y + x;

					if ((tempPrintArea1[tempAddress] & 0xF0) || (tempPrintArea2[tempAddress] & 0xF0))
					{
						if ((tempPrintArea1[tempAddress] & 0xF0) == 0)
						{
							if (DarkPixelNeighborPrint[tempAddress])
								exclusiveMatchingCount[1]++;
						}
						else
						{
							printDirectionMatchingCount[0]++;
							if (!DarkPixelNeighborPrint[tempAddress])
								eraseCount[0]++;
						}

						if ((tempPrintArea2[tempAddress] & 0xF0) == 0)
						{
							if (DarkPixelNeighborPrint[tempAddress])
								exclusiveMatchingCount[0]++;
						}
						else
						{
							printDirectionMatchingCount[1]++;
							if (!DarkPixelNeighborPrint[tempAddress])
								eraseCount[1]++;
						}
					}

					if ((tempPrintArea1[tempAddress] & 0x0F) || (tempPrintArea2[tempAddress] & 0x0F))
					{
						if ((tempPrintArea1[tempAddress] & 0x0F) == 0)
						{
							if (BrightPixelNeighborPrint[tempAddress])
								exclusiveMatchingCount[1]++;
						}
						else
						{
							printDirectionMatchingCount[0]++;
						}

						if ((tempPrintArea2[tempAddress] & 0x0F) == 0)
						{
							if (BrightPixelNeighborPrint[tempAddress])
								exclusiveMatchingCount[0]++;
						}
						else
						{
							printDirectionMatchingCount[1]++;
						}
					}
				}
			}
		}
		else
		{
			for (y = stY; y < edY; y++)
			{
				for (x = stX; x < edX; x++)
				{
					tempAddress = MAX_IMAGE_WIDTH * y + x;

					if ((tempPrintArea1[tempAddress] & 0xF0) || (tempPrintArea2[tempAddress] & 0xF0))
					{
						if ((tempPrintArea1[tempAddress] & 0xF0) == 0)
						{
							if (DarkPixelNeighborPrint[tempAddress])
								exclusiveMatchingCount[1]++;
						}
						else
						{
							printDirectionMatchingCount[0]++;
							if (!DarkPixelNeighborPrint[tempAddress])
								eraseCount[0]++;
						}

						if ((tempPrintArea2[tempAddress] & 0xF0) == 0)
						{
							if (DarkPixelNeighborPrint[tempAddress])
								exclusiveMatchingCount[0]++;
						}
						else
						{
							printDirectionMatchingCount[1]++;
							if (!DarkPixelNeighborPrint[tempAddress])
								eraseCount[1]++;
						}
					}
				}
			}
		}



		// 이제 인쇄의 방향이 정방향인지 역방향(180도 회전)인지 구분한다.
		// 10으로 나눈 이유는 integer의 최대값을 초과하지 않도록.
		if (TabletCharacter.MarvelingTablet)
		{
			if (printDirectionMatchingCount[0])
				machingMaxValue[0] = machingMaxValue[0] / 10 * (printDirectionMatchingCount[0] + exclusiveMatchingCount[0] / 2 - eraseCount[0]) / printDirectionMatchingCount[0];
			else
				machingMaxValue[0] = 0;

			if (printDirectionMatchingCount[1])
				machingMaxValue[1] = machingMaxValue[1] / 10 * (printDirectionMatchingCount[1] + exclusiveMatchingCount[1] / 2 - eraseCount[1]) / printDirectionMatchingCount[1];
			else
				machingMaxValue[1] = 0;
		}
		else
		{
			if (printDirectionMatchingCount[0])
				machingMaxValue[0] = machingMaxValue[0] / 10 * (printDirectionMatchingCount[0] + exclusiveMatchingCount[0] * 2 - eraseCount[0]) / printDirectionMatchingCount[0];
			else
				machingMaxValue[0] = 0;

			if (printDirectionMatchingCount[1])
				machingMaxValue[1] = machingMaxValue[1] / 10 * (printDirectionMatchingCount[1] + exclusiveMatchingCount[1] * 2 - eraseCount[1]) / printDirectionMatchingCount[1];
			else
				machingMaxValue[1] = 0;
		}

		if (machingMaxValue[0] > machingMaxValue[1])
		{
			printMatchingResultAngle[printNumber] = rotationAngle[0];
			printMatchingResultShiftX[printNumber] = shiftX[0];
			printMatchingResultShiftY[printNumber] = shiftY[0];
		}
		else
		{
			printMatchingResultAngle[printNumber] = rotationAngle[1];
			printMatchingResultShiftX[printNumber] = shiftX[1];
			printMatchingResultShiftY[printNumber] = shiftY[1];
		}


		// 이제 인쇄 방향을 구했다.
		// 구해진 인쇄 방향을 사용하여 현재의 인쇄 번호에 대한 정밀 매칭을 시도한다.

		maxValue = -1;
		shiftXByTotion = printMatchingResultShiftX[printNumber];
		shiftYByTotion = printMatchingResultShiftY[printNumber];
		tempRotateAngleArray[printNumber] = printMatchingResultAngle[printNumber];

		int sinValue, cosValue;
		for (r = tempRotateAngleArray[printNumber] - 8; r <= tempRotateAngleArray[printNumber] + 8; r += 2)
		{
			temp_r = r;
			if (temp_r >= 720)
			{
				temp_r -= 720;
			}
			else if (temp_r < 0)
			{
				temp_r += 720;
			}

			sinValue = SinData[temp_r];
			cosValue = CosData[temp_r];

			for (m = 0; m < printDataCount; m++)
			{
				tempX = position_printData[m][0];
				tempY = position_printData[m][1];

				rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX;
				rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY;

				tempPrintMatchingData[m][0] = rotateX;
				tempPrintMatchingData[m][1] = rotateY;
			}

			if (TabletCharacter.discriminationDisplay_kind == STAMP && !TabletGradeData.ETC_ApplyWhiteEngraveAlgorithm)
			{
				for (m = 0; m < expansion_printDataCount; m += 2)
				{
					tempX = expansion_position_printData[m][0];
					tempY = expansion_position_printData[m][1];

					rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX;
					rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY;

					tempExpansionPrintMatchingData[m][0] = rotateX;
					tempExpansionPrintMatchingData[m][1] = rotateY;
				}
			}

			for (j = -3 + shiftXByTotion; j <= 3 + shiftXByTotion; j += 2)
			{
				memset(matchingValueArray, 0, sizeof(int) * 4);
				for (m = 0; m < printDataCount; m++)
				{
					rotateX = tempPrintMatchingData[m][0];
					rotateY = tempPrintMatchingData[m][1];

					tempAddress = MAX_IMAGE_WIDTH * rotateY + rotateX;
					tempAddress = tempAddress + j + shiftYByTotion * 640;

					matchingValueArray[0] += (extractedPrintData[tempAddress - 1280]);
					matchingValueArray[1] += (extractedPrintData[tempAddress - 640]);
					matchingValueArray[2] += (extractedPrintData[tempAddress + 640]);
					matchingValueArray[3] += (extractedPrintData[tempAddress + 1280]);
				}

				if (TabletCharacter.discriminationDisplay_kind == STAMP && !TabletGradeData.ETC_ApplyWhiteEngraveAlgorithm)
				{
					for (m = 0; m < expansion_printDataCount; m += 2)
					{
						rotateX = tempExpansionPrintMatchingData[m][0];
						rotateY = tempExpansionPrintMatchingData[m][1];

						tempAddress = MAX_IMAGE_WIDTH * rotateY + rotateX;
						tempAddress = tempAddress + j + shiftYByTotion * 640;

						matchingValueArray[0] += (BrightPixelNeighborPrint[tempAddress - 1920]);
						matchingValueArray[1] += (BrightPixelNeighborPrint[tempAddress - 640]);
						matchingValueArray[2] += (BrightPixelNeighborPrint[tempAddress + 640]);
						matchingValueArray[3] += (BrightPixelNeighborPrint[tempAddress + 1920]);
					}
				}

				for (i = 0; i < 4; i++)
				{
					if (matchingValueArray[i] > maxValue)
					{
						maxValue = matchingValueArray[i];
						printMatchingResultAngle[printNumber] = temp_r;
						printMatchingResultShiftX[printNumber] = j;
						printMatchingResultShiftY[printNumber] = (2 * i - 3) + shiftYByTotion;
					}
				}
			}
		}

		standardMaxValue[printNumber] = 0;
		if (matchingDataCount != 0)
			standardMaxValue[printNumber] = maxValue * 10 / (matchingDataCount);

		printMatchingMaxValue[printNumber] = maxValue;
		printMatchingCount[printNumber]	= matchingDataCount;

		if (TabletCharacter.discriminationDisplay_num != TWO_FACE_DIFF)
		{
			break;
		}
	}

	// 이제 두개의 인쇄중 하나를 선택한다.
	int printMatchingCountValue = 0;
	if (TabletCharacter.discriminationDisplay_num == ONE_FACE || TabletCharacter.discriminationDisplay_num == TWO_FACE_SAME)
	{
		PrintMatchingResult.PrintRotationAngle = printMatchingResultAngle[0];
		PrintMatchingResult.PrintShiftX = printMatchingResultShiftX[0];
		PrintMatchingResult.PrintShiftY = printMatchingResultShiftY[0];

		maxValue = printMatchingMaxValue[0];
		printMatchingCountValue = printMatchingCount[0];
	}
	else
	{
		// 두개의 인쇄를 정밀하게 비교한다.
		memset(tempPrintArea1, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
		memset(tempPrintArea2, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

		int matchingDataCount;

		if (TabletCharacter.discriminationDisplay_kind == PRINT && TabletCharacter.discriminationDisplay_num == TWO_FACE_DIFF && TabletSetupData.ApplySimilarPrintMatchingAlgorithm)
		{
			// 두 인쇄가 서로 닮았을 경우.
			maskSize = 1;

			int similarPrintDetailMatchingAngle[2];
			int similarPrintDetailMatchingX[2];
			int similarPrintDetailMatchingY[2];
			int similarPrintDetailMatchingValue[2];
			int similarPrintDetailMatchingCount[2];	

			memset(similarPrintDetailMatchingAngle, 0, sizeof(int) * 2);
			memset(similarPrintDetailMatchingX, 0, sizeof(int) * 2);
			memset(similarPrintDetailMatchingY, 0, sizeof(int) * 2);
			memset(similarPrintDetailMatchingValue, 0, sizeof(int) * 2);
			memset(similarPrintDetailMatchingCount, 0, sizeof(int) * 2);

			for (printNumber = 0; printNumber <= 1; printNumber++)
			{
				short *similarPrintMaskInfo;
				unsigned char *tempPrintArea;
				if (printNumber == 0)
				{
					printDataCount = TabletSetupData.printData1Count;
					expansion_printDataCount = TabletSetupData.expansion_printData1Count;
					position_printData = TabletSetupData.position_printData1;
					expansion_position_printData = TabletSetupData.expansion_position_printData1;
					tempPrintArea = tempPrintArea1;
					similarPrintMaskInfo = TabletSetupData.SimilarPrint1MaskInfo;
				}
				else
				{
					printDataCount = TabletSetupData.printData2Count;
					expansion_printDataCount = TabletSetupData.expansion_printData2Count;
					position_printData = TabletSetupData.position_printData2;
					expansion_position_printData = TabletSetupData.expansion_position_printData2;
					tempPrintArea = tempPrintArea2;
					similarPrintMaskInfo = TabletSetupData.SimilarPrint2MaskInfo;
				}

				maxValue = 0;
				int sinValue, cosValue;
				for (r = printMatchingResultAngle[printNumber] - 4; r <= printMatchingResultAngle[printNumber] + 4; r++)
				{
					temp_r = r;
					if (temp_r >= 720)
					{
						temp_r -= 720;
					}
					else if (temp_r < 0)
					{
						temp_r += 720;
					}

					sinValue = SinData[temp_r];
					cosValue = CosData[temp_r];

					for (j = printMatchingResultShiftY[printNumber] - 4; j <= printMatchingResultShiftY[printNumber] + 4; j++)
					{
						for (i = printMatchingResultShiftX[printNumber] - 4; i <= printMatchingResultShiftX[printNumber] + 4; i++)
						{
							matchingValue = matchingDataCount = 0;
							for (m = 0; m < printDataCount; m++)
							{
								tempX = position_printData[m][0];
								tempY = position_printData[m][1];

								if (similarPrintMaskInfo[m]) // 다른 인쇄 정보
								{
									rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX;
									rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY;

									tempAddress = MAX_IMAGE_WIDTH * (rotateY + j) + (rotateX + i);									

									// 읽기만하므로 속도를 위해서 범위 무시.
									//if (rotateX > tabletAreaInfo[AREA_INFO_ST_X_ADDRESS] && rotateX < tabletAreaInfo[AREA_INFO_END_X_ADDRESS] && rotateY > tabletAreaInfo[AREA_INFO_ST_Y_ADDRESS] && rotateY < tabletAreaInfo[AREA_INFO_END_Y_ADDRESS])
									{
										matchingValue += extractedPrintData[tempAddress];
										matchingDataCount++;
									}
								}
							}

							if (maxValue < matchingValue)
							{
								maxValue = matchingValue;

								similarPrintDetailMatchingAngle[printNumber] = temp_r;
								similarPrintDetailMatchingX[printNumber] = i;
								similarPrintDetailMatchingY[printNumber] = j;
								similarPrintDetailMatchingValue[printNumber] = maxValue;
								similarPrintDetailMatchingCount[printNumber] = matchingDataCount;
							}
						}
					}
				}

				standardMaxValue[printNumber] = 0;
				if (similarPrintDetailMatchingCount[printNumber] != 0)
				{
					standardMaxValue[printNumber] = similarPrintDetailMatchingValue[printNumber] * 10 / (similarPrintDetailMatchingCount[printNumber]);
				}

				temp_r = similarPrintDetailMatchingAngle[printNumber];
				sinValue = SinData[temp_r];
				cosValue = CosData[temp_r];
				for (m = 0; m < printDataCount; m++)
				{
					tempX = position_printData[m][0];
					tempY = position_printData[m][1];

					if (similarPrintMaskInfo[m]) // 다른 인쇄 정보
					{
						rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX + similarPrintDetailMatchingX[printNumber];
						rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY + similarPrintDetailMatchingY[printNumber];

						for (y = rotateY - maskSize; y <= rotateY + maskSize; y++)
						{
							for (x = rotateX - maskSize; x <= rotateX + maskSize; x++)
							{
								tempAddress = MAX_IMAGE_WIDTH * y + x;
								if ((tempPrintArea[tempAddress] & 0xF0) == 0)
								{
									tempPrintArea[tempAddress] |= 0xF0;
								}
							}
						}
					}
				}					
			}

			// 두 인쇄를 비교하여 중요한 차이가 나는 점의 개수를 구한다.
			int exclusiveMatchingCount[2];
			int eraseCount[2];
			similarPrintDetailMatchingCount[0] = similarPrintDetailMatchingCount[1] = 0;
			exclusiveMatchingCount[0] = exclusiveMatchingCount[1] = 0;
			eraseCount[0] = eraseCount[1] = 0;
			for (y = stY; y < edY; y++)
			{
				for (x = stX; x < edX; x++)
				{
					tempAddress = MAX_IMAGE_WIDTH * y + x;

					if ((tempPrintArea1[tempAddress] & 0xF0) || (tempPrintArea2[tempAddress] & 0xF0))
					{
						if ((tempPrintArea1[tempAddress] & 0xF0) == 0)
						{
							if (DarkPixelNeighborPrint[tempAddress])
								exclusiveMatchingCount[1]++;
						}
						else
						{
							similarPrintDetailMatchingCount[0]++;
							if (!DarkPixelNeighborPrint[tempAddress])
								eraseCount[0]++;
						}

						if ((tempPrintArea2[tempAddress] & 0xF0) == 0)
						{
							if (DarkPixelNeighborPrint[tempAddress])
								exclusiveMatchingCount[0]++;
						}
						else
						{
							similarPrintDetailMatchingCount[1]++;
							if (!DarkPixelNeighborPrint[tempAddress])
								eraseCount[1]++;
						}
					}					
				}
			}

			if (TabletCharacter.MarvelingTablet)			
			{										
				if (similarPrintDetailMatchingCount[0])
					standardMaxValue[0] = standardMaxValue[0] * (similarPrintDetailMatchingCount[0] + exclusiveMatchingCount[0] / 2 - eraseCount[0]) / similarPrintDetailMatchingCount[0];

				if (similarPrintDetailMatchingCount[1])
					standardMaxValue[1] = standardMaxValue[1] * (similarPrintDetailMatchingCount[1] + exclusiveMatchingCount[1] / 2 - eraseCount[1]) / similarPrintDetailMatchingCount[1];
			}
			else
			{
				if (similarPrintDetailMatchingCount[0])
					standardMaxValue[0] = standardMaxValue[0] * (similarPrintDetailMatchingCount[0] + exclusiveMatchingCount[0] * 2 - eraseCount[0]) / similarPrintDetailMatchingCount[0];

				if (similarPrintDetailMatchingCount[1])
					standardMaxValue[1] = standardMaxValue[1] * (similarPrintDetailMatchingCount[1] + exclusiveMatchingCount[1] * 2 - eraseCount[1]) / similarPrintDetailMatchingCount[1];
			}
		}
		else
		{
			// 두 인쇄가 서로 유사하지 않을 때.				
			maskSize = 3;

			for (printNumber = 0; printNumber <= 1; printNumber++)
			{
				unsigned char *tempPrintArea;
				if (printNumber == 0)
				{
					printDataCount = TabletSetupData.printData1Count;
					expansion_printDataCount = TabletSetupData.expansion_printData1Count;
					position_printData = TabletSetupData.position_printData1;
					expansion_position_printData = TabletSetupData.expansion_position_printData1;
					tempPrintArea = tempPrintArea1;
				}
				else
				{
					printDataCount = TabletSetupData.printData2Count;
					expansion_printDataCount = TabletSetupData.expansion_printData2Count;
					position_printData = TabletSetupData.position_printData2;
					expansion_position_printData = TabletSetupData.expansion_position_printData2;
					tempPrintArea = tempPrintArea2;
				}

				if (!(TabletCharacter.discriminationDisplay_kind == PRINT || (TabletCharacter.discriminationDisplay_kind == STAMP && TabletGradeData.ETC_ApplyWhiteEngraveAlgorithm)))
				{
					temp_r = printMatchingResultAngle[printNumber];
					int sinValue, cosValue;
					sinValue = SinData[temp_r];
					cosValue = CosData[temp_r];
					for (m = 0; m < expansion_printDataCount; m += 2)
					{
						tempX = expansion_position_printData[m][0];
						tempY = expansion_position_printData[m][1];

						rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX + printMatchingResultShiftX[printNumber];
						rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY + printMatchingResultShiftY[printNumber];

						for (y = rotateY - 1; y <= rotateY + 1; y++)
						{
							for (x = rotateX - 1; x <= rotateX + 1; x++)
							{
								tempPrintArea[MAX_IMAGE_WIDTH * y + x] = 0x0F;
							}
						}
					}

					maskSize = 1;
				}

				temp_r = printMatchingResultAngle[printNumber];
				int sinValue, cosValue;
				sinValue = SinData[temp_r];
				cosValue = CosData[temp_r];

				for (m = 0; m < printDataCount; m += 2)
				{
					tempX = position_printData[m][0];
					tempY = position_printData[m][1];

					rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX + printMatchingResultShiftX[printNumber];
					rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY + printMatchingResultShiftY[printNumber];

					for (y = rotateY - maskSize; y <= rotateY + maskSize; y++)
					{
						for (x = rotateX - maskSize; x <= rotateX + maskSize; x++)
						{
							tempAddress = MAX_IMAGE_WIDTH * y + x;
							if ((tempPrintArea[tempAddress] & 0xF0) == 0)
							{
								tempPrintArea[tempAddress] |= 0xF0;
							}
						}
					}
				}
			}

			// 두 인쇄를 비교하여 중요한 차이가 나는 점의 개수를 구한다.
			int printDetailMatchingCount[2];
			int exclusiveMatchingCount[2];
			int eraseCount[2];
			printDetailMatchingCount[0] = printDetailMatchingCount[1] = 0;
			exclusiveMatchingCount[0] = exclusiveMatchingCount[1] = 0;
			eraseCount[0] = eraseCount[1] = 0;
			if (!(TabletCharacter.discriminationDisplay_kind == PRINT || (TabletCharacter.discriminationDisplay_kind == STAMP && TabletGradeData.ETC_ApplyWhiteEngraveAlgorithm)))
			{
				for (y = stY; y < edY; y++)
				{
					for (x = stX; x < edX; x++)
					{
						tempAddress = MAX_IMAGE_WIDTH * y + x;

						if ((tempPrintArea1[tempAddress] & 0xF0) || (tempPrintArea2[tempAddress] & 0xF0))
						{
							if ((tempPrintArea1[tempAddress] & 0xF0) == 0)
							{
								if (extractedPrintData[tempAddress])
									exclusiveMatchingCount[1]++;
							}
							else
							{
								printDetailMatchingCount[0]++;
								if (!extractedPrintData[tempAddress])
									eraseCount[0]++;
							}

							if ((tempPrintArea2[tempAddress] & 0xF0) == 0)
							{
								if (extractedPrintData[tempAddress])
									exclusiveMatchingCount[0]++;
							}
							else
							{
								printDetailMatchingCount[1]++;
								if (!extractedPrintData[tempAddress])
									eraseCount[1]++;
							}
						}

						if ((tempPrintArea1[tempAddress] & 0x0F) || (tempPrintArea2[tempAddress] & 0x0F))
						{
							if ((tempPrintArea1[tempAddress] & 0x0F) == 0)
							{
								if (BrightPixelNeighborPrint[tempAddress])
									exclusiveMatchingCount[1]++;
							}
							else
							{
								printDetailMatchingCount[0]++;
								if (!extractedPrintData[tempAddress])
									eraseCount[0]++;
							}

							if ((tempPrintArea2[tempAddress] & 0x0F) == 0)
							{
								if (BrightPixelNeighborPrint[tempAddress])
									exclusiveMatchingCount[0]++;
							}
							else
							{
								printDetailMatchingCount[1]++;
								if (!extractedPrintData[tempAddress])
									eraseCount[1]++;
							}
						}
					}
				}	
			}
			else
			{
				for (y = stY; y < edY; y++)
				{
					for (x = stX; x < edX; x++)
					{
						tempAddress = MAX_IMAGE_WIDTH * y + x;

						if ((tempPrintArea1[tempAddress] & 0xF0) || (tempPrintArea2[tempAddress] & 0xF0))
						{
							if ((tempPrintArea1[tempAddress] & 0xF0) == 0)
							{
								if (extractedPrintData[tempAddress])
									exclusiveMatchingCount[1]++;
							}
							else
							{
								printDetailMatchingCount[0]++;
								if (!extractedPrintData[tempAddress])
									eraseCount[0]++;
							}

							if ((tempPrintArea2[tempAddress] & 0xF0) == 0)
							{
								if (extractedPrintData[tempAddress])
									exclusiveMatchingCount[0]++;
							}
							else
							{
								printDetailMatchingCount[1]++;
								if (!extractedPrintData[tempAddress])
									eraseCount[1]++;
							}
						}
					}
				}					
			}			

			if (TabletCharacter.MarvelingTablet)
			{										
				if (printDetailMatchingCount[0])
					standardMaxValue[0] = standardMaxValue[0] * (printDetailMatchingCount[0] + exclusiveMatchingCount[0] / 2 - eraseCount[0]) / printDetailMatchingCount[0];

				if (printDetailMatchingCount[1])
					standardMaxValue[1] = standardMaxValue[1] * (printDetailMatchingCount[1] + exclusiveMatchingCount[1] / 2 - eraseCount[1]) / printDetailMatchingCount[1];					
			}
			else
			{
				if (printDetailMatchingCount[0])
					standardMaxValue[0] = standardMaxValue[0] * (printDetailMatchingCount[0] + exclusiveMatchingCount[0] * 2 - eraseCount[0]) / printDetailMatchingCount[0];

				if (printDetailMatchingCount[1])
					standardMaxValue[1] = standardMaxValue[1] * (printDetailMatchingCount[1] + exclusiveMatchingCount[1] * 2 - eraseCount[1]) / printDetailMatchingCount[1];
			}
		}

#ifdef PC_SIM
		PrintMatchingDiff = abs(standardMaxValue[0] - standardMaxValue[1]);
#endif

		// 두 인쇄중 하나를 선택한다.
		if (TabletCharacter.tabletColorN == ONECOLOR)
		{
			if (standardMaxValue[1] < standardMaxValue[0])
			{
				PrintMatchingResult.PrintRotationAngle = printMatchingResultAngle[0];
				PrintMatchingResult.PrintShiftX = printMatchingResultShiftX[0];
				PrintMatchingResult.PrintShiftY = printMatchingResultShiftY[0];

				maxValue = printMatchingMaxValue[0];
				printMatchingCountValue = printMatchingCount[0];
			}
			else
			{
				PrintMatchingResult.PrintRotationAngle = printMatchingResultAngle[1];
				PrintMatchingResult.PrintShiftX = printMatchingResultShiftX[1];
				PrintMatchingResult.PrintShiftY = printMatchingResultShiftY[1];

				maxValue = printMatchingMaxValue[1];
				printMatchingCountValue = printMatchingCount[1];
			}
		}
		else
		{
			if (SelectedFace == FRONT_FACE_FOR_COLOR)
			{
				PrintMatchingResult.PrintRotationAngle = printMatchingResultAngle[0];
				PrintMatchingResult.PrintShiftX = printMatchingResultShiftX[0];
				PrintMatchingResult.PrintShiftY = printMatchingResultShiftX[0];

				maxValue = printMatchingMaxValue[0];
				printMatchingCountValue = printMatchingCount[0];
			}
			else
			{
				PrintMatchingResult.PrintRotationAngle = printMatchingResultAngle[1];
				PrintMatchingResult.PrintShiftX = printMatchingResultShiftX[1];
				PrintMatchingResult.PrintShiftY = printMatchingResultShiftX[1];

				maxValue = printMatchingMaxValue[1];
				printMatchingCountValue = printMatchingCount[1];				
			}
		}
	}

	// 이제 인쇄 또는 각인의 위치, 각도, 번호(인쇄 번호)가 구해졌다.
	// 다음으로 인쇄 또는 각인에 대한 불량 판정을 진행한다.

	int printIsOrNotThreshold;
	int tempPrintIsOrNotThreshold;

	printIsOrNotThreshold = 10000; // 초기값.	

	if (ProcessingModeGlobal == STUDY_MODE || ProcessingModeGlobal == FIRST_STUDY_MODE)
	{
		if (TabletCharacter.discriminationDisplay_num == ONE_FACE)
		{
			if (ProcessingModeGlobal == FIRST_STUDY_MODE)
			{
				if (TabletCharacter.discriminationDisplay_kind == PRINT)
				{
					printIsOrNotThreshold = 10 * (SmallPrintCoreData1Count * 70 / 100); // 10 = 인쇄의 최소 threshold
				}
				else
				{
					printIsOrNotThreshold = 4 * (SmallPrintCoreData1Count * 70 / 100); // 4 = 각인의 최소 threshold
				}
			}
			else if (ProcessingModeGlobal == STUDY_MODE)
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
					printIsOrNotThreshold = TabletSetupData.ProtoEngraveDistinguishV_Cam1 * 60; // ProtoValue, 60%만 적용
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
					printIsOrNotThreshold = TabletSetupData.ProtoEngraveDistinguishV_Cam9 * 60; // ProtoValue, 60%만 적용
			}

			if (ProcessingModeGlobal == FIRST_STUDY_MODE)
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
				{
					ProtoEngraveDistinguishV_Cam1 = maxValue / 100;
				}
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
				{
					ProtoEngraveDistinguishV_Cam9 = maxValue / 100;
				}
			}
			else if (ProcessingModeGlobal == STUDY_MODE)
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 = maxValue / 100;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera1 = 0;
				}
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 = maxValue / 100;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera9 = 0;
				}
			}
		}
		else if (TabletCharacter.discriminationDisplay_num == TWO_FACE_SAME)
		{
			if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX || cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
			{
				if (TabletCharacter.discriminationDisplay_kind == PRINT)
				{
					printIsOrNotThreshold = 10 * (SmallPrintCoreData1Count * 70 / 100); // 4 = 각인의 최소 threshold
				}
				else
				{
					printIsOrNotThreshold = 4 * (SmallPrintCoreData1Count * 70 / 100); // 10 = 인쇄의 최소 threshold
				}
			}

			if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
			{
				TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 = maxValue / 100;
				TabletStudyData.Print2_IsOrNotThreshold_ForCamera1 = 0;
			}
			else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
			{
				TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 = maxValue / 100;
				TabletStudyData.Print2_IsOrNotThreshold_ForCamera9 = 0;
			}
		}
		else if (TabletCharacter.discriminationDisplay_num == TWO_FACE_DIFF)
		{
			if (standardMaxValue[1] < standardMaxValue[0])
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 = maxValue / 100;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera1 = 0;
				}
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 = maxValue / 100;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera9 = 0;
				}
			}
			else
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 = 0;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera1 = maxValue / 100;
				}
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 = 0;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera9 = maxValue / 100;
				}
			}
		}
	}
	else if (ProcessingModeGlobal == INSPECTION_MODE)
	{
		if (TabletCharacter.discriminationDisplay_num == ONE_FACE || TabletCharacter.discriminationDisplay_num == TWO_FACE_SAME)
		{
			if (TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 > BLURRED_ENGRAVE_STANDARD_V)
			{
				alpha = 60;
				// 정상각인을 매칭 하지 못하는 경우가 발생하여 해당 기능은 막아둠 by moon
				BlurredEngraveSW = 0;
			}
			else
			{
				alpha = 60;
				BlurredEngraveSW = 1;
			}

			if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
			{
				tempPrintIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 + TabletGradeData.EngraveMatchingOrNotValue * 4;
				if (tempPrintIsOrNotThreshold < 0)
					tempPrintIsOrNotThreshold = 0;

				printIsOrNotThreshold = tempPrintIsOrNotThreshold * alpha;
			}
			else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
			{
				tempPrintIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 + TabletGradeData.EngraveMatchingOrNotValue * 4;
				if (tempPrintIsOrNotThreshold < 0)
					tempPrintIsOrNotThreshold = 0;

				printIsOrNotThreshold = tempPrintIsOrNotThreshold * alpha;
			}
		}
		if (TabletCharacter.discriminationDisplay_num == TWO_FACE_DIFF)
		{
			if (standardMaxValue[1] < standardMaxValue[0])
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 * 80;
				}
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 * 80;
				}
			}
			else
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print2_IsOrNotThreshold_ForCamera1 * 80;
				}
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print2_IsOrNotThreshold_ForCamera9 * 80;
				}
			}
		}
	}

	if (TabletCharacter.discriminationDisplay_num == ONE_FACE && TabletCharacter.discriminationDisplay_kind != PRINT)
	{
		if (ProcessingModeGlobal == STUDY_MODE)
		{
			TabletStudyData.TabletEngraveMisMatchCount_Remaining_CAM1 = 0;
			TabletStudyData.TabletEngraveMisMatchCount_Empty_CAM1 = 0;

			TabletStudyData.TabletEngraveMisMatchCount_Remaining_CAM9 = 0;
			TabletStudyData.TabletEngraveMisMatchCount_Empty_CAM9 = 0;

			// 여기서 초기화를 해준 후 인쇄 여부 판정 후 인쇄 글자까지 완전히 매칭한 후 다시 값을 넣어주고 있다.
			if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
			{
				TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 = 0;
				TabletStudyData.Print2_IsOrNotThreshold_ForCamera1 = 0;
			}
			else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
			{
				TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 = 0;
				TabletStudyData.Print2_IsOrNotThreshold_ForCamera9 = 0;
			}
		}
	}

	if ((TabletCharacter.discriminationDisplay_num == ONE_FACE && maxValue > printIsOrNotThreshold) || (TabletCharacter.discriminationDisplay_num == TWO_FACE_DIFF) || (TabletCharacter.discriminationDisplay_num == TWO_FACE_SAME))
	{
		if (TabletCharacter.discriminationDisplay_num == ONE_FACE || TabletCharacter.discriminationDisplay_num == TWO_FACE_SAME || (TabletCharacter.discriminationDisplay_num == TWO_FACE_DIFF && standardMaxValue[1] < standardMaxValue[0]))
		{
			PrintMatchingResult.dataNumberWithMaxValue = 0;
		}
		else if (TabletCharacter.discriminationDisplay_num == TWO_FACE_DIFF && standardMaxValue[1] >= standardMaxValue[0])
		{
			PrintMatchingResult.dataNumberWithMaxValue = 2;
		}
	}

	constantShiftX = TabletMatchingResult.AdjustCenterXInImage;
	constantShiftY = TabletMatchingResult.AdjustCenterYInImage;
	
	if (PrintMatchingResult.dataNumberWithMaxValue == 0)
	{
		printNumber = 0;

		printDataCount = TabletSetupData.printData1Count;
		expansion_printDataCount = TabletSetupData.expansion_printData1Count;
		position_printData = TabletSetupData.position_printData1;
		expansion_position_printData = TabletSetupData.expansion_position_printData1;
	}
	else if (PrintMatchingResult.dataNumberWithMaxValue == 2)
	{
		printNumber = 1;

		printDataCount = TabletSetupData.printData2Count;
		expansion_printDataCount = TabletSetupData.expansion_printData2Count;
		position_printData = TabletSetupData.position_printData2;
		expansion_position_printData = TabletSetupData.expansion_position_printData2;
	}

	if (PrintMatchingResult.dataNumberWithMaxValue == 0 || PrintMatchingResult.dataNumberWithMaxValue == 2)
	{
		if (TabletCharacter.discriminationDisplay_kind == PRINT)
		{
			if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
			{
				MeanColorR = TabletSetupData.protoStudyColorR;
				MeanColorG = TabletSetupData.protoStudyColorG;
				MeanColorB = TabletSetupData.protoStudyColorB;
			}
			else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
			{
				MeanColorR = TabletSetupData.protoStudyColorR;
				MeanColorG = TabletSetupData.protoStudyColorG;
				MeanColorB = TabletSetupData.protoStudyColorB;
			}

			constantShiftX = TabletMatchingResult.PrintCenterX;
			constantShiftY = TabletMatchingResult.PrintCenterY;

#ifdef PC_SIM
			memset(ExtractPrintData, 0, 640 * 480);
#endif

			int cosValue, sinValue;
			if (PrintMatchingResult.PrintRotationAngle >= 0)
			{
				sinValue = SinData[PrintMatchingResult.PrintRotationAngle % 720];
				cosValue = CosData[PrintMatchingResult.PrintRotationAngle % 720];
			}
			else
			{
				sinValue = -SinData[(-PrintMatchingResult.PrintRotationAngle) % 720];
				cosValue = CosData[(-PrintMatchingResult.PrintRotationAngle) % 720];
			}

			for (n = 0; n < TabletSetupData.printLabelCount[printNumber]; n++)
			{
				for (m = 0; m < TabletSetupData.printLabelDataCnt[printNumber][n]; m++)
				{
					tempX = TabletSetupData.printLabelData[printNumber][n][m][0];
					tempY = TabletSetupData.printLabelData[printNumber][n][m][1];
					
					rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX + PrintMatchingResult.PrintShiftX;
					rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY + PrintMatchingResult.PrintShiftY;

					RotationPrintLabelData[n][m][0] = rotateX;
					RotationPrintLabelData[n][m][1] = rotateY;
				}
			}

			int reArrangeLargePrintLabel[THREED_PRINT_MAX_LABEL_COUNT];

			memset(reArrangeLargePrintLabel, 0, sizeof(int) * THREED_PRINT_MAX_LABEL_COUNT);

			int skipSW;
			int printLabelAddStep;
			int tempLabelN;

			for (n = 0; n < TabletSetupData.printLabelCount[printNumber]; n++)
			{
				maxValue = 0;
				for (m = 0; m < TabletSetupData.printLabelCount[printNumber]; m++)
				{
					skipSW = 0;
					if (n > 0)
					{
						// 이전루프에서 찾은 최대 라벨그룹을  skip
						for (k = 0; k < n; k++)
						{
							if (m == reArrangeLargePrintLabel[k])
							{
								skipSW = 1;
								break;
							}
						}
					}

					if (skipSW == 0)
					{
						if (maxValue < TabletSetupData.printLabelDataCnt[printNumber][m])
						{
							maxValue = TabletSetupData.printLabelDataCnt[printNumber][m];
							tempLabelN = m;
						}
					}
				}

				reArrangeLargePrintLabel[n] = tempLabelN;
			}

			int printLabelShiftX[THREED_PRINT_MAX_LABEL_COUNT];
			int printLabelShiftY[THREED_PRINT_MAX_LABEL_COUNT];

			int labelShiftMaxSize;
			int tempmaxValue;
			int overlapCount;

			memset(TempImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
			// PC에서 0.8ms 소요.
			for (n = 0; n < TabletSetupData.printLabelCount[printNumber]; n++)
			{
				tempLabelN = reArrangeLargePrintLabel[n];

				printLabelShiftX[tempLabelN] = printLabelShiftY[tempLabelN] = 0;

				if (TabletSetupData.printLabelDataCnt[printNumber][tempLabelN] > 100)
					printLabelAddStep = 4;
				else if (TabletSetupData.printLabelDataCnt[printNumber][tempLabelN] > 50)
					printLabelAddStep = 2;
				else
					printLabelAddStep = 1;

				labelShiftMaxSize = 6;
				tempmaxValue = -1000;
				for (i = -labelShiftMaxSize; i <= labelShiftMaxSize; i++)
				{
					for (j = -labelShiftMaxSize; j <= labelShiftMaxSize; j++)
					{
						matchingValue = overlapCount = 0;

						for (m = 0; m < TabletSetupData.printLabelDataCnt[printNumber][tempLabelN]; m += printLabelAddStep)
						{
							tempX = RotationPrintLabelData[tempLabelN][m][0] + j;
							tempY = RotationPrintLabelData[tempLabelN][m][1] + i;

							tempAddress = tempY * MAX_IMAGE_WIDTH + tempX;
							if (TempImage[tempAddress] == 0)
							{
								// avoid overlap
								matchingValue += DarkPixelNeighborPrint2[tempAddress];
							}
							else
							{
								overlapCount++;
							}
						}

						if (matchingValue > tempmaxValue && overlapCount == 0)
						{
							tempmaxValue = matchingValue;

							printLabelShiftX[tempLabelN] = j;
							printLabelShiftY[tempLabelN] = i;
						}
					}
				}

				for (m = 0; m < TabletSetupData.printLabelDataCnt[printNumber][tempLabelN]; m++)
				{
					rotateX = RotationPrintLabelData[tempLabelN][m][0] + printLabelShiftX[tempLabelN];
					rotateY = RotationPrintLabelData[tempLabelN][m][1] + printLabelShiftY[tempLabelN];

					TempImage[rotateY * MAX_IMAGE_WIDTH + rotateX] = 1;
				}
			}

			int printLabelHisto[256];
			int printLabelMeanColor;
			int BreakSW;
			int EraseCheck;
			int EraseCount = 0;

			// 소요시간 짧음.
			memset(printLabelHisto, 0, sizeof(int) * 256);
			printLabelMeanColor = 0;
			for (n = 0; n < TabletSetupData.printLabelCount[printNumber]; n++)
			{
				for (m = 0; m < TabletSetupData.printLabelDataCnt[printNumber][n]; m++)
				{
					rotateX = RotationPrintLabelData[n][m][0] + printLabelShiftX[n];
					rotateY = RotationPrintLabelData[n][m][1] + printLabelShiftY[n];

					tempAddress = rotateY * MAX_IMAGE_WIDTH + rotateX;
					realPrintMaskingArea[tempAddress] = n + 1;
					PrintLabelAvgColor[n] += MeanOneColorImage[tempAddress];

#ifdef PC_SIM
					ExtractPrintData[rotateY * MAX_IMAGE_WIDTH + rotateX] = 255;
#endif
					BreakSW = 0;
					EraseCheck = 1;

					// 지워짐 Count
					for (i = rotateY - 4; i <= rotateY + 4; i++)
					{
						for (j = rotateX - 4; j <= rotateX + 4; j++)
						{
							tempAddress = i * MAX_IMAGE_WIDTH + j;
							if (DarkPixelNeighborPrint[tempAddress])
							{
								EraseCheck = 0;
								BreakSW = 1;
								break;
							}
						}
						if (BreakSW)
							break;
					}

					if (EraseCheck)
					{
						EraseCount++;
#ifdef PC_SIM
						ErasePrintImage[MAX_IMAGE_WIDTH * rotateY + rotateX] = 1;
#endif
					}
					else
					{
						printLabelHisto[DarkPixelNeighborPrint2[MAX_IMAGE_WIDTH * rotateY + rotateX]]++;
					}
				}
			}

			maxValue = 0;
			for (m = 15; m < 256; m++)
			{
				if (maxValue < printLabelHisto[m])
				{
					maxValue = printLabelHisto[m];
					printLabelMeanColor = m;
				}
			}

			for (n = 0; n < TabletSetupData.printLabelCount[printNumber]; n++)
			{
				PrintLabelAvgColor[n] /= TabletSetupData.printLabelDataCnt[printNumber][n];
			}

			int printSpreadCount = 0;			
			int tempPrintPxCnt = 0;

			unsigned char *extensionPrintArea;	

			extensionPrintArea = DentedArea;
			memset(extensionPrintArea, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

			// PC에서 1ms 이상 소요.
			int xmax, ymax;
			for (i = stY; i <= edY; i++)
			{
				for (j = stX; j <= edX; j++)
				{
					tempAddress = i * MAX_IMAGE_WIDTH + j;
					if (DarkPixelNeighborPrint[tempAddress] == 255)
						tempPrintPxCnt++;

					if (realPrintMaskingArea[tempAddress])
					{
						for (y = max(0, i - (4 + printAreaMask)), ymax = min(MAX_IMAGE_HEIGHT - 1, i + (4 + printAreaMask)); y <= ymax; y++)
						{
							for (x = max(0, j - (4 + printAreaMask)), xmax = min(MAX_IMAGE_WIDTH - 1, j + (4 + printAreaMask)); x <= xmax; x++)
							{
								if (InspectionArea[y * MAX_IMAGE_WIDTH + x] != PRINT_AREA)
								{
									InspectionArea[y * MAX_IMAGE_WIDTH + x] = PRINT_AREA;
									PrintLabelArea[y * MAX_IMAGE_WIDTH + x] = realPrintMaskingArea[tempAddress];
								}
							}
						}
					}

					if (realPrintMaskingArea[tempAddress])
					{
						for (y = i - 2; y <= i + 2; y++)
						{
							for (x = j - 2; x <= j + 2; x++)
							{
								if (x > 0 && x < MAX_IMAGE_WIDTH && y > 0 && y < MAX_IMAGE_HEIGHT)
								{
									extensionPrintArea[y * MAX_IMAGE_WIDTH + x] = 255;
								}
							}
						}
					}
				}
			}

			for (y = stY; y <= edY; y++)
			{
				for (x = stX; x <= edX; x++)
				{
					tempAddress = MAX_IMAGE_WIDTH * y + x;

					if (!extensionPrintArea[tempAddress] && DarkPixelNeighborPrint[tempAddress] && 
						DarkPixelNeighborPrint2[tempAddress] * 2 > printLabelMeanColor)
					{
						printSpreadCount++;
					}
				}
			}

			int topSW, bottomSW, leftSW, rightSW, topleftSW, toprightSW, bottomleftSW, bottomrightSW;

			// PC에서 0.3ms 정도 소요.
			memset(TempImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
			for (y = stY; y <= edY; y++)
			{
				for (x = stX; x <= edX; x++)
				{
					tempAddress = MAX_IMAGE_WIDTH * y + x;

					if (extensionPrintArea[tempAddress] && realPrintMaskingArea[tempAddress] == 0)
					{
						topSW = bottomSW = leftSW = rightSW = topleftSW = toprightSW = bottomleftSW = bottomrightSW = 0;
						for (i = y - 3; i <= y + 3; i += 3)
						{
							for (j = x - 3; j <= x + 3; j += 3)
							{
								tempAddress2 = MAX_IMAGE_WIDTH * i + j;

								if (realPrintMaskingArea[tempAddress2])
								{
									if (j < x && i < y)
										topleftSW = 1;
									else if (j > x && i < y)
										toprightSW = 1;
									else if (j < x && i > y)
										bottomleftSW = 1;
									else if (j > x && i > y)
										bottomrightSW = 1;
									else if (j < x)
										leftSW = 1;
									else if (j > x)
										rightSW = 1;
									else if (i < y)
										topSW = 1;
									else if (i > y)
										bottomSW = 1;
								}
							}
						}

						if ((topSW && bottomSW) ||
							(leftSW && rightSW) ||
							(topleftSW && bottomrightSW) ||
							(toprightSW && bottomleftSW))
						{
							TempImage[tempAddress] = 1;
						}
					}
				}
			}

			int thresholdForPrintNeighbor = printLabelMeanColor / 2 + TabletGradeData.front_print_dirty_Inetensity * 4;
			int printSpotCount = 0;
			int selfValue;
			int colorDiff;
			int defectCount;

			// PC에서 0.3ms 이내 소요.
			memset(TempImage2, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
			for (y = stY; y <= edY; y++)
			{
				for (x = stX; x <= edX; x++)
				{
					tempAddress = MAX_IMAGE_WIDTH * y + x;
					if (TempImage[tempAddress])
					{
						if (DarkPixelNeighborPrint2[tempAddress] > thresholdForPrintNeighbor)
						{
							selfValue = ColorSourceImage[tempAddress * 3 + globalPrintSelectedRGB];

							topSW = bottomSW = leftSW = rightSW = topleftSW = toprightSW = bottomleftSW = bottomrightSW = 0;
							defectCount = 0;

							for (r = 12; r >= 4; r -= 4)
							{
								tempAddress2 = tempAddress - r;
								colorDiff = ColorSourceImage[tempAddress2 * 3 + globalPrintSelectedRGB] - selfValue;

								if (colorDiff > thresholdForPrintNeighbor)
								{
									leftSW = 1;
									defectCount++;
									break;
								}
							}

							if (defectCount < 1)
								continue;

							for (r = 12; r >= 4; r -= 4)
							{
								tempAddress2 = tempAddress + r;
								colorDiff = ColorSourceImage[tempAddress2 * 3 + globalPrintSelectedRGB] - selfValue;

								if (colorDiff > thresholdForPrintNeighbor)
								{
									rightSW = 1;
									defectCount++;
									break;
								}
							}

							if (defectCount < 2)
								continue;

							for (r = 12; r >= 4; r -= 4)
							{
								tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH;
								colorDiff = ColorSourceImage[tempAddress2 * 3 + globalPrintSelectedRGB] - selfValue;

								if (colorDiff > thresholdForPrintNeighbor)
								{
									topSW = 1;
									defectCount++;
									break;
								}
							}

							if (defectCount < 3)
								continue;

							for (r = 12; r >= 4; r -= 4)
							{
								tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH;
								colorDiff = ColorSourceImage[tempAddress2 * 3 + globalPrintSelectedRGB] - selfValue;

								if (colorDiff > thresholdForPrintNeighbor)
								{
									bottomSW = 1;
									defectCount++;
									break;
								}
							}

							if (defectCount < 4)
								continue;

							for (r = 12; r >= 4; r -= 4)
							{
								tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH - r;
								colorDiff = ColorSourceImage[tempAddress2 * 3 + globalPrintSelectedRGB] - selfValue;

								if (colorDiff > thresholdForPrintNeighbor)
								{
									topleftSW = 1;
									defectCount++;
									break;
								}
							}

							if (defectCount < 5)
								continue;

							for (r = 12; r >= 4; r -= 4)
							{
								tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH + r;
								colorDiff = ColorSourceImage[tempAddress2 * 3 + globalPrintSelectedRGB] - selfValue;

								if (colorDiff > thresholdForPrintNeighbor)
								{
									toprightSW = 1;
									defectCount++;
									break;
								}
							}

							if (defectCount < 6)
								continue;

							for (r = 12; r >= 4; r -= 4)
							{
								tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH - r;
								colorDiff = ColorSourceImage[tempAddress2 * 3 + globalPrintSelectedRGB] - selfValue;

								if (colorDiff > thresholdForPrintNeighbor)
								{
									bottomleftSW = 1;
									defectCount++;
									break;
								}
							}

							if (defectCount < 7)
								continue;

							for (r = 12; r >= 4; r -= 4)
							{
								tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH + r;
								colorDiff = ColorSourceImage[tempAddress2 * 3 + globalPrintSelectedRGB] - selfValue;

								if (colorDiff > thresholdForPrintNeighbor)
								{
									bottomrightSW = 1;
									defectCount++;
									break;
								}
							}

							if (defectCount >= 8)
							{
								printSpotCount++;
								TempImage2[tempAddress] = 1;
							}
						}
					}
				}
			}

			if (ProcessingModeGlobal == FIRST_STUDY_MODE)
			{
				CurrentPrintPixelCnt = tempPrintPxCnt;
			}

			if (ProcessingModeGlobal == INSPECTION_MODE && DefectSW == 0)
			{
				if (printSpotCount > TabletGradeData.front_dirty_Size)
				{
					DefectSW = 1;
					DefectInformationWrite(DEFECT_FRONT_DIRTY, cameraIndex, 0, 0, 0, 0, printSpotCount);

#ifdef PC_SIM
					memset(LabelImage_Virtual, 0, sizeof(short) * MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
					for (i = stY; i <= edY; i++)
					{
						for (j = stX; j <= edX; j++)
						{
							tempAddress = MAX_IMAGE_WIDTH * i + j;
							if (TempImage2[tempAddress])
							{
								LabelImage_Virtual[tempAddress] = 0xFF;
								LabelImage_Virtual[tempAddress - 1] = 0xFF;
								LabelImage_Virtual[tempAddress + 1] = 0xFF;
								LabelImage_Virtual[tempAddress - MAX_IMAGE_WIDTH] = 0xFF;
								LabelImage_Virtual[tempAddress + MAX_IMAGE_WIDTH] = 0xFF;
							}
						}
					}
#endif
				}
			}

			int ImportantEraseState = 0;

			if (ProcessingModeGlobal == INSPECTION_MODE && DefectSW == 0)
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
				{
					ImportantEraseState = EraseCount;

					if (TabletGradeData.front_print_spread_Intensity != 20)
					{
						if (printSpreadCount > (TabletGradeData.front_print_spread_Intensity) * (TabletGradeData.front_print_spread_Intensity + 1))
						{
							DefectSW = 1;
							DefectInformationWrite(DEFECT_PRINT_SPREAD, cameraIndex, 0, 0, 0, 0, printSpreadCount);

#ifdef PC_SIM
							memset(LabelImage_Virtual, 0, sizeof(short) * MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
							for (i = stY; i <= edY; i++)
							{
								for (j = stX; j <= edX; j++)
								{
									tempAddress = MAX_IMAGE_WIDTH * i + j;
									if (!extensionPrintArea[tempAddress] && DarkPixelNeighborPrint[tempAddress])
									{
										LabelImage_Virtual[tempAddress] = 0xFF;
										LabelImage_Virtual[tempAddress - 1] = 0xFF;
										LabelImage_Virtual[tempAddress + 1] = 0xFF;
										LabelImage_Virtual[tempAddress - MAX_IMAGE_WIDTH] = 0xFF;
										LabelImage_Virtual[tempAddress + MAX_IMAGE_WIDTH] = 0xFF;
									}
								}
							}
#endif
						}
					}

					if (TabletGradeData.front_print_erase_Intensity != 20)
					{
						if (ImportantEraseState > TabletGradeData.front_print_erase_Intensity * (TabletGradeData.front_print_erase_Intensity + 1))
						{
							DefectSW = 1;
							DefectInformationWrite(DEFECT_PRINT_ERASE, cameraIndex, 0, 0, 0, 0, ImportantEraseState);

#ifdef PC_SIM
							memset(LabelImage_Virtual, 0, sizeof(short) * MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
							for (i = stY; i <= edY; i++)
							{
								for (j = stX; j <= edX; j++)
								{
									tempAddress = MAX_IMAGE_WIDTH * i + j;
									if (ErasePrintImage[tempAddress])
									{
										LabelImage_Virtual[tempAddress] = 0xFF;
										LabelImage_Virtual[tempAddress - 1] = 0xFF;
										LabelImage_Virtual[tempAddress + 1] = 0xFF;
										LabelImage_Virtual[tempAddress - MAX_IMAGE_WIDTH] = 0xFF;
										LabelImage_Virtual[tempAddress + MAX_IMAGE_WIDTH] = 0xFF;
									}
								}
							}
#endif
						}
					}
				}
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
				{
					ImportantEraseState = EraseCount;

					if (TabletGradeData.front_print_spread_Intensity != 20)
					{
						if (printSpreadCount > (TabletGradeData.front_print_spread_Intensity) * (TabletGradeData.front_print_spread_Intensity + 1))
						{
							DefectSW = 1;
							DefectInformationWrite(DEFECT_PRINT_SPREAD, cameraIndex, 0, 0, 0, 0, printSpreadCount);

#ifdef PC_SIM
							memset(LabelImage_Virtual, 0, sizeof(short) * MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
							for (i = stY; i <= edY; i++)
							{
								for (j = stX; j <= edX; j++)
								{
									tempAddress = MAX_IMAGE_WIDTH * i + j;
									if (!extensionPrintArea[tempAddress] && DarkPixelNeighborPrint[tempAddress])
									{
										LabelImage_Virtual[tempAddress] = 0xFF;
										LabelImage_Virtual[tempAddress - 1] = 0xFF;
										LabelImage_Virtual[tempAddress + 1] = 0xFF;
										LabelImage_Virtual[tempAddress - MAX_IMAGE_WIDTH] = 0xFF;
										LabelImage_Virtual[tempAddress + MAX_IMAGE_WIDTH] = 0xFF;
									}
								}
							}
#endif
						}
					}

					if (TabletGradeData.front_print_erase_Intensity != 20)
					{
						if (ImportantEraseState > TabletGradeData.front_print_erase_Intensity * (TabletGradeData.front_print_erase_Intensity + 1))
						{
							DefectSW = 1;
							DefectInformationWrite(DEFECT_PRINT_ERASE, cameraIndex, 0, 0, 0, 0, ImportantEraseState);

#ifdef PC_SIM
							memset(LabelImage_Virtual, 0, sizeof(short) * MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
							for (i = stY; i <= edY; i++)
							{
								for (j = stX; j <= edX; j++)
								{
									tempAddress = MAX_IMAGE_WIDTH * i + j;
									if (ErasePrintImage[tempAddress])
									{
										LabelImage_Virtual[tempAddress] = 0xFF;
										LabelImage_Virtual[tempAddress - 1] = 0xFF;
										LabelImage_Virtual[tempAddress + 1] = 0xFF;
										LabelImage_Virtual[tempAddress - MAX_IMAGE_WIDTH] = 0xFF;
										LabelImage_Virtual[tempAddress + MAX_IMAGE_WIDTH] = 0xFF;
									}
								}
							}
#endif
						}
					}
				}
			}

			for (i = stY; i <= edY; i++)
			{
				for (j = stX; j <= edX; j++)
				{
					tempAddress = i * MAX_IMAGE_WIDTH + j;
					if (InspectionArea[tempAddress] == PRINT_AREA)
					{
						for (y = i - 5; y <= i + 5; y++)
						{
							for (x = j - 5; x <= j + 5; x++)
							{
								if (InspectionArea[y * MAX_IMAGE_WIDTH + x] == NORMAL_INPECTION_AREA)
								{
									InspectionArea[y * MAX_IMAGE_WIDTH + x] = PRINT_NEIGHBOR_SHORT;
								}
							}
						}
					}
				}
			}

		} // endif Print
		else if (TabletCharacter.discriminationDisplay_kind != PRINT)
		{
			int tempLabelCount;
			tempLabelCount = TabletSetupData.printLabelCount[printNumber];
#ifdef PC_SIM
			memset(ExtractPrintData, 0, 640 * 480);
#endif
			if (TabletGradeData.DirtyDefectCheckSWInNeighborPrint)
			{
				int printHistogram[256];
				int avgPrintColor;

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

				int cosValue, sinValue;
				if (PrintMatchingResult.PrintRotationAngle >= 0)
				{
					sinValue = SinData[PrintMatchingResult.PrintRotationAngle % 720];
					cosValue = CosData[PrintMatchingResult.PrintRotationAngle % 720];
				}
				else
				{
					sinValue = -SinData[(-PrintMatchingResult.PrintRotationAngle) % 720];
					cosValue = CosData[(-PrintMatchingResult.PrintRotationAngle) % 720];
				}

				for (m = 0; m < printDataCount; m++)
				{
					tempX = position_printData[m][0];
					tempY = position_printData[m][1];

					rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX + PrintMatchingResult.PrintShiftX;
					rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY + PrintMatchingResult.PrintShiftY;

					tempAddress = MAX_IMAGE_WIDTH * rotateY + rotateX;

					printHistogram[DarkPixelNeighborPrint[tempAddress]]++;
				}

				maxValue = 0;
				for (m = 1; m < 256; m++)
				{
					if (maxValue < printHistogram[m])
					{
						maxValue = printHistogram[m];
						avgPrintColor = m;
					}
				}

				if (printDataCount < 1500)
					addStep = 2;
				else if (printDataCount < 3000)
					addStep = 4;
				else
					addStep = 6;

				int nMatchingAngle;
				int nShiftX, nShiftY;

				// 초정밀매칭
				maxValue = 0;
				for (r = PrintMatchingResult.PrintRotationAngle - 3; r <= PrintMatchingResult.PrintRotationAngle + 3; r++)
				{
					temp_r = r;
					if (temp_r >= 720)
					{
						temp_r -= 720;
					}
					else if (temp_r < 0)
					{
						temp_r += 720;
					}

					int cosValue, sinValue;
					if (temp_r >= 0)
					{
						sinValue = SinData[temp_r];
						cosValue = CosData[temp_r];
					}
					else
					{
						sinValue = -SinData[-temp_r];
						cosValue = CosData[-temp_r];
					}

					for (i = PrintMatchingResult.PrintShiftY - 3; i <= PrintMatchingResult.PrintShiftY + 3; i++)
					{
						for (j = PrintMatchingResult.PrintShiftX - 3; j <= PrintMatchingResult.PrintShiftX + 3; j++)
						{
							matchingValue = 0;
							for (m = 0; m < printDataCount; m += addStep)
							{
								tempX = position_printData[m][0];
								tempY = position_printData[m][1];

								rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX + j;
								rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY + i;

								tempAddress = MAX_IMAGE_WIDTH * rotateY + rotateX;

								if (avgPrintColor < DarkPixelNeighborPrint[tempAddress])
									matchingValue += avgPrintColor;
								else
									matchingValue += DarkPixelNeighborPrint[tempAddress];
							}

							if (maxValue < matchingValue)
							{
								maxValue = matchingValue;

								nMatchingAngle = temp_r;
								nShiftX = j;
								nShiftY = i;
							}
						}
					}
				}

				PrintMatchingResult.PrintRotationAngle = nMatchingAngle;
				PrintMatchingResult.PrintShiftX = nShiftX;
				PrintMatchingResult.PrintShiftY = nShiftY;
			}

			int cosValue, sinValue;
			if (PrintMatchingResult.PrintRotationAngle >= 0)
			{
				sinValue = SinData[PrintMatchingResult.PrintRotationAngle % 720];
				cosValue = CosData[PrintMatchingResult.PrintRotationAngle % 720];
			}
			else
			{
				sinValue = -SinData[(-PrintMatchingResult.PrintRotationAngle) % 720];
				cosValue = CosData[(-PrintMatchingResult.PrintRotationAngle) % 720];
			}

			int labelShiftMaxSize;
			int tempmaxValue;

			int EraseCount = 0;			
			int labelTempPrintDataCnt;
			short labelTempPrintData[4000][2];
			int subMaskSize = 2;
			int labelShiftX;
			int labelShiftY;

			for (n = 0; n < tempLabelCount; n++)
			{
				labelTempPrintDataCnt = TabletSetupData.printLabelDataCnt[printNumber][n];
				for (m = 0; m < labelTempPrintDataCnt; m++)
				{
					tempX = TabletSetupData.printLabelData[printNumber][n][m][0];
					tempY = TabletSetupData.printLabelData[printNumber][n][m][1];
					
					rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX + PrintMatchingResult.PrintShiftX;
					rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY + PrintMatchingResult.PrintShiftY;

					labelTempPrintData[m][0] = rotateX;
					labelTempPrintData[m][1] = rotateY;
				}

				if (TabletGradeData.DirtyDefectCheckSWInNeighborPrint)
				{
					labelShiftMaxSize = addStep = subMaskSize = 1;
				}
				else
				{
					labelShiftMaxSize = 3;
					addStep = 2;
				}

				tempmaxValue = -1000;
				for (i = -labelShiftMaxSize; i <= labelShiftMaxSize; i += addStep)
				{
					for (j = -labelShiftMaxSize; j <= labelShiftMaxSize; j += addStep)
					{
						matchingValue = 0;
						for (m = 0; m < labelTempPrintDataCnt; m += addStep)
						{
							tempX = labelTempPrintData[m][0] + j;
							tempY = labelTempPrintData[m][1] + i;
							matchingValue += DarkPixelNeighborPrint[tempY * MAX_IMAGE_WIDTH + tempX];
						}
						if (matchingValue > tempmaxValue)
						{
							tempmaxValue = matchingValue;
							labelShiftX = j;
							labelShiftY = i;
						}
					}
				}

				for (m = 0; m < labelTempPrintDataCnt; m++)
				{
					tempX = labelTempPrintData[m][0] + labelShiftX;
					tempY = labelTempPrintData[m][1] + labelShiftY;

					tempAddress = MAX_IMAGE_WIDTH * (tempY) + tempX;

					if (ShapeBinaryImage[tempAddress])
					{
						InspectionArea[tempAddress] = PRINT_AREA;
						PrintLabelAvgColor[n] += MeanOneColorImage[tempAddress];
#ifdef PC_SIM
						ExtractPrintData[tempAddress] = 255;
#endif
					}
				}

				PrintLabelAvgColor[n] /= labelTempPrintDataCnt;

				if (ProcessingModeGlobal == INSPECTION_MODE)
				{
					int EraseCheck;

					for (m = 0; m < labelTempPrintDataCnt; m++)
					{
						tempX = labelTempPrintData[m][0] + labelShiftX;
						tempY = labelTempPrintData[m][1] + labelShiftY;

						if (InspectionArea[MAX_IMAGE_WIDTH * tempY + tempX] == PRINT_AREA && !DarkPixelNeighborPrint[tempY * MAX_IMAGE_WIDTH + tempX] && ShapeBinaryImageForPrintArea[MAX_IMAGE_WIDTH * tempY + tempX])
						{
							// Print Area로 세팅되었으나 인쇄 예상영역이 존재하지 않는 경우
							EraseCheck = 1;
							for (i = tempY - 5; i <= tempY + 5; i++)
							{
								for (j = tempX - 5; j <= tempX + 5; j++)
								{
									if (InspectionArea[MAX_IMAGE_WIDTH * i + j] == PRINT_AREA && DarkPixelNeighborPrint[i * MAX_IMAGE_WIDTH + j] > 3)
									{
										EraseCheck = 0;
										break;
									}
								}
								if (EraseCheck == 0)
									break;
							}

							if (EraseCheck)
							{
								EraseCount++;
#ifdef PC_SIM
								ErasePrintImage[MAX_IMAGE_WIDTH * tempY + tempX] = 1;
#endif
							}
						}
					}
				}

				for (m = 0; m < labelTempPrintDataCnt; m++)
				{
					tempX = labelTempPrintData[m][0] + labelShiftX;
					tempY = labelTempPrintData[m][1] + labelShiftY;

					PrintLabelArea[MAX_IMAGE_WIDTH * tempY + tempX] |= ((n + 1) << 4);

					for (i = tempY - (subMaskSize + printAreaMask); i <= tempY + (subMaskSize + printAreaMask); i++)
					{
						for (j = tempX - (subMaskSize + printAreaMask); j <= tempX + (subMaskSize + printAreaMask); j++)
						{
							tempAddress = MAX_IMAGE_WIDTH * (i) + j;
							if (ShapeBinaryImage[tempAddress])
							{
								InspectionArea[tempAddress] = PRINT_AREA;
								PrintLabelArea[tempAddress] |= (n + 1);
							}
						}
					}
				}

				if (!TabletGradeData.DirtyDefectCheckSWInNeighborPrint)
				{
					for (m = 0; m < labelTempPrintDataCnt; m++)
					{
						tempX = labelTempPrintData[m][0] + labelShiftX;
						tempY = labelTempPrintData[m][1] + labelShiftY;
						for (i = tempY - (4 + printAreaMask); i <= tempY + (4 + printAreaMask); i++)
						{
							for (j = tempX - (4 + printAreaMask); j <= tempX + (4 + printAreaMask); j++)
							{
								if (InspectionArea[MAX_IMAGE_WIDTH * (i) + j] == NORMAL_INPECTION_AREA)
									InspectionArea[MAX_IMAGE_WIDTH * (i) + j] = PRINT_NEIGHBOR_SHORT;
							}
						}
					}
				}
			}

			int ImportantEraseState = EraseCount;

			if (TabletCharacter.discriminationDisplay_num == ONE_FACE) // ONE_FACE에 대해서만 학습한다. TWO_FACE의 경우에는 항상 인쇄나 각인이 있기 때문에 IsOrNotThreshold 학습을 할 필요가 없다.
			{
				if (ProcessingModeGlobal == STUDY_MODE)
				{
					if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
					{
						TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 = min(2990, maxValue / 100); // 안정정인 학습 데이타 누적을 위하여 범위를 줄여줌.
						TabletStudyData.Print2_IsOrNotThreshold_ForCamera1 = 0;
					}
					else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
					{
						TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 = min(2990, maxValue / 100);
						TabletStudyData.Print2_IsOrNotThreshold_ForCamera9 = 0;
					}
				}

				int EngraveMisMatchCount = 0;

				for (y = stY; y < edY; y++)
				{
					for (x = stX; x < edX; x++)
					{
						tempAddress = MAX_IMAGE_WIDTH * y + x;
						if (DarkPixelNeighborPrint[tempAddress] >= 4)
						{
							if (InspectionArea[tempAddress] != PRINT_AREA && InspectionArea[tempAddress] != PRINT_NEIGHBOR_SHORT) // PRINT_NEIGHBOR_LONG
							{
								EngraveMisMatchCount++;
							}
						}
					}
				}					

				if (ProcessingModeGlobal == STUDY_MODE)
				{
					if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
					{
						TabletStudyData.TabletEngraveMisMatchCount_Remaining_CAM1 = EngraveMisMatchCount;
						TabletStudyData.TabletEngraveMisMatchCount_Empty_CAM1 = EraseCount;
					}
					else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
					{
						TabletStudyData.TabletEngraveMisMatchCount_Remaining_CAM9 = EngraveMisMatchCount;
						TabletStudyData.TabletEngraveMisMatchCount_Empty_CAM9 = EraseCount;
					}
				}
			}

			if (ProcessingModeGlobal == INSPECTION_MODE)
			{
				if (TabletGradeData.front_print_erase_Intensity != 20)
				{
					if (ImportantEraseState > TabletGradeData.front_print_erase_Intensity * (TabletGradeData.front_print_erase_Intensity + 1))
					{
						DefectSW = 1;
						DefectInformationWrite(DEFECT_PRINT_ERASE, cameraIndex, 0, 0, 0, 0, ImportantEraseState);

#ifdef PC_SIM
						memset(LabelImage_Virtual, 0, sizeof(short) * MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
						for (i = stY; i <= edY; i++)
						{
							for (j = stX; j <= edX; j++)
							{
								tempAddress = MAX_IMAGE_WIDTH * i + j;
								if (ErasePrintImage[tempAddress])
								{
									LabelImage_Virtual[tempAddress] = 0xFF;
									LabelImage_Virtual[tempAddress - 1] = 0xFF;
									LabelImage_Virtual[tempAddress + 1] = 0xFF;
									LabelImage_Virtual[tempAddress - MAX_IMAGE_WIDTH] = 0xFF;
									LabelImage_Virtual[tempAddress + MAX_IMAGE_WIDTH] = 0xFF;
								}
							}
						}
#endif
					}
				}
			}

			// 인쇄 주변 외곽 영역 크기 결정 PRINT_NEIGHBOR_LONG, Default = 1
			if (!TabletGradeData.DirtyDefectCheckSWInNeighborPrint)
			{
				int cosValue, sinValue;
				if (PrintMatchingResult.PrintRotationAngle >= 0)
				{
					sinValue = SinData[PrintMatchingResult.PrintRotationAngle % 720];
					cosValue = CosData[PrintMatchingResult.PrintRotationAngle % 720];
				}
				else
				{
					sinValue = -SinData[(-PrintMatchingResult.PrintRotationAngle) % 720];
					cosValue = CosData[(-PrintMatchingResult.PrintRotationAngle) % 720];
				}

				for (m = 0; m < expansion_printDataCount; m++)
				{
					tempX = expansion_position_printData[m][0];
					tempY = expansion_position_printData[m][1];

					rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + constantShiftX + PrintMatchingResult.PrintShiftX;
					rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + constantShiftY + PrintMatchingResult.PrintShiftY;

					tempAddress = MAX_IMAGE_WIDTH * (rotateY) + rotateX;

					if (InspectionArea[tempAddress] == NORMAL_INPECTION_AREA)
						InspectionArea[tempAddress] = PRINT_NEIGHBOR_LONG;
					if (InspectionArea[tempAddress + 1] == NORMAL_INPECTION_AREA)
						InspectionArea[tempAddress + 1] = PRINT_NEIGHBOR_LONG;
					if (InspectionArea[tempAddress - 1] == NORMAL_INPECTION_AREA)
						InspectionArea[tempAddress - 1] = PRINT_NEIGHBOR_LONG;
					if (InspectionArea[tempAddress - MAX_IMAGE_WIDTH] == NORMAL_INPECTION_AREA)
						InspectionArea[tempAddress - MAX_IMAGE_WIDTH] = PRINT_NEIGHBOR_LONG;
					if (InspectionArea[tempAddress + MAX_IMAGE_WIDTH] == NORMAL_INPECTION_AREA)
						InspectionArea[tempAddress + MAX_IMAGE_WIDTH] = PRINT_NEIGHBOR_LONG;
				}
			}
		}
	}

}
//---------------------------------------------------------------------------
void PrintMatchingForLowRotationCase(int cameraIndex)
{
	int x, y, i, j;
	int r, m, n, k;
	
	int addStep;

	int printNumber;
	int printDataCount;
	
	int maxValue;

	int tempAddress;

	int matchingValue;

	int tempX, tempY;
	int rotateX, rotateY;

	int temp_r;

	int stX, edX, stY, edY;

	int shiftXByTotion;
	int shiftYByTotion;

	int printAreaMask;		

	int transForm_SmallPrintDataCount[4];
	int transForm_SmallPrintCoreDataCount[4];

	printAreaMask = TabletGradeData.front_unInspectionIntensity_ForPrint;

	stX = tabletAreaInfo[AREA_INFO_ST_X_ADDRESS];
	edX = tabletAreaInfo[AREA_INFO_END_X_ADDRESS];
	stY = tabletAreaInfo[AREA_INFO_ST_Y_ADDRESS];
	edY = tabletAreaInfo[AREA_INFO_END_Y_ADDRESS];

	if (stX < 10)
		stX = 10;
	if (edX > MAX_IMAGE_WIDTH - 10)
		edX = MAX_IMAGE_WIDTH - 10;
	if (stY < 10)
		stY = 10;
	if (edY > MAX_IMAGE_HEIGHT - 10)
		edY = MAX_IMAGE_HEIGHT - 10;

	if (TabletMatchingResult.TabletFrontShapeYTotion > 0)
		shiftXByTotion = ((TabletCharacter.height - TabletCharacter.middle_height) / 2 * SinData[TabletMatchingResult.TabletFrontShapeYTotion * 2]) / 1024;
	else
		shiftXByTotion = -((TabletCharacter.height - TabletCharacter.middle_height) / 2 * SinData[-TabletMatchingResult.TabletFrontShapeYTotion * 2]) / 1024;

	if (TabletMatchingResult.TabletFrontShapeXTotion > 0)
		shiftYByTotion = ((TabletCharacter.height - TabletCharacter.middle_height) / 2 * SinData[TabletMatchingResult.TabletFrontShapeXTotion * 2]) / 1024;
	else
		shiftYByTotion = -((TabletCharacter.height - TabletCharacter.middle_height) / 2 * SinData[-TabletMatchingResult.TabletFrontShapeXTotion * 2]) / 1024;

	// (m == 0) -> 1번 Data 정제 틀어짐에 맞추어 회전
	// (m == 1) -> 1번 Data 뒤집어 보이는 것 정제 틀어짐에 맞추어 회전
	// (m == 2) -> 2번 Data 정제 틀어짐에 맞추어 회전
	// (m == 3) -> 2번 Data 뒤집어 보이는 것 정제 틀어짐에 맞추어 회전
	for (n = 0; n < 4; n++)
	{
		if (n == 0)
		{
			transForm_SmallPrintDataCount[n] = SmallPrintData1Count;
			transForm_SmallPrintCoreDataCount[n] = SmallPrintCoreData1Count;

			int cosValue, sinValue;
			if (TabletMatchingResult.TabletRotationAngle >= 0)
			{
				sinValue = SinData[TabletMatchingResult.TabletRotationAngle % 720];
				cosValue = CosData[TabletMatchingResult.TabletRotationAngle % 720];
			}
			else
			{
				sinValue = -SinData[(-TabletMatchingResult.TabletRotationAngle) % 720];
				cosValue = CosData[(-TabletMatchingResult.TabletRotationAngle) % 720];
			}

			for (m = 0; m < transForm_SmallPrintCoreDataCount[n]; m++)
			{
				tempX = Position_SmallPrintCoreData1[m][0];
				tempY = Position_SmallPrintCoreData1[m][1];
				
				rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage;
				rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage;

				transForm_Position_SmallPrintCoreData[n][m][0] = rotateX;
				transForm_Position_SmallPrintCoreData[n][m][1] = rotateY;
			}
		}
		else if (n == 1)
		{
			transForm_SmallPrintDataCount[n] = SmallPrintData1Count;
			transForm_SmallPrintCoreDataCount[n] = SmallPrintCoreData1Count;

			int cosValue, sinValue;
			if (TabletMatchingResult.TabletRotationAngle + 360 >= 0)
			{
				sinValue = SinData[(TabletMatchingResult.TabletRotationAngle + 360) % 720];
				cosValue = CosData[(TabletMatchingResult.TabletRotationAngle + 360) % 720];
			}
			else
			{
				sinValue = -SinData[(-TabletMatchingResult.TabletRotationAngle - 360) % 720];
				cosValue = CosData[(-TabletMatchingResult.TabletRotationAngle - 360) % 720];
			}

			for (m = 0; m < transForm_SmallPrintCoreDataCount[n]; m++)
			{
				tempX = Position_SmallPrintCoreData1[m][0];
				tempY = Position_SmallPrintCoreData1[m][1];

				rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage;
				rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage;

				transForm_Position_SmallPrintCoreData[n][m][0] = rotateX;
				transForm_Position_SmallPrintCoreData[n][m][1] = rotateY;
			}
		}
		else if (n == 2)
		{
			transForm_SmallPrintDataCount[n] = SmallPrintData2Count;
			transForm_SmallPrintCoreDataCount[n] = SmallPrintCoreData2Count;

			int cosValue, sinValue;
			if (TabletMatchingResult.TabletRotationAngle >= 0)
			{
				sinValue = SinData[TabletMatchingResult.TabletRotationAngle % 720];
				cosValue = CosData[TabletMatchingResult.TabletRotationAngle % 720];
			}
			else
			{
				sinValue = -SinData[(-TabletMatchingResult.TabletRotationAngle) % 720];
				cosValue = CosData[(-TabletMatchingResult.TabletRotationAngle) % 720];
			}

			for (m = 0; m < transForm_SmallPrintCoreDataCount[n]; m++)
			{
				tempX = Position_SmallPrintCoreData2[m][0];
				tempY = Position_SmallPrintCoreData2[m][1];

				rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage;
				rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage;

				transForm_Position_SmallPrintCoreData[n][m][0] = rotateX;
				transForm_Position_SmallPrintCoreData[n][m][1] = rotateY;
			}
		}
		else if (n == 3)
		{
			transForm_SmallPrintDataCount[n] = SmallPrintData2Count;
			transForm_SmallPrintCoreDataCount[n] = SmallPrintCoreData2Count;

			int cosValue, sinValue;
			if (TabletMatchingResult.TabletRotationAngle + 360 >= 0)
			{
				sinValue = SinData[(TabletMatchingResult.TabletRotationAngle + 360) % 720];
				cosValue = CosData[(TabletMatchingResult.TabletRotationAngle + 360) % 720];
			}
			else
			{
				sinValue = -SinData[(-TabletMatchingResult.TabletRotationAngle - 360) % 720];
				cosValue = CosData[(-TabletMatchingResult.TabletRotationAngle - 360) % 720];
			}

			for (m = 0; m < transForm_SmallPrintCoreDataCount[n]; m++)
			{
				tempX = Position_SmallPrintCoreData2[m][0];
				tempY = Position_SmallPrintCoreData2[m][1];
				
				rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage;
				rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage;

				transForm_Position_SmallPrintCoreData[n][m][0] = rotateX;
				transForm_Position_SmallPrintCoreData[n][m][1] = rotateY;
			}
		}
	}

	if (shiftXByTotion >= 5)
		shiftXByTotion = 5;
	if (shiftXByTotion <= -5)
		shiftXByTotion = -5;
	if (shiftYByTotion >= 5)
		shiftYByTotion = 5;
	if (shiftYByTotion <= -5)
		shiftYByTotion = -5;

	int XshiftRange, YshiftRange;

	XshiftRange = 12;

	if (!TabletGradeData.ETC_ApplyTiltTabletAlgorithm) // 0306 Grade
		YshiftRange = 15;
	else
		YshiftRange = 20;

	addStep = 2;
	if (TabletCharacter.length > 12900 / 37)
	{
		XshiftRange = 21;
		YshiftRange = 24;
		addStep = 3;
	}	

	int startN;
	int endN;

	if (TabletCharacter.tabletColorN == ONECOLOR)
	{
		PrintMatchingResult.dataNumberWithMaxValue = 0;

		if (TabletCharacter.discriminationDisplay_num != TWO_FACE_DIFF)
		{
			startN = 0;
			endN = 2;
		}
		else
		{
			startN = 0;
			endN = 4;
		}
	}
	else
	{
		if (SelectedFace == FRONT_FACE_FOR_COLOR)
		{
			PrintMatchingResult.dataNumberWithMaxValue = 0;
			startN = 0;
			endN = 2;
		}
		else
		{
			PrintMatchingResult.dataNumberWithMaxValue = 2;
			startN = 2;
			endN = 4;
		}
	}

	int shiftXForCase2[4];
	int shiftYForCase2[4];
	int eraseCountForCase2[4];
	int exclusiveMatchingCountForCase2[4];
	int maxMatchingValueForCase2[4];

	memset(shiftXForCase2, 0, sizeof(int) * 4);
	memset(shiftYForCase2, 0, sizeof(int) * 4);
	memset(maxMatchingValueForCase2, 0, sizeof(int) * 4);

	unsigned char *tempPrintArea1;

	tempPrintArea1 = AdjustThreeD_Data;

	memset(tempPrintArea1, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

	// 이것은 PC기준 2ms 이상이 소요된다.
	for (n = startN; n < endN; n++)
	{
		maxValue = -1;
		for (i = -YshiftRange + shiftYByTotion; i <= YshiftRange + shiftYByTotion; i += addStep)
		{
			for (j = -XshiftRange + shiftXByTotion; j <= XshiftRange + shiftXByTotion; j += addStep)
			{
				matchingValue = 0;
				eraseCountForCase2[n] = 0;

				for (m = 0; m < transForm_SmallPrintCoreDataCount[n]; m++)
				{
					tempX = transForm_Position_SmallPrintCoreData[n][m][0] + j;
					tempY = transForm_Position_SmallPrintCoreData[n][m][1] + i;					
					if (DarkPixelNeighborPrint[tempY * MAX_IMAGE_WIDTH + tempX])
					{
						matchingValue += DarkPixelNeighborPrint[tempY * MAX_IMAGE_WIDTH + tempX];
					}
					else
					{
						eraseCountForCase2[n]++;
					}
				}

				if (transForm_SmallPrintCoreDataCount[n])
				{
					matchingValue = matchingValue * (transForm_SmallPrintCoreDataCount[n] - eraseCountForCase2[n]) / transForm_SmallPrintCoreDataCount[n];
				}

				if (matchingValue > maxValue)
				{
					maxValue = matchingValue;
					shiftXForCase2[n] = j;
					shiftYForCase2[n] = i;
					maxMatchingValueForCase2[n] = matchingValue;
				}
			}
		}

		for (m = 0; m < transForm_SmallPrintCoreDataCount[n]; m++)
		{
			tempX = transForm_Position_SmallPrintCoreData[n][m][0] + shiftXForCase2[n];
			tempY = transForm_Position_SmallPrintCoreData[n][m][1] + shiftYForCase2[n];

			for (j = tempY - 2; j <= tempY + 2; j++)
			{
				for (i = tempX - 2; i <= tempX + 2; i++)
				{
					tempAddress = MAX_IMAGE_WIDTH * j + i;
					tempPrintArea1[tempAddress] |= (1 << (n));
				}
			}
		}
	}

	memset(exclusiveMatchingCountForCase2, 0, sizeof(int) * 4);

	// 이것은 PC기준 0.5 미만이 소요된다.
	for (y = stY; y < edY; y++)
	{
		for (x = stX; x < edX; x++)
		{
			tempAddress = MAX_IMAGE_WIDTH * y + x;

#ifdef PC_SIM
			if ((tempPrintArea1[tempAddress] & 0x01) && DarkPixelNeighborPrint[tempAddress])
				tempPrintArea1[tempAddress] |= (1 << (4));
			if ((tempPrintArea1[tempAddress] & 0x02) && DarkPixelNeighborPrint[tempAddress])
				tempPrintArea1[tempAddress] |= (1 << (5));
			if ((tempPrintArea1[tempAddress] & 0x04) && DarkPixelNeighborPrint[tempAddress])
				tempPrintArea1[tempAddress] |= (1 << (6));
			if ((tempPrintArea1[tempAddress] & 0x08) && DarkPixelNeighborPrint[tempAddress])
				tempPrintArea1[tempAddress] |= (1 << (7));
#endif

			if (tempPrintArea1[tempAddress] & 0x0F)
			{
				if ((tempPrintArea1[tempAddress] & 0x0F) == 0x01 && DarkPixelNeighborPrint[tempAddress])
				{
					exclusiveMatchingCountForCase2[0]++;
				}

				if ((tempPrintArea1[tempAddress] & 0x0F) == 0x02 && DarkPixelNeighborPrint[tempAddress])
				{
					exclusiveMatchingCountForCase2[1]++;
				}

				if ((tempPrintArea1[tempAddress] & 0x0F) == 0x04 && DarkPixelNeighborPrint[tempAddress])
				{
					exclusiveMatchingCountForCase2[2]++;
				}

				if ((tempPrintArea1[tempAddress] & 0x0F) == 0x08 && DarkPixelNeighborPrint[tempAddress])
				{
					exclusiveMatchingCountForCase2[3]++;
				}
			}
		}
	}

	int tempShiftX, tempShiftY, tempRotate;

	maxValue = -1;
	for (n = startN; n < endN; n++)
	{
		if (transForm_SmallPrintDataCount[n] + transForm_SmallPrintCoreDataCount[n])
		{
			// 매칭율 점수는 높으면서 남는 점(exclusiveMatchingCountForCase2)의 비율이 높을수록 좋다.
			if (TabletCharacter.MarvelingTablet)
			{
				maxMatchingValueForCase2[n] = maxMatchingValueForCase2[n] * 1000 / (transForm_SmallPrintDataCount[n] + transForm_SmallPrintCoreDataCount[n]) * (transForm_SmallPrintDataCount[n] + transForm_SmallPrintCoreDataCount[n] + exclusiveMatchingCountForCase2[n] / 2) / (transForm_SmallPrintDataCount[n] + transForm_SmallPrintCoreDataCount[n]);
			}
			else
			{
				maxMatchingValueForCase2[n] = maxMatchingValueForCase2[n] * 1000 / (transForm_SmallPrintDataCount[n] + transForm_SmallPrintCoreDataCount[n]) * (transForm_SmallPrintDataCount[n] + transForm_SmallPrintCoreDataCount[n] + exclusiveMatchingCountForCase2[n] * 2) / (transForm_SmallPrintDataCount[n] + transForm_SmallPrintCoreDataCount[n]);
			}
		}

		if (maxValue < maxMatchingValueForCase2[n])
		{
			maxValue = maxMatchingValueForCase2[n];

			tempShiftX = shiftXForCase2[n];
			tempShiftY = shiftYForCase2[n];
			PrintMatchingResult.dataNumberWithMaxValue = n;
		}
	}

	//// 정밀하게 2차 매칭이 필요하다. shape의 각도를 정밀하게 구할 수 없으므로 .
	// 이것은 PC기준 0.5 미만이 소요된다.
	int tempmaxValue = -1;
	tempRotate = 0;	
	unsigned char *CorePrintWeight;	
	for (n = PrintMatchingResult.dataNumberWithMaxValue; n <= PrintMatchingResult.dataNumberWithMaxValue; n++)
	{			
		if (n < 2)
			CorePrintWeight = CorePrint1Weight;
		else
			CorePrintWeight = CorePrint2Weight;

		int cosValue, sinValue;
		for (i = tempShiftY - 4; i <= tempShiftY + 4; i += 2)
		{
			for (j = tempShiftX - 6; j <= tempShiftX + 6; j += 2)
			{
				for (r = -4; r <= 4; r += 2)
				{
					matchingValue = 0;
					temp_r = r;

					if (temp_r >= 0)
					{
						sinValue = SinData[temp_r];
						cosValue = CosData[temp_r];
					}
					else
					{
						sinValue = -SinData[-temp_r];
						cosValue = CosData[-temp_r];
					}

					for (m = 0; m < transForm_SmallPrintCoreDataCount[n]; m += LOW_ROTATION_PRINT_ADD_M)
					{
						tempX = transForm_Position_SmallPrintCoreData[n][m][0];
						tempY = transForm_Position_SmallPrintCoreData[n][m][1];

						rotateX = ((tempX - TabletMatchingResult.AdjustCenterXInImage) * cosValue - (tempY - TabletMatchingResult.AdjustCenterYInImage) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage + j;
						rotateY = ((tempX - TabletMatchingResult.AdjustCenterXInImage) * sinValue + (tempY - TabletMatchingResult.AdjustCenterYInImage) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage + i;

						matchingValue += (DarkPixelNeighborPrint[rotateY * MAX_IMAGE_WIDTH + rotateX] * CorePrintWeight[m]);
					}

					if (transForm_SmallPrintDataCount[n] + transForm_SmallPrintCoreDataCount[n] &&
						(matchingValue * 1000 > tempmaxValue * (transForm_SmallPrintDataCount[n] + transForm_SmallPrintCoreDataCount[n])))
					{
						tempmaxValue = matchingValue * 1000 / (transForm_SmallPrintDataCount[n] + transForm_SmallPrintCoreDataCount[n]);
						PrintMatchingResult.PrintShiftX = j;
						PrintMatchingResult.PrintShiftY = i;
						tempRotate = r;
					}
				}
			}
		}
	}

	int printIsOrNotThreshold;
	int tempPrintIsOrNotThreshold;

	printIsOrNotThreshold = 15000;

	if (ProcessingModeGlobal == STUDY_MODE)
	{
		if (TabletCharacter.discriminationDisplay_num == ONE_FACE || TabletCharacter.discriminationDisplay_num == TWO_FACE_SAME)
		{
			if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
			{
				TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 = tempmaxValue / 100;
				TabletStudyData.Print2_IsOrNotThreshold_ForCamera1 = 0;
			}
			else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
			{
				TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 = tempmaxValue / 100;
				TabletStudyData.Print2_IsOrNotThreshold_ForCamera9 = 0;
			}
		}
		if (TabletCharacter.discriminationDisplay_num == TWO_FACE_DIFF)
		{
			if (PrintMatchingResult.dataNumberWithMaxValue < 2)
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 = tempmaxValue / 100;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera1 = 0;
				}
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 = tempmaxValue / 100;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera9 = 0;
				}
			}
			else
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 = 0;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera1 = tempmaxValue / 100;
				}
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 = 0;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera9 = tempmaxValue / 100;
				}
			}
		}
	}
	else if (ProcessingModeGlobal == INSPECTION_MODE)
	{
		if (TabletCharacter.discriminationDisplay_num == ONE_FACE || TabletCharacter.discriminationDisplay_num == TWO_FACE_SAME)
		{
			if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
			{
				tempPrintIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 + TabletGradeData.EngraveMatchingOrNotValue * 4;
				if (tempPrintIsOrNotThreshold < 0)
					tempPrintIsOrNotThreshold = 0;

				printIsOrNotThreshold = tempPrintIsOrNotThreshold * 70;
			}
			else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
			{
				tempPrintIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 + TabletGradeData.EngraveMatchingOrNotValue * 4;
				if (tempPrintIsOrNotThreshold < 0)
					tempPrintIsOrNotThreshold = 0;

				printIsOrNotThreshold = tempPrintIsOrNotThreshold * 70;
			}
		}
		if (TabletCharacter.discriminationDisplay_num == TWO_FACE_DIFF)
		{
			if (PrintMatchingResult.dataNumberWithMaxValue < 2)
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera1 * 100;
				}
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera9 * 100;
				}
			}
			else
			{
				if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print2_IsOrNotThreshold_ForCamera1 * 100;
				}
				else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print2_IsOrNotThreshold_ForCamera9 * 100;
				}
			}
		}
	}

	if (TabletCharacter.discriminationDisplay_num == ONE_FACE && tempmaxValue < printIsOrNotThreshold)
		PrintMatchingResult.dataNumberWithMaxValue = 2;

	if (PrintMatchingResult.dataNumberWithMaxValue < 2)
	{
		printNumber = 0;
	}
	else
	{
		printNumber = 1;
	}

	int TabletDirection;
	if (PrintMatchingResult.dataNumberWithMaxValue == 1 || PrintMatchingResult.dataNumberWithMaxValue == 3)
	{
		TabletDirection = 360;
	}
	else
	{
		TabletDirection = 0;
	}

	PrintMatchingResult.PrintRotationAngle = tempRotate;

	if (TabletGradeData.DirtyDefectCheckSWInNeighborPrint) // 이것은 보통은 off이지만 실행시 PC에서 9.8ms나 소요된다.
	{
		// 3차 정밀 매칭
		int printHistogram[256];
		int avgPrintColor;

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

		if (printNumber == 0)
		{
			printDataCount = TabletSetupData.printData1Count;
			memcpy(tempPosition_printData, TabletSetupData.position_printData1, sizeof(short) * PRINT_DATA_SIZE * 2);
		}
		else
		{
			printDataCount = TabletSetupData.printData2Count;
			memcpy(tempPosition_printData, TabletSetupData.position_printData2, sizeof(short) * PRINT_DATA_SIZE * 2);
		}

		r = TabletMatchingResult.TabletRotationAngle + tempRotate + TabletDirection;

		int cosValue, sinValue;
		if (r >= 0)
		{
			sinValue = SinData[r % 720];
			cosValue = CosData[r % 720];
		}
		else
		{
			sinValue = -SinData[(-r) % 720];
			cosValue = CosData[(-r) % 720];
		}

		for (m = 0; m < printDataCount; m++)
		{
			tempX = tempPosition_printData[m][0];
			tempY = tempPosition_printData[m][1];

			rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage + PrintMatchingResult.PrintShiftX;
			rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage + PrintMatchingResult.PrintShiftY;

			tempAddress = MAX_IMAGE_WIDTH * rotateY + rotateX;

			printHistogram[DarkPixelNeighborPrint[tempAddress]]++;
		}

		maxValue = 0;
		for (m = 1; m < 256; m++)
		{
			if (maxValue < printHistogram[m])
			{
				maxValue = printHistogram[m];
				avgPrintColor = m;
			}
		}

		if (TabletSetupData.printData1Count < 1500)
			addStep = 1;
		else if (TabletSetupData.printData1Count < 3000)
			addStep = 2;
		else
			addStep = 3;

		int nMatchingAngle;
		int nShiftX, nShiftY;

		maxValue = 0;
		for (r = TabletMatchingResult.TabletRotationAngle + tempRotate + TabletDirection - 3; r <= TabletMatchingResult.TabletRotationAngle + tempRotate + TabletDirection + 3; r++)
		{
			int cosValue, sinValue;
			if (r >= 0)
			{
				sinValue = SinData[r % 720];
				cosValue = CosData[r % 720];
			}
			else
			{
				sinValue = -SinData[(-r) % 720];
				cosValue = CosData[(-r) % 720];
			}

			for (i = PrintMatchingResult.PrintShiftY - 3; i <= PrintMatchingResult.PrintShiftY + 3; i++)
			{
				for (j = PrintMatchingResult.PrintShiftX - 3; j <= PrintMatchingResult.PrintShiftX + 3; j++)
				{
					matchingValue = 0;
					for (m = 0; m < printDataCount; m += addStep)
					{
						tempX = tempPosition_printData[m][0];
						tempY = tempPosition_printData[m][1];

						rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage + j;
						rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage + i;

						tempAddress = MAX_IMAGE_WIDTH * rotateY + rotateX;

						if (avgPrintColor < DarkPixelNeighborPrint[tempAddress])
							matchingValue += avgPrintColor;
						else
							matchingValue += DarkPixelNeighborPrint[tempAddress];
					}

					if (maxValue < matchingValue)
					{
						maxValue = matchingValue;

						nMatchingAngle = r;
						nShiftX = j;
						nShiftY = i;
					}
				}
			}
		}

		tempRotate = nMatchingAngle - TabletMatchingResult.TabletRotationAngle - TabletDirection;
		PrintMatchingResult.PrintShiftX = nShiftX;
		PrintMatchingResult.PrintShiftY = nShiftY;
	}

	int cosValue, sinValue;
	if (TabletMatchingResult.TabletRotationAngle + tempRotate >= 0)
	{
		sinValue = SinData[(TabletMatchingResult.TabletRotationAngle + tempRotate) % 720];
		cosValue = CosData[(TabletMatchingResult.TabletRotationAngle + tempRotate) % 720];
	}
	else
	{
		sinValue = -SinData[(-TabletMatchingResult.TabletRotationAngle - tempRotate) % 720];
		cosValue = CosData[(-TabletMatchingResult.TabletRotationAngle - tempRotate) % 720];
	}

	int labelShiftMaxSize;
	int tempLabelCount;

	tempLabelCount = TabletSetupData.printLabelCount[printNumber];
	int labelTempPrintDataCnt;
	short labelTempPrintData[4000][2];

	int subMaskSize = 2;
	int labelShiftX;
	int labelShiftY;
	int eraseCheckRange;
	int EraseCount = 0;

	// 각 글자를 매칭하여 영역 지정. PC기준으로 3.6ms 정도 소요된다.
	for (n = 0; n < tempLabelCount; n++)
	{
		labelTempPrintDataCnt = TabletSetupData.printLabelDataCnt[printNumber][n];

		for (m = 0; m < labelTempPrintDataCnt; m++)
		{
			if ((PrintMatchingResult.dataNumberWithMaxValue & 1) == 0)
			{
				tempX = TabletSetupData.printLabelData[printNumber][n][m][0];
				tempY = TabletSetupData.printLabelData[printNumber][n][m][1];
			}
			else
			{
				tempX = MAX_IMAGE_WIDTH - TabletSetupData.printLabelData[printNumber][n][m][0];
				tempY = MAX_IMAGE_HEIGHT - TabletSetupData.printLabelData[printNumber][n][m][1];
			}
			rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage + PrintMatchingResult.PrintShiftX;
			rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage + PrintMatchingResult.PrintShiftY;
			labelTempPrintData[m][0] = rotateX;
			labelTempPrintData[m][1] = rotateY;
		}

		if (TabletGradeData.DirtyDefectCheckSWInNeighborPrint)
		{
			eraseCheckRange = 3;
			labelShiftMaxSize = 1;
			addStep = 1;
			subMaskSize = 1;
		}
		else
		{
			eraseCheckRange = 5;
			labelShiftMaxSize = 7;
			addStep = 2;
		}

		tempmaxValue = -1000;
		for (i = -labelShiftMaxSize; i <= labelShiftMaxSize; i += addStep)
		{
			for (j = -labelShiftMaxSize; j <= labelShiftMaxSize; j += addStep)
			{
				matchingValue = 0;
				for (m = 0; m < labelTempPrintDataCnt; m += addStep)
				{
					tempX = labelTempPrintData[m][0] + j;
					tempY = labelTempPrintData[m][1] + i;
					matchingValue += DarkPixelNeighborPrint[tempY * MAX_IMAGE_WIDTH + tempX];
				}
				if (matchingValue > tempmaxValue)
				{
					tempmaxValue = matchingValue;
					labelShiftX = j;
					labelShiftY = i;
				}
			}
		}

#ifdef PC_SIM
		memset(ExtractPrintData, 0, 640 * 480);
#endif

		int printLabelAvgColor = 0;
		for (m = 0; m < labelTempPrintDataCnt; m++)
		{
			tempX = labelTempPrintData[m][0] + labelShiftX;
			tempY = labelTempPrintData[m][1] + labelShiftY;

			tempAddress = MAX_IMAGE_WIDTH * (tempY) + tempX;

			if (ShapeBinaryImage[tempAddress])
			{
				PrintLabelAvgColor[n] += MeanOneColorImage[tempAddress];
				printLabelAvgColor += DarkPixelNeighborPrint[tempAddress];
#ifdef PC_SIM
				ExtractPrintData[tempAddress] = 255;
#endif
			}
		}

		PrintLabelAvgColor[n] /= labelTempPrintDataCnt;
		printLabelAvgColor /= labelTempPrintDataCnt;

		int EraseCheck;		

		for (m = 0; m < labelTempPrintDataCnt; m++)
		{
			tempX = labelTempPrintData[m][0] + labelShiftX;
			tempY = labelTempPrintData[m][1] + labelShiftY;

			if (ProcessingModeGlobal == INSPECTION_MODE && ShapeBinaryImageForPrintArea[MAX_IMAGE_WIDTH * tempY + tempX])
			{
				EraseCheck = 1;
				for (i = tempY - eraseCheckRange; i <= tempY + eraseCheckRange; i++)
				{
					for (j = tempX - eraseCheckRange; j <= tempX + eraseCheckRange; j++)
					{
						if (DarkPixelNeighborPrint[i * MAX_IMAGE_WIDTH + j] >= 4)
						{
							EraseCheck = 0;
							break;
						}
					}
					if (EraseCheck == 0)
						break;
				}

				if (EraseCheck)
				{
					EraseCount++;
#ifdef PC_SIM
					ErasePrintImage[MAX_IMAGE_WIDTH * tempY + tempX] = 1;
#endif
				}
			}

			PrintLabelArea[MAX_IMAGE_WIDTH * tempY + tempX] |= ((n + 1) << 4);

			for (i = tempY - (subMaskSize + printAreaMask); i <= tempY + (subMaskSize + printAreaMask); i++)
			{
				for (j = tempX - (subMaskSize + printAreaMask); j <= tempX + (subMaskSize + printAreaMask); j++)
				{
					tempAddress = MAX_IMAGE_WIDTH * (i) + j;
					if (ShapeBinaryImage[tempAddress])
					{
						InspectionArea[tempAddress] = PRINT_AREA;
						PrintLabelArea[tempAddress] |= (n + 1);
					}
				}
			}
		}

		if (!TabletGradeData.DirtyDefectCheckSWInNeighborPrint)
		{
			for (m = 0; m < labelTempPrintDataCnt; m++)
			{
				tempX = labelTempPrintData[m][0] + labelShiftX;
				tempY = labelTempPrintData[m][1] + labelShiftY;
				for (i = tempY - (4 + printAreaMask); i <= tempY + (4 + printAreaMask); i++)
				{
					for (j = tempX - (4 + printAreaMask); j <= tempX + (4 + printAreaMask); j++)
					{
						if (InspectionArea[MAX_IMAGE_WIDTH * (i) + j] == NORMAL_INPECTION_AREA)
							InspectionArea[MAX_IMAGE_WIDTH * (i) + j] = PRINT_NEIGHBOR_SHORT;
					}
				}
			}
		}
	}

	// 이제 글자 매칭 및 영역 지정이 완료되었다.

	if (tempLabelCount != 0)
	{
		int ImportantEraseState = EraseCount;

		if (ProcessingModeGlobal == INSPECTION_MODE)
		{
			if (TabletGradeData.front_print_erase_Intensity != 20)
			{
				if (ImportantEraseState > TabletGradeData.front_print_erase_Intensity * (TabletGradeData.front_print_erase_Intensity + 1))
				{
					DefectSW = 1;
					DefectInformationWrite(DEFECT_PRINT_ERASE, cameraIndex, 0, 0, 0, 0, ImportantEraseState);

#ifdef PC_SIM
					memset(LabelImage_Virtual, 0, sizeof(short) * MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
					for (i = stY; i <= edY; i++)
					{
						for (j = stX; j <= edX; j++)
						{
							tempAddress = MAX_IMAGE_WIDTH * i + j;
							if (ErasePrintImage[tempAddress])
							{
								LabelImage_Virtual[tempAddress] = 0xFF;
								LabelImage_Virtual[tempAddress - 1] = 0xFF;
								LabelImage_Virtual[tempAddress + 1] = 0xFF;
								LabelImage_Virtual[tempAddress - MAX_IMAGE_WIDTH] = 0xFF;
								LabelImage_Virtual[tempAddress + MAX_IMAGE_WIDTH] = 0xFF;
							}
						}
					}
#endif
				}
			}
		}
	}

	// 이하의 내용은 체크가 true가 되어 실행되어도 0.1ms 정도 밖에 소요되지 않는다.
	if (!TabletGradeData.DirtyDefectCheckSWInNeighborPrint)
	{
		if (PrintMatchingResult.dataNumberWithMaxValue == 0)
		{
			if (TabletMatchingResult.TabletRotationAngle + tempRotate >= 0)
			{
				sinValue = SinData[(TabletMatchingResult.TabletRotationAngle + tempRotate) % 720];
				cosValue = CosData[(TabletMatchingResult.TabletRotationAngle + tempRotate) % 720];
			}
			else
			{
				sinValue = -SinData[(-TabletMatchingResult.TabletRotationAngle - tempRotate) % 720];
				cosValue = CosData[(-TabletMatchingResult.TabletRotationAngle - tempRotate) % 720];
			}

			for (m = 0; m < TabletSetupData.expansion_printData1Count; m++)
			{
				tempX = TabletSetupData.expansion_position_printData1[m][0];
				tempY = TabletSetupData.expansion_position_printData1[m][1];
				
				rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage + PrintMatchingResult.PrintShiftX;
				rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage + PrintMatchingResult.PrintShiftY;

				tempAddress = MAX_IMAGE_WIDTH * (rotateY) + rotateX;
				if (InspectionArea[tempAddress] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress + 1] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress + 1] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress - 1] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress - 1] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress + MAX_IMAGE_WIDTH] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress + MAX_IMAGE_WIDTH] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress - MAX_IMAGE_WIDTH] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress - MAX_IMAGE_WIDTH] = PRINT_NEIGHBOR_LONG;
			}
		}
		else if (PrintMatchingResult.dataNumberWithMaxValue == 1)
		{
			if (TabletMatchingResult.TabletRotationAngle + 360 + tempRotate >= 0)
			{
				sinValue = SinData[(TabletMatchingResult.TabletRotationAngle + 360 + tempRotate) % 720];
				cosValue = CosData[(TabletMatchingResult.TabletRotationAngle + 360 + tempRotate) % 720];
			}
			else
			{
				sinValue = -SinData[(-TabletMatchingResult.TabletRotationAngle - 360 - tempRotate) % 720];
				cosValue = CosData[(-TabletMatchingResult.TabletRotationAngle - 360 - tempRotate) % 720];
			}

			for (m = 0; m < TabletSetupData.expansion_printData1Count; m++)
			{
				tempX = TabletSetupData.expansion_position_printData1[m][0];
				tempY = TabletSetupData.expansion_position_printData1[m][1];
				
				rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage + PrintMatchingResult.PrintShiftX;
				rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage + PrintMatchingResult.PrintShiftY;

				tempAddress = MAX_IMAGE_WIDTH * (rotateY) + rotateX;
				if (InspectionArea[tempAddress] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress + 1] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress + 1] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress - 1] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress - 1] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress + MAX_IMAGE_WIDTH] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress + MAX_IMAGE_WIDTH] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress - MAX_IMAGE_WIDTH] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress - MAX_IMAGE_WIDTH] = PRINT_NEIGHBOR_LONG;
			}
		}
		else if (PrintMatchingResult.dataNumberWithMaxValue == 2)
		{
			if (TabletMatchingResult.TabletRotationAngle + tempRotate >= 0)
			{
				sinValue = SinData[(TabletMatchingResult.TabletRotationAngle + tempRotate) % 720];
				cosValue = CosData[(TabletMatchingResult.TabletRotationAngle + tempRotate) % 720];
			}
			else
			{
				sinValue = -SinData[(-TabletMatchingResult.TabletRotationAngle - tempRotate) % 720];
				cosValue = CosData[(-TabletMatchingResult.TabletRotationAngle - tempRotate) % 720];
			}

			for (m = 0; m < TabletSetupData.expansion_printData2Count; m++)
			{
				tempX = TabletSetupData.expansion_position_printData2[m][0];
				tempY = TabletSetupData.expansion_position_printData2[m][1];
				
				rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage + PrintMatchingResult.PrintShiftX;
				rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage + PrintMatchingResult.PrintShiftY;

				tempAddress = MAX_IMAGE_WIDTH * (rotateY) + rotateX;
				if (InspectionArea[tempAddress] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress + 1] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress + 1] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress - 1] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress - 1] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress + MAX_IMAGE_WIDTH] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress + MAX_IMAGE_WIDTH] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress - MAX_IMAGE_WIDTH] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress - MAX_IMAGE_WIDTH] = PRINT_NEIGHBOR_LONG;
			}
		}
		else if (PrintMatchingResult.dataNumberWithMaxValue == 3)
		{
			if (TabletMatchingResult.TabletRotationAngle + 360 + tempRotate >= 0)
			{
				sinValue = SinData[(TabletMatchingResult.TabletRotationAngle + 360 + tempRotate) % 720];
				cosValue = CosData[(TabletMatchingResult.TabletRotationAngle + 360 + tempRotate) % 720];
			}
			else
			{
				sinValue = -SinData[(-TabletMatchingResult.TabletRotationAngle - 360 - tempRotate) % 720];
				cosValue = CosData[(-TabletMatchingResult.TabletRotationAngle - 360 - tempRotate) % 720];
			}

			for (m = 0; m < TabletSetupData.expansion_printData2Count; m++)
			{
				tempX = TabletSetupData.expansion_position_printData2[m][0];
				tempY = TabletSetupData.expansion_position_printData2[m][1];
				
				rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage + PrintMatchingResult.PrintShiftX;
				rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage + PrintMatchingResult.PrintShiftY;

				tempAddress = MAX_IMAGE_WIDTH * (rotateY) + rotateX;
				if (InspectionArea[tempAddress] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress + 1] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress + 1] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress - 1] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress - 1] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress + MAX_IMAGE_WIDTH] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress + MAX_IMAGE_WIDTH] = PRINT_NEIGHBOR_LONG;
				if (InspectionArea[tempAddress - MAX_IMAGE_WIDTH] == NORMAL_INPECTION_AREA)
					InspectionArea[tempAddress - MAX_IMAGE_WIDTH] = PRINT_NEIGHBOR_LONG;
			}
		}
	}
}
//---------------------------------------------------------------------------
void ExtractFrontFaceSplitLine(int cameraIndex)
{
	// 2020-01-30
	// Q사 요청으로 인쇄정+할선 케이스에 대한 작업 진행
	// 할선위에 인쇄가 찍힌경우는 배제한다
	// 할선과 인쇄 영역이 명확하게 분리 되어있어야 가능
	int x, y;
	int st_x, end_x, st_y, end_y;
	int space;
	int tempAddress;
	int r;
	int selfValue;
	int darkPxielThreshold;
	int defectCheck;
	int colorDiff;
	int tempAddress2;
	int areaValue;
	int searchRange;
	int topSW, bottomSW, leftSW, rightSW, topleftSW, toprightSW, bottomleftSW, bottomrightSW;
	int maxcolorDiff;
	int colorDiffSum;

	space = 10;

	st_x = -(space + TabletCharacter.length / 2) + (TabletMatchingResult.AdjustCenterXInImage);
	end_x = (TabletCharacter.length / 2 + space) + (TabletMatchingResult.AdjustCenterXInImage);
	st_y = -(space + TabletCharacter.width / 2) + (TabletMatchingResult.AdjustCenterYInImage);
	end_y = (TabletCharacter.width / 2 + space) + (TabletMatchingResult.AdjustCenterYInImage);

	if (st_x < TabletSetupData.ImageCutStartX[cameraIndex - 1])
		st_x = TabletSetupData.ImageCutStartX[cameraIndex - 1];
	if (end_x > TabletSetupData.ImageCutEndX[cameraIndex - 1])
		end_x = TabletSetupData.ImageCutEndX[cameraIndex - 1];
	if (st_y < TabletSetupData.ImageCutStartY[cameraIndex - 1])
		st_y = TabletSetupData.ImageCutStartY[cameraIndex - 1];
	if (end_y > TabletSetupData.ImageCutEndY[cameraIndex - 1])
		end_y = TabletSetupData.ImageCutEndY[cameraIndex - 1];

	memset(ExtractedSplitLineImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

	searchRange = 12;
	darkPxielThreshold = 4;
	for (y = st_y; y < end_y; y++)
	{
		for (x = st_x; x < end_x; x++)
		{
			tempAddress = y * MAX_IMAGE_WIDTH + x;

			areaValue = InspectionArea[tempAddress];

			if (ShapeBinaryImage[tempAddress] && areaValue != PRINT_AREA)
			{
				selfValue = OneColorImage[tempAddress];
				defectCheck = 0;

				colorDiffSum = 0;
				topSW = bottomSW = leftSW = rightSW = topleftSW = toprightSW = bottomleftSW = bottomrightSW = 0;

				maxcolorDiff = 0;
				for (r = searchRange; r >= 4; r -= 4)
				{
					tempAddress2 = tempAddress + r;

					if (ShapeBinaryImage[tempAddress2])
					{
						colorDiff = OneColorImage[tempAddress2] - selfValue;

						if (colorDiff > darkPxielThreshold)
						{
							rightSW = 1;

							if (maxcolorDiff < colorDiff)
								maxcolorDiff = colorDiff;
						}
					}
				}

				if (rightSW)
				{
					colorDiffSum += maxcolorDiff;
					defectCheck++;
				}

				maxcolorDiff = 0;
				for (r = searchRange; r >= 4; r -= 4)
				{
					tempAddress2 = tempAddress - r;

					if (ShapeBinaryImage[tempAddress2])
					{
						colorDiff = OneColorImage[tempAddress2] - selfValue;

						if (colorDiff > darkPxielThreshold)
						{
							leftSW = 1;

							if (maxcolorDiff < colorDiff)
								maxcolorDiff = colorDiff;
						}
					}
				}

				if (leftSW)
				{
					colorDiffSum += maxcolorDiff;
					defectCheck++;
				}

				maxcolorDiff = 0;
				for (r = searchRange; r >= 4; r -= 4)
				{
					tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH;

					if (ShapeBinaryImage[tempAddress2])
					{
						colorDiff = OneColorImage[tempAddress2] - selfValue;

						if (colorDiff > darkPxielThreshold)
						{
							topSW = 1;

							if (maxcolorDiff < colorDiff)
								maxcolorDiff = colorDiff;
						}
					}
				}

				if (topSW)
				{
					colorDiffSum += maxcolorDiff;
					defectCheck++;
				}

				maxcolorDiff = 0;
				for (r = searchRange; r >= 4; r -= 4)
				{
					tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH;

					if (ShapeBinaryImage[tempAddress2])
					{
						colorDiff = OneColorImage[tempAddress2] - selfValue;

						if (colorDiff > darkPxielThreshold)
						{
							bottomSW = 1;

							if (maxcolorDiff < colorDiff)
								maxcolorDiff = colorDiff;
						}
					}
				}

				if (bottomSW)
				{
					colorDiffSum += maxcolorDiff;
					defectCheck++;
				}

				maxcolorDiff = 0;
				for (r = searchRange; r >= 4; r -= 4)
				{
					tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH - r;

					if (ShapeBinaryImage[tempAddress2])
					{
						colorDiff = OneColorImage[tempAddress2] - selfValue;

						if (colorDiff > darkPxielThreshold)
						{
							topleftSW = 1;

							if (maxcolorDiff < colorDiff)
								maxcolorDiff = colorDiff;
						}
					}
				}

				if (topleftSW)
				{
					colorDiffSum += maxcolorDiff;
					defectCheck++;
				}

				if (defectCheck < 1)
					continue;

				maxcolorDiff = 0;
				for (r = searchRange; r >= 4; r -= 4)
				{
					tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH + r;

					if (ShapeBinaryImage[tempAddress2])
					{
						colorDiff = OneColorImage[tempAddress2] - selfValue;

						if (colorDiff > darkPxielThreshold)
						{
							toprightSW = 1;

							if (maxcolorDiff < colorDiff)
								maxcolorDiff = colorDiff;
						}
					}
				}

				if (toprightSW)
				{
					colorDiffSum += maxcolorDiff;
					defectCheck++;
				}

				if (defectCheck < 2)
					continue;

				maxcolorDiff = 0;
				for (r = searchRange; r >= 4; r -= 4)
				{
					tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH - r;

					if (ShapeBinaryImage[tempAddress2])
					{
						colorDiff = OneColorImage[tempAddress2] - selfValue;

						if (colorDiff > darkPxielThreshold)
						{
							bottomleftSW = 1;

							if (maxcolorDiff < colorDiff)
								maxcolorDiff = colorDiff;
						}
					}
				}

				if (bottomleftSW)
				{
					colorDiffSum += maxcolorDiff;
					defectCheck++;
				}

				if (defectCheck < 3)
					continue;

				maxcolorDiff = 0;
				for (r = searchRange; r >= 4; r -= 4)
				{
					tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH + r;

					if (ShapeBinaryImage[tempAddress2])
					{
						colorDiff = OneColorImage[tempAddress2] - selfValue;

						if (colorDiff > darkPxielThreshold)
						{
							bottomrightSW = 1;

							if (maxcolorDiff < colorDiff)
								maxcolorDiff = colorDiff;
						}
					}
				}

				if (bottomrightSW)
				{
					colorDiffSum += maxcolorDiff;
					defectCheck++;
				}

				if (defectCheck >= 4 &&
					((topSW && bottomSW) ||
						(leftSW && rightSW) ||
						(topleftSW && bottomrightSW) ||
						(toprightSW && bottomleftSW)))						
				{
					colorDiffSum /= defectCheck;

					ExtractedSplitLineImage[tempAddress] = colorDiffSum;
				}
			}
		}
	}
}
//---------------------------------------------------------------------------
void FrontFaceSplitLineMatching(int cameraIndex)
{
	int startX, endX, startY, endY;
	int step;
	int printMatchingRangeX;
	int printMatchingRangeAngle;
	int constantShiftAddress;
	int matchingValueArray[50];
	int maxValue;
	int r, m, i, j;
	int tr;
	int tempAddress;
	int tempRotateAngleArray;
	int temp_r;
	int matchingShiftX, matchingShiftY;
	int rotationAngle;
	int tempX, tempY;
	int rotateX, rotateY;
	int splitLineValue;
	int tempCount;

	constantShiftAddress = MAX_IMAGE_WIDTH * TabletMatchingResult.AdjustCenterYInImage + TabletMatchingResult.AdjustCenterXInImage;

	startX = tabletAreaInfo[AREA_INFO_ST_X_ADDRESS];
	endX = tabletAreaInfo[AREA_INFO_END_X_ADDRESS];
	startY = tabletAreaInfo[AREA_INFO_ST_Y_ADDRESS];
	endY = tabletAreaInfo[AREA_INFO_END_Y_ADDRESS];

	printMatchingRangeX = 8;
	printMatchingRangeAngle = 12;

	step = 8;

	maxValue = -1;
	for (r = 0; r < 720; r += step)
	{
		tr = r;
		memset(matchingValueArray, 0, sizeof(int) * 42);

		for (m = 0; m < SmallSplitLineDataCount; m += 3)
		{
			tempAddress = detailedSplitLineRotationAddress[tr][m] + constantShiftAddress;

			matchingValueArray[0] += (ExtractedSplitLineImage[tempAddress]);
			matchingValueArray[1] += (ExtractedSplitLineImage[tempAddress - 1923]);
			matchingValueArray[2] += (ExtractedSplitLineImage[tempAddress - 1917]);
			matchingValueArray[3] += (ExtractedSplitLineImage[tempAddress + 1923]);
			matchingValueArray[4] += (ExtractedSplitLineImage[tempAddress + 1917]);
			matchingValueArray[5] += (ExtractedSplitLineImage[tempAddress - 3846]);
			matchingValueArray[6] += (ExtractedSplitLineImage[tempAddress - 3834]);
			matchingValueArray[7] += (ExtractedSplitLineImage[tempAddress + 3846]);
			matchingValueArray[8] += (ExtractedSplitLineImage[tempAddress + 3834]);
			matchingValueArray[9] += (ExtractedSplitLineImage[tempAddress - 5769]);
			matchingValueArray[10] += (ExtractedSplitLineImage[tempAddress - 5751]);
			matchingValueArray[11] += (ExtractedSplitLineImage[tempAddress + 5769]);
			matchingValueArray[12] += (ExtractedSplitLineImage[tempAddress + 5751]);
			matchingValueArray[13] += (ExtractedSplitLineImage[tempAddress - 3]);
			matchingValueArray[14] += (ExtractedSplitLineImage[tempAddress - 6]);
			matchingValueArray[15] += (ExtractedSplitLineImage[tempAddress - 9]);
			matchingValueArray[16] += (ExtractedSplitLineImage[tempAddress + 3]);
			matchingValueArray[17] += (ExtractedSplitLineImage[tempAddress + 6]);
			matchingValueArray[18] += (ExtractedSplitLineImage[tempAddress + 9]);
			matchingValueArray[19] += (ExtractedSplitLineImage[tempAddress + 1920]);
			matchingValueArray[20] += (ExtractedSplitLineImage[tempAddress + 3840]);
			matchingValueArray[21] += (ExtractedSplitLineImage[tempAddress + 5760]);
			matchingValueArray[22] += (ExtractedSplitLineImage[tempAddress - 1920]);
			matchingValueArray[23] += (ExtractedSplitLineImage[tempAddress - 3840]);
			matchingValueArray[24] += (ExtractedSplitLineImage[tempAddress - 5760]);
			matchingValueArray[25] += (ExtractedSplitLineImage[tempAddress - 5764]);
			matchingValueArray[26] += (ExtractedSplitLineImage[tempAddress + 5764]);
			matchingValueArray[27] += (ExtractedSplitLineImage[tempAddress - 5756]);
			matchingValueArray[28] += (ExtractedSplitLineImage[tempAddress + 5756]);
			matchingValueArray[29] += (ExtractedSplitLineImage[tempAddress - 2569]);
			matchingValueArray[30] += (ExtractedSplitLineImage[tempAddress + 2569]);
			matchingValueArray[31] += (ExtractedSplitLineImage[tempAddress - 2551]);
			matchingValueArray[32] += (ExtractedSplitLineImage[tempAddress + 2551]);
		}

		for (i = 0; i < 42; i++)
		{
			if (matchingValueArray[i] > maxValue)
			{
				maxValue = matchingValueArray[i];
				tempRotateAngleArray = r;
			}
		}
	}

	step = 2;

	maxValue = -1;
	for (r = tempRotateAngleArray - printMatchingRangeAngle; r <= tempRotateAngleArray + printMatchingRangeAngle; r += step)
	{
		temp_r = r;
		if (temp_r >= 720)
		{
			temp_r -= 720;
		}
		else if (temp_r < 0)
		{
			temp_r += 720;
		}

		for (j = -printMatchingRangeX; j <= printMatchingRangeX; j += 2)
		{
			memset(matchingValueArray, 0, sizeof(int) * 15);

			for (m = 0; m < SmallSplitLineDataCount; m++)
			{
				tempAddress = detailedSplitLineRotationAddress[temp_r][m] + constantShiftAddress + j;

				matchingValueArray[0] += (ExtractedSplitLineImage[tempAddress - 8960]);
				matchingValueArray[1] += (ExtractedSplitLineImage[tempAddress - 7680]);
				matchingValueArray[2] += (ExtractedSplitLineImage[tempAddress - 6400]);
				matchingValueArray[3] += (ExtractedSplitLineImage[tempAddress - 5120]);
				matchingValueArray[4] += (ExtractedSplitLineImage[tempAddress - 3840]);
				matchingValueArray[5] += (ExtractedSplitLineImage[tempAddress - 2560]);
				matchingValueArray[6] += (ExtractedSplitLineImage[tempAddress - 1280]);
				matchingValueArray[7] += (ExtractedSplitLineImage[tempAddress]);
				matchingValueArray[8] += (ExtractedSplitLineImage[tempAddress + 1280]);
				matchingValueArray[9] += (ExtractedSplitLineImage[tempAddress + 2560]);
				matchingValueArray[10] += (ExtractedSplitLineImage[tempAddress + 3840]);
				matchingValueArray[11] += (ExtractedSplitLineImage[tempAddress + 5120]);
				matchingValueArray[12] += (ExtractedSplitLineImage[tempAddress + 6400]);
				matchingValueArray[13] += (ExtractedSplitLineImage[tempAddress + 7680]);
				matchingValueArray[14] += (ExtractedSplitLineImage[tempAddress + 8960]);
			}

			for (i = 0; i < 15; i++)
			{
				if (matchingValueArray[i] > maxValue)
				{
					maxValue = matchingValueArray[i];

					matchingShiftX = j;
					matchingShiftY = (i - 7) * 2;
					rotationAngle = temp_r;
				}
			}
		}
	}

	int cosValue, sinValue;
	if (rotationAngle >= 0)
	{
		sinValue = SinData[rotationAngle % 720];
		cosValue = CosData[rotationAngle % 720];
	}
	else
	{
		sinValue = -SinData[(-rotationAngle) % 720];
		cosValue = CosData[(-rotationAngle) % 720];
	}

	splitLineValue = tempCount = globalTabletSplitLineDataCount = 0;
	for (m = 0; m < TabletSetupData.tabletSplitLineDataCount; m++)
	{
		tempX = TabletSetupData.tabletSplitLineData[m][0];
		tempY = TabletSetupData.tabletSplitLineData[m][1];

		rotateX = ((tempX - HALF_IMAGE_WIDTH) * cosValue - (tempY - HALF_IMAGE_HEIGHT) * sinValue) / 1024 + TabletMatchingResult.AdjustCenterXInImage + matchingShiftX;
		rotateY = ((tempX - HALF_IMAGE_WIDTH) * sinValue + (tempY - HALF_IMAGE_HEIGHT) * cosValue) / 1024 + TabletMatchingResult.AdjustCenterYInImage + matchingShiftY;

		if (rotateX > startX && rotateX < endX && rotateX > startY && rotateY < endY)
		{
			tempAddress = MAX_IMAGE_WIDTH * rotateY + rotateX;

			if (ShapeBinaryImage[tempAddress])
			{
				splitLineValue += ExtractedSplitLineImage[tempAddress];

				if (tempCount < PRINT_DATA_SIZE)
				{
					globalTabletSplitLineData[tempCount][0] = rotateX;
					globalTabletSplitLineData[tempCount][1] = rotateY;
					tempCount++;
				}
			}
		}
	}

	globalTabletSplitLineDataCount = tempCount;

	if (tempCount)
	{
		splitLineValue = splitLineValue * TabletSetupData.tabletSplitLineDataCount / tempCount;
	}

	if (splitLineValue > TabletGradeData.SplitLineMatchingThreshold * TabletSetupData.tabletSplitLineDataCount)
	{
		globalFrontFaceSplitLineMatchingSW = 1;
	}
}
//---------------------------------------------------------------------------
void ExtractBrightPixelNeighborPrint(int cameraIndex)
{
	int x, y, i, j, m;	
	int tempAddress;
	int r, r2;
	int selfValue;
	int brightPxielThreshold;
	int darkPxielThreshold;
	int defectCheck, defectCheck2;
	int maxValue;
	int colorDiff;
	int tmepCount;
	int compareAcceptArea[15][15];
	int selfPositionValue;

	int tempAddress2;
	int areaValue;
	int searchRange;
	int darkDefectCheckSW;
	int yShift;
	int PrintThreshold;
	int GrayLV;
	int topCheckSW, botCheckSW, leftCheckSW, rightCheckSW, topLeftCheckSW, topRightCheckSW, botLeftCheckSW, botRightCheckSW;
	int topSW, bottomSW, leftSW, rightSW, topleftSW, toprightSW, bottomleftSW, bottomrightSW;
	int maxcolorDiff;
	int colorDiffSum;
	int printColor[3];
	int printSelectedRGB;
	int rgb;
	int tabletColor[3];

	int st_x = tabletAreaInfo[AREA_INFO_ST_X_ADDRESS];
	int end_x = tabletAreaInfo[AREA_INFO_END_X_ADDRESS];
	int st_y = tabletAreaInfo[AREA_INFO_ST_Y_ADDRESS];
	int end_y = tabletAreaInfo[AREA_INFO_END_Y_ADDRESS];

	if (st_x < TabletSetupData.ImageCutStartX[cameraIndex - 1])
		st_x = TabletSetupData.ImageCutStartX[cameraIndex - 1];
	if (end_x > TabletSetupData.ImageCutEndX[cameraIndex - 1])
		end_x = TabletSetupData.ImageCutEndX[cameraIndex - 1];
	if (st_y < TabletSetupData.ImageCutStartY[cameraIndex - 1])
		st_y = TabletSetupData.ImageCutStartY[cameraIndex - 1];
	if (end_y > TabletSetupData.ImageCutEndY[cameraIndex - 1])
		end_y = TabletSetupData.ImageCutEndY[cameraIndex - 1];

	int AdjustCenterXInImage = TabletMatchingResult.AdjustCenterXInImage;
	int AdjustCenterYInImage = TabletMatchingResult.AdjustCenterYInImage;

	int tempShiftX, tempShiftY;
	int range;

	range = TabletGradeData.frontShapeEdgeNeighborRange;

	tempShiftX = AdjustCenterXInImage - ImageWidth / 2;
	tempShiftY = AdjustCenterYInImage - ImageHeight / 2;
	if (TabletCharacter.shape != TRIANGLE && TabletCharacter.shape != SQUARE && TabletCharacter.shape != HEXA && TabletCharacter.shape != ETC && TabletCharacter.discriminationDisplay_kind != PRINT)
	{
		int xmax, ymax;
		for (y = ImageHeight / 2 - TabletCharacter.width / 2, ymax = ImageHeight / 2 + TabletCharacter.width / 2; y < ymax; y++)
		{
			for (x = ImageWidth / 2 - TabletCharacter.length / 2, xmax = ImageWidth / 2 + TabletCharacter.length / 2; x < xmax; x++)
			{
				tempAddress = y * MAX_IMAGE_WIDTH + x;
				if (TabletSetupData.OpenCloseSearchArea[tempAddress])
				{
					if (ShapeBinaryImage[(y + tempShiftY) * MAX_IMAGE_WIDTH + x + tempShiftX] == 1)
						ShapeBinaryImage[(y + tempShiftY) * MAX_IMAGE_WIDTH + x + tempShiftX] = 2;
				}
			}
		}

		if (!TabletGradeData.ETC_AdjustPrintAreaSW)
		{
			for (y = st_y; y < end_y; y++)
			{
				for (x = st_x; x < end_x; x++)
				{
					tempAddress = y * MAX_IMAGE_WIDTH + x;

					if (ShapeBinaryImage[y * MAX_IMAGE_WIDTH + x] == 2 &&
						ShapeBinaryImage[(y + 5) * MAX_IMAGE_WIDTH + (x)] == 2 &&
						ShapeBinaryImage[(y - 5) * MAX_IMAGE_WIDTH + (x)] == 2 &&
						ShapeBinaryImage[(y)*MAX_IMAGE_WIDTH + x + (5)] == 2 &&
						ShapeBinaryImage[(y)*MAX_IMAGE_WIDTH + x - (5)] == 2)
					{
						ShapeBinaryImageForPrintArea[y * MAX_IMAGE_WIDTH + x] = 1;
					}
				}
			}
		}
		else
		{
			for (y = st_y; y < end_y; y++)
			{
				for (x = st_x; x < end_x; x++)
				{
					tempAddress = y * MAX_IMAGE_WIDTH + x;

					if (ShapeBinaryImage[y * MAX_IMAGE_WIDTH + x] == 2 &&
						ShapeBinaryImage[(y + range) * MAX_IMAGE_WIDTH + (x)] &&
						ShapeBinaryImage[(y - range) * MAX_IMAGE_WIDTH + (x)] &&
						ShapeBinaryImage[(y)*MAX_IMAGE_WIDTH + x + (range)] &&
						ShapeBinaryImage[(y)*MAX_IMAGE_WIDTH + x - (range)])
					{
						ShapeBinaryImageForPrintArea[y * MAX_IMAGE_WIDTH + x] = 1;
					}
				}
			}
		}
	}
	else
	{
		int xmax, ymax;
		for (y = ImageHeight / 2 - TabletCharacter.width / 2, ymax = ImageHeight / 2 + TabletCharacter.width / 2; y < ymax; y++)
		{
			for (x = ImageWidth / 2 - TabletCharacter.length / 2, xmax = ImageWidth / 2 + TabletCharacter.length / 2; x < xmax; x++)
			{
				tempAddress = y * MAX_IMAGE_WIDTH + x;

				if (ShapeBinaryImage[(y + tempShiftY) * MAX_IMAGE_WIDTH + x + tempShiftX] == 1)
					ShapeBinaryImage[(y + tempShiftY) * MAX_IMAGE_WIDTH + x + tempShiftX] = 2;
			}
		}

		if (!TabletGradeData.ETC_AdjustPrintAreaSW)
		{
			for (y = st_y; y < end_y; y++)
			{
				for (x = st_x; x < end_x; x++)
				{
					tempAddress = y * MAX_IMAGE_WIDTH + x;

					if (ShapeBinaryImage[y * MAX_IMAGE_WIDTH + x] == 2 &&
						ShapeBinaryImage[(y + 10) * MAX_IMAGE_WIDTH + (x)] == 2 &&
						ShapeBinaryImage[(y - 10) * MAX_IMAGE_WIDTH + (x)] == 2 &&
						ShapeBinaryImage[(y)*MAX_IMAGE_WIDTH + x + (10)] == 2 &&
						ShapeBinaryImage[(y)*MAX_IMAGE_WIDTH + x - (10)] == 2)
					{
						ShapeBinaryImageForPrintArea[y * MAX_IMAGE_WIDTH + x] = 1;
					}
				}
			}
		}
		else
		{
			for (y = st_y; y < end_y; y++)
			{
				for (x = st_x; x < end_x; x++)
				{
					tempAddress = y * MAX_IMAGE_WIDTH + x;

					if (ShapeBinaryImage[y * MAX_IMAGE_WIDTH + x] == 2 &&
						ShapeBinaryImage[(y + range) * MAX_IMAGE_WIDTH + (x)] == 2 &&
						ShapeBinaryImage[(y - range) * MAX_IMAGE_WIDTH + (x)] == 2 &&
						ShapeBinaryImage[(y)*MAX_IMAGE_WIDTH + x + (range)] == 2 &&
						ShapeBinaryImage[(y)*MAX_IMAGE_WIDTH + x - (range)] == 2)
					{
						ShapeBinaryImageForPrintArea[y * MAX_IMAGE_WIDTH + x] = 1;
					}
				}
			}
		}
	}	

	memset(BrightPixelNeighborPrint, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
	memset(DarkPixelNeighborPrint, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
	memset(DarkPixelNeighborPrint2, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

	if (TabletGradeData.ETC_ApplyWhiteEngraveAlgorithm) // 각인이 흰색으로 보이는 정제 전용 알고리즘.
	{
		if (TabletCharacter.kind == UNCOATING)
			brightPxielThreshold = 2;
		else
			brightPxielThreshold = 4;

		darkPxielThreshold = 4 + (TabletGradeData.EngraveDistinguishGrade - 2);

		if (TabletCharacter.CurvedSurfaceTablet)
		{
			darkPxielThreshold += 10; // 각인 외에 굴곡진 음영이 있는 정제의 경우 굴곡진 표면의 음영을 무시하기 위하여 값을 더해준다.
		}

		for (y = st_y; y < end_y; y++)
		{
			for (x = st_x; x < end_x; x++)
			{
				tempAddress = y * MAX_IMAGE_WIDTH + x;
				if (ShapeBinaryImageForPrintArea[tempAddress])
				{
					selfValue = OneColorImage[tempAddress];

					r = 10;
					defectCheck = 0;
					maxValue = -1;

					for (i = y - r; i <= y + r; i += r)
					{
						for (j = x - r; j <= x + r; j += r)
						{
							colorDiff = selfValue - OneColorImage[i * MAX_IMAGE_WIDTH + j];
							if (colorDiff >= darkPxielThreshold)
							{
								defectCheck++;
								if (colorDiff > maxValue)
									maxValue = colorDiff;
							}
						}
					}

					if (defectCheck >= 5)
					{
						for (i = y; i <= y + 1; i++)
						{
							for (j = x; j <= x + 1; j++)
							{
								DarkPixelNeighborPrint[i * MAX_IMAGE_WIDTH + j] = maxValue;
							}
						}
					}
				}
			}
		}

		for (m = 0; m < 15; m++)
		{
			for (i = 0; i < 15; i++)
			{
				compareAcceptArea[m][i] = 1;
			}
		}
		for (m = 0; m < 15; m++)
		{
			compareAcceptArea[FRONT_SHAPE_EDGE][m] = 0;
			compareAcceptArea[m][FRONT_SHAPE_EDGE] = 0;
		}

		maxValue = 0;
		searchRange = 6;
		darkPxielThreshold = 4;
		for (i = st_y; i < end_y; i++)
		{
			for (j = st_x; j < end_x; j++)
			{
				tempAddress = MAX_IMAGE_WIDTH * i + j;
				areaValue = InspectionArea[tempAddress];
				if (areaValue && ShapeBinaryImageForPrintArea[tempAddress])
				{
					selfPositionValue = MeanOneColorImage[tempAddress];
					darkDefectCheckSW = 0;
					topCheckSW = botCheckSW = leftCheckSW = rightCheckSW = topLeftCheckSW = topRightCheckSW = botLeftCheckSW = botRightCheckSW = 0;

					for (r = searchRange; r >= 4; r -= 2)
					{
						yShift = r * MAX_IMAGE_WIDTH;
						tempAddress2 = tempAddress - yShift;
						if (compareAcceptArea[areaValue][InspectionArea[tempAddress2]] && !topCheckSW)
						{
							colorDiff = MeanOneColorImage[tempAddress2] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
								topCheckSW = 1;
							}
						}
						tempAddress2 = tempAddress + yShift;
						if (compareAcceptArea[areaValue][InspectionArea[tempAddress2]] && !botCheckSW)
						{
							colorDiff = MeanOneColorImage[tempAddress2] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
								botCheckSW = 1;
							}
						}
						tempAddress2 = tempAddress - r;
						if (compareAcceptArea[areaValue][InspectionArea[tempAddress2]] && !leftCheckSW)
						{
							colorDiff = MeanOneColorImage[tempAddress2] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
								leftCheckSW = 1;
							}
						}
						tempAddress2 = tempAddress + r;
						if (compareAcceptArea[areaValue][InspectionArea[tempAddress2]] && !rightCheckSW)
						{
							colorDiff = MeanOneColorImage[tempAddress2] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
								rightCheckSW = 1;
							}
						}
						tempAddress2 = tempAddress + yShift + r;
						if (compareAcceptArea[areaValue][InspectionArea[tempAddress2]] && !botRightCheckSW)
						{
							colorDiff = MeanOneColorImage[tempAddress2] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
								botRightCheckSW = 1;
							}
						}
						tempAddress2 = tempAddress - yShift - r;
						if (compareAcceptArea[areaValue][InspectionArea[tempAddress2]] && !topLeftCheckSW)
						{
							colorDiff = MeanOneColorImage[tempAddress2] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
								topLeftCheckSW = 1;
							}
						}
						tempAddress2 = tempAddress + yShift - r;
						if (compareAcceptArea[areaValue][InspectionArea[tempAddress2]] && !botLeftCheckSW)
						{
							colorDiff = MeanOneColorImage[tempAddress2] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
								botLeftCheckSW = 1;
							}
						}
						tempAddress2 = tempAddress - yShift + r;
						if (compareAcceptArea[areaValue][InspectionArea[tempAddress2]] && !topRightCheckSW)
						{
							colorDiff = MeanOneColorImage[tempAddress2] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
								topRightCheckSW = 1;
							}
						}

						if (darkDefectCheckSW >= 6)
						{
							DarkPixelNeighborPrint[tempAddress] = maxValue;
						}
					}
				}
			}
		}
	}
	else if (TabletCharacter.discriminationDisplay_kind != PRINT && TabletGradeData.ETC_EngraveMatchingOption_LightEngrave == 1)
	{
		// 옅은 각인 정제
		// 간단히 평균 이미지와의 차이로 각인을 구분한다.
		int avgValue;
		brightPxielThreshold = 0;
		darkPxielThreshold = 0;
		for (y = st_y; y < end_y; y++)
		{
			for (x = st_x; x < end_x; x++)
			{
				tempAddress = y * MAX_IMAGE_WIDTH + x;
				if (ShapeBinaryImageForPrintArea[tempAddress])
				{
					selfValue = OneColorImage[tempAddress];
					avgValue = (OneColorImage[tempAddress - 1] + OneColorImage[tempAddress - 2] + OneColorImage[tempAddress + 1] + OneColorImage[tempAddress + 2] +
								OneColorImage[tempAddress - MAX_IMAGE_WIDTH] + OneColorImage[tempAddress - 2 * MAX_IMAGE_WIDTH] + OneColorImage[tempAddress + MAX_IMAGE_WIDTH] + OneColorImage[tempAddress + 2 * MAX_IMAGE_WIDTH]) / 8;
					colorDiff = selfValue - avgValue;
					if (colorDiff > brightPxielThreshold)
					{
						BrightPixelNeighborPrint[tempAddress] = min(20, 2 * colorDiff);
					}
					else if (-colorDiff > darkPxielThreshold)
					{
						DarkPixelNeighborPrint[tempAddress] = min(20, 2 * -colorDiff); // 2D 각인에서 너무 큰 값은 각인이 아니라 검정색 이물질일 가능성이 크므로 각인 매칭의 정확성을 위하여 크기를 제한해줌.
					}
				}
			}
		}
	}
	else if (TabletCharacter.discriminationDisplay_kind != PRINT)
	{
		// 일반 각인 정제
		unsigned char *oneColorImage;
		if (TabletCharacter.MarvelingTablet)
		{
			oneColorImage = MeanOneColorImage;
		}
		else
		{
			oneColorImage = OneColorImage;
		}
		
		searchRange = 8;
		brightPxielThreshold = 6;
		for (y = st_y; y < end_y; y++)
		{
			for (x = st_x; x < end_x; x++)
			{
				tempAddress = y * MAX_IMAGE_WIDTH + x;
				if (ShapeBinaryImageForPrintArea[tempAddress])
				{
					selfValue = oneColorImage[tempAddress];
					defectCheck = 0;
					maxValue = -1;

					colorDiffSum = 0;
					topSW = bottomSW = leftSW = rightSW = topleftSW = toprightSW = bottomleftSW = bottomrightSW = 0;

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 2)
					{
						tempAddress2 = tempAddress + r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = selfValue - oneColorImage[tempAddress2];

							if (colorDiff > brightPxielThreshold)
							{
								rightSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (rightSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 2)
					{
						tempAddress2 = tempAddress - r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = selfValue - oneColorImage[tempAddress2];

							if (colorDiff > brightPxielThreshold)
							{
								leftSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (leftSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 2)
					{
						tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = selfValue - oneColorImage[tempAddress2];

							if (colorDiff > brightPxielThreshold)
							{
								topSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (topSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 2)
					{
						tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = selfValue - oneColorImage[tempAddress2];

							if (colorDiff > brightPxielThreshold)
							{
								bottomSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (bottomSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 2)
					{
						tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH - r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = selfValue - oneColorImage[tempAddress2];

							if (colorDiff > brightPxielThreshold)
							{
								topleftSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (topleftSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					if (defectCheck < 1)
						continue;

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 2)
					{
						tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH + r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = selfValue - oneColorImage[tempAddress2];

							if (colorDiff > brightPxielThreshold)
							{
								toprightSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (toprightSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					if (defectCheck < 2)
						continue;

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 2)
					{
						tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH - r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = selfValue - oneColorImage[tempAddress2];

							if (colorDiff > brightPxielThreshold)
							{
								bottomleftSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (bottomleftSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					if (defectCheck < 3)
						continue;

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 2)
					{
						tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH + r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = selfValue - oneColorImage[tempAddress2];

							if (colorDiff > brightPxielThreshold)
							{
								bottomrightSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (bottomrightSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					if (defectCheck >= 4)
					{
						if ((topSW && bottomSW) ||
							(leftSW && rightSW) ||
							(topleftSW && bottomrightSW) ||
							(toprightSW && bottomleftSW))
						{
							colorDiffSum /= defectCheck;

							BrightPixelNeighborPrint[tempAddress] = colorDiffSum;
						}
					}
				}
			}
		}

		searchRange = 12;
		darkPxielThreshold = 4 + (TabletGradeData.EngraveDistinguishGrade - 2);

		if (TabletCharacter.CurvedSurfaceTablet)
		{
			darkPxielThreshold += 10; // 각인 외에 굴곡진 음영이 있는 정제의 경우 굴곡진 표면의 음영을 무시하기 위하여 값을 더해준다.
		}

		for (y = st_y; y < end_y; y++)
		{
			for (x = st_x; x < end_x; x++)
			{
				tempAddress = y * MAX_IMAGE_WIDTH + x;
				if (ShapeBinaryImageForPrintArea[tempAddress] && !BrightPixelNeighborPrint[tempAddress])
				{
					selfValue = oneColorImage[tempAddress];
					defectCheck = 0;
					maxValue = -1;

					colorDiffSum = 0;
					topSW = bottomSW = leftSW = rightSW = topleftSW = toprightSW = bottomleftSW = bottomrightSW = 0;

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 4)
					{
						tempAddress2 = tempAddress + r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = oneColorImage[tempAddress2] - selfValue;

							if (colorDiff > darkPxielThreshold)
							{
								rightSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (rightSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 4)
					{
						tempAddress2 = tempAddress - r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = oneColorImage[tempAddress2] - selfValue;

							if (colorDiff > darkPxielThreshold)
							{
								leftSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (leftSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 4)
					{
						tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = oneColorImage[tempAddress2] - selfValue;

							if (colorDiff > darkPxielThreshold)
							{
								topSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (topSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 4)
					{
						tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = oneColorImage[tempAddress2] - selfValue;

							if (colorDiff > darkPxielThreshold)
							{
								bottomSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (bottomSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 4)
					{
						tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH - r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = oneColorImage[tempAddress2] - selfValue;

							if (colorDiff > darkPxielThreshold)
							{
								topleftSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (topleftSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					if (defectCheck < 1)
						continue;

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 4)
					{
						tempAddress2 = tempAddress - r * MAX_IMAGE_WIDTH + r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = oneColorImage[tempAddress2] - selfValue;

							if (colorDiff > darkPxielThreshold)
							{
								toprightSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (toprightSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					if (defectCheck < 2)
						continue;

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 4)
					{
						tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH - r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = oneColorImage[tempAddress2] - selfValue;

							if (colorDiff > darkPxielThreshold)
							{
								bottomleftSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (bottomleftSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					if (defectCheck < 3)
						continue;

					maxcolorDiff = 0;
					for (r = searchRange; r >= 4; r -= 4)
					{
						tempAddress2 = tempAddress + r * MAX_IMAGE_WIDTH + r;

						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = oneColorImage[tempAddress2] - selfValue;

							if (colorDiff > darkPxielThreshold)
							{
								bottomrightSW = 1;

								if (maxcolorDiff < colorDiff)
									maxcolorDiff = colorDiff;
							}
						}
					}

					if (bottomrightSW)
					{
						colorDiffSum += maxcolorDiff;
						defectCheck++;
					}

					if (defectCheck >= 4 && 
						((topSW && bottomSW) ||
							(leftSW && rightSW) ||
							(topleftSW && bottomrightSW) ||
							(toprightSW && bottomleftSW)))
					{
						colorDiffSum /= defectCheck;

						DarkPixelNeighborPrint[tempAddress] = min(20, colorDiffSum); // 2D 각인에서 너무 큰 값은 각인이 아니라 검정색 이물질일 가능성이 크므로 각인 매칭의 정확성을 위하여 크기를 제한해줌.
					}
				}
			}
		}
	}
	else
	{
		// 인쇄의 경우.
		// 2015-10-27  revision by moon
		// darkThreshold 값에서 정확한 인쇄영역을 찾는데 애로사항 발생 -> 사용자가 설정한 Threshold값으로 적용함
		if (TabletCharacter.discriminationDisplay_num == ONE_FACE)
		{
			printColor[0] = TabletSetupData.PrintColor[0][0];
			printColor[1] = TabletSetupData.PrintColor[0][1];
			printColor[2] = TabletSetupData.PrintColor[0][2];
		}
		else
		{
			if (cameraIndex == 1)
			{
				printColor[0] = TabletSetupData.PrintColor[0][0];
				printColor[1] = TabletSetupData.PrintColor[0][1];
				printColor[2] = TabletSetupData.PrintColor[0][2];
			}
			else
			{
				printColor[0] = TabletSetupData.PrintColor[1][0];
				printColor[1] = TabletSetupData.PrintColor[1][1];
				printColor[2] = TabletSetupData.PrintColor[1][2];
			}
		}

		if (ProcessingModeGlobal == INSPECTION_MODE)
		{
			if (cameraIndex == 1)
			{
				tabletColor[0] = TabletStudyData.tabletColorB_ForCamera1;
				tabletColor[1] = TabletStudyData.tabletColorG_ForCamera1;
				tabletColor[2] = TabletStudyData.tabletColorR_ForCamera1;
			}
			else
			{
				tabletColor[0] = TabletStudyData.tabletColorB_ForCamera9;
				tabletColor[1] = TabletStudyData.tabletColorG_ForCamera9;
				tabletColor[2] = TabletStudyData.tabletColorR_ForCamera9;
			}
		}
		else
		{
			tabletColor[0] = TabletSetupData.protoStudyColorB;
			tabletColor[1] = TabletSetupData.protoStudyColorG;
			tabletColor[2] = TabletSetupData.protoStudyColorR;
		}

		maxValue = 0;
		for (rgb = 0; rgb < 3; rgb++)
		{
			colorDiff = abs(tabletColor[rgb] - printColor[rgb]);

			if (maxValue < colorDiff)
			{
				maxValue = colorDiff;
				printSelectedRGB = rgb;
			}
		}

		globalPrintSelectedRGB = printSelectedRGB;

		PrintThreshold = (TabletSetupData.PrintThreshold * 115 / 100) - TabletGradeData.EngraveMatchingOrNotValue;
		if (PrintThreshold < 0)
			PrintThreshold = 0;

		darkPxielThreshold = 15;
		// if (TabletCharacter.kind == SUGARCOATING)
		//   darkPxielThreshold = 15;

		// DarkPixelNeighborPrint 구하기.
		// 특징추출 및 등급설정에서 지정된 프린트 밝기(PrintThreshold)보다 어두운 경우에 한하여 주변보다 어두운 픽셀을 구한다.
		// 2015-10-27 revision by moon
		// 인쇄 서칭방식 수정
		// 2D 카메라에 대해서만 수정 적용
		for (y = st_y; y < end_y; y++)
		{
			for (x = st_x; x < end_x; x++)
			{
				tempAddress = y * MAX_IMAGE_WIDTH + x;
				if (ShapeBinaryImageForPrintArea[tempAddress])
				{
					// 2021-04-21
					// gray value 고려방식에서 정제 most factor 고려방식으로 변경
					// GrayLV = (colorSourceImage[tempAddress * 3 + 0] + colorSourceImage[tempAddress * 3 + 1] + colorSourceImage[tempAddress * 3 + 2]) / 3;
					GrayLV = ColorSourceImage[tempAddress * 3 + selectedRGB];

					selfValue = ColorSourceImage[tempAddress * 3 + printSelectedRGB];

					defectCheck = 0;
					defectCheck2 = 0;
					maxValue = -1;
					r = 25; // 인쇄가 굵은 것이 있어서 추출이 잘 안돼 10에서 25으로 탐색 범위를 넓힘,.
					r2 = 12;

					// 2015-11-17 revision by moon
					// 정제 색상과 인쇄 색상이 유사한 경우 혹은 인쇄가 많이 지워져 있는 경우 인쇄 영역을 정상적으로 찾지 못하는 경우가 발생
					// 이에 따라 PrintThreshold 값은 러프하게 설정하며 SelfDiff이미지와의 AND 영역을 인쇄 영역으로 가정하는 것으로 수정
					// PrintThreshold 만 사용하는 경우 흐린 인쇄의 경우 추출이 어려우며 모서리 영역을 인쇄로 판단하는 경우가 발생
					// DarkThreshold 만 사용하는 경우 볼록한 정제의 인쇄영역을 찾을 때 중심부근과 모서리 부근에서 ROI 셋팅되어 인쇄 매칭이 정상적으로 되지 않음
					// 이에 두 변수를 러프하게 설정한 후 AND 영역을 사용하도록 함

					if (GrayLV < PrintThreshold)
					{
						defectCheck = 3;
					}

					if (TabletCharacter.kind == SUGARCOATING)
					{
						if (defectCheck == 3)
						{
							for (i = y - r; i <= y + r; i += r)
							{
								for (j = x - r; j <= x + r; j += r)
								{
									colorDiff = ColorSourceImage[(i * MAX_IMAGE_WIDTH + j) * 3 + printSelectedRGB] - selfValue;
									if (colorDiff >= darkPxielThreshold)
									{
										defectCheck2++;
									}
								}
							}

							if (defectCheck2 < 5)
							{
								defectCheck2 = 0;

								for (i = y - r2; i <= y + r2; i += r2)
								{
									for (j = x - r2; j <= x + r2; j += r2)
									{
										colorDiff = ColorSourceImage[(i * MAX_IMAGE_WIDTH + j) * 3 + printSelectedRGB] - selfValue;
										if (colorDiff >= darkPxielThreshold)
										{
											defectCheck2++;
										}
									}
								}
							}

							if (defectCheck2 >= 5)
							{
								for (i = y; i <= y + 1; i++)
								{
									for (j = x; j <= x + 1; j++)
									{
										DarkPixelNeighborPrint[i * MAX_IMAGE_WIDTH + j] = 255;
									}
								}
							}
						}
					}
					else if (TabletCharacter.kind != SUGARCOATING)
					{
						if (defectCheck == 3)
						{
							for (i = y - r; i <= y + r; i += 5)
							{
								for (j = x - r; j <= x + r; j += 5)
								{
									colorDiff = ColorSourceImage[(i * MAX_IMAGE_WIDTH + j) * 3 + printSelectedRGB] - selfValue;
									if (colorDiff >= darkPxielThreshold)
									{
										defectCheck2++;
									}
								}
							}

							if (defectCheck2 >= 3)
							{
								DarkPixelNeighborPrint[tempAddress] = 255;
							}
						}
					}
				}
			}
		}

		// DarkPixelNeighborPrint2 구하기. 
		// 순수하게 프린트 RGB중 하나의 값으로 일정값이상 주변보다 어두운 픽셀을 구한다.
		darkPxielThreshold = 15;
		searchRange = 12;
		for (y = st_y; y < end_y; y++)
		{
			for (x = st_x; x < end_x; x++)
			{
				tempAddress = y * MAX_IMAGE_WIDTH + x;
				if (ShapeBinaryImageForPrintArea[tempAddress])
				{
					selfPositionValue = ColorSourceImage[tempAddress * 3 + printSelectedRGB];

					maxValue = 0;
					darkDefectCheckSW = 0;

					for (r = searchRange; r >= 4; r -= 4)
					{
						yShift = r * MAX_IMAGE_WIDTH;
						tempAddress2 = tempAddress - yShift;
						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = ColorSourceImage[tempAddress2 * 3 + printSelectedRGB] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
							}
						}
						tempAddress2 = tempAddress + yShift;
						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = ColorSourceImage[tempAddress2 * 3 + printSelectedRGB] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
							}
						}
						tempAddress2 = tempAddress - r;
						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = ColorSourceImage[tempAddress2 * 3 + printSelectedRGB] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
							}
						}
						tempAddress2 = tempAddress + r;
						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = ColorSourceImage[tempAddress2 * 3 + printSelectedRGB] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
							}
						}
						tempAddress2 = tempAddress + yShift + r;
						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = ColorSourceImage[tempAddress2 * 3 + printSelectedRGB] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
							}
						}
						tempAddress2 = tempAddress - yShift - r;
						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = ColorSourceImage[tempAddress2 * 3 + printSelectedRGB] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
							}
						}
						tempAddress2 = tempAddress + yShift - r;
						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = ColorSourceImage[tempAddress2 * 3 + printSelectedRGB] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
							}
						}
						tempAddress2 = tempAddress - yShift + r;
						if (ShapeBinaryImageForPrintArea[tempAddress2])
						{
							colorDiff = ColorSourceImage[tempAddress2 * 3 + printSelectedRGB] - selfPositionValue;
							if (colorDiff > darkPxielThreshold)
							{
								if (colorDiff > maxValue)
									maxValue = colorDiff;

								darkDefectCheckSW++;
							}
						}

						if (darkDefectCheckSW >= 3)
						{
							DarkPixelNeighborPrint2[tempAddress] = maxValue;
							break;
						}
					}
				}
			}
		}
	}

	// 처리된 정보를 취합 후 최종처리.
	if (TabletGradeData.ETC_ApplyWhiteEngraveAlgorithm) // 각인이 흰색으로 보이는 정제 전용 알고리즘.
	{
		TabletMatchingResult.PrintCenterX = AdjustCenterXInImage;
		TabletMatchingResult.PrintCenterY = AdjustCenterYInImage;
	}
	else if (TabletCharacter.discriminationDisplay_kind != PRINT)
	{
		TabletMatchingResult.PrintCenterX = AdjustCenterXInImage;
		TabletMatchingResult.PrintCenterY = AdjustCenterYInImage;
	}
	else
	{
		int x, y;
		int i, j;
		int m;
		if (TabletCharacter.kind == SUGARCOATING)
		{
			for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
			{
				x = TabletSetupData.FrontShapeEdgePoint[m][0] + AdjustCenterXInImage - HALF_IMAGE_WIDTH;
				y = TabletSetupData.FrontShapeEdgePoint[m][1] + AdjustCenterYInImage - HALF_IMAGE_HEIGHT;
				for (i = y - 14; i <= y + 14; i += 2)
				{
					for (j = x - 14; j <= x + 14; j += 2)
					{
						DarkPixelNeighborPrint[i * MAX_IMAGE_WIDTH + j] = 0;
					}
				}
			}
		}

		int tmepCount = 0;
		TabletMatchingResult.PrintCenterX = 0;
		TabletMatchingResult.PrintCenterY = 0;
		for (y = st_y; y < end_y; y++) // 최종 취합이므로 전체 범위로 루프.
		{
			for (x = st_x; x < end_x; x++)
			{
				if (DarkPixelNeighborPrint[y * MAX_IMAGE_WIDTH + x])
				{
					TabletMatchingResult.PrintCenterX += x;
					TabletMatchingResult.PrintCenterY += y;
					tmepCount++;
				}
			}
		}

		// 2015-10-07 by moon
		// Print Center Position 구하는 과정
		// 인쇄가 존재하지 않는 정제 단면에서 인쇄 매칭을 시도하는 경우 발생
		// 인쇄 색상, 정제 자체 색상에 비해 darkPixelThreshold 값이 너무 낮음
		// darkPixelThreshold이 정제 색상 및 인쇄 색상에 고려하여 Dynamic하게 변화될 수 있도록 수정이 필요함
		// 테스트를 위해 임의로 100으로 수정함. 매칭 상태 양호. 단, 인쇄 주변에서 과검 발생
		// 인쇄 주변의 불량 예상군 판별 방식에 대한 로직 분석 필요
		// + 실제 인쇄에 비해 인쇄 영역이 너무 두껍게 설정됨. 대상 정제에서 추출되는 영역 역시 마찬가지. 인쇄 영역 구하는 방식 재검토 필요(Gradient Image 확인)

		if (tmepCount)
		{
			TabletMatchingResult.PrintCenterX /= tmepCount;
			TabletMatchingResult.PrintCenterY /= tmepCount;
		}
		else
		{
			TabletMatchingResult.PrintCenterX = AdjustCenterXInImage;
			TabletMatchingResult.PrintCenterY = AdjustCenterYInImage;
		}
	}	
}
//---------------------------------------------------------------------------