#ifdef PC_SIM
#include <mem.h>
#endif
#ifdef TARGET_PC
#include <mem.h>
#endif
#include <math.h>
#include "PrintMatching3D.h"
#include "cpb_module.h"
//---------------------------------------------------------------------------
void PrintMatchingForThreeD(int cameraIndex)
{
	switch (TabletCharacter.shape)
	{
	case ROUND:
	case SQUARE:
	case HEXA:
	case TRIANGLE:
		PrintMatchingThreeDForEachCase(CASE1, cameraIndex);
		break;

	case OBLONG:
	case OVAL:
	case ETC:
		if (TabletCharacter.shape == ETC && (TabletCharacter.symmetric_line_count == ASYMMETRY_TABLET || TabletCharacter.arrangeInfo != ARRANGE))
			PrintMatchingThreeDForEachCase(CASE1, cameraIndex);
		else
			PrintMatchingThreeDForEachCase(CASE2, cameraIndex);
		break;
	}
}
//---------------------------------------------------------------------------
void PrintMatchingThreeDForEachCase(int option, int cameraIndex)
{
	int i, j;
	int labelShiftX, labelShiftY;
	int diskNumber, printNumber;
	int tempRotate;
	int step;
	int r, m, n;
	int tempX, tempY;
	int rotateX, rotateY;
	int matchingValue;
	int matchingValueArray[50];
	int tempRotateAngleArray[2];
	int tempRotateAngle;
	int maxValue;
	int tempmaxValue;

	int printMatchingRangeX;
	int printMatchingRangeAngle;
	int standardMaxValue[2];
	int temp_r;

	int printIsOrNotThreshold;
	int tr;
	int tempAddress;
	int checkSW;
	int selfValue;
	int tempAddress2;
	int startX, endX, startY, endY;

	TTransform_printData Transform_printData; // 80K
	unsigned char neighberSourceValue[PRINT_DATA_SIZE];
	int reverseTransX, reverseTransY;
	int tempCount;
	int printAreaMask;
	int notPrintArea;
	int labelPrintDataTotalCount;
	int AllowEngraveLv;	
	int HalfWidth;
	int HalfHeight;
	int x, y;
	int printMatchingResultShiftX[2];
	int printMatchingResultShiftY[2];
	int printMatchingResultAngle[2];
	unsigned char *tempPrintArea1;
	unsigned char *tempPrintArea2;
	unsigned char *printNoneMatchingArea;
	int erasePercentage;
	int shiftX, shiftY;
	int ThreeDPrintNum;
	int allPrintCount;
	int SplitLineCount;
	int EngraveIsSplitLineSW;
	int fstLabelShiftX, fstLabelShiftY;
	int shiftAddress;
	int shiftXfromZeroPos;
	int shiftYfromZeroPos;
	int RealX, RealY;
	int AverageDentedValue;
	int tempX2, tempY2;
	int AllowedPrintAngle[720];
	int angle;
	int AlignedTabletLimitRotationAngle;
	int matchingShiftX;
	int SplitLineSkipSW;
	int SplitLineShiftX[2];
	int SplitLineShiftY[2];
	int SplitLineAngle[2];
	short *label_Image;
	int printLabelN;
	int realPrintBoundary;
	int option_EngraveIntensity;
	int option_EngraveDefectSize;
	int maxPrintValue;
	int normalizeValue;
	int expectedNormalizeValue;
	int globalSplitPartialMatchingSW[2];
	int FinalMatchingShiftX;
	int FinalMatchingShiftY;

	if (TabletCharacter.discriminationDisplay_kind == STAMP)
	{
		ThreeDPrintNum = TabletCharacter.discriminationDisplay_num;
	}
	else
	{
		if (TabletCharacter.tabletDivisionLineInfo == ONESIDE_DIVISION_LINE)
		{
			ThreeDPrintNum = ONE_FACE;
		}
		else if (TabletCharacter.tabletDivisionLineInfo == BOTHSIDE_DIVISION_LINE)
		{
			ThreeDPrintNum = TWO_FACE_DIFF;
		}
	}

	if (TabletCharacter.shape == OBLONG || TabletCharacter.shape == OVAL)
	{
		shiftX = AdjustTabletCenterX - MAX_IMAGE_WIDTH / 2;
		shiftY = AdjustTabletCenterInfo[1] - MAX_IMAGE_HEIGHT / 2; // Y축은COG 값을 적용해줘야 각인의 중심점이 일치함.
	}
	else
	{
		shiftX = AdjustTabletCenterX - MAX_IMAGE_WIDTH / 2;
		shiftY = AdjustTabletCenterY - MAX_IMAGE_HEIGHT / 2;
	}

	// 단차가 큰 정제의 경우 3D 카메라의 특성에 의하여 우측으로 밀리는 경향이 있다.
	// 높이에 따라 뒤로 밀어주자. 만약 정제마다 설정이 달라야한다면 기타 설정 등에서 설정 옵션으로 만들자.
	if (Max3DHeight > 96)
	{
		shiftX += (Max3DHeight - 96) / 8;
	}

	shiftAddress = MAX_IMAGE_WIDTH * shiftY + shiftX;

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

	printNoneMatchingArea = OneColorImage;

	HalfWidth = MAX_IMAGE_WIDTH / 2;
	HalfHeight = MAX_IMAGE_HEIGHT / 2;

	AllowEngraveLv = TabletGradeData.EngraveDistinguishGradeFor3D;
	printAreaMask = TabletGradeData.front_unInspectionIntensity_ForOptionPrint;

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

	tempPrintArea1 = BrightPixelNeighborPrint;
	tempPrintArea2 = DarkPixelNeighborPrint;

	if (TabletCharacter.length <= 90000 / TabletSetupData.cameraZoom[0])
	{
		printMatchingRangeX = 10;
		matchingShiftX = 2;
	}
	else if (TabletCharacter.length <= 100000 / TabletSetupData.cameraZoom[0])
	{
		printMatchingRangeX = 12;
		matchingShiftX = 2;
	}
	else
	{
		printMatchingRangeX = 14;
		matchingShiftX = 2;
	}

	if (TabletCharacter.shape == OBLONG || TabletCharacter.shape == OVAL)
	{
		printMatchingRangeX = 24;
		matchingShiftX = 4;
	}

	step = 8;
	if (ExecutiveSearchingRotationAngle)
	{
		memset(AllowedPrintAngle, 0, sizeof(int) * 720);

		AlignedTabletLimitRotationAngle = 8;																																		 // +- 4도
		for (angle = ProtoTabletRotationAngle - AlignedTabletLimitRotationAngle - step * 2; angle <= ProtoTabletRotationAngle + AlignedTabletLimitRotationAngle + step * 2; angle++) // forward
		{
			AllowedPrintAngle[(angle + 720) % 720] = 1;
		}

		for (angle = ProtoTabletRotationAngle - AlignedTabletLimitRotationAngle + 360 - step * 2; angle <= ProtoTabletRotationAngle + AlignedTabletLimitRotationAngle + 360 + step * 2; angle++) // reverse
		{
			AllowedPrintAngle[(angle + 720) % 720] = 1;
		}

		printMatchingRangeAngle = 9;
	}
	else
	{
		for (angle = 0; angle < 720; angle++)
		{
			AllowedPrintAngle[angle] = 1;
		}

		printMatchingRangeAngle = 15;
	}

	int bigSplitLineSW[2], onlySplitLineSW[2];
	bigSplitLineSW[0] = bigSplitLineSW[1] = 0;
	onlySplitLineSW[0] = onlySplitLineSW[1] = 0;

	memset(realPrintMaskingArea, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
	globalSplitPartialMatchingSW[0] = globalSplitPartialMatchingSW[1] = 0;

	for (int printIndex = 0; printIndex <= 1; printIndex++)
	{
		int SmallPrintCoreDataCountFor3D;
		int (*detailedCorePrintRotationAddressFor3D)[2500];
		int Disk1printDataCount;
		int Disk2printDataCount;
		int Disk1slice_printDataCount;
		int Disk2slice_printDataCount;
		char *ThreeDSplitLineData;
		unsigned char *tempPrintArea;
		unsigned char *tempPrintAreaOther;
		if (printIndex == 0)
		{
			SmallPrintCoreDataCountFor3D = SmallPrintCoreData1CountFor3D;
			detailedCorePrintRotationAddressFor3D = detailedCorePrintRotationAddress1For3D;
			Disk1printDataCount = Tablet3DSetupData.Disk1printData1Count;
			Disk2printDataCount = Tablet3DSetupData.Disk2printData1Count;
			Disk1slice_printDataCount = Tablet3DSetupData.Disk1slice_printData1Count;
			Disk2slice_printDataCount = Tablet3DSetupData.Disk2slice_printData1Count;
			ThreeDSplitLineData = ThreeDSplitLineData1;
			tempPrintArea = tempPrintArea1;
			tempPrintAreaOther = tempPrintArea2;
		}
		else
		{
			SmallPrintCoreDataCountFor3D = SmallPrintCoreData2CountFor3D;
			detailedCorePrintRotationAddressFor3D = detailedCorePrintRotationAddress2For3D;
			Disk1printDataCount = Tablet3DSetupData.Disk1printData2Count;
			Disk2printDataCount = Tablet3DSetupData.Disk2printData2Count;
			Disk1slice_printDataCount = Tablet3DSetupData.Disk1slice_printData2Count;
			Disk2slice_printDataCount = Tablet3DSetupData.Disk2slice_printData2Count;
			ThreeDSplitLineData = ThreeDSplitLineData2;
			tempPrintArea = tempPrintArea2;
			tempPrintAreaOther = tempPrintArea1;
		}

		maxValue = -1;
		for (r = 0; r < 720; r += step) // 대략적인 각인의 회전을 구함.
		{
			if (!AllowedPrintAngle[r])
				continue;

			tr = r;

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

			for (m = 0; m < SmallPrintCoreDataCountFor3D; m += THREE_D_PRINT_ADD_M1)
			{
				tempAddress = detailedCorePrintRotationAddressFor3D[tr][m] + shiftAddress;

				//if (tempAddress < 12800 || tempAddress > 296100) // 읽기만하므로 속도를 위해서 범위 무시.
				//	continue;

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

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

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

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

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

		EngraveIsSplitLineSW = -1;
		SplitLineSkipSW = 0;
		if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
		{
			if (Disk1slice_printDataCount && TabletCharacter.tabletDivisionLineInfo != NONE_DIVISION_LINE)
			{
				if ((Disk1slice_printDataCount * 100 / Disk1printDataCount) < 90)
				{
					SplitLineSkipSW = 1;
				}

				if (abs(Disk1printDataCount - Disk1slice_printDataCount) < 50)
				{
					EngraveIsSplitLineSW = 1;
					onlySplitLineSW[printIndex] = 1;
				}
				else
				{
					EngraveIsSplitLineSW = 0;
					globalSplitPartialMatchingSW[printIndex] = 1;
				}

				if (Disk1slice_printDataCount > 4000)
				{
					bigSplitLineSW[printIndex] = 1;
				}
			}
		}
		else if (cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
		{
			if (Disk2slice_printDataCount && TabletCharacter.tabletDivisionLineInfo != NONE_DIVISION_LINE)
			{
				if ((Disk2slice_printDataCount * 100 / Disk2printDataCount) < 90)
				{
					SplitLineSkipSW = 1;
				}

				if (abs(Disk2printDataCount - Disk2slice_printDataCount) < 50)
				{
					EngraveIsSplitLineSW = 1;
					onlySplitLineSW[printIndex] = 1;
				}
				else
				{
					EngraveIsSplitLineSW = 0;
					globalSplitPartialMatchingSW[printIndex] = 1;
				}

				if (Disk2slice_printDataCount > 4000)
				{
					bigSplitLineSW[printIndex] = 1;
				}
			}
		}

		tempRotateAngle = tempRotateAngleArray[printIndex];

		memset(printNoneMatchingArea, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
		memcpy(tempDentedArea, DentedArea, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
		if (SplitLineSkipSW || EngraveIsSplitLineSW == 0)
		{
			maxValue = -1;
			for (int k = 0; k <= 360; k += 360)
			{
				for (r = tempRotateAngle + k - printMatchingRangeAngle; r <= tempRotateAngle + k + printMatchingRangeAngle; r += 3)
				{
					temp_r = r;
					if (temp_r >= 720)
					{
						temp_r -= 720;
					}
					else if (temp_r < 0)
					{
						temp_r += 720;
					}

					if (!AllowedPrintAngle[temp_r])
						continue;

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

						for (m = 0; m < SmallPrintCoreDataCountFor3D; m += THREE_D_PRINT_ADD_M2)
						{
							if (ThreeDSplitLineData[m])
							{
								tempAddress = detailedCorePrintRotationAddressFor3D[temp_r][m] + shiftAddress;
								tempAddress = tempAddress + j;

								//if (tempAddress < 12800 || tempAddress > 296100) // 읽기만하므로 속도를 위해서 범위 무시.
								//	continue;

								matchingValueArray[0] += (DentedArea[tempAddress - 6400]);
								matchingValueArray[1] += (DentedArea[tempAddress - 5120]);
								matchingValueArray[2] += (DentedArea[tempAddress - 3840]);
								matchingValueArray[3] += (DentedArea[tempAddress - 2560]);
								matchingValueArray[4] += (DentedArea[tempAddress - 1280]);
								matchingValueArray[5] += (DentedArea[tempAddress]);
								matchingValueArray[6] += (DentedArea[tempAddress + 1280]);
								matchingValueArray[7] += (DentedArea[tempAddress + 2560]);
								matchingValueArray[8] += (DentedArea[tempAddress + 3840]);
								matchingValueArray[9] += (DentedArea[tempAddress + 5120]);
								matchingValueArray[10] += (DentedArea[tempAddress + 6400]);
							}
						}

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

								SplitLineAngle[printIndex] = temp_r;
								SplitLineShiftX[printIndex] = j;
								SplitLineShiftY[printIndex] = i * 2 - 10;
							}
						}
					}
				}
			}

			if (SplitLineSkipSW)
			{
				temp_r = SplitLineAngle[printIndex];
				for (m = 0; m < SmallPrintCoreDataCountFor3D; m += THREE_D_PRINT_ADD_M2)
				{
					if (ThreeDSplitLineData[m])
					{
						tempAddress = detailedCorePrintRotationAddressFor3D[temp_r][m] + shiftAddress;
						tempAddress = tempAddress + SplitLineShiftX[printIndex] + SplitLineShiftY[printIndex] * MAX_IMAGE_WIDTH;

						if (tempAddress < 12800 || tempAddress > 296100)
							continue;

						for (tempY = -3; tempY <= 3; tempY++)
						{
							for (tempX = -3; tempX <= 3; tempX++)
							{
								tempAddress2 = MAX_IMAGE_WIDTH * tempY + tempX;
								printNoneMatchingArea[tempAddress + tempAddress2] = 1;
							}
						}
					}
				}

				for (y = startY; y < endY; y++)
				{
					for (x = startX; x < endX; x++)
					{
						tempAddress = MAX_IMAGE_WIDTH * y + x;

						if (printNoneMatchingArea[tempAddress])
						{
							tempDentedArea[tempAddress] = 0;
						}
					}
				}
			}
		}

		// 여기서 인쇄의 방향이 결정된다.
		maxValue = -1;
		for (int k = 0; k <= 360; k += 360)
		{
			for (r = tempRotateAngle + k - printMatchingRangeAngle; r <= tempRotateAngle + k + printMatchingRangeAngle; r += 3)
			{
				temp_r = r;
				if (temp_r >= 720)
				{
					temp_r -= 720;
				}
				else if (temp_r < 0)
				{
					temp_r += 720;
				}
				
				if (!AllowedPrintAngle[temp_r])
					continue;

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

					for (m = 0; m < SmallPrintCoreDataCountFor3D; m += THREE_D_PRINT_ADD_M2)
					{
						if (SplitLineSkipSW && ThreeDSplitLineData[m]) // 분할선의 경우 방향 결정에서 제외한다. 안그러면 방해가 됨.
						{
							continue;
						}

						tempAddress = detailedCorePrintRotationAddressFor3D[temp_r][m] + shiftAddress;
						tempAddress = tempAddress + j;

						//if (tempAddress < 12800 || tempAddress > 296100) // 읽기만하므로 속도를 위해서 범위 무시.
						//	continue;

						matchingValueArray[0] += (tempDentedArea[tempAddress - 6400]);
						matchingValueArray[1] += (tempDentedArea[tempAddress - 5120]);
						matchingValueArray[2] += (tempDentedArea[tempAddress - 3840]);
						matchingValueArray[3] += (tempDentedArea[tempAddress - 2560]);
						matchingValueArray[4] += (tempDentedArea[tempAddress - 1280]);
						matchingValueArray[5] += (tempDentedArea[tempAddress]);
						matchingValueArray[6] += (tempDentedArea[tempAddress + 1280]);
						matchingValueArray[7] += (tempDentedArea[tempAddress + 2560]);
						matchingValueArray[8] += (tempDentedArea[tempAddress + 3840]);
						matchingValueArray[9] += (tempDentedArea[tempAddress + 5120]);
						matchingValueArray[10] += (tempDentedArea[tempAddress + 6400]);
					}

					for (i = 0; i < 11; i++)
					{
						if (matchingValueArray[i] > maxValue)
						{
							maxValue = matchingValueArray[i];
							printMatchingResultAngle[printIndex] = temp_r;
							printMatchingResultShiftX[printIndex] = j;
							printMatchingResultShiftY[printIndex] = i * 2 - 10;
						}
					}
				}
			}
		}


		if (ThreeDPrintNum != TWO_FACE_DIFF) // ThreeDPrintNum == ONE_FACE || ThreeDPrintNum == TWO_FACE_SAME
		{
			PrintMatchingResult.PrintRotationAngle = printMatchingResultAngle[0];
			PrintMatchingResult.PrintShiftX = printMatchingResultShiftX[0];
			PrintMatchingResult.PrintShiftY = printMatchingResultShiftY[0];

			if (SplitLineSkipSW)
			{
				temp_r = PrintMatchingResult.PrintRotationAngle;
				for (m = 0; m < SmallPrintCoreData1CountFor3D; m += 2)
				{
					if (ThreeDSplitLineData1[m])
					{
						tempAddress = detailedCorePrintRotationAddress1For3D[temp_r][m] + shiftAddress;
						tempAddress = tempAddress + PrintMatchingResult.PrintShiftX + PrintMatchingResult.PrintShiftY * MAX_IMAGE_WIDTH;

						if (tempAddress < 12800 || tempAddress > 296100)
							continue;

						maxValue += DentedArea[tempAddress];
					}
				}
			}

			shiftXfromZeroPos = PrintMatchingResult.PrintShiftX;
			shiftYfromZeroPos = PrintMatchingResult.PrintShiftY;

			PrintMatchingResult.PrintShiftX += shiftX;
			PrintMatchingResult.PrintShiftY += shiftY;

			break; // 인쇄가 1개이므로 루프 종료.
		}
		else // ThreeDPrintNum == TWO_FACE_DIFF
		{
			// 방향이 결정된 두개의 인쇄를 서로 비교하기 위하여 exclusiveMatchingCount 등을 구한다.
			memset(tempPrintArea, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

			temp_r = printMatchingResultAngle[printIndex];
			for (m = 0; m < SmallPrintCoreDataCountFor3D; m += 2)
			{
				tempAddress = detailedCorePrintRotationAddressFor3D[temp_r][m] + shiftAddress;
				tempAddress = tempAddress + printMatchingResultShiftX[printIndex] + printMatchingResultShiftY[printIndex] * MAX_IMAGE_WIDTH;

				if (tempAddress < 12800 || tempAddress > 296100)
					continue;

				for (tempY = -3; tempY <= 3; tempY++)
				{
					for (tempX = -3; tempX <= 3; tempX++)
					{
						tempAddress2 = MAX_IMAGE_WIDTH * tempY + tempX;
						tempPrintArea[tempAddress + tempAddress2] = 1;
					}
				}
			}

			standardMaxValue[printIndex] = 0;

			// 최종적으로 두개의 인쇄를 비교.
			if (printIndex == 1)
			{
				int printMachingCount[2];
				int printMatchingValue[2];
				int exclusiveMatchingCount[2];
				int eraseCount[2];
				int value;

				printMachingCount[0] = printMachingCount[1] = 0;
				printMatchingValue[0] = printMatchingValue[1] = 0;
				exclusiveMatchingCount[0] = exclusiveMatchingCount[1] = 0;
				eraseCount[0] = eraseCount[1] = 0;

				for (int printIndexTemp = 0; printIndexTemp <= 1; printIndexTemp++)
				{
					if (printIndexTemp == 0)
					{
						tempPrintArea = tempPrintArea1;
						tempPrintAreaOther = tempPrintArea2;
					}
					else
					{
						tempPrintArea = tempPrintArea2;
						tempPrintAreaOther = tempPrintArea1;
					}

					for (y = startY; y < endY; y++)
					{
						for (x = startX; x < endX; x++)
						{
							tempAddress = MAX_IMAGE_WIDTH * y + x;

							value = min(3, DentedArea[tempAddress]);

#ifdef PC_SIM
							if (tempPrintArea[tempAddress] && value)
								tempPrintArea[tempAddress] = 2;
#endif

							if (tempPrintArea[tempAddress])
							{
								printMatchingValue[printIndexTemp] += value;
								printMachingCount[printIndexTemp]++;

								if (value == 0)
								{
									eraseCount[printIndexTemp]++; // printMatchingValue에 삭제된 점의 효과가 포함되지만 삭제된 점의 개수에 대하여 가중하기 위하여 값을 별도로 누적함.
								}

								if (!tempPrintAreaOther[tempAddress] && value)
								{
									exclusiveMatchingCount[printIndexTemp]++; // 내쪽에만 매칭이 되고 다른쪽 각인은 매칭이 안될 때 중요한 차이가 발생하는 점으로 인정한다.
								}
							}
						}
					}
				}

				if (printMachingCount[0] && printMachingCount[1] && printMatchingValue[0] && printMatchingValue[1])
				{
					// 팜비오 정제처럼 매우 두껍고 큰 할선이 있는 경우 3D의 왜곡 현상 때문에 분할선의 매칭에서 큰 오차가 발생할 수 있다.
					// 그렇게 될 경우 분할선의 오차가 각인 판정에 과도하게 반영되어 분할선만 있는 것과 분할선과 글자가 함께 있는 것이 구분이 잘 안될 수 있다.
					// 따라서 분할선이 크고 둘중에 한쪽에는 분할선만 있는 경우 단순히 매칭되는 점의 개수를 비교하자.
					if (bigSplitLineSW[0] == 1 && bigSplitLineSW[1] == 1 && onlySplitLineSW[0] != onlySplitLineSW[1])
					{
						// 분할선이 크고 양쪽에 분할선이 있고 그중에 한쪽에는 분할선만 있는 경우. 점의 개수로만 판정.
						standardMaxValue[0] = 1000 * (printMachingCount[0] + exclusiveMatchingCount[0] * 10 - eraseCount[0]) / printMachingCount[0];
						standardMaxValue[1] = 1000 * (printMachingCount[1] + exclusiveMatchingCount[1] * 10 - eraseCount[1]) / printMachingCount[1];
					}
					else
					{
						// 그 외의 경우 기존의 판정 방식.
						standardMaxValue[0] = 1000 * printMatchingValue[0] / printMachingCount[0] * (printMachingCount[0] + exclusiveMatchingCount[0] * 10 - eraseCount[0]) / printMachingCount[0];
						standardMaxValue[1] = 1000 * printMatchingValue[1] / printMachingCount[1] * (printMachingCount[1] + exclusiveMatchingCount[1] * 10 - eraseCount[1]) / printMachingCount[1];
					}
				}

				if (standardMaxValue[1] < standardMaxValue[0])
				{
					shiftXfromZeroPos = printMatchingResultShiftX[0];
					shiftYfromZeroPos = printMatchingResultShiftY[0];

					PrintMatchingResult.PrintRotationAngle = printMatchingResultAngle[0];
					PrintMatchingResult.PrintShiftX = printMatchingResultShiftX[0] + shiftX;
					PrintMatchingResult.PrintShiftY = printMatchingResultShiftY[0] + shiftY;

					PrintMatchingResult.SplitRotationAngle = SplitLineAngle[0];
					PrintMatchingResult.SplitShiftX = SplitLineShiftX[0] + shiftX;
					PrintMatchingResult.SplitShiftY = SplitLineShiftY[0] + shiftY;

					maxValue = printMatchingValue[0];
				}
				else
				{
					shiftXfromZeroPos = printMatchingResultShiftX[1];
					shiftYfromZeroPos = printMatchingResultShiftY[1];

					PrintMatchingResult.PrintRotationAngle = printMatchingResultAngle[1];
					PrintMatchingResult.PrintShiftX = printMatchingResultShiftX[1] + shiftX;
					PrintMatchingResult.PrintShiftY = printMatchingResultShiftY[1] + shiftY;

					PrintMatchingResult.SplitRotationAngle = SplitLineAngle[1];
					PrintMatchingResult.SplitShiftX = SplitLineShiftX[1] + shiftX;
					PrintMatchingResult.SplitShiftY = SplitLineShiftY[1] + shiftY;

					maxValue = printMatchingValue[1];
				}
			}
		}
	}

	// 이제 인쇄1,2중 하나가 선택되었고 각도와 위치가 구해졌다.

	printIsOrNotThreshold = 500; // 초기값.

	if (ProcessingModeGlobal == INSPECTION_MODE)
	{
		maxPrintValue = 0;
		if (maxPrintValue < Tablet3DSetupData.Disk1printData1Count * Tablet3DSetupData.PrintAverageDepth[0][0])
			maxPrintValue = Tablet3DSetupData.Disk1printData1Count * Tablet3DSetupData.PrintAverageDepth[0][0];
		if (maxPrintValue < Tablet3DSetupData.Disk1printData2Count * Tablet3DSetupData.PrintAverageDepth[0][1])
			maxPrintValue = Tablet3DSetupData.Disk1printData2Count * Tablet3DSetupData.PrintAverageDepth[0][1];
		if (maxPrintValue < Tablet3DSetupData.Disk2printData1Count * Tablet3DSetupData.PrintAverageDepth[1][0])
			maxPrintValue = Tablet3DSetupData.Disk2printData1Count * Tablet3DSetupData.PrintAverageDepth[1][0];
		if (maxPrintValue < Tablet3DSetupData.Disk2printData2Count * Tablet3DSetupData.PrintAverageDepth[1][1])
			maxPrintValue = Tablet3DSetupData.Disk2printData2Count * Tablet3DSetupData.PrintAverageDepth[1][1];

		expectedNormalizeValue = (maxPrintValue / 1200) + 1;

		if (maxPrintValue > 1800 && expectedNormalizeValue >= 10) // 1800 = 각인 판정을 위한 기준치의 최대범위 (실제수치는 2000이지만 여유값 적용)
		{
			normalizeValue = expectedNormalizeValue * 80 / 100; // 80%
		}
		else
		{
			normalizeValue = 8;
		}

		if (ThreeDPrintNum == ONE_FACE || ThreeDPrintNum == TWO_FACE_SAME)
		{
			if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
			{
				printIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera5 * normalizeValue;
			}
			else if (cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
			{
				printIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera13 * normalizeValue;
			}
		}
		if (ThreeDPrintNum == TWO_FACE_DIFF)
		{
			if (standardMaxValue[1] < standardMaxValue[0])
			{
				if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera5 * normalizeValue;
				}
				else if (cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print1_IsOrNotThreshold_ForCamera13 * normalizeValue;
				}
			}
			else
			{
				if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print2_IsOrNotThreshold_ForCamera5 * normalizeValue;
				}
				else if (cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
				{
					printIsOrNotThreshold = TabletStudyData.Print2_IsOrNotThreshold_ForCamera13 * normalizeValue;
				}
			}
		}
	}
	else if (ProcessingModeGlobal == STUDY_MODE || ProcessingModeGlobal == FIRST_STUDY_MODE)
	{
		maxPrintValue = 0;
		if (maxPrintValue < Tablet3DSetupData.Disk1printData1Count * Tablet3DSetupData.PrintAverageDepth[0][0])
			maxPrintValue = Tablet3DSetupData.Disk1printData1Count * Tablet3DSetupData.PrintAverageDepth[0][0];
		if (maxPrintValue < Tablet3DSetupData.Disk1printData2Count * Tablet3DSetupData.PrintAverageDepth[0][1])
			maxPrintValue = Tablet3DSetupData.Disk1printData2Count * Tablet3DSetupData.PrintAverageDepth[0][1];
		if (maxPrintValue < Tablet3DSetupData.Disk2printData1Count * Tablet3DSetupData.PrintAverageDepth[1][0])
			maxPrintValue = Tablet3DSetupData.Disk2printData1Count * Tablet3DSetupData.PrintAverageDepth[1][0];
		if (maxPrintValue < Tablet3DSetupData.Disk2printData2Count * Tablet3DSetupData.PrintAverageDepth[1][1])
			maxPrintValue = Tablet3DSetupData.Disk2printData2Count * Tablet3DSetupData.PrintAverageDepth[1][1];

		// 1200 = 실제값은 아래의 기준값 1800이 들어가야하지만, 각인 추출과정에서 각인을 얇게 그린다던지 하는 경우에 point 개수가 실제와 달라 maxPrintvalue가 낮게 나올 수 있음
		expectedNormalizeValue = (maxPrintValue / 1200) + 1;

		if (maxPrintValue > 1800 && expectedNormalizeValue >= 10) // 1800 = 각인 판정을 위한 기준치의 최대범위 (실제수치는 2000이지만 여유값 적용)
		{
			normalizeValue = expectedNormalizeValue;
		}
		else
		{
			normalizeValue = 10;
		}

		if (ThreeDPrintNum == ONE_FACE || ThreeDPrintNum == TWO_FACE_SAME)
		{
			// *2 : Dented value의 최소값을 2로 제한
			printIsOrNotThreshold = SmallPrintCoreData1CountFor3D * 2;

			if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
			{
				TabletStudyData.Print1_IsOrNotThreshold_ForCamera5 = maxValue / normalizeValue;
				TabletStudyData.Print2_IsOrNotThreshold_ForCamera5 = 0;
			}
			else if (cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
			{
				TabletStudyData.Print1_IsOrNotThreshold_ForCamera13 = maxValue / normalizeValue;
				TabletStudyData.Print2_IsOrNotThreshold_ForCamera13 = 0;
			}
		}
		if (ThreeDPrintNum == TWO_FACE_DIFF)
		{
			if (standardMaxValue[1] < standardMaxValue[0])
			{
				if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera5 = maxValue / normalizeValue;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera5 = 0;
				}
				else if (cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera13 = maxValue / normalizeValue;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera13 = 0;
				}
			}
			else
			{
				if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera5 = 0;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera5 = maxValue / normalizeValue;
				}
				else if (cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
				{
					TabletStudyData.Print1_IsOrNotThreshold_ForCamera13 = 0;
					TabletStudyData.Print2_IsOrNotThreshold_ForCamera13 = maxValue / normalizeValue;
				}
			}
		}
	}

	PrintMatchingResult.dataNumberWithMaxValue = 2;

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

	if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
	{
		diskNumber = 0;
	}
	else if (cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
	{
		diskNumber = 1;
	}

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

	if (ProcessingModeGlobal == FIRST_STUDY_MODE)
	{
		memset(TempImage, 0, MAX_IMAGE_HEIGHT * MAX_IMAGE_WIDTH);
	}

	memset(printNoneMatchingArea, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

	if ((ThreeDPrintNum == ONE_FACE && printNumber == 0) || ThreeDPrintNum == TWO_FACE_SAME || ThreeDPrintNum == TWO_FACE_DIFF)
	{
		// 분할선 판정
		if (diskNumber == 0 && printNumber == 0)
		{
			allPrintCount = Tablet3DSetupData.Disk1printData1Count;
			SplitLineCount = Tablet3DSetupData.Disk1slice_printData1Count;
		}
		else if (diskNumber == 0 && printNumber == 1)
		{
			allPrintCount = Tablet3DSetupData.Disk1printData2Count;
			SplitLineCount = Tablet3DSetupData.Disk1slice_printData2Count;
		}
		else if (diskNumber == 1 && printNumber == 0)
		{
			allPrintCount = Tablet3DSetupData.Disk2printData1Count;
			SplitLineCount = Tablet3DSetupData.Disk2slice_printData1Count;
		}
		else if (diskNumber == 1 && printNumber == 1)
		{
			allPrintCount = Tablet3DSetupData.Disk2printData2Count;
			SplitLineCount = Tablet3DSetupData.Disk2slice_printData2Count;
		}

		EngraveIsSplitLineSW = 0;
		if (SplitLineCount && TabletCharacter.tabletDivisionLineInfo != NONE_DIVISION_LINE)
		{
			if (abs(allPrintCount - SplitLineCount) < 50)
			{
				EngraveIsSplitLineSW = 1;
			}
		}

		if (EngraveIsSplitLineSW)
		{
			PrintMatchingResult.PrintShiftX -= shiftXfromZeroPos;
			PrintMatchingResult.PrintShiftY -= shiftYfromZeroPos;
		}

		memset(ThreeDPrintPartialCheckArea, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

		labelPrintDataTotalCount = 0;
		for (n = 0; n < Tablet3DSetupData.printLabelCount[diskNumber][printNumber]; n++)
		{
			if (globalSplitPartialMatchingSW[printNumber] && !EngraveIsSplitLineSW)
			{
				if (ThreeDSplitLineLabel[diskNumber][printNumber][n])
				{
					// 분할선
					tempRotate = PrintMatchingResult.SplitRotationAngle;

					FinalMatchingShiftX = PrintMatchingResult.SplitShiftX;
					FinalMatchingShiftY = PrintMatchingResult.SplitShiftY;
				}
				else
				{
					// 이외
					tempRotate = PrintMatchingResult.PrintRotationAngle;

					FinalMatchingShiftX = PrintMatchingResult.PrintShiftX;
					FinalMatchingShiftY = PrintMatchingResult.PrintShiftY;
				}
			}
			else
			{
				tempRotate = PrintMatchingResult.PrintRotationAngle;

				FinalMatchingShiftX = PrintMatchingResult.PrintShiftX;
				FinalMatchingShiftY = PrintMatchingResult.PrintShiftY;
			}

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

			tempmaxValue = -1000;
			labelPrintDataTotalCount += Tablet3DSetupData.printLabelDataCnt[diskNumber][printNumber][n];
			Transform_printData.printDataCount = Tablet3DSetupData.printLabelDataCnt[diskNumber][printNumber][n];
			for (m = 0; m < Transform_printData.printDataCount; m++)
			{
				tempX = Tablet3DSetupData.printLabelData[diskNumber][printNumber][n][m][0];
				tempY = Tablet3DSetupData.printLabelData[diskNumber][printNumber][n][m][1];

				rotateX = ((tempX - HalfWidth) * cosValue - (tempY - HalfHeight) * sinValue) / 1024 + HalfWidth + FinalMatchingShiftX;
				rotateY = ((tempX - HalfWidth) * sinValue + (tempY - HalfHeight) * cosValue) / 1024 + HalfHeight + FinalMatchingShiftY;

				if (rotateX < 4)
					rotateX = 4;
				if (rotateX > MAX_IMAGE_WIDTH - 4)
					rotateX = MAX_IMAGE_WIDTH - 4;
				if (rotateY < 4)
					rotateY = 4;
				if (rotateY > MAX_IMAGE_HEIGHT - 4)
					rotateY = MAX_IMAGE_HEIGHT - 4;

				Transform_printData.Transform_position_printData[m][0] = rotateX;
				Transform_printData.Transform_position_printData[m][1] = rotateY;
			}

			for (i = -3; i <= 3; i += 2)
			{
				for (j = -3; j <= 3; j += 2)
				{
					matchingValue = 0;
					for (m = 0; m < Transform_printData.printDataCount; m++)
					{
						tempX = Transform_printData.Transform_position_printData[m][0] + j;
						tempY = Transform_printData.Transform_position_printData[m][1] + i;

						//if (tempX > 2 && tempX < MAX_IMAGE_WIDTH - 2 && tempY > 2 && tempY < MAX_IMAGE_HEIGHT - 2) // 읽기만하므로 속도를 위해서 범위 무시.
						{
							tempAddress = tempY * MAX_IMAGE_WIDTH + tempX;
							if (realPrintMaskingArea[tempAddress] == PRINT_AREA) // 글자끼리 겹치기 않게 하기 위해서
							{
								matchingValue = 0;
								break;
							}
							else
							{
								matchingValue += (DentedArea[tempAddress]);
								matchingValue += (DentedArea[tempAddress - 1]);
								matchingValue += (DentedArea[tempAddress + 1]);
							}
						}
					}

					if (matchingValue > tempmaxValue)
					{
						tempmaxValue = matchingValue;
						labelShiftX = j;
						labelShiftY = i;
					}
				}
			}

			if (EngraveIsSplitLineSW)
			{
				// 분할선이 나눠져있을리는 없으니..
				// shift정보는 모든 label이 동일해야함

				if (n == 0)
				{
					fstLabelShiftX = labelShiftX;
					fstLabelShiftY = labelShiftY;
				}
				else
				{
					labelShiftX = fstLabelShiftX;
					labelShiftY = fstLabelShiftY;
				}
			}

			if (ProcessingModeGlobal != FIRST_STUDY_MODE)
			{
				Transform_printData.printDataCount = 0;
				tempCount = 0;

				for (m = 0; m < Tablet3DSetupData.printLabelDataCnt[diskNumber][printNumber][n]; m++)
				{
					tempX = Tablet3DSetupData.printLabelData[diskNumber][printNumber][n][m][0];
					tempY = Tablet3DSetupData.printLabelData[diskNumber][printNumber][n][m][1];

					rotateX = ((tempX - HalfWidth) * cosValue - (tempY - HalfHeight) * sinValue) / 1024 + HalfWidth + FinalMatchingShiftX;
					rotateY = ((tempX - HalfWidth) * sinValue + (tempY - HalfHeight) * cosValue) / 1024 + HalfHeight + FinalMatchingShiftY;

					if (rotateX < 4)
						rotateX = 4;
					if (rotateX > MAX_IMAGE_WIDTH - 4)
						rotateX = MAX_IMAGE_WIDTH - 4;
					if (rotateY < 4)
						rotateY = 4;
					if (rotateY > MAX_IMAGE_HEIGHT - 4)
						rotateY = MAX_IMAGE_HEIGHT - 4;

					Transform_printData.Transform_position_printData[tempCount][0] = rotateX;
					Transform_printData.Transform_position_printData[tempCount][1] = rotateY;
					tempCount++;
				}

				realPrintBoundary = tempCount;

				// 가끔 인쇄 확장 영역이 뒤집힌 경우가 있는데 그것은 1차 학습을 안해줘서 그런 것이다.
				for (m = 0; m < Tablet3DSetupData.printLabelDataCntForExpandMasking[diskNumber][printNumber][n]; m++)
				{
					tempX = Tablet3DSetupData.printLabelDataForExpandMasking[diskNumber][printNumber][n][m][0];
					tempY = Tablet3DSetupData.printLabelDataForExpandMasking[diskNumber][printNumber][n][m][1];

					rotateX = ((tempX - HalfWidth) * cosValue - (tempY - HalfHeight) * sinValue) / 1024 + HalfWidth + FinalMatchingShiftX;
					rotateY = ((tempX - HalfWidth) * sinValue + (tempY - HalfHeight) * cosValue) / 1024 + HalfHeight + FinalMatchingShiftY;

					if (rotateX < 4)
						rotateX = 4;
					if (rotateX > MAX_IMAGE_WIDTH - 4)
						rotateX = MAX_IMAGE_WIDTH - 4;
					if (rotateY < 4)
						rotateY = 4;
					if (rotateY > MAX_IMAGE_HEIGHT - 4)
						rotateY = MAX_IMAGE_HEIGHT - 4;

					Transform_printData.Transform_position_printData[tempCount][0] = rotateX;
					Transform_printData.Transform_position_printData[tempCount][1] = rotateY;
					tempCount++;
				}
				Transform_printData.printDataCount = tempCount;

				for (m = 0; m < Transform_printData.printDataCount; m++)
				{
					tempX = Transform_printData.Transform_position_printData[m][0] + labelShiftX;
					tempY = Transform_printData.Transform_position_printData[m][1] + labelShiftY;

					tempAddress = MAX_IMAGE_WIDTH * tempY + tempX;

					if (m < realPrintBoundary)
					{
						realPrintMaskingArea[tempAddress] = PRINT_AREA;
					}
					else
					{
						realPrintMaskingArea[tempAddress] = EXPANDED_PRINT_AREA;
					}

					if (Tablet3DSetupData.printMaskData[diskNumber][printNumber][n][m])
					{
						ThreeDPrintPartialCheckArea[tempAddress] = 1;
					}

					for (i = tempY - 1; i <= tempY + 1; i++)
					{
						for (j = tempX - 1; j <= tempX + 1; j++)
						{
							if (j > 2 && j < MAX_IMAGE_WIDTH - 2 && i > 2 && i < MAX_IMAGE_HEIGHT - 2)
							{
								tempAddress = MAX_IMAGE_WIDTH * i + j;
								if (RotationThreeDImage[tempAddress])
								{
									if (realPrintMaskingArea[tempAddress] == 0)
									{
										realPrintMaskingArea[tempAddress] = FRONT_MASKING_AREA;
									}
								}
							}
						}
					}
				}
			}
			else
			{
				AverageDentedValue = tempCount = 0;
				for (m = 0; m < Transform_printData.printDataCount; m++)
				{
					tempX = Transform_printData.Transform_position_printData[m][0] + labelShiftX;
					tempY = Transform_printData.Transform_position_printData[m][1] + labelShiftY;

					for (i = tempY - 1; i <= tempY + 1; i++)
					{
						for (j = tempX - 1; j <= tempX + 1; j++)
						{
							if (j > 2 && j < MAX_IMAGE_WIDTH - 2 && i > 2 && i < MAX_IMAGE_HEIGHT - 2)
							{
								tempAddress = MAX_IMAGE_WIDTH * i + j;
								if (RotationThreeDImage[tempAddress])
								{
									realPrintMaskingArea[tempAddress] = PRINT_AREA;

									if (DentedArea[tempAddress])
									{
										AverageDentedValue += DentedArea[tempAddress];
										tempCount++;
									}
								}
							}
						}
					}
				}

				if (tempCount)
				{
					AverageDentedValue /= tempCount;
					AverageDentedValue /= 2;

					if (AverageDentedValue <= 1)
						AverageDentedValue = 2;
				}
				else
				{
					AverageDentedValue = 2;
				}

				for (m = 0; m < Transform_printData.printDataCount; m++)
				{
					tempX = Transform_printData.Transform_position_printData[m][0] + labelShiftX;
					tempY = Transform_printData.Transform_position_printData[m][1] + labelShiftY;

					for (i = tempY - 6; i <= tempY + 6; i++)
					{
						for (j = tempX - 6; j <= tempX + 6; j++)
						{
							if (j > 2 && j < MAX_IMAGE_WIDTH - 2 && i > 2 && i < MAX_IMAGE_HEIGHT - 2)
							{
								tempAddress = MAX_IMAGE_WIDTH * i + j;
								if (RotationThreeDImage[tempAddress] && realPrintMaskingArea[tempAddress] != PRINT_AREA)
								{
									if (DentedArea[tempAddress] >= AverageDentedValue)
									{
										// 역방향 회전.
										reverseTransX = ((j - labelShiftX - HalfWidth - FinalMatchingShiftX) * cosValue + (i - labelShiftY - HalfHeight - FinalMatchingShiftY) * sinValue) / 1024 + HalfWidth;
										reverseTransY = (-(j - labelShiftX - HalfWidth - FinalMatchingShiftX) * sinValue + (i - labelShiftY - HalfHeight - FinalMatchingShiftY) * cosValue) / 1024 + HalfHeight;

										if (reverseTransX > 2 && reverseTransX < MAX_IMAGE_WIDTH - 2 && reverseTransY > 2 && reverseTransY < MAX_IMAGE_HEIGHT - 2)
											TempImage[MAX_IMAGE_WIDTH * reverseTransY + reverseTransX] = n + 1;
									}
								}
							}
						}
					}
				}
			}
		}

		if (ProcessingModeGlobal == INSPECTION_MODE)
		{
			memset(tempPrintArea1, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
			option_EngraveIntensity = TabletGradeData.ETC_PartialThreeDStampDefectIntensity;
			option_EngraveDefectSize = TabletGradeData.ETC_PartialThreeDStampDefectSize;

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

			notPrintArea = 0;
			for (y = startY; y <= endY; y++)
			{
				for (x = startX; x <= endX; x++)
				{
					tempAddress = MAX_IMAGE_WIDTH * y + x;

					if (realPrintMaskingArea[tempAddress] == PRINT_AREA && !noneGradientArea[tempAddress])
					{
						// 모서리에 치우친 각인은 지워짐 판정 대상에서 제외
						checkSW = 0;
						for (i = y - 3; i <= y + 3; i++)
						{
							for (j = x - 3; j <= x + 3; j++)
							{
								if (j > 2 && j < MAX_IMAGE_WIDTH - 2 && i > 2 && i < MAX_IMAGE_HEIGHT - 2)
								{
									tempAddress2 = MAX_IMAGE_WIDTH * i + j;
									if (RotationThreeDImage[tempAddress2])
									{
										if (DentedArea[tempAddress2] >= AllowEngraveLv)
										{
											checkSW = 1;
										}
									}
								}
							}
						}

						if (checkSW == 0)
						{
							notPrintArea++;

#ifdef PC_SIM
							tempDentedArea[tempAddress] = 1;
#endif
						}

						if (ThreeDPrintPartialCheckArea[tempAddress])
						{
							// 모서리에 치우친 각인은 지워짐 판정 대상에서 제외
							checkSW = 0;
							for (i = y - 3; i <= y + 3; i++)
							{
								for (j = x - 3; j <= x + 3; j++)
								{
									if (j > 2 && j < MAX_IMAGE_WIDTH - 2 && i > 2 && i < MAX_IMAGE_HEIGHT - 2)
									{
										tempAddress2 = MAX_IMAGE_WIDTH * i + j;
										if (RotationThreeDImage[tempAddress2])
										{
											if (DentedArea[tempAddress2] >= option_EngraveIntensity)
											{
												checkSW = 1;
											}
										}
									}
								}
							}

							if (checkSW == 0)
							{
								tempPrintArea1[tempAddress] = 1;
							}
						}
					}
				}
			}

			if (notPrintArea > TabletGradeData.option_PrintMark_Intensity * labelPrintDataTotalCount / 100)
			{
				if (labelPrintDataTotalCount > 0)
					erasePercentage = (notPrintArea / (float)(labelPrintDataTotalCount)) * 100;
				else
					erasePercentage = 0;

				DefectSW = 1;
				DefectInformationWrite(DEFECT_3D_PRINT_ERASE, cameraIndex, 0, 0, 0, 0, erasePercentage);
			}

			if (TabletGradeData.ETC_Partial3DPrintCheckSW)
			{
				if (DefectSW == 0)
				{
					label_Image = RotationEdgeImage;
					memset(label_Image, 0, sizeof(short) * MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
					printLabelN = PrintLabeling(tempPrintArea1, label_Image, startX, endX, startY, endY);

					for (m = 1; m <= printLabelN; m++)
					{
						if (labelingPxCount[m] > option_EngraveDefectSize)
						{
							DefectSW = 1;
							DefectInformationWrite(DEFECT_3D_PRINT_ERASE_PARTIAL, cameraIndex, LabelStX[m], LabelEdX[m], LabelStY[m], LabelEdY[m], labelingPxCount[m]);

#ifdef PC_SIM
							memcpy(tempDentedArea, tempPrintArea1, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
#endif
							break;
						}
					}
				}
			}
		}

		// 원본이미지에 매칭
		for (y = startY; y <= endY; y++)
		{
			for (x = startX; x <= endX; x++)
			{
				tempAddress = MAX_IMAGE_WIDTH * y + x;

				if (realPrintMaskingArea[tempAddress] == PRINT_AREA || realPrintMaskingArea[tempAddress] == EXPANDED_PRINT_AREA)
				{
					RealX = ThreeDRotationShiftArray[tempAddress][0];
					RealY = ThreeDRotationShiftArray[tempAddress][1];

					for (tempY = -(2 + printAreaMask); tempY <= (2 + printAreaMask); tempY++)
					{
						for (tempX = -(2 + printAreaMask); tempX <= (2 + printAreaMask); tempX++)
						{
							tempX2 = RealX + tempX;
							tempY2 = RealY + tempY;
							if (tempX2 > 10 && tempX2 < MAX_IMAGE_WIDTH - 10 && tempY2 > 10 && tempY2 < MAX_IMAGE_HEIGHT - 10)
							{
								tempAddress2 = MAX_IMAGE_WIDTH * tempY2 + tempX2;

								if (AdjustThreeD_Data[tempAddress2])
								{
									InspectionArea[tempAddress2] = PRINT_AREA;
								}
							}
						}
					}
				}
			}
		}

#ifdef PC_SIM
		if (DefectSW)
		{
			memset(LabelImage_Virtual, 0, sizeof(short) * MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
			for (y = startY; y <= endY; y++)
			{
				for (x = startX; x <= endX; x++)
				{
					tempAddress = MAX_IMAGE_WIDTH * y + x;
					if (tempDentedArea[tempAddress])
					{
						RealX = ThreeDRotationShiftArray[tempAddress][0];
						RealY = ThreeDRotationShiftArray[tempAddress][1];
						if (RealX > 10 && RealX < MAX_IMAGE_WIDTH - 10 && RealY > 10 && RealY < MAX_IMAGE_HEIGHT - 10)
						{
							tempAddress2 = MAX_IMAGE_WIDTH * RealY + RealX;
							LabelImage_Virtual[tempAddress2] = 0xFF;
						}
					}
				}
			}
		}
#endif
	}
}
//---------------------------------------------------------------------------
