//---------------------------------------------------------------------------
// For SELMA200, 20180223, moon, 완료
// CameraIndex 관련 수정 완료
//---------------------------------------------------------------------------

#include <vcl.h>
#include <math.h>
#include <jpeg.hpp>
#pragma hdrstop

#include "DefectInfo_Form.h"
#include "Environment.h"
#include "Progress_Form.h"
#include "Keyboard_Form.h"
#include "AbstractDB.h"
#include "ThreeDImageViewer_Form.h"
#include "MultiLanguage.h"
#include "RealSizeImage_Form.h"
#include "TPBCameraSetting_Form.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "TntExtCtrls"
#pragma link "TntGrids"
#pragma link "TntStdCtrls"
#pragma resource "*.dfm"
TDefectInfoForm *DefectInfoForm;
//---------------------------------------------------------------------------
#define DEFECT_SERIES_STAIN			  0
#define DEFECT_SERIES_DIRTY			  1
#define DEFECT_SERIES_COLOR_DIRTY	2
#define DEFECT_SERIES_COLOR			  3
#define DEFECT_SERIES_CRACK			  4
#define DEFECT_SERIES_PRINT			  5
#define DEFECT_SERIES_UNINS			  6
#define DEFECT_SERIES_OTHER			  7

#define SORT_BY_TIME_ASCENDING_ORDER		    0
#define SORT_BY_TIME_DESCENDING_ORDER		    1
#define SORT_BY_SIZE_ASCENDING_ORDER		    2
#define SORT_BY_SIZE_DESCENDING_ORDER		    3
#define SORT_BY_CAMERA_ASCENDING_ORDER		  4
#define SORT_BY_CAMERA_DESCENDING_ORDER		  5

unsigned char OriginalImage[SYSTEM_CAMERA_HD_WIDTH * SYSTEM_CAMERA_HD_HEIGHT * 3];

//---------------------------------------------------------------------------
__fastcall TDefectInfoForm::TDefectInfoForm(TComponent* Owner)
	: TTntForm(Owner)
{
	if (DefaultLCID == 1028 || DefaultLCID == 2052 || DefaultLCID == 3076 || DefaultLCID == 4100)
  {
		ComponentSetFontName(this, "SimSun");
    SavedDefectImage->Canvas->Font->Name = "SimSun";
  }
	else if (DefaultLCID == 1041)
  {
		ComponentSetFontName(this, "Meiryo UI");
    SavedDefectImage->Canvas->Font->Name = "Meiryo UI";
  }
  else if(DefaultLCID == 3082)
  {
    ComponentSetFontName(this, "Segoe UI");
    ComponentSetMultiLine(this);
  }
  else
    SavedDefectImage->Canvas->Font->Name = "Malgun Gothic";

	GetDefaultString();

  if(ProductData.SubSamplingMode == IMAGE_FULL_SCALE_MODE)
  {
    SourceImageWidth[0] = SYSTEM_CAMERA_HD_WIDTH;
    SourceImageHeight[0] = SYSTEM_CAMERA_HD_HEIGHT;

    SourceImageWidth[1] = SYSTEM_CAMERA_WIDTH;
    SourceImageHeight[1] = SYSTEM_CAMERA_HEIGHT;

    rate[0] = 2;
    rate[1] = 1;
    FontSizeAdjust[0] =  3;// Font 12*2 - 6  2D ERROR
    FontSizeAdjust[1] =  0; // 3D ERROR
  }
  else
  {
    SourceImageWidth[0] = SYSTEM_CAMERA_WIDTH;
    SourceImageHeight[0] = SYSTEM_CAMERA_HEIGHT;

    SourceImageWidth[1] = SYSTEM_CAMERA_WIDTH;
    SourceImageHeight[1] = SYSTEM_CAMERA_HEIGHT;

    rate[0] = 1;
    rate[1] = 1;
    FontSizeAdjust[0] =  0;
    FontSizeAdjust[1] =  0;
  }

  SavedDefectImage->Canvas->Font->Style = TFontStyles() << fsBold;


	ProductCode = "";
	LOTName = "";

	ProcessingPCSIM = false;
	bEngraveDefect = false;

	threeDProcessingStep = THREED_NONE_STEP;

	SavedDefectImage->Width = SYSTEM_CAMERA_WIDTH;
	SavedDefectImage->Height = SYSTEM_CAMERA_HEIGHT;
	SavedDefectImage->Picture->Bitmap->Width = SYSTEM_CAMERA_WIDTH;
	SavedDefectImage->Picture->Bitmap->Height = SYSTEM_CAMERA_HEIGHT;
	SavedDefectImage->Picture->Bitmap->PixelFormat = pf24bit;

	for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
	{
		TTntImage *anImage = (TTntImage *)FindComponent("DefectImage" + IntToStr(globalCameraIndex + 1));
		anImage->Picture->Bitmap->Width = SYSTEM_CAMERA_WIDTH;
		anImage->Picture->Bitmap->Height = SYSTEM_CAMERA_HEIGHT;
		anImage->Picture->Bitmap->PixelFormat = pf24bit;
	}

	DefectDataList = new TList;
	DefectViewList = new TList;

	FilterCameraMask = 0xFFFFFFFF;
	FilterDefectSeriesMask = 0xFFFFFFFF;

	SortMethod = SORT_BY_TIME_DESCENDING_ORDER;

	ScrollImage->Picture->Bitmap->Width = ScrollImage->Width;
	ScrollImage->Picture->Bitmap->Height = ScrollImage->Height;
	ScrollImage->Picture->Bitmap->PixelFormat = pf24bit;
	for (int y = 0; y < ScrollImage->Height; y++)
	{
		byte *pBitmap = (byte *)ScrollImage->Picture->Bitmap->ScanLine[y];
		byte colorB = 0xFF - abs(y - ScrollImage->Height / 2) * 0x4F / (ScrollImage->Height / 2);
		byte colorG = 0x7F - abs(y - ScrollImage->Height / 2) * 0x1F / (ScrollImage->Height / 2);
		byte colorR = 0x7F - abs(y - ScrollImage->Height / 2) * 0x1F / (ScrollImage->Height / 2);
		if (y % 10 == 0)
		{
			colorB = colorG = colorR = 0;
		}

		for (int x = 0; x < ScrollImage->Width; x++)
		{
			pBitmap[x * 3] = colorB;
			pBitmap[x * 3 + 1] = colorG;
			pBitmap[x * 3 + 2] = colorR;
		}
	}

	CurrentDefectStX = 0;
	CurrentDefectStY = 0;
	CurrentDefectEdX = 0;
	CurrentDefectEdY = 0;

	GlobalCameraIndex = 0;
	IsScrollImageMouseDown = false;

	ScrollGroupBox->DoubleBuffered = true;
	DefectImagePanel->DoubleBuffered = true;

	SavedDefectData.GlobalCameraIndex = -1;
	SavedDefectData.TabletNumber = 0;

	Current3DBitmap = new Graphics::TBitmap;

	zoomInOutShiftX = 0;
	zoomInOutShiftY = 0;
	zoomInOutSize = 2;
	zoomImageNavigateFlag = 0;
	navigateStdX = 0;
	navigateStdY = 0;
	zoomROIX1 = 0;
	zoomROIY1 = 0;
	zoomROIX2 = 0;
	zoomROIY2 = 0;

	CurrentDefectStX = 0;
	CurrentDefectStY = 0;
	CurrentDefectEdX = 0;
	CurrentDefectEdY = 0;

	Panel7->Color = clBlack;
	Panel8->Color = clBlack;

	ZoomSizeLabel->Caption = "x " + IntToStr(zoomInOutSize);

  CurrentViewStepCount = 1;
  EnableScroll = true;

  ExtractedPrintInfoImage->Visible = false;
  PrintInfoPanel->Visible = false;
  ThreeDDebugInfoPanel->Visible = false;
  ThreeDDebugButton->Caption = "3D Debug (Off)";
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::GetDefaultString()
{
	RefreshButton->Caption = DEFECTINFOFORM_BUTTON_CAPTION_01;
	GroupBox5->Caption = DEFECTINFOFORM_GROUPBOX_CAPTION_01;
	GroupBox3->Caption = DEFECTINFOFORM_GROUPBOX_CAPTION_02;
	ScrollGroupBox->Caption = DEFECTINFOFORM_GROUPBOX_CAPTION_03;
	GroupBox2->Caption = DEFECTINFOFORM_GROUPBOX_CAPTION_04;
	FilterCameraFrontPanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_01;
	FilterCameraSidePanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_02;
	FilterCameraOptionPanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_03;
	FilterSeriesPanel6->Caption = DEFECTINFOFORM_PANEL_CAPTION_04;
	FilterSeriesPanel8->Caption = DEFECTINFOFORM_PANEL_CAPTION_05;
	FilterSeriesPanel7->Caption = DEFECTINFOFORM_PANEL_CAPTION_06;
	Panel30->Caption = DEFECTINFOFORM_PANEL_CAPTION_07;
	Panel17->Caption = DEFECTINFOFORM_PANEL_CAPTION_08;
	FilterSeriesPanel4->Caption = DEFECTINFOFORM_PANEL_CAPTION_09;
	FilterSeriesPanel3->Caption = DEFECTINFOFORM_PANEL_CAPTION_10;
	SortByTimePanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_13;
	FilterCameraAllPanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_14;
	FilterSeriesAllPanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_14;
	FilterSeriesPanel2->Caption = DEFECTINFOFORM_PANEL_CAPTION_15;
	SortByCameraPanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_16;
	SortBySizePanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_19;
	FilterSeriesPanel5->Caption = DEFECTINFOFORM_PANEL_CAPTION_22;
	FilterSeriesPanel1->Caption = DEFECTINFOFORM_PANEL_CAPTION_23;

  ErrorMsg[0] = DEFECTINFOFORM_MSG_01;
  ErrorMsg[1] = DEFECTINFOFORM_MSG_02;
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::ReadDataButton1Click(TObject *Sender)
{
	int spbIndex = StrToInt(SPBIndexEdit->Text) - 1;
	int cpbIndex = StrToInt(CPBIndexEdit->Text) - 1;
	struct
	{
		int DataType;
		int CPBIndex;
	} requestData;

	requestData.CPBIndex = cpbIndex;
	requestData.DataType = 0;

	if (Comm_Request(COMM_SPB + spbIndex, CMD_READ_CPB_IMAGE, &requestData, sizeof(requestData),
		CPBImage, SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT * 4))
	{
		// draw image
		SavedDefectImage->Picture->Bitmap->Height = SYSTEM_CAMERA_HEIGHT;
		SavedDefectImage->Picture->Bitmap->Width = SYSTEM_CAMERA_WIDTH;
		SavedDefectImage->Picture->Bitmap->PixelFormat = pf24bit;

		int globalCameraIndex;
		for (globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
		{
			if (CameraMapInfo[globalCameraIndex].SPBIndex == spbIndex &&
				SPBSystemSetupData[spbIndex].CameraDistributionIndex[cpbIndex] == 0xFF)
			{
				break;
			}
		}
		if (globalCameraIndex == SYSTEM_TOTAL_CAMERA_COUNT)
		{
			globalCameraIndex = 0;
		}

    // to do: 3d 용 width와 height로 변경할 것
    for (int y = 0; y < SYSTEM_CAMERA_HEIGHT; y++)
    {
      byte *pBitmap = (byte *)SavedDefectImage->Picture->Bitmap->ScanLine[y];
      byte *pCPBImage = &CPBImage[y * SYSTEM_CAMERA_WIDTH];
      byte *pInsp = &CPBImage[SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT * 3 + y * SYSTEM_CAMERA_WIDTH];
      for (int x = 0; x < SYSTEM_CAMERA_WIDTH; x++)
      {
        pBitmap[x * 3] = pCPBImage[x];
        pBitmap[x * 3 + 1] = pCPBImage[x];
        pBitmap[x * 3 + 2] = pCPBImage[x];

        if(pInsp[x] == SIDE_SHAPE_BOTTOM_EDGE_SHORT_NEIGHBOR)
        {
          pBitmap[3*x] = 255;
          pBitmap[3*x+1] = pCPBImage[x];
          pBitmap[3*x+2] = 255;
        }
        else if(pInsp[x] == SIDE_SHAPE_BOTTOM_EDGE_LONG_NEIGHBOR)
        {
          pBitmap[3*x] = pCPBImage[x];
          pBitmap[3*x+1] = 255;
          pBitmap[3*x+2] = 255;
        }
        else if (pInsp[x] == SIDE_SHAPE_TOP_NORMAL_BOUNDARY_AREA)
        {
          pBitmap[3 * x] = 0;
          pBitmap[3 * x + 1] = min(pCPBImage[x] + 60, 255);
          pBitmap[3 * x + 2] = min(pCPBImage[x] + 60, 255);
        }
        else if (pInsp[x] == SIDE_SHAPE_UNINSPECTION_AREA)
        {
          pBitmap[3 * x] = min(pCPBImage[x] + 60, 255);
          pBitmap[3 * x + 1] = min(pCPBImage[x] + 60, 255);
          pBitmap[3 * x + 2] = 0;
        }
        else if(pInsp[x] == SIDE_SHAPE_TOP_EDGE_UPPER_NEIGHBOR)
        {
          pBitmap[3*x] = pCPBImage[x];
          pBitmap[3*x+1] = pCPBImage[x];
          pBitmap[3*x+2] = min(pCPBImage[x] + 60, 255);
        }
        else if(pInsp[x] == NORMAL_INPECTION_AREA)
        {
          pBitmap[3*x] = pCPBImage[x];
          pBitmap[3*x+1] = pCPBImage[x];
          pBitmap[3*x+2] = min(pCPBImage[x] + 60, 255);
        }
        else if(pInsp[x] == NORMAL_INPECTION_AREA2)
        {
          pBitmap[3*x] = pCPBImage[x];
          pBitmap[3*x+1] = min(pCPBImage[x] + 60, 255);
          pBitmap[3*x+2] = pCPBImage[x];
        }
        else if (pInsp[x] == SIDE_SHAPE_MULTI_TABLET_BOUNDARY_AREA)
        {
          pBitmap[3*x] = 0;
          pBitmap[3*x+1] = min(pCPBImage[x] + 60, 255);
          pBitmap[3*x+2] = min(pCPBImage[x] + 60, 255);
        }
      }
    }

    SavedDefectImage->Repaint();
	}
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::FormCreate(TObject *Sender)
{
  try
  {
    if (!ReadSetupData(&TabletSetupData))
    {
      ShowMessageW(ErrorMsg[0]);
    }

    if (!ReadStudyData(&TabletStudyData))
    {
      ShowMessageW(ErrorMsg[1]);
    }

    if (!CPBSetupInfo.InspectionSetupDataValid)
    {
      setPosSetupData(&TabletSetupData);
    }

    MakeTabletCharacterData(&ProductData, &TabletCharacter, &MachineParams);
    CPBCommonVariableInitial();

    SideFaceSetUpDataTransForm_For_PCSIM(tempSideData);
    /////////////////////////////////////////////////////////////////////////////

    FilterCameraOptionPanel->Visible = true;

    DefectStringGrid->ColWidths[0] = 100;
    DefectStringGrid->ColWidths[1] = DefectStringGrid->Width - 130;

    DefectListStringGrid->ColWidths[0] = 80;
    DefectListStringGrid->ColWidths[2] = 80;
    DefectListStringGrid->ColWidths[3] = 80;
    DefectListStringGrid->ColWidths[1] = max(0, DefectListStringGrid->Width - 30 - 80 - 80 - 80);

    CurrentDisplayImage = new Graphics::TBitmap();
    CurrentDisplayImage->Width = MAX_IMAGE_WIDTH;
    CurrentDisplayImage->Height = MAX_IMAGE_HEIGHT;
    CurrentDisplayImage->PixelFormat = pf24bit;

    GroupBox1->DoubleBuffered = true;

    ZoomInImage->Canvas->Pen->Color = clBlack;
    ZoomInImage->Canvas->Brush->Color = clBlack;
    ZoomInImage->Canvas->Brush->Style = bsSolid;
    ZoomInImage->Canvas->Rectangle(0, 0, ZoomInImage->Width, ZoomInImage->Height);

    zoomInOutImage->Canvas->Pen->Color = clBlack;
    zoomInOutImage->Canvas->Brush->Color = clBlack;
    zoomInOutImage->Canvas->Brush->Style = bsSolid;
    zoomInOutImage->Canvas->Rectangle(0, 0, zoomInOutImage->Width, zoomInOutImage->Height);

    bMouseDown = false;
    MouseDownStartTime = GetTickCount();
    FullSizeImageLoadTimer->Enabled = false;
    ProgressBar1->Visible = false;

    ThreeDLaserInfoViewerCheckBox->Visible = false;
    ThreeDLaserInfoViewerCheckBox->Checked = false;
    DepthRefImage->Visible = false;
    
    if(MachineSetupData.LasercomplexerInfo.Laser_complexer_Enable)
    {
      bViewThreeDPositionInfo = true;
    }
    else
    {
      bViewThreeDPositionInfo = false;
    }

    //SetDepthbar();
  }
  catch(...)
  {
    WritePCProgramErrorLog(this->Name, __LINE__);
  }

	CheckTPB_BoardExist();
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::ReadDataButton2Click(TObject *Sender)
{
	int spbIndex = StrToInt(SPBIndexEdit->Text) - 1;
	int cpbIndex = StrToInt(CPBIndexEdit->Text) - 1;

	struct
	{
		int DataType;
		int CPBIndex;
	} requestData;

	requestData.CPBIndex = cpbIndex;
	requestData.DataType = 1;

	if (Comm_Request(COMM_SPB + spbIndex, CMD_READ_CPB_IMAGE, &requestData, sizeof(requestData),
		CPBImage, SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT * 5))
	{
		// draw image
		SavedDefectImage->Picture->Bitmap->Height = SYSTEM_CAMERA_HEIGHT;
		SavedDefectImage->Picture->Bitmap->Width = SYSTEM_CAMERA_WIDTH;
		SavedDefectImage->Picture->Bitmap->PixelFormat = pf24bit;

		int globalCameraIndex;
		for (globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
		{
			if (CameraMapInfo[globalCameraIndex].SPBIndex == spbIndex &&
				SPBSystemSetupData[spbIndex].CameraDistributionIndex[cpbIndex] == 0xFF)
			{
				break;
			}
		}
		if (globalCameraIndex == SYSTEM_TOTAL_CAMERA_COUNT)
		{
			globalCameraIndex = 0;
		}

    // to do: 3d 용 width와 height로 변경할 것
    for (int y = 0; y < SYSTEM_CAMERA_HEIGHT; y++)
    {
      byte *pBitmap = (byte *)SavedDefectImage->Picture->Bitmap->ScanLine[y];
      byte *pCPBImage = &CPBImage[y * SYSTEM_CAMERA_WIDTH];
      unsigned short *pLabel = (unsigned short *)&CPBImage[SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT * 3 + y * SYSTEM_CAMERA_WIDTH * 2];
      for (int x = 0; x < SYSTEM_CAMERA_WIDTH; x++)
      {
        pBitmap[x * 3] = pCPBImage[x];
        pBitmap[x * 3 + 1] = pCPBImage[x];
        pBitmap[x * 3 + 2] = pCPBImage[x];
        if (pLabel[x] == 55)
        {
          pBitmap[x * 3] = 0;
          pBitmap[x * 3 + 1] = 0;
          pBitmap[x * 3 + 2] = 0xFF;
        }
        else if (pLabel[x] != 0)
        {
          pBitmap[x * 3] = (pLabel[x] * 17) & 0xFF;
          pBitmap[x * 3 + 1] = (pLabel[x] * 41) & 0xFF;
          pBitmap[x * 3 + 2] = (pLabel[x] * 73) & 0xFF;
        }
      }
    }
		SavedDefectImage->Repaint();
	}
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::ResetDefectData(void)
{
	SavedDefectIndex = 0;
	while (DefectDataList->Count)
	{
		TDefectDataUnit *aDefectDataUnit = (TDefectDataUnit *)DefectDataList->First();
		DefectDataList->Remove(aDefectDataUnit);
		delete aDefectDataUnit;
	}

	RefreshStringGrid();
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::ShowDefectInfo(void)
{
	DefectStringGrid->Cells[0][1] = DEFECTINFOFORM_STRGRID_CELL_03;
	DefectStringGrid->Cells[0][2] = DEFECTINFOFORM_STRGRID_CELL_04;
	DefectStringGrid->Cells[0][3] = DEFECTINFOFORM_STRGRID_CELL_01;
	DefectStringGrid->Cells[0][4] = DEFECTINFOFORM_STRGRID_CELL_05;

	DefectStringGrid->Cells[1][1] = IntToStr(SavedDefectData.TabletNumber);
	DefectStringGrid->Cells[1][2] = ConvertCameraIndex(SavedDefectData.GlobalCameraIndex);
	DefectStringGrid->Cells[1][3] = GetDefectSeriesStr(SavedDefectData.CPBDefectInfo.defectSeries);

	if (SavedDefectData.CPBDefectInfo.defectSeries == FAT_TALBET || SavedDefectData.CPBDefectInfo.defectSeries == THIN_TALBET) // 화면에 표시 되는 Size는 기준 두께보다 얼마나 두껍고 얇은 정제인지를 표시함
		DefectStringGrid->Cells[1][4] = FloatToStr((float)SavedDefectData.CPBDefectInfo.size * 30 / 1000.0) + " mm";
	else if (SavedDefectData.CPBDefectInfo.defectSeries == DEFECT_3D_PRINT_ERASE)
		DefectStringGrid->Cells[1][4] = FloatToStr(SavedDefectData.CPBDefectInfo.size) + " %";
  else if (SavedDefectData.CPBDefectInfo.defectSeries == DEFECT_FRONT_WHITE_ENGRAVE)
    DefectStringGrid->Cells[1][4] = IntToStr(SavedDefectData.CPBDefectInfo.size) + " Grade";
  else if(SavedDefectData.CPBDefectInfo.defectSeries == DEFECT_PRINT_POSITION_ERROR)
    DefectStringGrid->Cells[1][4] = FloatToStr(SavedDefectData.CPBDefectInfo.size*0.04) + " mm";
  else if(SavedDefectData.CPBDefectInfo.defectSeries == DEFECT_PRINT_ROTATION_ERROR)
    DefectStringGrid->Cells[1][4] = IntToStr(SavedDefectData.CPBDefectInfo.size) + " Degree";
	else
		DefectStringGrid->Cells[1][4] = FloatToStr(DefectSizePixelToMili(SavedDefectData.CPBDefectInfo.size) / 100.0) + "mm";
}

//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::InitDefectInfo(WideString productCode, WideString lotName, int shiftstep, bool Inspectionstatus)
{
	if (EnableScroll == false)
		return ;

	ExtractedPrintInfoImage->Visible = false;
	PrintInfoPanel->Visible = false;

	ProductCode = productCode;
	LOTName = lotName;
	InspectionSataus = Inspectionstatus;

	EnableScroll = false;

	while (DefectDataList->Count)
	{
		TDefectDataUnit *aDefectDataUnit = (TDefectDataUnit *)DefectDataList->First();
		DefectDataList->Remove(aDefectDataUnit);
		delete aDefectDataUnit;
	}

	if (!DefectDataDB.ConnectTable(productCode, lotName, Inspectionstatus))
	{
		RefreshStringGrid();
		return ;
	}


	TProgressForm *progressForm = new TProgressForm(this, true);
	progressForm->Text = DEFECTINFOFORM_PROGRESSBAR_TEXT_01;
	progressForm->Show();
	progressForm->Repaint();

	int readDefectDataCount = 0;
	int LIMIT = 0;
	int DefectStartIndex = 0;

	MaxLimitViewStepCount = (DefectDataDB.DataCount) / LIMIT_NOT_INSPECTION_DEFECT_COUNT;

	if ((DefectDataDB.DataCount % LIMIT_NOT_INSPECTION_DEFECT_COUNT) != 0)
		MaxLimitViewStepCount += 1;


	if (shiftstep == -1)
	{
		if (CurrentViewStepCount != 1)
			CurrentViewStepCount -= 1;
	}
	else if (shiftstep == 1)
	{
		if (CurrentViewStepCount != MaxLimitViewStepCount)
			CurrentViewStepCount += 1;
	}

	if (InspectionSataus)
	{
		DefectViewStepControlPanel->Visible = false;
		DefectStartIndex = DefectDataDB.DataCount - 1 - ((CurrentViewStepCount - 1) * LIMIT_INSPECTION_DEFECT_COUNT); // 여기가 -1하는게 맞나?
		LIMIT = DefectStartIndex - LIMIT_INSPECTION_DEFECT_COUNT;
		if (LIMIT < 0 )
			LIMIT = 0;
		progressForm->Max = DefectDataDB.DataCount - (DefectDataDB.DataCount - LIMIT_INSPECTION_DEFECT_COUNT);
	}
	else
	{
		DefectViewStepControlPanel->Visible = true;
		DefectStartIndex = DefectDataDB.DataCount - 1 - ((CurrentViewStepCount - 1) * LIMIT_NOT_INSPECTION_DEFECT_COUNT);
		LIMIT = DefectStartIndex - LIMIT_NOT_INSPECTION_DEFECT_COUNT;
		if (LIMIT < 0 )
			LIMIT = 0;
		progressForm->Max = DefectDataDB.DataCount - (DefectDataDB.DataCount - LIMIT_NOT_INSPECTION_DEFECT_COUNT);
	}

	progressForm->Position = 0;

	//for (int defectDataIndex = DefectDataDB.DataCount - 1; defectDataIndex >= 0; defectDataIndex--)
	DefectDataDB.StandardDataCount = LIMIT; // 기준 값 설정
	for (int defectDataIndex = DefectStartIndex; defectDataIndex >= LIMIT; defectDataIndex--)
	{
		TDefectDataUnit *aDefectData = new TDefectDataUnit;
		if (DefectDataDB.GetDefectData(&(aDefectData->DefectData), defectDataIndex))
		{
			aDefectData->DefectIndex = defectDataIndex + 1;
			DefectDataList->Add(aDefectData);
		}
		else
		{
			delete aDefectData;
		}
		progressForm->Position++;
		readDefectDataCount++;
		Application->ProcessMessages();

		if (progressForm->Break)
		{
			if (progressForm->ActiveStopButton)
			{
				break;
			}
			else if (EnableScroll == false)
			{
				progressForm->Show();
			}
			//break;
		}
	}

	progressForm->Close();
	delete progressForm;

	if (SortMethod == SORT_BY_TIME_ASCENDING_ORDER)
	{
		DefectDataList->Sort(SortDefectDataByTabletNumber_Ascending);
	}
	else if (SortMethod == SORT_BY_TIME_DESCENDING_ORDER)
	{
		DefectDataList->Sort(SortDefectDataByTabletNumber_Descending);
	}
	else if (SortMethod == SORT_BY_SIZE_ASCENDING_ORDER)
	{
		DefectDataList->Sort(SortDefectDataByDefectSize_Ascending);
	}
	else if (SortMethod == SORT_BY_SIZE_DESCENDING_ORDER)
	{
		DefectDataList->Sort(SortDefectDataByDefectSize_Descending);
	}

	for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
	{
		TTntImage *anImage = (TTntImage *)FindComponent("DefectImage" + IntToStr(globalCameraIndex + 1));
		anImage->Canvas->Brush->Color = clBlack;
		anImage->Canvas->Brush->Style = bsSolid;
		anImage->Canvas->FillRect(Rect(0, 0, anImage->Picture->Bitmap->Width, anImage->Picture->Bitmap->Height));
		anImage->Enabled = false;
	}

	SavedDefectImage->Canvas->Brush->Color = clWhite;
	SavedDefectImage->Canvas->Brush->Style = bsSolid;
	SavedDefectImage->Canvas->FillRect(Rect(0, 0, max(SourceImageWidth[0], SourceImageWidth[1]), max(SourceImageHeight[0], SourceImageHeight[1])));

	zoomInOutShiftX = 0;
	zoomInOutShiftY = 0;
	zoomInOutSize = 2;
	zoomImageNavigateFlag = 0;
	navigateStdX = 0;
	navigateStdY = 0;
	zoomROIX1 = 0;
	zoomROIY1 = 0;
	zoomROIX2 = 0;
	zoomROIY2 = 0;

	CurrentDefectStX = 0;
	CurrentDefectStY = 0;
	CurrentDefectEdX = 0;
	CurrentDefectEdY = 0;

	Panel7->Color = clBlack;
	Panel8->Color = clBlack;

	ZoomSizeLabel->Caption = "x " + IntToStr(zoomInOutSize);

	ZoomInImage->Canvas->Pen->Color = clBlack;
	ZoomInImage->Canvas->Brush->Color = clBlack;
	ZoomInImage->Canvas->Brush->Style = bsSolid;
	ZoomInImage->Canvas->Rectangle(0, 0, ZoomInImage->Width, ZoomInImage->Height);

	zoomInOutImage->Canvas->Pen->Color = clBlack;
	zoomInOutImage->Canvas->Brush->Color = clBlack;
	zoomInOutImage->Canvas->Brush->Style = bsSolid;
	zoomInOutImage->Canvas->Rectangle(0, 0, zoomInOutImage->Width, zoomInOutImage->Height);

	if (MaxLimitViewStepCount == 0)
		DefectViewLimitCountEdit->Caption = " / " + IntToStr(MaxLimitViewStepCount + 1);
	else
		DefectViewLimitCountEdit->Caption = " / " + IntToStr(MaxLimitViewStepCount);

	CurrentViewStepEdit->Text = IntToStr(CurrentViewStepCount);

	RefreshStringGrid();

	EnableScroll = true;
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::RefreshStringGrid(void)
{
	// make defect view list
	while (DefectViewList->Count)
	{
		TDefectViewUnit *aDefectViewUnit = (TDefectViewUnit *)DefectViewList->First();
    DefectViewList->Remove(aDefectViewUnit);
		delete aDefectViewUnit;
	}
  

	for (int defectDataIndex = 0; defectDataIndex < DefectDataList->Count; defectDataIndex++)
	{
		TDefectDataUnit *aDefectDataUnit = (TDefectDataUnit *)DefectDataList->Items[defectDataIndex];
		int defectTabletNumber = aDefectDataUnit->DefectData.TabletNumber;
		//}
		///*  check

		if ((FilterCameraMask & (0x00000001 << aDefectDataUnit->DefectData.GlobalCameraIndex)) == 0) continue;

		int defectSeriesGroup = DEFECT_SERIES_OTHER;
		switch (aDefectDataUnit->DefectData.CPBDefectInfo.defectSeries)
		{
		case DEFECT_COLOR_R:
		case DEFECT_COLOR_G:
		case DEFECT_COLOR_B:
			defectSeriesGroup = DEFECT_SERIES_COLOR;
			break;

		case DEFECT_FRONT_DIRTY:
		case DEFECT_SIDE_DIRTY:
    case DEFECT_SIDE_EDGE_DIRTY_OPTION:
    case DEFECT_SIDE_EDGE_DARK:
    case DEFECT_SIDE_EDGE_BRIGHT:
		case DEFECT_SIDE_EDGE_NEIGHBOR:
		case DEFECT_2D_DARK_SPOT_MARVELING:
		case DEFECT_2D_BRIGHT_SPOT_MARVELING:
			defectSeriesGroup = DEFECT_SERIES_DIRTY;
			break;

		case DEFECT_FRONT_COLOR_DIRTY:
		case DEFECT_SIDE_COLOR_DIRTY:
			defectSeriesGroup = DEFECT_SERIES_COLOR_DIRTY;
			break;

		case DEFECT_FRONT_STAIN:
		case DEFECT_SIDE_STAIN:
		case DEFECT_FRONT_EDGE_STAIN:
		case DEFECT_2D_DARK_STAIN_MARVELING:
		case DEFECT_2D_BRIGHT_STAIN_MARVELING:
			defectSeriesGroup = DEFECT_SERIES_STAIN;
			break;

		case DEFECT_PRINT_ERASE:
		case DEFECT_PRINT_SPREAD:
		case DEFECT_3D_PRINT_ERASE:
		case DEFECT_UNPRINT:
    case DEFECT_3D_PRINT_ERASE_PARTIAL:
			defectSeriesGroup = DEFECT_SERIES_PRINT;
			break;

		case DEFECT_TABLET_SIZE:
		case DEFECT_3D_BREAKING_FOR_NORMAL_AREA:
		case DEFECT_3D_BREAKING_FOR_EDGE_AREA:
    case DEFECT_3D_BREAKING_FOR_EDGE_NEIGHBOR:
    case DEFECT_SIDE_EDGE_NEIGHBOR_BREAK:
			defectSeriesGroup = DEFECT_SERIES_CRACK;
			break;

		case UNINS_CLOSED:
		case UNINS_TABLET_POSITION:
		case UNINS_BRIGHTNESS_DROPPED:
		case UNINS_BRIGHTNESS_CHASE:
			defectSeriesGroup = DEFECT_SERIES_UNINS;
			break;

		default:
			defectSeriesGroup = DEFECT_SERIES_OTHER;
			break;
		}
		if ((FilterDefectSeriesMask & (0x00000001 << defectSeriesGroup)) == 0) continue;

		bool bDefectTabletExist = false;
		TDefectViewUnit *existDefectViewUnit;
		for (int defectViewIndex = 0; defectViewIndex < DefectViewList->Count; defectViewIndex++)
		{
			TDefectViewUnit *aDefectViewUnit = (TDefectViewUnit *)DefectViewList->Items[defectViewIndex];
			if (aDefectViewUnit->TabletNumber == defectTabletNumber)
			{
				existDefectViewUnit = aDefectViewUnit;
				bDefectTabletExist = true;
				break;
			}
		}
		if (bDefectTabletExist)
		{
			int globalCameraIndex = aDefectDataUnit->DefectData.GlobalCameraIndex;
			if (!existDefectViewUnit->DefectDataExist[globalCameraIndex])
			{
				existDefectViewUnit->DefectDataExist[globalCameraIndex] = true;
				existDefectViewUnit->DefectDataIndex[globalCameraIndex] = aDefectDataUnit->DefectIndex;
				existDefectViewUnit->CameraInspectPosition[globalCameraIndex] = aDefectDataUnit->DefectData.CameraInspectPosition;
				existDefectViewUnit->DefectImageCount++;
			}
		}
		else
		{
			TDefectViewUnit *aDefectViewUnit = new TDefectViewUnit;
			for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
			{
				aDefectViewUnit->DefectDataExist[globalCameraIndex] = false;
				aDefectViewUnit->DefectDataIndex[globalCameraIndex] = 0;
				aDefectViewUnit->CameraInspectPosition[globalCameraIndex] = 0;
			}

			aDefectViewUnit->TabletNumber = defectTabletNumber;
			aDefectViewUnit->DefectImageCount = 1;
			aDefectViewUnit->DefectSeries = aDefectDataUnit->DefectData.CPBDefectInfo.defectSeries;

			int globalCameraIndex = aDefectDataUnit->DefectData.GlobalCameraIndex;
			aDefectViewUnit->MajorCamIndex = globalCameraIndex;
			aDefectViewUnit->DefectDataExist[globalCameraIndex] = true;
			aDefectViewUnit->DefectDataIndex[globalCameraIndex] = aDefectDataUnit->DefectIndex;
			aDefectViewUnit->CameraInspectPosition[globalCameraIndex] = aDefectDataUnit->DefectData.CameraInspectPosition;

			DefectViewList->Add(aDefectViewUnit);
		}
	}

	if(DefectListStringGrid->Row != 1)
  {
	  DefectListStringGrid->Row = 1;
  }
  else
  {
    // event trigger
    DefectListStringGrid->Col = 2;
    DefectListStringGrid->Col = 1;
  }
  
	CurrentViewIndex = 0;

	if (DefectViewList->Count == 0)
	{
		DefectListStringGrid->RowCount = 2;
		DefectListStringGrid->Cells[0][1] = "";
		DefectListStringGrid->Cells[1][1] = "";
		DefectListStringGrid->Cells[2][1] = "";
		DefectListStringGrid->Cells[3][1] = "";
	}
	else
	{
		DefectListStringGrid->RowCount = DefectViewList->Count + 1;
	}
	DefectListStringGrid->Cells[0][0] = DEFECTINFOFORM_STRGRID_CELL_03;
	DefectListStringGrid->Cells[1][0] = DEFECTINFOFORM_STRGRID_CELL_01;
	DefectListStringGrid->Cells[2][0] = DEFECTINFOFORM_STRGRID_CELL_02;
	DefectListStringGrid->Cells[3][0] = DEFECTINFOFORM_STRGRID_CELL_04;

	memset(DefectSeriesCount, 0, sizeof(int) * MAX_DEFECT_SERIES_COUNT + 1);
	for (int defectViewIndex = 0; defectViewIndex < DefectViewList->Count; defectViewIndex++)
	{
		TDefectViewUnit *aDefectViewUnit = (TDefectViewUnit *)DefectViewList->Items[defectViewIndex];
		DefectListStringGrid->Cells[0][defectViewIndex + 1] = IntToStr(aDefectViewUnit->TabletNumber);
		DefectListStringGrid->Cells[1][defectViewIndex + 1] = GetDefectSeriesStr(aDefectViewUnit->DefectSeries);
		DefectListStringGrid->Cells[2][defectViewIndex + 1] = IntToStr(aDefectViewUnit->DefectImageCount);
		DefectListStringGrid->Cells[3][defectViewIndex + 1] = ConvertCameraIndex(aDefectViewUnit->MajorCamIndex);//IntToStr(aDefectViewUnit->MajorCamIndex + 1);

		if (aDefectViewUnit->DefectSeries < MAX_CPB_DEFECT_SERIES_COUNT)
		{
			DefectSeriesCount[aDefectViewUnit->DefectSeries]++;
		}
		else if (aDefectViewUnit->DefectSeries >= THIN_TALBET &&
			aDefectViewUnit->DefectSeries <= FAT_TALBET)
		{
			DefectSeriesCount[MAX_CPB_DEFECT_SERIES_COUNT + aDefectViewUnit->DefectSeries - THIN_TALBET]++;
		}
		else
		{
			DefectSeriesCount[MAX_DEFECT_SERIES_COUNT]++;
		}
	}
	//*/ check

}
//---------------------------------------------------------------------------


void __fastcall TDefectInfoForm::FormDestroy(TObject *Sender)
{
	while (DefectDataList->Count)
	{
		TDefectDataUnit *aDefectDataUnit = (TDefectDataUnit *)DefectDataList->First();
		DefectDataList->Remove(aDefectDataUnit);
		delete aDefectDataUnit;
	}
	delete DefectDataList;

	while (DefectViewList->Count)
	{
		TDefectViewUnit *aDefectViewUnit = (TDefectViewUnit *)DefectViewList->First();
		DefectViewList->Remove(aDefectViewUnit);
		delete aDefectViewUnit;
	}

	delete DefectViewList;
	delete Current3DBitmap;
	delete CurrentDisplayImage;
}
//---------------------------------------------------------------------------


void __fastcall TDefectInfoForm::DefectListStringGridClick(TObject *Sender)
{
  if(EnableScroll == false) return;
  
  bool bThreeD;
  
	ProcessingPCSIM = false;
	bEngraveDefect = false;
	threeDProcessingStep = THREED_NONE_STEP;

  ExtractedPrintInfoImage->Visible = false;
  PrintInfoPanel->Visible = false;
  ThreeDDebugInfoPanel->Visible = false;
  ThreeDDebugButton->Caption = "3D Debug (Off)";

	for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
	{
		TTntImage *anImage = (TTntImage *)FindComponent("DefectImage" + IntToStr(globalCameraIndex + 1));
		anImage->Canvas->Brush->Color = clBlack;
		anImage->Canvas->Brush->Style = bsSolid;
		anImage->Canvas->FillRect(Rect(0, 0, anImage->Picture->Bitmap->Width, anImage->Picture->Bitmap->Height));
		anImage->Enabled = false;
	}

	SavedDefectImage->Canvas->Brush->Color = clWhite;
	SavedDefectImage->Canvas->Brush->Style = bsSolid;
	SavedDefectImage->Canvas->FillRect(Rect(0, 0, max(SourceImageWidth[0], SourceImageWidth[1]), max(SourceImageHeight[0], SourceImageHeight[1])));

	CurrentViewIndex = DefectListStringGrid->Row - 1;
	if (CurrentViewIndex < 0 || CurrentViewIndex >= DefectViewList->Count) return;

	TDefectViewUnit *aDefectViewUnit = (TDefectViewUnit *)DefectViewList->Items[CurrentViewIndex];

	int defectIndex = aDefectViewUnit->DefectDataIndex[aDefectViewUnit->MajorCamIndex];

	AnsiString saveDir = GetDefectDataPath(ProductCode, LOTName);

	AnsiString saveImageFileName = "Image" + IntToStr(defectIndex) + ".fbm";
	if (ExtractImageFromContainer(SavedDefectImage->Picture->Bitmap, GetDefectContainerFileName(defectIndex), saveImageFileName, TabletSetupData.ImageOffSetSW[aDefectViewUnit->MajorCamIndex], TabletSetupData.referenceImageForOffset[aDefectViewUnit->MajorCamIndex], ProductData.SubSamplingMode))
	{
		TDefectData_PC *defectData;
		for (int defectDataIndex = 0; defectDataIndex < DefectDataList->Count; defectDataIndex++)
		{
			TDefectDataUnit *aDefectDataUnit = (TDefectDataUnit *)DefectDataList->Items[defectDataIndex];
			if (aDefectDataUnit->DefectIndex == defectIndex)
			{
				defectData = &(aDefectDataUnit->DefectData);
			}
		}

		CurrentDefectStX = defectData->CPBDefectInfo.defectPositionStartX;
		CurrentDefectStY = defectData->CPBDefectInfo.defectPositionStartY;
		CurrentDefectEdX = defectData->CPBDefectInfo.defectPositionEndX;
		CurrentDefectEdY = defectData->CPBDefectInfo.defectPositionEndY;

		if (defectData->CameraInspectPosition == CAMERA_POSITION_3D)
		{
			SPBThreeDImage->Picture->Bitmap->Assign(SavedDefectImage->Picture->Bitmap);
			SPBThreeDImage->Refresh();

			Remake3DDefectImage(SavedDefectImage);
			Current3DBitmap->Assign(SavedDefectImage->Picture->Bitmap);
		}
		else
		{
			CurrentDisplayImage->Assign(SavedDefectImage->Picture->Bitmap);
			LoadZoomInOutNavigationImage(ZOOM_IMAGE_DEFECT, 0, 0);
		}

		//temp OriginalImage
		tempSavedDefectImage->Picture->Bitmap->Assign(SavedDefectImage->Picture->Bitmap);

		GlobalCameraIndex = defectData->GlobalCameraIndex;

		if ((GlobalCameraIndex + 1) != SD1_3D_FRONT_FACE_CAMERA_INDEX &&
			(GlobalCameraIndex + 1) != SD2_3D_FRONT_FACE_CAMERA_INDEX)
		{
      bThreeD = false;
      
			// show defected position
			SavedDefectImage->Canvas->Pen->Color = clWhite;
      SavedDefectImage->Canvas->Pen->Width = 2;
			SavedDefectImage->Canvas->Brush->Style = bsClear;
			SavedDefectImage->Canvas->Rectangle(
				(defectData->CPBDefectInfo.defectPositionStartX - 4) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionStartY - 4) * rate[bThreeD],
				(defectData->CPBDefectInfo.defectPositionEndX + 4) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionEndY + 4) * rate[bThreeD]);

			SavedDefectImage->Canvas->Pen->Color = clRed;
      SavedDefectImage->Canvas->Pen->Width = 2;
			SavedDefectImage->Canvas->Brush->Style = bsClear;
			SavedDefectImage->Canvas->Rectangle(
				(defectData->CPBDefectInfo.defectPositionStartX - 2) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionStartY - 2) * rate[bThreeD],
				(defectData->CPBDefectInfo.defectPositionEndX + 2) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionEndY + 2) * rate[bThreeD]);

			// show boundary area
			SavedDefectImage->Canvas->Pen->Color = clBlue;
      SavedDefectImage->Canvas->Pen->Width = 2;
			SavedDefectImage->Canvas->Brush->Style = bsClear;
			SavedDefectImage->Canvas->Rectangle(
				ProductData.BoundaryLeft[defectData->GlobalCameraIndex] * rate[bThreeD], ProductData.BoundaryTop[defectData->GlobalCameraIndex] * rate[bThreeD],
				ProductData.BoundaryRight[defectData->GlobalCameraIndex] * rate[bThreeD], ProductData.BoundaryBottom[defectData->GlobalCameraIndex] * rate[bThreeD]);

			SavedDefectImage->Repaint();
		}
    else
    {
      bThreeD = true;
    }

		SavedDefectData = *defectData;
		CurrentImageIndex = defectIndex;
		ShowDefectInfo();

    if(bViewThreeDPositionInfo)
    {
      if ((GlobalCameraIndex + 1) == SD1_3D_FRONT_FACE_CAMERA_INDEX ||
			    (GlobalCameraIndex + 1) == SD2_3D_FRONT_FACE_CAMERA_INDEX)
      {
        ThreeDLaserInfoViewerCheckBox->Visible = true;

        if(ThreeDLaserInfoViewerCheckBox->Checked)
        {
          ThreeDResultLabel1->Visible = true;
          ThreeDResultLabel2->Visible = true;
          ThreeDResultLabel3->Visible = true;
        }
        else
        {
          ThreeDResultLabel1->Visible = false;
          ThreeDResultLabel2->Visible = false;
          ThreeDResultLabel3->Visible = false;
        }
      }
      else
      {
        ThreeDLaserInfoViewerCheckBox->Visible = false;
        ThreeDResultLabel1->Visible = false;
        ThreeDResultLabel2->Visible = false;
        ThreeDResultLabel3->Visible = false;
      }
    }
    else
    {
      ThreeDLaserInfoViewerCheckBox->Visible = false;
      ThreeDResultLabel1->Visible = false;
      ThreeDResultLabel2->Visible = false;
      ThreeDResultLabel3->Visible = false;
    }

    if ((GlobalCameraIndex + 1) == SD1_3D_FRONT_FACE_CAMERA_INDEX ||
        (GlobalCameraIndex + 1) == SD2_3D_FRONT_FACE_CAMERA_INDEX)
    {
      DepthRefImage->Visible = true;
      DepthRefImage->BringToFront();
    }
    else
    {
      DepthRefImage->Visible = false;
    }

		if ((GlobalCameraIndex + 1) == SD1_3D_FRONT_FACE_CAMERA_INDEX ||
			(GlobalCameraIndex + 1) == SD2_3D_FRONT_FACE_CAMERA_INDEX)
		{
			DoProcessingFor3D(GlobalCameraIndex);

			// show defected position
			SavedDefectImage->Canvas->Pen->Color = clWhite;
      SavedDefectImage->Canvas->Pen->Width = 2;
			SavedDefectImage->Canvas->Brush->Style = bsClear;
			SavedDefectImage->Canvas->Rectangle(
				(defectData->CPBDefectInfo.defectPositionStartX - 4) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionStartY - 4) * rate[bThreeD],
				(defectData->CPBDefectInfo.defectPositionEndX + 4) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionEndY + 4) * rate[bThreeD]);

			SavedDefectImage->Canvas->Pen->Color = clRed;
      SavedDefectImage->Canvas->Pen->Width = 2;
			SavedDefectImage->Canvas->Brush->Style = bsClear;
			SavedDefectImage->Canvas->Rectangle(
				(defectData->CPBDefectInfo.defectPositionStartX - 2) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionStartY - 2) * rate[bThreeD],
				(defectData->CPBDefectInfo.defectPositionEndX + 2) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionEndY + 2) * rate[bThreeD]);

			SavedDefectImage->Repaint();
		}

		int currentImageIndex = 0;
		for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
		{
			if (aDefectViewUnit->DefectDataExist[globalCameraIndex])
			{
				int otherDefectIndex = aDefectViewUnit->DefectDataIndex[globalCameraIndex];
				AnsiString otherImageFileName = "Image" + IntToStr(otherDefectIndex) + ".fbm";
				TTntImage *anImage = (TTntImage *)FindComponent("DefectImage" + IntToStr(currentImageIndex + 1));
				ExtractImageFromContainer(anImage->Picture->Bitmap, GetDefectContainerFileName(otherDefectIndex), otherImageFileName, TabletSetupData.ImageOffSetSW[globalCameraIndex], TabletSetupData.referenceImageForOffset[globalCameraIndex],ProductData.SubSamplingMode);

				if (aDefectViewUnit->CameraInspectPosition[globalCameraIndex] == CAMERA_POSITION_3D)
				{
					Remake3DSubDefectImage(anImage);
					Current3DBitmap->Assign(anImage->Picture->Bitmap);
				}

				if (globalCameraIndex == aDefectViewUnit->MajorCamIndex)
				{
					anImage->Canvas->Pen->Color = clRed;
				}
				else
				{
					anImage->Canvas->Pen->Color = clWhite;
				}
				anImage->Canvas->Pen->Width = 4;
				anImage->Canvas->Brush->Style = bsClear;
				anImage->Canvas->Rectangle(4, 4, anImage->Picture->Bitmap->Width - 4, anImage->Picture->Bitmap->Height - 4);
				anImage->Tag = globalCameraIndex;
				anImage->Enabled = true;
				currentImageIndex++;
			}
		}

		if ((aDefectViewUnit->DefectDataExist[0] && aDefectViewUnit->DefectDataExist[1]) || (aDefectViewUnit->DefectDataExist[5] && aDefectViewUnit->DefectDataExist[6]))
		{
			int DefectIndexInGroup;
			if (aDefectViewUnit->DefectDataExist[0] && aDefectViewUnit->DefectDataExist[1])
			{
				DefectIndexInGroup = aDefectViewUnit->DefectDataIndex[0];
			}
			else
			{
				DefectIndexInGroup = aDefectViewUnit->DefectDataIndex[5];
			}

			for (int defectDataIndex = 0; defectDataIndex < DefectDataList->Count; defectDataIndex++)
			{
				TDefectDataUnit *tempDefectDataUnit = (TDefectDataUnit *)DefectDataList->Items[defectDataIndex];
				if (tempDefectDataUnit->DefectIndex == DefectIndexInGroup)
				{
					defectData = &(tempDefectDataUnit->DefectData);
					break;
				}
			}

			if (defectData->CPBDefectInfo.defectSeries == DEFECT_2D_AND_3D_PRINT_NOT_MATCHING)
				bEngraveDefect = true;
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::SubDefectImageClick(TObject *Sender)
{
	if (CurrentViewIndex < 0 || CurrentViewIndex >= DefectViewList->Count) return;
	TTntImage *theImage = (TTntImage *)Sender;
	int cameraIndex = theImage->Tag;

  bool bThreeD;

	GlobalCameraIndex = cameraIndex;

  ExtractedPrintInfoImage->Visible = false;
  PrintInfoPanel->Visible = false;
  ThreeDDebugInfoPanel->Visible = false;
  ThreeDDebugButton->Caption = "3D Debug (Off)";
  
	ProcessingPCSIM = false;
	bEngraveDefect = false;
	threeDProcessingStep = THREED_NONE_STEP;

	TDefectViewUnit *aDefectViewUnit = (TDefectViewUnit *)DefectViewList->Items[CurrentViewIndex];
	int defectIndex = aDefectViewUnit->DefectDataIndex[cameraIndex];

	AnsiString saveDir = GetDefectDataPath(ProductCode, LOTName);

	AnsiString saveImageFileName = "Image" + IntToStr(defectIndex) + ".fbm";
	if (ExtractImageFromContainer(SavedDefectImage->Picture->Bitmap, GetDefectContainerFileName(defectIndex), saveImageFileName, TabletSetupData.ImageOffSetSW[cameraIndex], TabletSetupData.referenceImageForOffset[cameraIndex],ProductData.SubSamplingMode))
	{
		TDefectData_PC *defectData;
		for (int defectDataIndex = 0; defectDataIndex < DefectDataList->Count; defectDataIndex++)
		{
			TDefectDataUnit *aDefectDataUnit = (TDefectDataUnit *)DefectDataList->Items[defectDataIndex];
			if (aDefectDataUnit->DefectIndex == defectIndex)
			{
				defectData = &(aDefectDataUnit->DefectData);
			}
		}

		CurrentDefectStX = defectData->CPBDefectInfo.defectPositionStartX;
		CurrentDefectStY = defectData->CPBDefectInfo.defectPositionStartY;
		CurrentDefectEdX = defectData->CPBDefectInfo.defectPositionEndX;
		CurrentDefectEdY = defectData->CPBDefectInfo.defectPositionEndY;

		if (defectData->CameraInspectPosition == CAMERA_POSITION_3D)
		{
			SPBThreeDImage->Picture->Bitmap->Assign(SavedDefectImage->Picture->Bitmap);
			SPBThreeDImage->Refresh();

			Remake3DDefectImage(SavedDefectImage);
			Current3DBitmap->Assign(SavedDefectImage->Picture->Bitmap);
		}
		else
		{
			CurrentDisplayImage->Assign(SavedDefectImage->Picture->Bitmap);
			LoadZoomInOutNavigationImage(ZOOM_IMAGE_DEFECT, 0, 0);
		}

		//temp OriginalImage
		tempSavedDefectImage->Picture->Bitmap->Assign(SavedDefectImage->Picture->Bitmap);

		if ((GlobalCameraIndex + 1) != SD1_3D_FRONT_FACE_CAMERA_INDEX &&
			(GlobalCameraIndex + 1) != SD2_3D_FRONT_FACE_CAMERA_INDEX)
		{
      bThreeD = false;
      
			// show defected position
			SavedDefectImage->Canvas->Pen->Color = clWhite;
      SavedDefectImage->Canvas->Pen->Width = 2;
			SavedDefectImage->Canvas->Brush->Style = bsClear;
			SavedDefectImage->Canvas->Rectangle(
				(defectData->CPBDefectInfo.defectPositionStartX - 4) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionStartY - 4) * rate[bThreeD],
				(defectData->CPBDefectInfo.defectPositionEndX + 4) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionEndY + 4) * rate[bThreeD]);

			SavedDefectImage->Canvas->Pen->Color = clRed;
      SavedDefectImage->Canvas->Pen->Width = 2;
			SavedDefectImage->Canvas->Brush->Style = bsClear;
			SavedDefectImage->Canvas->Rectangle(
				(defectData->CPBDefectInfo.defectPositionStartX - 2) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionStartY - 2) * rate[bThreeD],
				(defectData->CPBDefectInfo.defectPositionEndX + 2) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionEndY + 2) * rate[bThreeD]);

			// show boundary area
			SavedDefectImage->Canvas->Pen->Color = clBlue;
      SavedDefectImage->Canvas->Pen->Width = 2;
			SavedDefectImage->Canvas->Brush->Style = bsClear;
			SavedDefectImage->Canvas->Rectangle(
				ProductData.BoundaryLeft[defectData->GlobalCameraIndex] * rate[bThreeD], ProductData.BoundaryTop[defectData->GlobalCameraIndex] * rate[bThreeD],
				ProductData.BoundaryRight[defectData->GlobalCameraIndex] * rate[bThreeD], ProductData.BoundaryBottom[defectData->GlobalCameraIndex] * rate[bThreeD]);

			SavedDefectImage->Repaint();
		}
    else
    {
      bThreeD = true;
    }

		SavedDefectData = *defectData;
		CurrentImageIndex = defectIndex;
		ShowDefectInfo();

    if(bViewThreeDPositionInfo)
    {
      if ((GlobalCameraIndex + 1) == SD1_3D_FRONT_FACE_CAMERA_INDEX ||
			    (GlobalCameraIndex + 1) == SD2_3D_FRONT_FACE_CAMERA_INDEX)
      {
        ThreeDLaserInfoViewerCheckBox->Visible = true;
      }
      else
      {
        ThreeDLaserInfoViewerCheckBox->Visible = false;
      }
    }
    else
    {
      ThreeDLaserInfoViewerCheckBox->Visible = false;
    }

    if ((GlobalCameraIndex + 1) == SD1_3D_FRONT_FACE_CAMERA_INDEX ||
        (GlobalCameraIndex + 1) == SD2_3D_FRONT_FACE_CAMERA_INDEX)
    {
      DepthRefImage->Visible = true;
      DepthRefImage->BringToFront();
    }
    else
    {
      DepthRefImage->Visible = false;
    }

		if ((GlobalCameraIndex + 1) == SD1_3D_FRONT_FACE_CAMERA_INDEX ||
			(GlobalCameraIndex + 1) == SD2_3D_FRONT_FACE_CAMERA_INDEX)
		{
			DoProcessingFor3D(GlobalCameraIndex);

			// show defected position
			SavedDefectImage->Canvas->Pen->Color = clWhite;
      SavedDefectImage->Canvas->Pen->Width = 2;
			SavedDefectImage->Canvas->Brush->Style = bsClear;
			SavedDefectImage->Canvas->Rectangle(
				(defectData->CPBDefectInfo.defectPositionStartX - 4) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionStartY - 4) * rate[bThreeD],
				(defectData->CPBDefectInfo.defectPositionEndX + 4) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionEndY + 4) * rate[bThreeD]);

			SavedDefectImage->Canvas->Pen->Color = clRed;
      SavedDefectImage->Canvas->Pen->Width = 2;
			SavedDefectImage->Canvas->Brush->Style = bsClear;
			SavedDefectImage->Canvas->Rectangle(
				(defectData->CPBDefectInfo.defectPositionStartX - 2) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionStartY - 2) * rate[bThreeD],
				(defectData->CPBDefectInfo.defectPositionEndX + 2) * rate[bThreeD], (defectData->CPBDefectInfo.defectPositionEndY + 2) * rate[bThreeD]);

			SavedDefectImage->Repaint();
		}

		for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
		{
			TTntImage *anImage = (TTntImage *)FindComponent("DefectImage" + IntToStr(globalCameraIndex + 1));
			if (anImage->Enabled)
			{
				if (anImage->Tag == cameraIndex)
				{
					anImage->Canvas->Pen->Color = clRed;
				}
				else
				{
					anImage->Canvas->Pen->Color = clWhite;
				}
				anImage->Canvas->Pen->Width = 4;
				anImage->Canvas->Brush->Style = bsClear;
				anImage->Canvas->Rectangle(4, 4, anImage->Picture->Bitmap->Width - 4, anImage->Picture->Bitmap->Height + 4);
			}
		}

		if ((aDefectViewUnit->DefectDataExist[SD1_2D_FRONT_FACE_CAMERA_INDEX - 1] && aDefectViewUnit->DefectDataExist[SD1_3D_FRONT_FACE_CAMERA_INDEX - 1]) ||
			(aDefectViewUnit->DefectDataExist[SD2_2D_FRONT_FACE_CAMERA_INDEX - 1] && aDefectViewUnit->DefectDataExist[SD2_3D_FRONT_FACE_CAMERA_INDEX - 1]))
		{
			int DefectIndexInGroup;
			if (aDefectViewUnit->DefectDataExist[SD1_2D_FRONT_FACE_CAMERA_INDEX - 1] &&
				aDefectViewUnit->DefectDataExist[SD1_3D_FRONT_FACE_CAMERA_INDEX - 1])
			{
				DefectIndexInGroup = aDefectViewUnit->DefectDataIndex[SD1_2D_FRONT_FACE_CAMERA_INDEX - 1];
			}
			else
			{
				DefectIndexInGroup = aDefectViewUnit->DefectDataIndex[SD2_2D_FRONT_FACE_CAMERA_INDEX - 1];
			}

			for (int defectDataIndex = 0; defectDataIndex < DefectDataList->Count; defectDataIndex++)
			{
				TDefectDataUnit *tempDefectDataUnit = (TDefectDataUnit *)DefectDataList->Items[defectDataIndex];
				if (tempDefectDataUnit->DefectIndex == DefectIndexInGroup)
				{
					defectData = &(tempDefectDataUnit->DefectData);
					break;
				}
			}

			if (defectData->CPBDefectInfo.defectSeries == DEFECT_2D_AND_3D_PRINT_NOT_MATCHING)
				bEngraveDefect = true;
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::ReadTabletInfoButtonClick(TObject *Sender)
{
	//TInspectionStatusForm *inspectionStatusForm = new TInspectionStatusForm(this);
	//inspectionStatusForm->ShowModal();
	//delete inspectionStatusForm;
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::RefreshButtonClick(TObject *Sender)
{
	InitDefectInfo(ProductCode, LOTName,0,InspectionSataus);
}
//---------------------------------------------------------------------------
int __fastcall SortDefectDataByTabletNumber_Ascending(void *firstUnit, void *secondUnit)
{
	TDefectDataUnit *firstDefectDataUnit = (TDefectDataUnit *)firstUnit;
	TDefectDataUnit *secondDefectDataUnit = (TDefectDataUnit *)secondUnit;
	return (firstDefectDataUnit->DefectData.TabletNumber - secondDefectDataUnit->DefectData.TabletNumber);
}
//---------------------------------------------------------------------------
int __fastcall SortDefectDataByTabletNumber_Descending(void *firstUnit, void *secondUnit)
{
	TDefectDataUnit *firstDefectDataUnit = (TDefectDataUnit *)firstUnit;
	TDefectDataUnit *secondDefectDataUnit = (TDefectDataUnit *)secondUnit;
	return (secondDefectDataUnit->DefectData.TabletNumber - firstDefectDataUnit->DefectData.TabletNumber);
}
//---------------------------------------------------------------------------
int __fastcall SortDefectDataByDefectSize_Ascending(void *firstUnit, void *secondUnit)
{
	TDefectDataUnit *firstDefectDataUnit = (TDefectDataUnit *)firstUnit;
	TDefectDataUnit *secondDefectDataUnit = (TDefectDataUnit *)secondUnit;
	return (firstDefectDataUnit->DefectData.CPBDefectInfo.size - secondDefectDataUnit->DefectData.CPBDefectInfo.size);
}
//---------------------------------------------------------------------------
int __fastcall SortDefectDataByDefectSize_Descending(void *firstUnit, void *secondUnit)
{
	TDefectDataUnit *firstDefectDataUnit = (TDefectDataUnit *)firstUnit;
	TDefectDataUnit *secondDefectDataUnit = (TDefectDataUnit *)secondUnit;
	return (secondDefectDataUnit->DefectData.CPBDefectInfo.size - firstDefectDataUnit->DefectData.CPBDefectInfo.size);
}
//---------------------------------------------------------------------------
int __fastcall SortDefectDataByCamera_Ascending(void *firstUnit, void *secondUnit)
{
	TDefectDataUnit *firstDefectDataUnit = (TDefectDataUnit *)firstUnit;
	TDefectDataUnit *secondDefectDataUnit = (TDefectDataUnit *)secondUnit;
	return (firstDefectDataUnit->DefectData.GlobalCameraIndex - secondDefectDataUnit->DefectData.GlobalCameraIndex);
}
//---------------------------------------------------------------------------
int __fastcall SortDefectDataByCamera_Descending(void *firstUnit, void *secondUnit)
{
	TDefectDataUnit *firstDefectDataUnit = (TDefectDataUnit *)firstUnit;
	TDefectDataUnit *secondDefectDataUnit = (TDefectDataUnit *)secondUnit;
	return (secondDefectDataUnit->DefectData.GlobalCameraIndex - firstDefectDataUnit->DefectData.GlobalCameraIndex);
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::FilterCameraAllPanelClick(TObject *Sender)
{
	FilterCameraAllPanel->Color = clWhite;
	FilterCameraAllPanel->Font->Color = clBlack;
	FilterCameraFrontPanel->Color = clWhite;
	FilterCameraFrontPanel->Font->Color = clBlack;
	FilterCameraSidePanel->Color = clWhite;
	FilterCameraSidePanel->Font->Color = clBlack;
	FilterCameraOptionPanel->Color = clWhite;
	FilterCameraOptionPanel->Font->Color = clBlack;

	FilterCameraAllPanel->Color = clBlue;
	FilterCameraAllPanel->Font->Color = clWhite;

	FilterCameraMask = 0xFFFFFFFF;
	RefreshStringGrid();
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::FilterCameraFrontPanelClick(
	TObject *Sender)
{
	FilterCameraAllPanel->Color = clWhite;
	FilterCameraAllPanel->Font->Color = clBlack;
	FilterCameraFrontPanel->Color = clWhite;
	FilterCameraFrontPanel->Font->Color = clBlack;
	FilterCameraSidePanel->Color = clWhite;
	FilterCameraSidePanel->Font->Color = clBlack;
	FilterCameraOptionPanel->Color = clWhite;
	FilterCameraOptionPanel->Font->Color = clBlack;

	FilterCameraFrontPanel->Color = clBlue;
	FilterCameraFrontPanel->Font->Color = clWhite;

	FilterCameraMask = (0x00000001 << SD1_2D_FRONT_FACE_CAMERA_INDEX - 1) |
		(0x00000001 << SD2_2D_FRONT_FACE_CAMERA_INDEX - 1);
	RefreshStringGrid();
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::FilterCameraSidePanelClick(
	TObject *Sender)
{
	FilterCameraAllPanel->Color = clWhite;
	FilterCameraAllPanel->Font->Color = clBlack;
	FilterCameraFrontPanel->Color = clWhite;
	FilterCameraFrontPanel->Font->Color = clBlack;
	FilterCameraSidePanel->Color = clWhite;
	FilterCameraSidePanel->Font->Color = clBlack;
	FilterCameraOptionPanel->Color = clWhite;
	FilterCameraOptionPanel->Font->Color = clBlack;

	FilterCameraSidePanel->Color = clBlue;
	FilterCameraSidePanel->Font->Color = clWhite;

	FilterCameraMask = ((0x00000001 << SD1_2D_SIDE_FACE_P45_CAMERA_INDEX - 1) |
		(0x00000001 << SD1_2D_SIDE_FACE_00_CAMERA_INDEX - 1) |
		(0x00000001 << SD1_2D_SIDE_FACE_M45_CAMERA_INDEX - 1) |
		(0x00000001 << SD1_2D_OTHER_SIDE_FACE_P45_CAMERA_INDEX - 1) |
		(0x00000001 << SD1_2D_OTHER_SIDE_FACE_00_CAMERA_INDEX - 1) |
		(0x00000001 << SD1_2D_OTHER_SIDE_FACE_M45_CAMERA_INDEX - 1) |
		(0x00000001 << SD2_2D_SIDE_FACE_P45_CAMERA_INDEX - 1) |
		(0x00000001 << SD2_2D_SIDE_FACE_00_CAMERA_INDEX - 1) |
		(0x00000001 << SD2_2D_SIDE_FACE_M45_CAMERA_INDEX - 1) |
		(0x00000001 << SD2_2D_OTHER_SIDE_FACE_P45_CAMERA_INDEX - 1) |
		(0x00000001 << SD2_2D_OTHER_SIDE_FACE_00_CAMERA_INDEX - 1) |
		(0x00000001 << SD2_2D_OTHER_SIDE_FACE_M45_CAMERA_INDEX - 1));

	RefreshStringGrid();
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::FilterSeriesPanelClick(TObject *Sender)
{
	TTntPanel *thePanel = (TTntPanel *)Sender;

	int defectSeriesIndex = thePanel->Tag;

	FilterSeriesAllPanel->Color = clWhite;
	FilterSeriesAllPanel->Font->Color = clBlack;
	for (int defectSeriesIndex = 0; defectSeriesIndex < 8; defectSeriesIndex++)
	{
		TTntPanel *aPanel = (TTntPanel *)FindComponent("FilterSeriesPanel" + IntToStr(defectSeriesIndex + 1));
		aPanel->Color = clWhite;
		aPanel->Font->Color = clBlack;
	}
	thePanel->Color = clBlue;
	thePanel->Font->Color = clWhite;

	if (defectSeriesIndex == 0)
	{
		FilterDefectSeriesMask = 0xFFFFFFFF;
	}
	else
	{
		FilterDefectSeriesMask = 0x00000001 << (defectSeriesIndex - 1);
	}
	RefreshStringGrid();
}
//---------------------------------------------------------------------------


void __fastcall TDefectInfoForm::ScrollImageMouseDown(TObject *Sender,
	TMouseButton Button, TShiftState Shift, int X, int Y)
{
	if (!IsScrollImageMouseDown)
	{
		ScrollImageMouseDownPos.x = X;
		ScrollImageMouseDownPos.y = Y;
		ScrollImageMouseMovePos.x = X;
		ScrollImageMouseMovePos.y = Y;
		IsScrollImageMouseDown = true;
		StringGridMouseDownPos = DefectListStringGrid->Row;
		LastScrollTime = GetTickCount();
	}
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::ScrollImageMouseMove(TObject *Sender,
	TShiftState Shift, int X, int Y)
{
  if(EnableScroll == false) return;
  
	if (Y < 0 || Y >= ScrollImage->Height) return;
	if (IsScrollImageMouseDown)
	{
		ScrollImageMouseMovePos.x = X;
		ScrollImageMouseMovePos.y = Y;
		int scrollCount = (Y - ScrollImageMouseDownPos.y) / 10;
		int newRow = StringGridMouseDownPos + scrollCount;
		if (newRow < 1) newRow = 1;
		else if (newRow >= DefectListStringGrid->RowCount) newRow = DefectListStringGrid->RowCount - 1;
		DefectListStringGrid->Row = newRow;
		if (scrollCount != 0)
		{
      if(DefectListStringGrid->RowCount -1 == newRow)
      {
          ScrollPageChange(SCROLL_DOWN);
        return;

      }
      else if(newRow == 1 && scrollCount <= -1)
      {
          ScrollPageChange(SCROLL_UP);
        return;
      }

			for (int y = 0; y < ScrollImage->Height; y++)
			{
				byte *pBitmap = (byte *)ScrollImage->Picture->Bitmap->ScanLine[y];
				byte colorB = 0xFF - abs(y - ScrollImage->Height / 2 - scrollCount * 10) * 0x4F / (ScrollImage->Height / 2);
				byte colorG = 0x7F - abs(y - ScrollImage->Height / 2 - scrollCount * 10) * 0x1F / (ScrollImage->Height / 2);
				byte colorR = 0x7F - abs(y - ScrollImage->Height / 2 - scrollCount * 10) * 0x1F / (ScrollImage->Height / 2);
				if (y % 10 == 0)
				{
					colorB = colorG = colorR = 0;
				}

				for (int x = 0; x < ScrollImage->Width; x++)
				{
					pBitmap[x * 3] = colorB;
					pBitmap[x * 3 + 1] = colorG;
					pBitmap[x * 3 + 2] = colorR;
				}
			}

			ScrollImage->Repaint();
			LastScrollTime = GetTickCount();
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::ScrollImageMouseUp(TObject *Sender,
	TMouseButton Button, TShiftState Shift, int X, int Y)
{
	IsScrollImageMouseDown = false;

	for (int y = 0; y < ScrollImage->Height; y++)
	{
		byte *pBitmap = (byte *)ScrollImage->Picture->Bitmap->ScanLine[y];
		byte colorB = 0xFF - abs(y - ScrollImage->Height / 2) * 0x4F / (ScrollImage->Height / 2);
		byte colorG = 0x7F - abs(y - ScrollImage->Height / 2) * 0x1F / (ScrollImage->Height / 2);
		byte colorR = 0x7F - abs(y - ScrollImage->Height / 2) * 0x1F / (ScrollImage->Height / 2);

		if (y % 10 == 0)
		{
			colorB = colorG = colorR = 0;
		}

		for (int x = 0; x < ScrollImage->Width; x++)
		{
			pBitmap[x * 3] = colorB;
			pBitmap[x * 3 + 1] = colorG;
			pBitmap[x * 3 + 2] = colorR;
		}
	}
	ScrollImage->Repaint();
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::ScrollTimerTimer(TObject *Sender)
{
	if (IsScrollImageMouseDown)
	{
		if (GetTickCount() - LastScrollTime > 500)
		{
			if (ScrollImageMouseDownPos.y < ScrollImage->Height / 2)
			{
				if (DefectListStringGrid->Row > 1)
				{
					DefectListStringGrid->Row--;
				}
			}
			else
			{
				if (DefectListStringGrid->Row < DefectListStringGrid->RowCount - 1)
				{
					DefectListStringGrid->Row++;
				}
			}

			ScrollImageMouseDownPos.x = ScrollImageMouseMovePos.x;
			ScrollImageMouseDownPos.y = ScrollImageMouseMovePos.y;
			StringGridMouseDownPos = DefectListStringGrid->Row;
			LastScrollTime = GetTickCount();

			for (int y = 0; y < ScrollImage->Height; y++)
			{
				byte *pBitmap = (byte *)ScrollImage->Picture->Bitmap->ScanLine[y];
				byte colorB = 0xFF - abs(y - ScrollImage->Height / 2) * 0x4F / (ScrollImage->Height / 2);
				byte colorG = 0x7F - abs(y - ScrollImage->Height / 2) * 0x1F / (ScrollImage->Height / 2);
				byte colorR = 0x7F - abs(y - ScrollImage->Height / 2) * 0x1F / (ScrollImage->Height / 2);

				if (y % 10 == 0)
				{
					colorB = colorG = colorR = 0;
				}

				for (int x = 0; x < ScrollImage->Width; x++)
				{
					pBitmap[x * 3] = colorB;
					pBitmap[x * 3 + 1] = colorG;
					pBitmap[x * 3 + 2] = colorR;
				}
			}

			int radius = 40;

			for (int y = ScrollImageMouseDownPos.y - radius; y < ScrollImageMouseDownPos.y + radius; y++)
			{
				if (y < 0 || y >= ScrollImage->Height) continue;
				byte *pBitmap = (byte *)ScrollImage->Picture->Bitmap->ScanLine[y];
				for (int x = ScrollImageMouseDownPos.x - radius; x < ScrollImageMouseDownPos.x + radius; x++)
				{
					if (x < 0 || x >= ScrollImage->Width) continue;
					if (radius * radius > (y - ScrollImageMouseDownPos.y) * (y - ScrollImageMouseDownPos.y) + (x - ScrollImageMouseDownPos.x) * (x - ScrollImageMouseDownPos.x))
					{
						pBitmap[x * 3] = pBitmap[x * 3] - sqrt(radius * radius - (y - ScrollImageMouseDownPos.y) * (y - ScrollImageMouseDownPos.y) - (x - ScrollImageMouseDownPos.x) * (x - ScrollImageMouseDownPos.x)) * pBitmap[x * 3] / radius / 2;
						pBitmap[x * 3 + 1] = pBitmap[x * 3 + 1] - sqrt(radius * radius - (y - ScrollImageMouseDownPos.y) * (y - ScrollImageMouseDownPos.y) - (x - ScrollImageMouseDownPos.x) * (x - ScrollImageMouseDownPos.x)) * pBitmap[x * 3 + 1] / radius / 2;
						pBitmap[x * 3 + 2] = pBitmap[x * 3 + 2] - sqrt(radius * radius - (y - ScrollImageMouseDownPos.y) * (y - ScrollImageMouseDownPos.y) - (x - ScrollImageMouseDownPos.x) * (x - ScrollImageMouseDownPos.x)) * pBitmap[x * 3 + 2] / radius / 2;
					}
				}
			}
			ScrollImage->Repaint();
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::SortByTimePanelClick(TObject *Sender)
{
	SortBySizePanel->Color = clWhite;
	SortBySizePanel->Font->Color = clBlack;
	SortBySizePanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_19;

	SortByCameraPanel->Color = clWhite;
	SortByCameraPanel->Font->Color = clBlack;
	SortByCameraPanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_16;

	SortByTimePanel->Color = clBlue;
	SortByTimePanel->Font->Color = clWhite;
	if (SortMethod == SORT_BY_TIME_DESCENDING_ORDER)
	{
		SortMethod = SORT_BY_TIME_ASCENDING_ORDER;
		DefectDataList->Sort(SortDefectDataByTabletNumber_Ascending);
		SortByTimePanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_12;
	}
	else
	{
		SortMethod = SORT_BY_TIME_DESCENDING_ORDER;
		DefectDataList->Sort(SortDefectDataByTabletNumber_Descending);
		SortByTimePanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_13;
	}
	RefreshStringGrid();
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::SortBySizePanelClick(TObject *Sender)
{
	SortByTimePanel->Color = clWhite;
	SortByTimePanel->Font->Color = clBlack;
	SortByTimePanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_11;

	SortByCameraPanel->Color = clWhite;
	SortByCameraPanel->Font->Color = clBlack;
	SortByCameraPanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_16;

	SortBySizePanel->Color = clBlue;
	SortBySizePanel->Font->Color = clWhite;
	if (SortMethod == SORT_BY_SIZE_DESCENDING_ORDER)
	{
		SortMethod = SORT_BY_SIZE_ASCENDING_ORDER;
		DefectDataList->Sort(SortDefectDataByDefectSize_Ascending);
		SortBySizePanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_20;
	}
	else
	{
		SortMethod = SORT_BY_SIZE_DESCENDING_ORDER;
		DefectDataList->Sort(SortDefectDataByDefectSize_Descending);
		SortBySizePanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_21;
	}
	RefreshStringGrid();
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::SortByCameraPanelClick(TObject *Sender)
{
	SortBySizePanel->Color = clWhite;
	SortBySizePanel->Font->Color = clBlack;
	SortBySizePanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_19;

	SortByTimePanel->Color = clWhite;
	SortByTimePanel->Font->Color = clBlack;
	SortByTimePanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_11;

	SortByCameraPanel->Color = clBlue;
	SortByCameraPanel->Font->Color = clWhite;
	if (SortMethod == SORT_BY_CAMERA_ASCENDING_ORDER)
	{
		SortMethod = SORT_BY_CAMERA_DESCENDING_ORDER;
		DefectDataList->Sort(SortDefectDataByCamera_Descending);
		SortByCameraPanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_17;
	}
	else
	{
		SortMethod = SORT_BY_CAMERA_ASCENDING_ORDER;
		DefectDataList->Sort(SortDefectDataByCamera_Ascending);
		SortByCameraPanel->Caption = DEFECTINFOFORM_PANEL_CAPTION_18;
	}
	RefreshStringGrid();
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::NumberEditClick(TObject *Sender)
{
  if(EnableScroll == false) return;
  
	TTntEdit *theEdit = (TTntEdit *)Sender;
	KeyboardForm->Text = theEdit->Text;
	if (KeyboardForm->ShowKeypad() == mrOk)
	{
    if(theEdit->Tag == 999)
    {
      int Data = StrToInt(KeyboardForm->Text);
      int CurrentStep = CurrentViewStepCount;

      if(Data != CurrentStep)
      {
        if(Data <= 0)
        {
          theEdit->Text = "1";
          CurrentViewStepCount = 1;
        }
        else
        {
          if(Data <= MaxLimitViewStepCount)
          {
            theEdit->Text = IntToStr(Data);
            CurrentViewStepCount = Data;
          }
          else
            return;
        }

        InitDefectInfo(ProductCode, LOTName); 
      }

    }
    else
  		theEdit->Text = KeyboardForm->Text;

	}
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::FilterCameraOptionPanelClick(
	TObject *Sender)
{
	FilterCameraAllPanel->Color = clWhite;
	FilterCameraAllPanel->Font->Color = clBlack;
	FilterCameraFrontPanel->Color = clWhite;
	FilterCameraFrontPanel->Font->Color = clBlack;
	FilterCameraSidePanel->Color = clWhite;
	FilterCameraSidePanel->Font->Color = clBlack;
	FilterCameraAllPanel->Color = clWhite;
	FilterCameraAllPanel->Font->Color = clBlack;

	FilterCameraOptionPanel->Color = clBlue;
	FilterCameraOptionPanel->Font->Color = clWhite;

	FilterCameraMask = (0x00000001 << SD1_3D_FRONT_FACE_CAMERA_INDEX - 1) |
		(0x00000001 << SD2_3D_FRONT_FACE_CAMERA_INDEX - 1);

	RefreshStringGrid();
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::Remake3DDefectImage(TTntImage *anImage)
{
	int bitmapWidth = anImage->Picture->Bitmap->Width;
	int bitmapHeight = anImage->Picture->Bitmap->Height;
	unsigned char *defectBitmap = new unsigned char[bitmapWidth * bitmapHeight];

	for (int y = 0; y < bitmapHeight; y++)
	{
		unsigned char *pBitmap = (unsigned char *)anImage->Picture->Bitmap->ScanLine[y];
		memcpy(defectBitmap + y * bitmapWidth, pBitmap, bitmapWidth);
	}

	anImage->Picture->Bitmap->Width = bitmapWidth * 2;
	anImage->Picture->Bitmap->Height = bitmapHeight;
	SetGrayPalette(SavedDefectImage->Picture->Bitmap);

	anImage->Width = bitmapWidth * 2;
	anImage->Height = bitmapHeight;

	byte *tempBitmapA = new byte[bitmapWidth * bitmapHeight * 2];
	byte *tempBitmapB = new byte[bitmapWidth * bitmapHeight * 2];

	memset(tempBitmapA, 0, bitmapWidth * bitmapHeight * 2);

	for (int y = 0; y < bitmapHeight; y++)
	{
		byte *pSrc = (byte *)anImage->Picture->Bitmap->ScanLine[y];
		for (int x = 0; x < bitmapWidth * 2; x += 2)
		{
			tempBitmapA[y * bitmapWidth * 2 + x] = pSrc[x / 2];
		}
	}

	for (int y = 1; y < bitmapHeight - 1; y++)
	{
		for (int x = 1; x < bitmapWidth * 2 - 1; x += 2)
		{
			int tempAddress = (y * bitmapWidth * 2 + x);
			int tempSum = 0;
			int tempCount = 0;
			if (tempBitmapA[tempAddress - 1])
			{
				tempSum += tempBitmapA[tempAddress - 1];
				tempCount++;
			}
			if (tempBitmapA[tempAddress + 1])
			{
				tempSum += tempBitmapA[tempAddress + 1];
				tempCount++;
			}
			if (tempBitmapA[tempAddress - 1 - bitmapWidth * 2])
			{
				tempSum += tempBitmapA[tempAddress - 1 - bitmapWidth * 2];
				tempCount++;
			}
			if (tempBitmapA[tempAddress - 1 + bitmapWidth * 2])
			{
				tempSum += tempBitmapA[tempAddress - 1 + bitmapWidth * 2];
				tempCount++;
			}
			if (tempBitmapA[tempAddress + 1 - bitmapWidth * 2])
			{
				tempSum += tempBitmapA[tempAddress + 1 - bitmapWidth * 2];
				tempCount++;
			}
			if (tempBitmapA[tempAddress + 1 + bitmapWidth * 2])
			{
				tempSum += tempBitmapA[tempAddress + 1 + bitmapWidth * 2];
				tempCount++;
			}

			if (tempCount)
				tempBitmapA[(tempAddress)] = tempSum / tempCount;
		}
	}

	memset(tempBitmapB, 0, bitmapWidth * bitmapHeight * 2);
	for (int y = 0; y < bitmapHeight; y++)
	{
		for (int x = 0; x < bitmapWidth * 2; x++)
		{
			int tempAddress = (y * bitmapWidth * 2 + x);

			if (tempBitmapA[tempAddress] != 0)
			{
				tempBitmapB[tempAddress] = tempBitmapA[tempAddress];
			}
		}
	}

	memcpy(tempBitmapA, tempBitmapB, bitmapWidth * bitmapHeight * 2);
	for (int y = 1; y < bitmapHeight - 1; y++)
	{
		for (int x = 1; x < bitmapWidth * 2 - 1; x++)
		{
			int tempAddress = (y * bitmapWidth * 2 + x);
			int tempSum = 0;
			int tempCount = 0;
			if (tempBitmapA[tempAddress] == 0)
			{
				if (tempBitmapB[tempAddress - bitmapWidth * 2])
				{
					tempSum += tempBitmapB[tempAddress - bitmapWidth * 2];
					tempCount++;
				}
				if (tempBitmapB[tempAddress + bitmapWidth * 2])
				{
					tempSum += tempBitmapB[tempAddress + bitmapWidth * 2];
					tempCount++;
				}
				if (tempBitmapB[tempAddress - bitmapWidth * 2 - 1])
				{
					tempSum += tempBitmapB[tempAddress - bitmapWidth * 2 - 1];
					tempCount++;
				}
				if (tempBitmapB[tempAddress - bitmapWidth * 2 + 1])
				{
					tempSum += tempBitmapB[tempAddress - bitmapWidth * 2 + 1];
					tempCount++;
				}
				if (tempBitmapB[tempAddress + bitmapWidth * 2 - 1])
				{
					tempSum += tempBitmapB[tempAddress + bitmapWidth * 2 - 1];
					tempCount++;
				}
				if (tempBitmapB[tempAddress + bitmapWidth * 2 + 1])
				{
					tempSum += tempBitmapB[tempAddress + bitmapWidth * 2 + 1];
					tempCount++;
				}

				if (tempCount >= 1)
					tempBitmapA[(tempAddress)] = tempSum / tempCount;
			}
		}
	}

	for (int y = 0; y < bitmapHeight; y++)
	{
		byte *pBitmap = (byte *)anImage->Picture->Bitmap->ScanLine[y];
		for (int x = 0; x < bitmapWidth * 2; x++)
		{
			pBitmap[x] = tempBitmapA[y * bitmapWidth * 2 + x];
		}
	}

	delete[] tempBitmapA;
	delete[] tempBitmapB;
	delete[] defectBitmap;
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::Remake3DDefectImage_24bit(TTntImage *anImage)
{
	int bitmapWidth = anImage->Picture->Bitmap->Width;
	int bitmapHeight = anImage->Picture->Bitmap->Height;
	unsigned char *defectBitmap = new unsigned char[bitmapWidth * bitmapHeight * 3];

	for (int y = 0; y < bitmapHeight; y++)
	{
		unsigned char *pBitmap = (unsigned char *)anImage->Picture->Bitmap->ScanLine[y];
		memcpy(defectBitmap + y * bitmapWidth * 3, pBitmap, bitmapWidth * 3);
	}

	anImage->Picture->Bitmap->Width = bitmapWidth * 2;
	anImage->Picture->Bitmap->Height = bitmapHeight;
	SetGrayPalette(SavedDefectImage->Picture->Bitmap);

	anImage->Width = bitmapWidth * 2;
	anImage->Height = bitmapHeight;

	byte *pBitmap = (byte *)anImage->Picture->Bitmap->ScanLine[0];
	memset(pBitmap, 0, bitmapWidth * 2 * 3);
	pBitmap = (byte *)anImage->Picture->Bitmap->ScanLine[bitmapHeight - 1];
	memset(pBitmap, 0, bitmapWidth * 2 * 3);
	for (int y = 1; y < bitmapHeight - 1; y++)
	{
		byte *pBitmap = (byte *)anImage->Picture->Bitmap->ScanLine[y];

		byte *pSrc1 = defectBitmap + (y - 1) * bitmapWidth * 3;
		byte *pSrc2 = defectBitmap + (y)* bitmapWidth * 3;
		byte *pSrc3 = defectBitmap + (y + 1) * bitmapWidth * 3;

		pBitmap[0] = pBitmap[3] = pBitmap[bitmapWidth * 2 * 3 - 6] = pBitmap[bitmapWidth * 2 * 3 - 3] = 0;
		pBitmap[1] = pBitmap[4] = pBitmap[bitmapWidth * 2 * 3 - 5] = pBitmap[bitmapWidth * 2 * 3 - 2] = 0;
		pBitmap[2] = pBitmap[5] = pBitmap[bitmapWidth * 2 * 3 - 4] = pBitmap[bitmapWidth * 2 * 3 - 1] = 0;

		for (int x = 2; x < bitmapWidth * 2 - 2; x++)
		{
			if (x & 2)
			{
				pBitmap[x * 3 + 0] = (pSrc1[x / 2 * 3] + pSrc1[x / 2 * 3 + 3] +
					pSrc2[x / 2 * 3] + pSrc2[x / 2 * 3 + 3] +
					pSrc3[x / 2 * 3] + pSrc3[x / 2 * 3 + 3]) / 6;

				pBitmap[x * 3 + 1] = (pSrc1[x / 2 * 3 + 1] + pSrc1[x / 2 * 3 + 4] +
					pSrc2[x / 2 * 3 + 1] + pSrc2[x / 2 * 3 + 4] +
					pSrc3[x / 2 * 3 + 1] + pSrc3[x / 2 * 3 + 4]) / 6;

				pBitmap[x * 3 + 2] = (pSrc1[x / 2 * 3 + 2] + pSrc1[x / 2 * 3 + 5] +
					pSrc2[x / 2 * 3 + 2] + pSrc2[x / 2 * 3 + 5] +
					pSrc3[x / 2 * 3 + 2] + pSrc3[x / 2 * 3 + 5]) / 6;
			}
			else
			{
				pBitmap[x * 3 + 0] = (pSrc1[x / 2 * 3 - 3] + pSrc1[x / 2 * 3] + pSrc1[x / 2 * 3 + 3] +
					pSrc2[x / 2 * 3 - 3] + pSrc2[x / 2 * 3] + pSrc2[x / 2 * 3 + 3] +
					pSrc3[x / 2 * 3 - 3] + pSrc3[x / 2 * 3] + pSrc3[x / 2 * 3 + 3]) / 9;

				pBitmap[x * 3 + 1] = (pSrc1[x / 2 * 3 - 2] + pSrc1[x / 2 * 3 + 1] + pSrc1[x / 2 * 3 + 4] +
					pSrc2[x / 2 * 3 - 2] + pSrc2[x / 2 * 3 + 1] + pSrc2[x / 2 * 3 + 4] +
					pSrc3[x / 2 * 3 - 2] + pSrc3[x / 2 * 3 + 1] + pSrc3[x / 2 * 3 + 4]) / 9;

				pBitmap[x * 3 + 2] = (pSrc1[x / 2 * 3 - 1] + pSrc1[x / 2 * 3 + 2] + pSrc1[x / 2 * 3 + 5] +
					pSrc2[x / 2 * 3 - 1] + pSrc2[x / 2 * 3 + 2] + pSrc2[x / 2 * 3 + 5] +
					pSrc3[x / 2 * 3 - 1] + pSrc3[x / 2 * 3 + 2] + pSrc3[x / 2 * 3 + 5]) / 9;
			}
		}
	}

	delete[] defectBitmap;
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::Remake3DSubDefectImage(TTntImage *anImage)
{
	int bitmapWidth = anImage->Picture->Bitmap->Width;
	int bitmapHeight = anImage->Picture->Bitmap->Height;
	unsigned char *defectBitmap = new unsigned char[bitmapWidth * bitmapHeight];

	for (int y = 0; y < bitmapHeight; y++)
	{
		unsigned char *pBitmap = (unsigned char *)anImage->Picture->Bitmap->ScanLine[y];
		memcpy(defectBitmap + y * bitmapWidth, pBitmap, bitmapWidth);
	}

	anImage->Picture->Bitmap->Width = bitmapWidth * 2;
	anImage->Picture->Bitmap->Height = bitmapHeight;
	SetGrayPalette(SavedDefectImage->Picture->Bitmap);

	byte *pBitmap = (byte *)anImage->Picture->Bitmap->ScanLine[0];
	memset(pBitmap, 0, bitmapWidth * 2);
	pBitmap = (byte *)anImage->Picture->Bitmap->ScanLine[bitmapHeight - 1];
	memset(pBitmap, 0, bitmapWidth * 2);
	for (int y = 1; y < bitmapHeight - 1; y++)
	{
		byte *pBitmap = (byte *)anImage->Picture->Bitmap->ScanLine[y];

		byte *pSrc1 = defectBitmap + (y - 1) * bitmapWidth;
		byte *pSrc2 = defectBitmap + (y)* bitmapWidth;
		byte *pSrc3 = defectBitmap + (y + 1) * bitmapWidth;

		pBitmap[0] = pBitmap[1] = pBitmap[bitmapWidth * 2 - 2] = pBitmap[bitmapWidth * 2 - 1] = 0;

		for (int x = 2; x < bitmapWidth * 2 - 2; x++)
		{
			if (x & 2)
			{
				pBitmap[x] = (pSrc1[x / 2] + pSrc1[x / 2 + 1] +
					pSrc2[x / 2] + pSrc2[x / 2 + 1] +
					pSrc3[x / 2] + pSrc3[x / 2 + 1]) / 6;
			}
			else
			{
				pBitmap[x] = (pSrc1[x / 2 - 1] + pSrc1[x / 2] + pSrc1[x / 2 + 1] +
					pSrc2[x / 2 - 1] + pSrc2[x / 2] + pSrc2[x / 2 + 1] +
					pSrc3[x / 2 - 1] + pSrc3[x / 2] + pSrc3[x / 2 + 1]) / 9;
			}
		}
	}

	delete[] defectBitmap;
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::Remake3DSubDefectImage_24bit(TTntImage *anImage)
{
	int bitmapWidth = anImage->Picture->Bitmap->Width;
	int bitmapHeight = anImage->Picture->Bitmap->Height;
	unsigned char *defectBitmap = new unsigned char[bitmapWidth * bitmapHeight * 3];

	for (int y = 0; y < bitmapHeight; y++)
	{
		unsigned char *pBitmap = (unsigned char *)anImage->Picture->Bitmap->ScanLine[y];
		memcpy(defectBitmap + y * bitmapWidth * 3, pBitmap, bitmapWidth * 3);
	}

	anImage->Picture->Bitmap->Width = bitmapWidth * 2;
	anImage->Picture->Bitmap->Height = bitmapHeight;
	SetGrayPalette(SavedDefectImage->Picture->Bitmap);

	byte *pBitmap = (byte *)anImage->Picture->Bitmap->ScanLine[0];
	memset(pBitmap, 0, bitmapWidth * 2 * 3);
	pBitmap = (byte *)anImage->Picture->Bitmap->ScanLine[bitmapHeight - 1];
	memset(pBitmap, 0, bitmapWidth * 2 * 3);
	for (int y = 1; y < bitmapHeight - 1; y++)
	{
		byte *pBitmap = (byte *)anImage->Picture->Bitmap->ScanLine[y];

		byte *pSrc1 = defectBitmap + (y - 1) * bitmapWidth * 3;
		byte *pSrc2 = defectBitmap + (y)* bitmapWidth * 3;
		byte *pSrc3 = defectBitmap + (y + 1) * bitmapWidth * 3;

		pBitmap[0] = pBitmap[3] = pBitmap[bitmapWidth * 2 * 3 - 6] = pBitmap[bitmapWidth * 2 * 3 - 3] = 0;
		pBitmap[1] = pBitmap[4] = pBitmap[bitmapWidth * 2 * 3 - 5] = pBitmap[bitmapWidth * 2 * 3 - 2] = 0;
		pBitmap[2] = pBitmap[5] = pBitmap[bitmapWidth * 2 * 3 - 4] = pBitmap[bitmapWidth * 2 * 3 - 1] = 0;

		for (int x = 2; x < bitmapWidth * 2 - 2; x++)
		{
			if (x & 2)
			{
				pBitmap[x * 3 + 0] = (pSrc1[x / 2 * 3] + pSrc1[x / 2 * 3 + 3] +
					pSrc2[x / 2 * 3] + pSrc2[x / 2 * 3 + 3] +
					pSrc3[x / 2 * 3] + pSrc3[x / 2 * 3 + 3]) / 6;

				pBitmap[x * 3 + 1] = (pSrc1[x / 2 * 3 + 1] + pSrc1[x / 2 * 3 + 4] +
					pSrc2[x / 2 * 3 + 1] + pSrc2[x / 2 * 3 + 4] +
					pSrc3[x / 2 * 3 + 1] + pSrc3[x / 2 * 3 + 4]) / 6;

				pBitmap[x * 3 + 2] = (pSrc1[x / 2 * 3 + 2] + pSrc1[x / 2 * 3 + 5] +
					pSrc2[x / 2 * 3 + 2] + pSrc2[x / 2 * 3 + 5] +
					pSrc3[x / 2 * 3 + 2] + pSrc3[x / 2 * 3 + 5]) / 6;
			}
			else
			{
				pBitmap[x * 3 + 0] = (pSrc1[x / 2 * 3 - 3] + pSrc1[x / 2 * 3] + pSrc1[x / 2 * 3 + 3] +
					pSrc2[x / 2 * 3 - 3] + pSrc2[x / 2 * 3] + pSrc2[x / 2 * 3 + 3] +
					pSrc3[x / 2 * 3 - 3] + pSrc3[x / 2 * 3] + pSrc3[x / 2 * 3 + 3]) / 9;

				pBitmap[x * 3 + 1] = (pSrc1[x / 2 * 3 - 2] + pSrc1[x / 2 * 3 + 1] + pSrc1[x / 2 * 3 + 4] +
					pSrc2[x / 2 * 3 - 2] + pSrc2[x / 2 * 3 + 1] + pSrc2[x / 2 * 3 + 4] +
					pSrc3[x / 2 * 3 - 2] + pSrc3[x / 2 * 3 + 1] + pSrc3[x / 2 * 3 + 4]) / 9;

				pBitmap[x * 3 + 2] = (pSrc1[x / 2 * 3 - 1] + pSrc1[x / 2 * 3 + 2] + pSrc1[x / 2 * 3 + 5] +
					pSrc2[x / 2 * 3 - 1] + pSrc2[x / 2 * 3 + 2] + pSrc2[x / 2 * 3 + 5] +
					pSrc3[x / 2 * 3 - 1] + pSrc3[x / 2 * 3 + 2] + pSrc3[x / 2 * 3 + 5]) / 9;
			}
		}
	}

	delete[] defectBitmap;
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::Panel2Resize(TObject *Sender)
{
	DefectListStringGrid->ColWidths[0] = 80;
	DefectListStringGrid->ColWidths[1] = max(0, DefectListStringGrid->Width - 30 - 80 - 80 - 80);
	DefectListStringGrid->ColWidths[2] = 80;
	DefectListStringGrid->ColWidths[3] = 80;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TDefectInfoForm::GetDefectContainerFileName(int defectIndex)
{
	int containerIndex = defectIndex / DEFECT_DATA_CONTAINER_SIZE;
	AnsiString saveDir = ProgramPath.Defect + "\\" + ProductCode + "\\" + LOTName;
	return saveDir + "\\DefectImage" + IntToStr(containerIndex + 1) + ".FAC";
}
//---------------------------------------------------------------------------

bool __fastcall TDefectInfoForm::ReadSetupData(TTabletSetupData *tabletSetupData)
{
	AnsiString setupDataFileName = ProgramPath.Product + "\\" + ProductData.ProductCode + "\\" + ProductData.ProductCode + ".sdt";
	if (FileExists(setupDataFileName))
	{
		TFileStream *fileStream = new TFileStream(setupDataFileName, fmOpenRead);
		if (fileStream)
		{
			memset(tabletSetupData, 0, sizeof(TTabletSetupData));
			fileStream->Read(tabletSetupData, fileStream->Size);
			delete fileStream;
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::DoProcessing(int cameraIndex)
{
	if (!ReadSetupData(&TabletSetupData))
	{
		ShowMessageW(DEFECTINFOFORM_MSG_01);
	}

	if (!ReadStudyData(&TabletStudyData))
	{
		ShowMessageW(DEFECTINFOFORM_MSG_02);
	}

	AnsiString gradeFileName = ProgramPath.Product + "\\" + ProductData.ProductCode + "\\" + ProductData.ProductCode + ".grd";
	LoadGradeData(gradeFileName, TabletGradeData);

	InspectionOrStudy = INSPECTION_MODE;

	cameraIndex = cameraIndex + 1;

	MakeTabletCharacterData(&ProductData, &TabletCharacter, &MachineParams);
  
  SetSideFaceDataAddress(&tempSideData[0]); // spbIndex... 일단 2,3,4 번 카메라의 res만 유효하게 사용해본다.

  int SDNum;
	if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
  {
		SDNum = SUCTION_DISK_NUM1;
    FrontFaceSetUpDataTransForm(FRONT_FACE, SDNum);
  }
	else if (cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
  {
		SDNum = SUCTION_DISK_NUM2;
    FrontFaceSetUpDataTransForm(FRONT_FACE, SDNum);
  }

	ImageLoad(cameraIndex, 0);

	switch (cameraIndex)
	{
	case SD1_2D_FRONT_FACE_CAMERA_INDEX:
	case SD2_2D_FRONT_FACE_CAMERA_INDEX:

		InspectionKind = FRONT_FACE;
		ProcessingStartForFrontFace(InspectionOrStudy, cameraIndex, 1);
		break;

	case SD1_2D_SIDE_FACE_P45_CAMERA_INDEX:
	case SD2_2D_SIDE_FACE_P45_CAMERA_INDEX:
	case SD1_2D_OTHER_SIDE_FACE_P45_CAMERA_INDEX:
	case SD2_2D_OTHER_SIDE_FACE_P45_CAMERA_INDEX:
		InspectionKind = SIDE_FACE_P45;
		ProcessingStartForSideFace_P45(InspectionOrStudy, cameraIndex, 1);
		break;

	case SD1_2D_SIDE_FACE_00_CAMERA_INDEX:
	case SD2_2D_SIDE_FACE_00_CAMERA_INDEX:
	case SD1_2D_OTHER_SIDE_FACE_00_CAMERA_INDEX:
	case SD2_2D_OTHER_SIDE_FACE_00_CAMERA_INDEX:
		InspectionKind = SIDE_FACE_0;
		ProcessingStartForSideFace_0(InspectionOrStudy, cameraIndex, 1);
		break;

	case SD1_2D_SIDE_FACE_M45_CAMERA_INDEX:
	case SD2_2D_SIDE_FACE_M45_CAMERA_INDEX:
	case SD1_2D_OTHER_SIDE_FACE_M45_CAMERA_INDEX:
	case SD2_2D_OTHER_SIDE_FACE_M45_CAMERA_INDEX:
		InspectionKind = SIDE_FACE_M45;
		ProcessingStartForSideFace_M45(InspectionOrStudy, cameraIndex, 1);
		break;
	}

	ProcessingResultDisplay(cameraIndex);
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::ImageLoad(int cameraIndex, int threeDImage)
{
	int x, y;
  int ImageWidth;
  int ImageHeight;
  int tempAddress;
  
  if(!threeDImage && ProductData.SubSamplingMode == IMAGE_FULL_SCALE_MODE)
  {
    ImageWidth = SYSTEM_CAMERA_HD_WIDTH;
    ImageHeight = SYSTEM_CAMERA_HD_HEIGHT;
  }
  else
  {
    ImageWidth = SYSTEM_CAMERA_WIDTH;
    ImageHeight = SYSTEM_CAMERA_HEIGHT;
  }

	Graphics::TBitmap *pTmpImage = new Graphics::TBitmap;
	Graphics::TBitmap *pTmp3DImage = new Graphics::TBitmap;
  pTmpImage->Width = ImageWidth;
  pTmpImage->Height = ImageHeight;

	pTmp3DImage->PixelFormat = pf8bit;
	if (!threeDImage)
	{
		pTmpImage->PixelFormat = pf24bit;
	}
	else
	{
		pTmp3DImage->PixelFormat = pf8bit;
	}

	pTmpImage->Assign(tempSavedDefectImage->Picture->Bitmap);
	pTmp3DImage->Assign(SPBThreeDImage->Picture->Bitmap);

	memset(OriginalImage, 0, SYSTEM_CAMERA_HD_WIDTH * SYSTEM_CAMERA_HD_HEIGHT * 3);

	Byte *ptr;

	if (!threeDImage)
	{
		for (y = 0; y < ImageHeight; y++)
		{
			ptr = (Byte*)pTmpImage->ScanLine[y];
			for (x = 0; x < ImageWidth; x++)
			{
        tempAddress = ImageWidth * y + x;

				BayerImage[tempAddress * 3 + 0] = ptr[3 * x + 0];
				BayerImage[tempAddress * 3 + 1] = ptr[3 * x + 1];
				BayerImage[tempAddress * 3 + 2] = ptr[3 * x + 2];

				OriginalImage[tempAddress * 3 + 0] = ptr[3 * x + 0];
				OriginalImage[tempAddress * 3 + 1] = ptr[3 * x + 1];
				OriginalImage[tempAddress * 3 + 2] = ptr[3 * x + 2];
			}
		}
	}
	else
	{
		const int THREE_D_SRC_IMAGE_WIDTH = 512;

		memset(ThreeD_Data, 0, HALF_MAX_IMAGE_WIDTH*MAX_IMAGE_HEIGHT);
		memset(ThreeD_Image, 0, MAX_IMAGE_WIDTH*MAX_IMAGE_HEIGHT);
		for (y = 10; y < ImageHeight - 10; y++)
		{
			ptr = (Byte*)pTmpImage->ScanLine[y];
			for (x = 10; x < ImageWidth - 10; x++)
			{
        tempAddress = ImageWidth * y + x;
        
				OriginalImage[tempAddress * 3 + 0] = ptr[x];
				OriginalImage[tempAddress * 3 + 1] = ptr[x];
				OriginalImage[tempAddress * 3 + 2] = ptr[x];
			}
		}

		for (y = 0; y < ImageHeight; y++)
		{
			ptr = (Byte*)pTmp3DImage->ScanLine[y];
			for (x = 0; x < ImageWidth / 2; x++)
			{
				ThreeD_Data[ImageWidth / 2 * y + x] = ptr[x];
			}
		}
	}

	delete pTmpImage;
	delete pTmp3DImage;
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::ProcessingResultDisplay(int cameraIndex)
{
  Byte *ptr;
  int tempAddress;
  int tempAddress2;

  if(TabletCharacter.discriminationDisplay_kind == PRINT || TabletCharacter.discriminationDisplay_kind == STAMP)
  {
    if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX || cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX) // 정면
    {
      if(DefectSW == 0 || DefectSW == 1)
      {
        ExtractedPrintInfoImage->Visible = true;
        PrintInfoPanel->Visible = true;

        int shiftX, shiftY;
        shiftX = ProtoTabletCenterX - 150;
        shiftY = ProtoTabletCenterY - 150;

        Graphics::TBitmap *img2;
        img2 = new Graphics::TBitmap();
        img2->Width = 300;
        img2->Height = 300;
        img2->PixelFormat = pf24bit;
        for (int y = 0; y < 300; y++)
        {
          ptr = (byte*)img2->ScanLine[y];
          for (int x = 0; x < 300; x++)
          {
            tempAddress = MAX_IMAGE_WIDTH * (y + shiftY) + (x + shiftX);

            if(TabletCharacter.discriminationDisplay_kind == PRINT)
            {
              ptr[3 * x + 0] = ColorSourceImage[tempAddress * 3 + 0];
              ptr[3 * x + 1] = ColorSourceImage[tempAddress * 3 + 1];
              ptr[3 * x + 2] = ColorSourceImage[tempAddress * 3 + 2];

              if(DarkPixelNeighborPrint[tempAddress])
              {
                ptr[3 * x + selectedRGB] = min(255, ptr[3 * x + selectedRGB] * 2);
              }
            }
            else
            {
              ptr[3*x + 0] = min(255, DarkPixelNeighborPrint[tempAddress] * 10);
              ptr[3*x + 1] = min(255, DarkPixelNeighborPrint[tempAddress] * 10);
              ptr[3*x + 2] = min(255, DarkPixelNeighborPrint[tempAddress] * 10);
            }
          }
        }

        ExtractedPrintInfoImage->Picture->Bitmap->Assign(img2);
        ExtractedPrintInfoImage->Refresh();

        delete img2;
      }
    }
  }

  if(TabletCharacter.HighResolutionImage)
  {
    memcpy(ColorSourceImage, tempColorSourceImage, HD_IMAGE_WIDTH * HD_IMAGE_HEIGHT * 3);
  }

	if (cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX ||
		cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX) // 정면
	{
		Graphics::TBitmap *img1;
		img1 = new Graphics::TBitmap();
		img1->Width = SourceImageWidth[0];
		img1->Height = SourceImageHeight[0];
		img1->PixelFormat = pf24bit;

		int areaValue;

    for (int y = 10; y < SourceImageHeight[0] - 10; y++)
    {
      ptr = (byte*)img1->ScanLine[y];
      for (int x = 10; x < SourceImageWidth[0] - 10; x++)
      {
        tempAddress = SourceImageWidth[0] * y + x;
        tempAddress2 = MAX_IMAGE_WIDTH * (y / rate[0]) + x / rate[0];

        areaValue = InspectionArea[tempAddress2];

        if (areaValue != 0)
        {
          if (areaValue == FRONT_SHAPE_EDGE_NEIGHBOR)
          {
            ptr[3 * x] = min(255, ColorSourceImage[(tempAddress) * 3 + 0] + 60);
            ptr[3 * x + 1] = ColorSourceImage[(tempAddress) * 3 + 1];
            ptr[3 * x + 2] = 255;
          }
          else if (areaValue == FRONT_SHAPE_EDGE)
          {
            ptr[3 * x] = 255;
            ptr[3 * x + 1] = ColorSourceImage[(tempAddress) * 3 + 1];
            ptr[3 * x + 2] = min(255, ColorSourceImage[(tempAddress) * 3 + 2] + 60);
          }
          else if (areaValue == NORMAL_INPECTION_AREA)
          {
            ptr[3 * x] = ColorSourceImage[(tempAddress) * 3 + 0];
            ptr[3 * x + 1] = min(ColorSourceImage[(tempAddress) * 3 + 1] + 60, 255);
            ptr[3 * x + 2] = ColorSourceImage[(tempAddress) * 3 + 2];
          }
          else if (areaValue == PRINT_AREA || areaValue == FRONT_FACE_SPLIT_AREA)
          {
            ptr[3 * x] = min(ColorSourceImage[(tempAddress) * 3 + 0] + 40, 255);
            ptr[3 * x + 1] = min(ColorSourceImage[(tempAddress) * 3 + 1] + 40, 255);
            ptr[3 * x + 2] = 0;
          }
          else if (areaValue == PRINT_NEIGHBOR_SHORT)
          {
            ptr[3 * x] = 0;
            ptr[3 * x + 1] = min(ColorSourceImage[(tempAddress) * 3 + 1] + 70, 255);
            ptr[3 * x + 2] = min(ColorSourceImage[(tempAddress) * 3 + 2] + 70, 255);
          }
          else if (areaValue == PRINT_NEIGHBOR_LONG)
          {
            ptr[3 * x] = min(ColorSourceImage[(tempAddress) * 3 + 0] + 50, 255);
            ptr[3 * x + 1] = 0;
            ptr[3 * x + 2] = min(ColorSourceImage[(tempAddress) * 3 + 2] + 20, 255);
          }
          else if (areaValue == FRONT_SHAPE_EDGE_AND_PRINT_SHORT || areaValue == FRONT_SHAPE_EDGE_AND_PRINT_LONG)
          {
            ptr[3 * x] = min(ColorSourceImage[(tempAddress) * 3 + 0] + 70, 255);
            ptr[3 * x + 1] = 0;
            ptr[3 * x + 2] = 0;
          }
          else if (areaValue == FRONT_MASKING_AREA)
          {
            ptr[3 * x] = 255;
            ptr[3 * x + 1] = ColorSourceImage[(tempAddress) * 3 + 1];
            ptr[3 * x + 2] = ColorSourceImage[(tempAddress) * 3 + 2];
          }
          else
          {
            ptr[3 * x] = ColorSourceImage[(tempAddress) * 3 + 0];
            ptr[3 * x + 1] = ColorSourceImage[(tempAddress) * 3 + 1];
            ptr[3 * x + 2] = ColorSourceImage[(tempAddress) * 3 + 2];
          }

          if(DefectSW && (DefectInformation.defectSeries == DEFECT_PRINT_SPREAD || DefectInformation.defectSeries == DEFECT_PRINT_ERASE))
          {
            if(LabelImage_Virtual[tempAddress2])
            {
              ptr[3*x] = 0;
              ptr[3*x+1] = 0;
              ptr[3*x+2] = 255;
            }
          }
          else
          {
            if (LabelImage_Virtual[tempAddress2])
            {
              ptr[3 * x] = (LabelImage_Virtual[tempAddress2] * 17) & 0xFF;
              ptr[3 * x + 1] = (LabelImage_Virtual[tempAddress2] * 41) & 0xFF;
              ptr[3 * x + 2] = (LabelImage_Virtual[tempAddress2] * 73) & 0xFF;
            }
          }
        }
        else
        {
          ptr[3 * x] = ColorSourceImage[(tempAddress) * 3 + 0];
          ptr[3 * x + 1] = ColorSourceImage[(tempAddress) * 3 + 1];
          ptr[3 * x + 2] = ColorSourceImage[(tempAddress) * 3 + 2];
        }
      }
    } 

		SavedDefectImage->Picture->Bitmap->Assign(img1);
		SavedDefectImage->Refresh();
		delete(img1);
	}
	else if (cameraIndex == SD1_2D_SIDE_FACE_P45_CAMERA_INDEX ||
		cameraIndex == SD2_2D_SIDE_FACE_P45_CAMERA_INDEX ||
		cameraIndex == SD1_2D_OTHER_SIDE_FACE_P45_CAMERA_INDEX ||
		cameraIndex == SD2_2D_OTHER_SIDE_FACE_P45_CAMERA_INDEX ||
		cameraIndex == SD1_2D_SIDE_FACE_M45_CAMERA_INDEX ||
		cameraIndex == SD2_2D_SIDE_FACE_M45_CAMERA_INDEX ||
		cameraIndex == SD1_2D_OTHER_SIDE_FACE_M45_CAMERA_INDEX ||
		cameraIndex == SD2_2D_OTHER_SIDE_FACE_M45_CAMERA_INDEX ||
		cameraIndex == SD1_2D_SIDE_FACE_00_CAMERA_INDEX ||
		cameraIndex == SD2_2D_SIDE_FACE_00_CAMERA_INDEX ||
		cameraIndex == SD1_2D_OTHER_SIDE_FACE_00_CAMERA_INDEX ||
		cameraIndex == SD2_2D_OTHER_SIDE_FACE_00_CAMERA_INDEX)
	{
		Graphics::TBitmap *img1;
		img1 = new Graphics::TBitmap();
		img1->Width = SourceImageWidth[0];
		img1->Height = SourceImageHeight[0];
		img1->PixelFormat = pf24bit;
		int areaValue;

    for(int y = 10; y < SourceImageHeight[0]-10; y++)
    {
      ptr = (byte*) img1->ScanLine[y];
      for(int x = 10; x < SourceImageWidth[0]-10; x++)
      {
        tempAddress =  SourceImageWidth[0]*y+x;//MAX_IMAGE_WIDTH*y + x;
        tempAddress2 = MAX_IMAGE_WIDTH * (y / rate[0]) + x / rate[0];
        areaValue = InspectionArea[tempAddress2];

        if(areaValue == SIDE_SHAPE_BOTTOM_EDGE_SHORT_NEIGHBOR)
        {
          ptr[3*x] = 255;
          ptr[3*x+1] = ColorSourceImage[(tempAddress)*3+1];
          ptr[3*x+2] = 255;
        }
        else if(areaValue == SIDE_SHAPE_BOTTOM_EDGE_LONG_NEIGHBOR)
        {
          ptr[3*x] = ColorSourceImage[(tempAddress)*3+0];
          ptr[3*x+1] = 255;
          ptr[3*x+2] = 255;
        }
        else if (areaValue == SIDE_SHAPE_TOP_NORMAL_BOUNDARY_AREA)
        {
          ptr[3 * x] = 0;
          ptr[3 * x + 1] = min(ColorSourceImage[(tempAddress) * 3 + 1] + 60, 255);
          ptr[3 * x + 2] = min(ColorSourceImage[(tempAddress) * 3 + 2] + 60, 255);
        }
        else if (areaValue == SIDE_SHAPE_UNINSPECTION_AREA)
        {
          ptr[3 * x] = min(ColorSourceImage[(tempAddress) * 3 + 0] + 60, 255);
          ptr[3 * x + 1] = min(ColorSourceImage[(tempAddress) * 3 + 1] + 60, 255);
          ptr[3 * x + 2] = 0;
        }
        else if(areaValue == SIDE_SHAPE_TOP_EDGE_UPPER_NEIGHBOR)
        {
          ptr[3*x] = ColorSourceImage[(tempAddress)*3+0];
          ptr[3*x+1] = ColorSourceImage[(tempAddress)*3+1];
          ptr[3*x+2] = min(ColorSourceImage[(tempAddress)*3+2] + 60, 255);
        }
        else if(areaValue == NORMAL_INPECTION_AREA)
        {
          ptr[3*x] = ColorSourceImage[(tempAddress)*3+0];
          ptr[3*x+1] = ColorSourceImage[(tempAddress)*3+1];
          ptr[3*x+2] = min(ColorSourceImage[(tempAddress)*3+2] + 60, 255);
        }
        else if(areaValue == NORMAL_INPECTION_AREA2)
        {
          ptr[3*x] = ColorSourceImage[(tempAddress)*3+0];
          ptr[3*x+1] = min(ColorSourceImage[(tempAddress)*3+1] + 60, 255);
          ptr[3*x+2] = ColorSourceImage[(tempAddress)*3+2];
        }
        else if (areaValue == SIDE_SHAPE_MULTI_TABLET_BOUNDARY_AREA)
        {
          ptr[3 * x] = 0;
          ptr[3 * x + 1] = min(ColorSourceImage[(tempAddress) * 3 + 1] + 60, 255);
          ptr[3 * x + 2] = min(ColorSourceImage[(tempAddress) * 3 + 0] + 60, 255);
        }
        else
        {
          ptr[3*x] = ColorSourceImage[(tempAddress)*3+0];
          ptr[3*x+1] = ColorSourceImage[(tempAddress)*3+1];
          ptr[3*x+2] = ColorSourceImage[(tempAddress)*3+2];
        }

        if(LabelImage_Virtual[tempAddress2])
        {
          ptr[3*x] = 0;
          ptr[3*x+1] = 0;
          ptr[3*x+2] = 255;
        }
      }
    }

		SavedDefectImage->Picture->Bitmap->Assign(img1);
		SavedDefectImage->Refresh();
		delete(img1);
	}

	CurrentDisplayImage->Assign(SavedDefectImage->Picture->Bitmap);
	LoadZoomInOutNavigationImage(ZOOM_IMAGE_DEFECT, 0, 0);

  bool bThreeD;
  if (cameraIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX &&
			cameraIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX)
  {
    bThreeD = false;
  }
  else
  {
    bThreeD = true;
  }

	if (DefectSW)
	{
		// show defected position
    AnsiString DefectSizeStr;
    if(DefectInformation.defectSeries == FAT_TALBET || DefectInformation.defectSeries == THIN_TALBET) // 화면에 표시 되는 Size는 기준 두께보다 얼마나 두껍고 얇은 정제인지를 표시함
      DefectSizeStr = FloatToStr((float)DefectInformation.size*30/1000.0) +" mm";
    else if(DefectInformation.defectSeries == DEFECT_3D_PRINT_ERASE)
      DefectSizeStr = FloatToStr(DefectInformation.size) + " %";
    else if(DefectInformation.defectSeries == DEFECT_FRONT_WHITE_ENGRAVE)
      DefectSizeStr = IntToStr(DefectInformation.size) + " Grade";
    else if(DefectInformation.defectSeries == DEFECT_PRINT_POSITION_ERROR)
      DefectSizeStr = FloatToStr(DefectInformation.size*0.04) + " mm";
    else if(DefectInformation.defectSeries == DEFECT_PRINT_ROTATION_ERROR)
      DefectSizeStr = IntToStr(DefectInformation.size) + " Degree";
    else
      DefectSizeStr = FloatToStr(DefectSizePixelToMili(DefectInformation.size) / 100.0) + "mm";

		SavedDefectImage->Canvas->Font->Color = clWhite;
		SavedDefectImage->Canvas->Font->Size = 12 * rate[bThreeD] + FontSizeAdjust[bThreeD];
    SavedDefectImage->Canvas->TextOutW(15 * rate[bThreeD], 15 * rate[bThreeD], GetDefectSeriesStr(DefectInformation.defectSeries) + "//" + DefectSizeStr);

		SavedDefectImage->Canvas->Pen->Color = clWhite;
    SavedDefectImage->Canvas->Pen->Width = 2;
		SavedDefectImage->Canvas->Brush->Style = bsClear;
		SavedDefectImage->Canvas->Rectangle(
			(DefectInformation.defectPositionStartX - 4) * rate[bThreeD], (DefectInformation.defectPositionStartY - 4) * rate[bThreeD],
			(DefectInformation.defectPositionEndX + 4) * rate[bThreeD], (DefectInformation.defectPositionEndY + 4) * rate[bThreeD]);

		SavedDefectImage->Canvas->Pen->Color = clRed;
    SavedDefectImage->Canvas->Pen->Width = 2;
		SavedDefectImage->Canvas->Brush->Style = bsClear;
		SavedDefectImage->Canvas->Rectangle(
			(DefectInformation.defectPositionStartX - 2) * rate[bThreeD], (DefectInformation.defectPositionStartY - 2) * rate[bThreeD],
			(DefectInformation.defectPositionEndX + 2) * rate[bThreeD], (DefectInformation.defectPositionEndY + 2) * rate[bThreeD]);


		// show boundary area
		SavedDefectImage->Canvas->Pen->Color = clBlue;
    SavedDefectImage->Canvas->Pen->Width = 2;
		SavedDefectImage->Canvas->Brush->Style = bsClear;
		SavedDefectImage->Canvas->Rectangle(
			ProductData.BoundaryLeft[cameraIndex - 1] * rate[bThreeD], ProductData.BoundaryTop[cameraIndex - 1] * rate[bThreeD],
			ProductData.BoundaryRight[cameraIndex - 1] * rate[bThreeD], ProductData.BoundaryBottom[cameraIndex - 1] * rate[bThreeD]);

		SavedDefectImage->Repaint();
	}
	else
	{
		SavedDefectImage->Canvas->Font->Color = clWhite;
		SavedDefectImage->Canvas->Font->Size = 12 * rate[bThreeD]+FontSizeAdjust[bThreeD];

		if (!(TabletCharacter.discriminationDisplay_kind == STAMP && TabletCharacter.discriminationDisplay_num == ONE_FACE))
		{
			bEngraveDefect = false;
		}

		if (!bEngraveDefect)
			SavedDefectImage->Canvas->TextOutW(15 * rate[bThreeD], 15 * rate[bThreeD], "OK");
		else
			SavedDefectImage->Canvas->TextOutW(15 * rate[bThreeD], 15 * rate[bThreeD], GetDefectSeriesStr(DEFECT_2D_AND_3D_PRINT_NOT_MATCHING));

		SavedDefectImage->Canvas->Rectangle(
			ProductData.BoundaryLeft[cameraIndex - 1] * rate[bThreeD], ProductData.BoundaryTop[cameraIndex - 1] * rate[bThreeD],
			ProductData.BoundaryRight[cameraIndex - 1] * rate[bThreeD], ProductData.BoundaryBottom[cameraIndex - 1] * rate[bThreeD]);

		SavedDefectImage->Repaint();
	}
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::RestoreOriginalImg()
{
  bool bThreeD;
  
  if (GlobalCameraIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX - 1 &&
		GlobalCameraIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX - 1)
	{
    bThreeD = false;
  }
  else
  {
    bThreeD = true;
  }

	Graphics::TBitmap *img1;
	img1 = new Graphics::TBitmap();
	img1->Width = SourceImageWidth[bThreeD];
	img1->Height = SourceImageHeight[bThreeD];
	img1->PixelFormat = pf24bit;

	int tempAddress;
	int x, y;

	Byte* ptr;

	for (y = 0; y < SourceImageHeight[bThreeD]; y++)
	{
		ptr = (Byte*)img1->ScanLine[y];
		for (x = 0; x < SourceImageWidth[bThreeD]; x++)
		{
			tempAddress = SourceImageWidth[bThreeD] * y + x;

			ptr[3 * x + 0] = OriginalImage[tempAddress * 3 + 0];
			ptr[3 * x + 1] = OriginalImage[tempAddress * 3 + 1];
			ptr[3 * x + 2] = OriginalImage[tempAddress * 3 + 2];
		}
	}
	SavedDefectImage->Picture->Bitmap->Assign(img1);

	CurrentDisplayImage->Assign(SavedDefectImage->Picture->Bitmap);
	LoadZoomInOutNavigationImage(ZOOM_IMAGE_DEFECT, 0, 0);

	if (!bThreeD)
	{
		// show defected position
		SavedDefectImage->Canvas->Pen->Color = clWhite;
    SavedDefectImage->Canvas->Pen->Width = 2;
		SavedDefectImage->Canvas->Brush->Style = bsClear;
		SavedDefectImage->Canvas->Rectangle((CurrentDefectStX - 4) * rate[bThreeD], (CurrentDefectStY - 4) * rate[bThreeD], (CurrentDefectEdX + 4) * rate[bThreeD], (CurrentDefectEdY + 4) * rate[bThreeD]);

		SavedDefectImage->Canvas->Pen->Color = clRed;
    SavedDefectImage->Canvas->Pen->Width = 2;
		SavedDefectImage->Canvas->Brush->Style = bsClear;
		SavedDefectImage->Canvas->Rectangle((CurrentDefectStX - 2) * rate[bThreeD], (CurrentDefectStY - 2) * rate[bThreeD], (CurrentDefectEdX + 2) * rate[bThreeD], (CurrentDefectEdY + 2) * rate[bThreeD]);
	}

	// show boundary area
	SavedDefectImage->Canvas->Pen->Color = clBlue;
  SavedDefectImage->Canvas->Pen->Width = 2;
	SavedDefectImage->Canvas->Brush->Style = bsClear;
	SavedDefectImage->Canvas->Rectangle(
		ProductData.BoundaryLeft[GlobalCameraIndex] * rate[bThreeD], ProductData.BoundaryTop[GlobalCameraIndex] * rate[bThreeD],
		ProductData.BoundaryRight[GlobalCameraIndex] * rate[bThreeD], ProductData.BoundaryBottom[GlobalCameraIndex] * rate[bThreeD]);

	SavedDefectImage->Repaint();

	delete img1;
}
//---------------------------------------------------------------------------
bool __fastcall TDefectInfoForm::ReadStudyData(TTabletStudyData *tabletStudyData)
{
	AnsiString studyDataFileName = ProgramPath.Product + "\\" + ProductData.ProductCode + "\\" + ProductData.ProductCode + ".stu";
	if (FileExists(studyDataFileName))
	{
		TFileStream *fileStream = new TFileStream(studyDataFileName, fmOpenRead);
		if (fileStream)
		{
			fileStream->Read(tabletStudyData, sizeof(TTabletStudyData));
			delete fileStream;
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::DoProcessingFor3D(int cameraIndex)
{
	if (!ReadStudyData(&TabletStudyData))
	{
		ShowMessageW(DEFECTINFOFORM_MSG_02);
	}

	if (!ReadSetupData(&TabletSetupData))
	{
		ShowMessageW(DEFECTINFOFORM_MSG_01);
	}

	if (!Read3DSetupData(&Tablet3DSetupData))
	{
		ShowMessageW(DEFECTINFOFORM_MSG_01);
	}

	InspectionOrStudy = INSPECTION_MODE;

	cameraIndex = cameraIndex + 1;

	AnsiString gradeFileName = ProgramPath.Product + "\\" + ProductData.ProductCode + "\\" + ProductData.ProductCode + ".grd";
	LoadGradeData(gradeFileName, TabletGradeData);

	InspectionKind = FRONT_FACE_SPECIAL;

	MakeTabletCharacterData(&ProductData, &TabletCharacter, &MachineParams);

	int SDNum;
	if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
		SDNum = SUCTION_DISK_NUM1;
	else
		SDNum = SUCTION_DISK_NUM2;

	CPBCommonVariableInitial();
	SetUpDataTransFormForThreeD(InspectionKind, SDNum);

	ImageLoad(cameraIndex, 1);

  if(ThreeDLaserInfoViewerCheckBox->Checked)
  {
    GettingThreeDPositionInformationForLaserComplexer(InspectionOrStudy, cameraIndex, 0x02);
  }
  else
  {
    ProcessingStartForFrontFace_3D(InspectionOrStudy, cameraIndex, 0x02);
    LoadFrontFace3DDebugData();
  }

	if (ProcessingPCSIM)
		ProcessingResultDisplayFor3D(cameraIndex);
	else
	{
    if(ThreeDLaserInfoViewerCheckBox->Checked)
    {
      SavedDefectImage->Picture->Bitmap->Assign(tempSavedDefectImage->Picture->Bitmap);
      SavedDefectImage->Refresh();
    }
    else
    {
      Graphics::TBitmap *img1;
      img1 = new Graphics::TBitmap();
      img1->Width = MAX_IMAGE_WIDTH;
      img1->Height = MAX_IMAGE_HEIGHT;
      img1->PixelFormat = pf24bit;
      int tempAddress;

      Byte *ptr;

      for (int i = 0; i < ImageHeight; i++)
      {
        ptr = (byte*)img1->ScanLine[i];
        for (int j = 0; j < ImageWidth; j++)
        {
          tempAddress = MAX_IMAGE_WIDTH * i + j;

          ptr[3 * j] = ThreeD_Image[tempAddress];
          ptr[3 * j + 1] = ThreeD_Image[tempAddress];
          ptr[3 * j + 2] = ThreeD_Image[tempAddress];
        }
      }

      SavedDefectImage->Picture->Bitmap->Assign(img1);
      SavedDefectImage->Refresh();

      CurrentDisplayImage->Assign(SavedDefectImage->Picture->Bitmap);
      LoadZoomInOutNavigationImage(ZOOM_IMAGE_DEFECT, 0, 0);

      delete(img1);
    }
	}
}
//---------------------------------------------------------------------------
bool __fastcall TDefectInfoForm::Read3DSetupData(TTablet3DSetupData *tablet3DSetupData)
{
	AnsiString setupDataFileName = ProgramPath.Product + "\\" + ProductData.ProductCode + "\\" + ProductData.ProductCode + ".sdt_3D";
	if (FileExists(setupDataFileName))
	{
		TFileStream *fileStream = new TFileStream(setupDataFileName, fmOpenRead);
		if (fileStream)
		{
			fileStream->Read(tablet3DSetupData, sizeof(TTablet3DSetupData));
			delete fileStream;
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::ProcessingResultDisplayFor3D(int cameraIndex)
{
  if(ThreeDLaserInfoViewerCheckBox->Checked)
  {
    Graphics::TBitmap *img1;
    img1 = new Graphics::TBitmap();
    img1->Width = MAX_IMAGE_WIDTH;
    img1->Height = MAX_IMAGE_HEIGHT;
    img1->PixelFormat = pf24bit;
    int tempAddress, tempAddress2;
    int areaValue;
    int x, y;
    bool bThreeD = true;

    Byte *ptr;

    for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
    {
      ptr = (Byte *)img1->ScanLine[y];
      for(x = 0; x < MAX_IMAGE_WIDTH; x++)
      {
        tempAddress = MAX_IMAGE_WIDTH * y + x;
      
        ptr[3 * x + 0] = ThreeD_Image[tempAddress];
        ptr[3 * x + 1] = ThreeD_Image[tempAddress];
        ptr[3 * x + 2] = ThreeD_Image[tempAddress];
      }
    }

    SavedDefectImage->Picture->Bitmap->Assign(img1);

    SavedDefectImage->Canvas->Pen->Width = 1;

    SavedDefectImage->Canvas->Pen->Color = clLime;
    SavedDefectImage->Canvas->Brush->Style = bsClear;
    SavedDefectImage->Canvas->MoveTo(TabletCharacter.Disk1ThreeDImageCenterXForLaser, 0);
    SavedDefectImage->Canvas->LineTo(TabletCharacter.Disk1ThreeDImageCenterXForLaser, MAX_IMAGE_HEIGHT);
    SavedDefectImage->Canvas->MoveTo(0, TabletCharacter.Disk1ThreeDImageCenterYForLaser);
    SavedDefectImage->Canvas->LineTo(MAX_IMAGE_WIDTH, TabletCharacter.Disk1ThreeDImageCenterYForLaser);

    SavedDefectImage->Canvas->Pen->Color = clYellow;
    SavedDefectImage->Canvas->Brush->Style = bsClear;
    SavedDefectImage->Canvas->MoveTo(ProtoTabletCenterX, 0);
    SavedDefectImage->Canvas->LineTo(ProtoTabletCenterX, MAX_IMAGE_HEIGHT);
    SavedDefectImage->Canvas->MoveTo(0, ProtoTabletCenterY);
    SavedDefectImage->Canvas->LineTo(MAX_IMAGE_WIDTH, ProtoTabletCenterY);

    SavedDefectImage->Canvas->Pen->Color = clWhite;
    SavedDefectImage->Canvas->Brush->Style = bsClear;
    SavedDefectImage->Canvas->Rectangle(threeDminX, threeDminY, threeDmaxX, threeDmaxY);

    SavedDefectImage->Canvas->Pen->Color = clRed;
    SavedDefectImage->Canvas->Brush->Style = bsClear;
    SavedDefectImage->Canvas->MoveTo(AdjustTabletCenterInfo[0], 0);
    SavedDefectImage->Canvas->LineTo(AdjustTabletCenterInfo[0], MAX_IMAGE_HEIGHT);
    SavedDefectImage->Canvas->MoveTo(0, AdjustTabletCenterInfo[1]);
    SavedDefectImage->Canvas->LineTo(MAX_IMAGE_WIDTH, AdjustTabletCenterInfo[1]);


    int tempData[MAX_IMAGE_WIDTH][2];
    int angleViewer[MAX_IMAGE_WIDTH][2];
    memset(tempData, 0, sizeof(int) * MAX_IMAGE_WIDTH * 2);
    memset(angleViewer, 0, sizeof(int) * MAX_IMAGE_WIDTH * 2);
    for(int m = 0; m < MAX_IMAGE_WIDTH; m++)
    {
      tempData[m][0] = m;
      tempData[m][1] = ProtoTabletCenterY;
    }

    int rX, rY;
    int tempCount = 0;
    int r = ThreeDPositionInfo_CPB.TabletRotationAngle * 2;
    for(int m = 0; m < MAX_IMAGE_WIDTH; m++)
    {
      x = tempData[m][0];
      y = tempData[m][1];

      if (ThreeDPositionInfo_CPB.TabletRotationAngle >= 0)
      {
        rX = ((x - ProtoTabletCenterX) * CosData[r] - (y - ProtoTabletCenterY) * SinData[r]) / 1024 + ProtoTabletCenterX;
        rY = ((x - ProtoTabletCenterX) * SinData[r] + (y - ProtoTabletCenterY) * CosData[r]) / 1024 + ProtoTabletCenterY;
      }
      else
      {
        rX = ((x - ProtoTabletCenterX) * CosData[-r] + (y - ProtoTabletCenterY) * SinData[-r]) / 1024 + ProtoTabletCenterX;
        rY = (-(x - ProtoTabletCenterX) * SinData[-r] + (y - ProtoTabletCenterY) * CosData[-r]) / 1024 + ProtoTabletCenterY;
      }

      if(rX > 0 && rX < MAX_IMAGE_WIDTH && rY > 0 && rY < MAX_IMAGE_HEIGHT)
      {
        angleViewer[tempCount][0] = rX;
        angleViewer[tempCount][1] = rY;
        tempCount++;
      }
    }

    for(int m = 0; m < tempCount; m++)
    {
      x = angleViewer[m][0];
      y = angleViewer[m][1];

      ptr = (Byte *)SavedDefectImage->Picture->Bitmap->ScanLine[y];

      ptr[3 * x + 0] = 255;
      ptr[3 * x + 1] = 0;
      ptr[3 * x + 2] = 0;
    }

    SavedDefectImage->Refresh();

    ThreeDResultLabel1->Caption = "X : " + FloatToStr(ThreeDPositionInfo_CPB.TabletCenterX * 41.67);
    ThreeDResultLabel2->Caption = "Y : 1(" + IntToStr(ThreeDPositionInfo_CPB.TabletCenterY) + ")";
    ThreeDResultLabel3->Caption = "Angle : " + IntToStr(ThreeDPositionInfo_CPB.TabletRotationAngle * 100);

    delete(img1);

    CurrentDisplayImage->Assign(SavedDefectImage->Picture->Bitmap);
    LoadZoomInOutNavigationImage(ZOOM_IMAGE_DEFECT, 0, 0);
  }
  else
  {
    Byte *ptr;
    int tempAddress;
    int tempAddress2;
  
    if(TabletCharacter.discriminationDisplay_kind == STAMP)
    {
      if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX || cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX) // 정면 3D
      {
        if(DefectSW == 0 || DefectSW == 1)
        {
          ExtractedPrintInfoImage->Visible = true;
          PrintInfoPanel->Visible = true;

          int shiftX, shiftY;
          shiftX = ProtoTabletCenterX - 150;
          shiftY = ProtoTabletCenterY - 150;

          Graphics::TBitmap *img2;
          img2 = new Graphics::TBitmap();
          img2->Width = 300;
          img2->Height = 300;
          img2->PixelFormat = pf24bit;
          for (int y = 0; y < 300; y++)
          {
            ptr = (byte*)img2->ScanLine[y];
            for (int x = 0; x < 300; x++)
            {
              tempAddress = MAX_IMAGE_WIDTH * (y + shiftY) + (x + shiftX);

              TColor depthColor = ThreeDDepth(DentedArea[tempAddress], 20);

              ptr[3*x + 0] = (depthColor & 0x00FF0000) >> 16;
              ptr[3*x + 1] = (depthColor & 0x0000FF00) >> 8;
              ptr[3*x + 2] = (depthColor & 0x000000FF) >> 0;
            }
          }

          ExtractedPrintInfoImage->Picture->Bitmap->Assign(img2);
          ExtractedPrintInfoImage->Refresh();

          delete img2;
        }
      }
    }

    Graphics::TBitmap *img1;
    img1 = new Graphics::TBitmap();
    img1->Width = MAX_IMAGE_WIDTH;
    img1->Height = MAX_IMAGE_HEIGHT;
    img1->PixelFormat = pf24bit;
    int areaValue;
    bool bThreeD = true;

    for (int i = 0; i < ImageHeight; i++)
    {
      ptr = (byte*)img1->ScanLine[i];
      for (int j = 0; j < ImageWidth; j++)
      {
        tempAddress = MAX_IMAGE_WIDTH * i + j;

        ptr[3*j + 0] = AdjustThreeD_Data[tempAddress];
        ptr[3*j + 1] = AdjustThreeD_Data[tempAddress];
        ptr[3*j + 2] = AdjustThreeD_Data[tempAddress];

        if(InspectionArea[tempAddress])
        {
          ptr[3*j + 0] = max(0, AdjustThreeD_Data[tempAddress] - InspectionArea[tempAddress] * 8);
          ptr[3*j + 1] = max(0, AdjustThreeD_Data[tempAddress] - InspectionArea[tempAddress] * 8);
          ptr[3*j + 2] = max(0, AdjustThreeD_Data[tempAddress] - InspectionArea[tempAddress] * 8);
        }

        if(LabelImage_Virtual[tempAddress])
        {
          if(DefectSW)
          {
            TColor depthColor = ThreeDDepth(ExpectedThreeDDefectArea[tempAddress], 20);

            ptr[3*j + 0] = (depthColor & 0x00FF0000) >> 16;
            ptr[3*j + 1] = (depthColor & 0x0000FF00) >> 8;
            ptr[3*j + 2] = (depthColor & 0x000000FF) >> 0;
          }
        }
      }
    }

    SavedDefectImage->Picture->Bitmap->Assign(img1);
    SavedDefectImage->Refresh();
    delete(img1);

    CurrentDisplayImage->Assign(SavedDefectImage->Picture->Bitmap);
    LoadZoomInOutNavigationImage(ZOOM_IMAGE_DEFECT, 0, 0);

    if (DefectSW)
    {
      // show defected position
      AnsiString DefectSizeStr;
      if(DefectInformation.defectSeries == FAT_TALBET || DefectInformation.defectSeries == THIN_TALBET) // 화면에 표시 되는 Size는 기준 두께보다 얼마나 두껍고 얇은 정제인지를 표시함
        DefectSizeStr = FloatToStr((float)DefectInformation.size*30/1000.0) +" mm";
      else if(DefectInformation.defectSeries == DEFECT_3D_PRINT_ERASE)
        DefectSizeStr = FloatToStr(DefectInformation.size) + " %";
      else if(DefectInformation.defectSeries == DEFECT_FRONT_WHITE_ENGRAVE)
        DefectSizeStr = IntToStr(DefectInformation.size) + " Grade";
      else if(DefectInformation.defectSeries == DEFECT_PRINT_POSITION_ERROR)
        DefectSizeStr = FloatToStr(DefectInformation.size*0.04) + " mm";
      else if(DefectInformation.defectSeries == DEFECT_PRINT_ROTATION_ERROR)
        DefectSizeStr = IntToStr(DefectInformation.size) + " Degree";
      else
        DefectSizeStr = FloatToStr(DefectSizePixelToMili(DefectInformation.size) / 100.0) + "mm";

      SavedDefectImage->Canvas->Brush->Color = clBlack;
      SavedDefectImage->Canvas->Font->Color = clWhite;
      SavedDefectImage->Canvas->Font->Size = 12;
      SavedDefectImage->Canvas->TextOutW(15, 15, GetDefectSeriesStr(DefectInformation.defectSeries) + "//" + DefectSizeStr);

      SavedDefectImage->Canvas->Pen->Color = clWhite;
      SavedDefectImage->Canvas->Pen->Width = 2;
      SavedDefectImage->Canvas->Brush->Style = bsClear;
      SavedDefectImage->Canvas->Rectangle(
        (DefectInformation.defectPositionStartX - 4) * rate[bThreeD], (DefectInformation.defectPositionStartY - 4) * rate[bThreeD],
        (DefectInformation.defectPositionEndX + 4) * rate[bThreeD], (DefectInformation.defectPositionEndY + 4) * rate[bThreeD]);

      SavedDefectImage->Canvas->Pen->Color = clRed;
      SavedDefectImage->Canvas->Pen->Width = 2;
      SavedDefectImage->Canvas->Brush->Style = bsClear;
      SavedDefectImage->Canvas->Rectangle(
        (DefectInformation.defectPositionStartX - 2) * rate[bThreeD], (DefectInformation.defectPositionStartY - 2) * rate[bThreeD],
        (DefectInformation.defectPositionEndX + 2) * rate[bThreeD], (DefectInformation.defectPositionEndY + 2) * rate[bThreeD]);

      SavedDefectImage->Repaint();
    }
    else
    {
      // 2019-06-14
      // CPB에서 불량판정된 두께불량 이미지는 SPB에서 PC로 전달되게 되어있음
      // 이때 HCB에서는 1번, 2번 디스크 모두에서 동일한 유형의 두께불량이 발생하였을 때만 최종 불량판정을 내리게 되는데,
      // 두개의 디스크 중 하나라도 양품이거나 불량 유형이 일치 하지 않는 경우에는 해당 정제는 양품처리되기때문에
      // 불량이미지만 PC로 전송되고, HCB와 SPB의 처리결과가 서로 일치하지 않는 문제가 발생함
      // -> 불량 개수와 불량 카운트가 서로 일치하지 않는 문제의 원인 중 하나

      // SPB에서는 해당 이미지를 불량이미지 판정이 아닌 waiting 상태로 세팅한 상태에서 HCB에서 검사 취합 판정 결과를 SPB로 전송하여 불량인 경우에만 이미지를 PC로 전송하도록 변경해야함

      int heightDiffSize;
      if (ThickErrorSW == 1)
      {
        if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
          heightDiffSize = Max3DHeight - TabletStudyData.tabletMaxThickForFirstDisk;
        else
          heightDiffSize = Max3DHeight - TabletStudyData.tabletMaxThickForSecondDisk;

        SavedDefectImage->Canvas->Brush->Color = clBlack;
        SavedDefectImage->Canvas->Font->Color = clWhite;
        SavedDefectImage->Canvas->Font->Size = 12;
        SavedDefectImage->Canvas->TextOutW(15, 15, GetDefectSeriesStr(THIN_TALBET));
        SavedDefectImage->Repaint();

        DefectStringGrid->Cells[1][4] = FloatToStr((float)heightDiffSize*30/1000.0) +" mm";
      }
      else if (ThickErrorSW == 2)
      {
        if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
          heightDiffSize = Max3DHeight - TabletStudyData.tabletMaxThickForFirstDisk;
        else
          heightDiffSize = Max3DHeight - TabletStudyData.tabletMaxThickForSecondDisk;

        SavedDefectImage->Canvas->Brush->Color = clBlack;
        SavedDefectImage->Canvas->Font->Color = clWhite;
        SavedDefectImage->Canvas->Font->Size = 12;
        SavedDefectImage->Canvas->TextOutW(15, 15, GetDefectSeriesStr(FAT_TALBET));
        SavedDefectImage->Repaint();

        DefectStringGrid->Cells[1][4] = FloatToStr((float)heightDiffSize*30/1000.0) +" mm";
      }
      else
      {
        SavedDefectImage->Canvas->Brush->Color = clBlack;
        SavedDefectImage->Canvas->Font->Color = clWhite;
        SavedDefectImage->Canvas->Font->Size = 12;

        if (!(TabletCharacter.discriminationDisplay_kind == STAMP && TabletCharacter.discriminationDisplay_num == ONE_FACE))
        {
          bEngraveDefect = false;
        }

        if (!bEngraveDefect)
          SavedDefectImage->Canvas->TextOutW(15, 15, "OK");
        else
          SavedDefectImage->Canvas->TextOutW(15, 15, GetDefectSeriesStr(DEFECT_2D_AND_3D_PRINT_NOT_MATCHING));

        SavedDefectImage->Repaint();
      }
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::setPosSetupData(TTabletSetupData *pTabletSetupData)
{
	// modify disk base height position
	for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
	{
    pTabletSetupData->cameraZoom[globalCameraIndex] = MachineParams.CameraResolution[globalCameraIndex];

		pTabletSetupData->ImageCutStartX[globalCameraIndex] = ProductData.BoundaryLeft[globalCameraIndex] / 4 * 4;
		pTabletSetupData->ImageCutEndX[globalCameraIndex] = ProductData.BoundaryRight[globalCameraIndex] / 4 * 4;
		pTabletSetupData->ImageCutStartY[globalCameraIndex] = ProductData.BoundaryTop[globalCameraIndex] / 4 * 4;
		pTabletSetupData->ImageCutEndY[globalCameraIndex] = ProductData.BoundaryBottom[globalCameraIndex] / 4 * 4;

		pTabletSetupData->DiskBaseHeightPosition[globalCameraIndex] = MachineParams.DiscCenterPos[globalCameraIndex] / 4 * 4;
	}

	WriteSetupData(pTabletSetupData);
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::WriteSetupData(TTabletSetupData *tabletSetupData)
{
	AnsiString setupDataFileName = ProgramPath.Product + "\\" + ProductData.ProductCode + "\\" + ProductData.ProductCode + ".sdt";

	if (FileExists(setupDataFileName))
	{
		TFileStream *fileStream = new TFileStream(setupDataFileName, fmOpenWrite);
		if (fileStream)
		{
			fileStream->Write(tabletSetupData, sizeof(TTabletSetupData));
			delete fileStream;
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::ZoomInBtnClick(TObject *Sender)
{
	int zoomInOutROIWidth;
	int zoomInOutROIHeight;

	zoomInOutROIWidth = MAX_ZOOM_W_PIXEL / zoomInOutSize;
	zoomInOutROIHeight = MAX_ZOOM_H_PIXEL / zoomInOutSize;

	tempStdX = zoomROIX1 + zoomInOutROIWidth / 4;
	tempStdY = zoomROIY1 + zoomInOutROIHeight / 4;

	zoomInOutSize *= 2;

	if (zoomInOutSize > 4)
	{
		zoomInOutSize = 4;

		tempStdX = zoomROIX1;
		tempStdY = zoomROIY1;
	}

	Panel7->Color = clRed;
	Panel8->Color = clBlack;

	LoadZoomInOutNavigationImage(ZOOM_IMAGE_SHIFT, 0, 0);
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::ZoomOutBtnClick(TObject *Sender)
{
	int zoomInOutROIWidth;
	int zoomInOutROIHeight;

	zoomInOutROIWidth = MAX_ZOOM_W_PIXEL / zoomInOutSize;
	zoomInOutROIHeight = MAX_ZOOM_H_PIXEL / zoomInOutSize;

	tempStdX = zoomROIX1 - zoomInOutROIWidth / 2;
	tempStdY = zoomROIY1 - zoomInOutROIHeight / 2;

	zoomInOutSize /= 2;

	if (zoomInOutSize < 2)
	{
		zoomInOutSize = 2;

		tempStdX = zoomROIX1;
		tempStdY = zoomROIY1;
	}

	Panel7->Color = clBlack;
	Panel8->Color = clRed;

	LoadZoomInOutNavigationImage(ZOOM_IMAGE_SHIFT, 0, 0);
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::LoadZoomInOutNavigationImage(int mode, int dX, int dY)
{
  bool bThreeD;

  if ((GlobalCameraIndex + 1) != SD1_3D_FRONT_FACE_CAMERA_INDEX &&
			(GlobalCameraIndex + 1) != SD2_3D_FRONT_FACE_CAMERA_INDEX)
  {
    bThreeD = false;
  }
  else
  {
    bThreeD = true;
  }
  
	int defectCenterX, defectCenterY;

	int zoomInOutROIWidth;
	int zoomInOutROIHeight;

	zoomInOutROIWidth = MAX_ZOOM_W_PIXEL / zoomInOutSize;
	zoomInOutROIHeight = MAX_ZOOM_H_PIXEL / zoomInOutSize;

	if (mode == ZOOM_IMAGE_DEFECT)
	{
		defectCenterX = (CurrentDefectStX * rate[bThreeD] + CurrentDefectEdX * rate[bThreeD]) / 2;
		defectCenterY = (CurrentDefectStY * rate[bThreeD] + CurrentDefectEdY * rate[bThreeD]) / 2;

		tempStdX = defectCenterX - zoomInOutROIWidth / 2;
		tempStdY = defectCenterY - zoomInOutROIHeight / 2;

		zoomROIX1 = tempStdX;
		zoomROIY1 = tempStdY;
	}
	else
	{
		zoomROIX1 = tempStdX + dX * rate[bThreeD];
		zoomROIY1 = tempStdY + dY * rate[bThreeD];
	}

	if (zoomROIX1 < 0)
		zoomROIX1 = 0;
	if (zoomROIY1 < 0)
		zoomROIY1 = 0;
	if (zoomROIX1 + zoomInOutROIWidth > SourceImageWidth[bThreeD])
		zoomROIX1 = SourceImageWidth[bThreeD] - zoomInOutROIWidth;
	if (zoomROIY1 + zoomInOutROIHeight > SourceImageHeight[bThreeD])
		zoomROIY1 = SourceImageHeight[bThreeD] - zoomInOutROIHeight;

	zoomROIX2 = zoomROIX1 + zoomInOutROIWidth;
	zoomROIY2 = zoomROIY1 + zoomInOutROIHeight;

	ZoomSizeLabel->Caption = "x " + IntToStr(zoomInOutSize);

	Graphics::TBitmap *img1;
	img1 = new Graphics::TBitmap();
	img1->Width = SourceImageWidth[bThreeD];
	img1->Height = SourceImageHeight[bThreeD];
	img1->PixelFormat = pf24bit;

	Byte *ptr, *ptr2;
	int x, y;

	int dpSW;
	dpSW = 0;

	if (CurrentDisplayImage->PixelFormat == pf24bit)
	{
		for (y = 10; y < SourceImageHeight[bThreeD] - 10; y++)
		{
			ptr = (byte*)CurrentDisplayImage->ScanLine[y];
			for (x = 10; x < SourceImageWidth[bThreeD] - 10; x++)
			{
				if (ptr[3 * x + 0] != 255 && ptr[3 * x + 1] != 255 && ptr[3 * x + 2] != 255)
				{
					dpSW = 1;
					break;
				}
			}

			if (dpSW)
				break;
		}

		for (y = 0; y < SourceImageHeight[bThreeD]; y++)
		{
			ptr = (byte*)CurrentDisplayImage->ScanLine[y];
			ptr2 = (byte*)img1->ScanLine[y];
			for (x = 0; x < SourceImageWidth[bThreeD]; x++)
			{
				if (dpSW == 0)
				{
					ptr2[3 * x + 0] = 0;
					ptr2[3 * x + 1] = 0;
					ptr2[3 * x + 2] = 0;
				}
				else
				{
					ptr2[3 * x + 0] = ptr[3 * x + 0];
					ptr2[3 * x + 1] = ptr[3 * x + 1];
					ptr2[3 * x + 2] = ptr[3 * x + 2];
				}
			}
		}
	}
	else if (CurrentDisplayImage->PixelFormat == pf8bit)
	{
    // 3D
		for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
		{
			ptr = (byte*)CurrentDisplayImage->ScanLine[y];
			for (x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
			{
				if (ptr[x] != 255)
				{
					dpSW = 1;
					break;
				}
			}

			if (dpSW)
				break;
		}

		for (y = 0; y < MAX_IMAGE_HEIGHT; y++)
		{
			ptr = (byte*)CurrentDisplayImage->ScanLine[y];
			ptr2 = (byte*)img1->ScanLine[y];
			for (x = 0; x < MAX_IMAGE_WIDTH; x++)
			{
				if (dpSW == 0)
				{
					ptr2[3 * x + 0] = 0;
					ptr2[3 * x + 1] = 0;
					ptr2[3 * x + 2] = 0;
				}
				else
				{
					ptr2[3 * x + 0] = ptr[x];
					ptr2[3 * x + 1] = ptr[x];
					ptr2[3 * x + 2] = ptr[x];
				}
			}
		}
	}

	zoomInOutImage->Picture->Bitmap->Assign(img1);

	if (dpSW)
	{
		zoomInOutImage->Canvas->Pen->Width = 4 * rate[bThreeD];
		zoomInOutImage->Canvas->Pen->Color = clRed;
		zoomInOutImage->Canvas->Brush->Style = bsClear;
		zoomInOutImage->Canvas->Rectangle(zoomROIX1, zoomROIY1, zoomROIX2, zoomROIY2);
		zoomInOutImage->Refresh();
	}
	delete img1;

	refreshZoomInTabletImage();
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::zoomInOutImageMouseDown(TObject *Sender,
	TMouseButton Button, TShiftState Shift, int X, int Y)
{
	zoomImageNavigateFlag = 1;

	navigateStdX = X * (float) 3.2;
	navigateStdY = Y * (float) 3.2;

	tempStdX = zoomROIX1;
	tempStdY = zoomROIY1;
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::zoomInOutImageMouseUp(TObject *Sender,
	TMouseButton Button, TShiftState Shift, int X, int Y)
{
	zoomImageNavigateFlag = 0;
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::zoomInOutImageMouseMove(TObject *Sender,
	TShiftState Shift, int X, int Y)
{
	if (zoomImageNavigateFlag)
	{
		int dX, dY;
		dX = X * (float) 3.2 - navigateStdX;
		dY = Y * (float) 3.2 - navigateStdY;

		LoadZoomInOutNavigationImage(ZOOM_IMAGE_SHIFT, dX, dY);
	}
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::refreshZoomInTabletImage()
{
  bool bThreeD;

  if ((GlobalCameraIndex + 1) != SD1_3D_FRONT_FACE_CAMERA_INDEX &&
			(GlobalCameraIndex + 1) != SD2_3D_FRONT_FACE_CAMERA_INDEX)
  {
    bThreeD = false;
  }
  else
  {
    bThreeD = true;
  }
      
	Byte *ptr;

	int m, k;
	int maxLineCount;
	if (zoomInOutSize == 2)
		maxLineCount = 2;
	else if (zoomInOutSize == 4)
		maxLineCount = 3;
	else if (zoomInOutSize == 8)
		maxLineCount = 4;

	int tempAddress, tempAddress2;
	int tempX, tempY;

	memset(originalColorSourceImage, 0, HD_IMAGE_WIDTH * HD_IMAGE_HEIGHT * 3);
	for (int y = 0; y < SourceImageHeight[bThreeD]; y++)
	{
		ptr = (byte*)CurrentDisplayImage->ScanLine[y];
		for (int x = 0; x < SourceImageWidth[bThreeD]; x++)
		{
			tempAddress = SourceImageWidth[bThreeD] * y + x;
			originalColorSourceImage[tempAddress * 3 + 0] = ptr[3 * x + 0];
			originalColorSourceImage[tempAddress * 3 + 1] = ptr[3 * x + 1];
			originalColorSourceImage[tempAddress * 3 + 2] = ptr[3 * x + 2];
		}
	}

	memset(extensionColorSourceImage, 0, MAX_ZOOM_W_PIXEL * MAX_ZOOM_H_PIXEL * 3);

	for (int y = zoomROIY1; y < zoomROIY2; y++)
	{
		for (int x = zoomROIX1; x < zoomROIX2; x++)
		{
			tempAddress = SourceImageWidth[bThreeD] * y + x;

			tempX = (x - zoomROIX1) * zoomInOutSize;
			tempY = (y - zoomROIY1) * zoomInOutSize;

			for (int j = tempY; j < tempY + zoomInOutSize; j++)
			{
				for (int i = tempX; i < tempX + zoomInOutSize; i++)
				{
					tempAddress2 = MAX_ZOOM_W_PIXEL * j + i;

					extensionColorSourceImage[tempAddress2 * 3 + 0] = originalColorSourceImage[tempAddress * 3 + 0];
					extensionColorSourceImage[tempAddress2 * 3 + 1] = originalColorSourceImage[tempAddress * 3 + 1];
					extensionColorSourceImage[tempAddress2 * 3 + 2] = originalColorSourceImage[tempAddress * 3 + 2];
				}
			}
		}
	}

	Graphics::TBitmap *img1;
	img1 = new Graphics::TBitmap();
	img1->Width = MAX_ZOOM_W_PIXEL;
	img1->Height = MAX_ZOOM_H_PIXEL;
	img1->PixelFormat = pf24bit;

	for (int y = 0; y < MAX_ZOOM_H_PIXEL; y++)
	{
		ptr = (byte*)img1->ScanLine[y];
		for (int x = 0; x < MAX_ZOOM_W_PIXEL; x++)
		{
			tempAddress = MAX_ZOOM_W_PIXEL * y + x;
			ptr[3 * x + 0] = extensionColorSourceImage[tempAddress * 3 + 0];
			ptr[3 * x + 1] = extensionColorSourceImage[tempAddress * 3 + 1];
			ptr[3 * x + 2] = extensionColorSourceImage[tempAddress * 3 + 2];
		}
	}

	ZoomInImage->Visible = true;
	ZoomInImage->Picture->Bitmap->Assign(img1);
	ZoomInImage->Refresh();
	delete(img1);
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::upImageClick(TObject *Sender)
{
	if (DefectListStringGrid->Row - 1 > 0)
		DefectListStringGrid->Row = DefectListStringGrid->Row - 1;
  else if(DefectListStringGrid->Row == 1)
    ScrollPageChange(SCROLL_UP);
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::downImageClick(TObject *Sender)
{
	if (DefectListStringGrid->Row + 1 < DefectListStringGrid->RowCount)
		DefectListStringGrid->Row = DefectListStringGrid->Row + 1;
  else if(DefectListStringGrid->Row == DefectListStringGrid->RowCount-1)
  {
      ScrollPageChange(SCROLL_DOWN);
  }
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::Panel9DblClick(TObject *Sender)
{
	SavePictureDialog1->FileName = "";
	if (SavePictureDialog1->Execute())
	{
		tempSavedDefectImage->Picture->Bitmap->SaveToFile(SavePictureDialog1->FileName);
	}
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::Panel17DblClick(TObject *Sender)
{
	if (UserInfo.AccessLevel == SYSTEM_HIGHEST_ACCESS_LEVEL)
	{
		if (DebuggingGroupBox->Visible)
		{
			DebuggingGroupBox->Visible = false;
		}
		else
		{
			DebuggingGroupBox->Visible = true;
		}
	}
}
//---------------------------------------------------------------------------


void __fastcall TDefectInfoForm::RefreshInspectionSetupData()
{
  if (!ReadSetupData(&TabletSetupData))
	{
		ShowMessageW(DEFECTINFOFORM_MSG_01);
	}

	if (!ReadStudyData(&TabletStudyData))
	{
		ShowMessageW(DEFECTINFOFORM_MSG_02);
	}

	if (!CPBSetupInfo.InspectionSetupDataValid)
	{
		setPosSetupData(&TabletSetupData);
	}

	MakeTabletCharacterData(&ProductData, &TabletCharacter, &MachineParams);
	CPBCommonVariableInitial();

	SideFaceSetUpDataTransForm_For_PCSIM(tempSideData);
}

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

void __fastcall TDefectInfoForm::SavedDefectImageMouseUp(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
  bMouseDown = false;
  FullSizeImageLoadTimer->Enabled = false;
  ProgressBar1->Visible = false;

  if(RecentRealImageLoad_Percent > 0.85f)
  {
    TRealSizeImageForm *RealSizeImageForm = new  TRealSizeImageForm(this);
    TTntImage *Image = (TTntImage*)SrcImage;
    RealSizeImageForm->SetImage(Image);
    RealSizeImageForm->ShowModal();
    delete RealSizeImageForm;
  }

}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::SavedDefectImageMouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
  RecentRealImageLoad_Percent= 0;
  bMouseDown = true;
  MouseDownStartTime = Now().Val;

  SrcImage = (TTntImage*)Sender;

  bool bLoadFullSizeImageSW = false;
  bool bThreeD;
  
  if (GlobalCameraIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX - 1 &&
      GlobalCameraIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX - 1)
  {
    bThreeD = false;
  }
  else
  {
    bThreeD = true;
  }

  if(ProductData.SubSamplingMode == IMAGE_FULL_SCALE_MODE && !bThreeD)
  {
    bLoadFullSizeImageSW = true;
  }
  
  if(bLoadFullSizeImageSW && FullSizeImageLoadTimer->Enabled == false)
  {
    FullSizeImageLoadTimer->Enabled = true;
    ProgressBar1->Position = 0;

    ProgressBar1->Max = FULL_SIZE_IMAGE_LOADING_TIME * 1000;
  }
  else
  {
    FullSizeImageLoadTimer->Enabled = false;
    ProgressBar1->Visible = false;
  }
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::FullSizeImageLoadTimerTimer(
      TObject *Sender)
{
  if(bMouseDown)
  {
    bool timerEnabled = FullSizeImageLoadTimer->Enabled;
    FullSizeImageLoadTimer->Enabled = false;

    double CurrentTime = Now().Val;
    bool bThreeD;
    double flowtime;

    if (GlobalCameraIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX - 1 &&
        GlobalCameraIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX - 1)
    {
      bThreeD = false;
    }
    else
    {
      bThreeD = true;
    }

    if(ProductData.SubSamplingMode == IMAGE_FULL_SCALE_MODE && !bThreeD)
    {
      //RecentRealImageLoad_Percent  = (CurrentTime - MouseDownStartTime) * 24 * 3600 ;
      if((CurrentTime - MouseDownStartTime) * 24 * 3600> FULL_SIZE_IMAGE_LOADING_TIME)
      {

        timerEnabled = false;
        ProgressBar1->Visible = false;
        bMouseDown = false;
        TRealSizeImageForm *RealSizeImageForm = new  TRealSizeImageForm(this);
        TTntImage *Image = (TTntImage*)SrcImage;
        RealSizeImageForm->SetImage(Image);
        RecentRealImageLoad_Percent = 0;
        RealSizeImageForm->ShowModal();
        delete RealSizeImageForm;



      }
      else
      {
        RecentRealImageLoad_Percent  = (CurrentTime - MouseDownStartTime) * 24 * 3600 ;
        flowtime = (CurrentTime - MouseDownStartTime) * 24 * 3600 * 1000;

        if(flowtime > FULL_SIZE_IMAGE_LOADING_TIME * 1000 / 4)
        {
          ProgressBar1->Visible = true;
          ProgressBar1->Position = (int)flowtime;
        }
      }
    }
    else
    {
      bMouseDown = false;
      timerEnabled = false;
      ProgressBar1->Visible = false;
    }

    FullSizeImageLoadTimer->Enabled = timerEnabled;
  }
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::SavedDefectImageDblClick(TObject *Sender)
{
  bool bThreeD;

  if (!ProcessingPCSIM)
  {
    ProcessingPCSIM = true;
    threeDProcessingStep = THREED_NONE_STEP;

    if (GlobalCameraIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX - 1 &&
      GlobalCameraIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX - 1)
    {
      DoProcessing(GlobalCameraIndex);
    }
    else
    {
      threeDProcessingStep = THREED_INSPECTION_RESULT_STEP;
      DoProcessingFor3D(GlobalCameraIndex);
    }
  }
  else if (ProcessingPCSIM)
  {
    if (GlobalCameraIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX - 1 &&
      GlobalCameraIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX - 1)
    {
      ProcessingPCSIM = false;
      RestoreOriginalImg();
    }
    else
    {
      if (threeDProcessingStep == THREED_INSPECTION_RESULT_STEP)
      {
        ProcessingPCSIM = true;
        threeDProcessingStep = THREED_ORIGIN_IMAGE_STEP;

        RestoreOriginalImg();
      }
      else if (threeDProcessingStep == THREED_ORIGIN_IMAGE_STEP)
      {
        bThreeD = true;
        
        ProcessingPCSIM = false;
        threeDProcessingStep = THREED_NONE_STEP;

        DoProcessingFor3D(GlobalCameraIndex);

        SavedDefectImage->Canvas->Pen->Color = clWhite;
        SavedDefectImage->Canvas->Pen->Width = 2;
        SavedDefectImage->Canvas->Brush->Style = bsClear;
        SavedDefectImage->Canvas->Rectangle((CurrentDefectStX - 4) * rate[bThreeD], (CurrentDefectStY - 4) * rate[bThreeD], (CurrentDefectEdX + 4) * rate[bThreeD], (CurrentDefectEdY + 4) * rate[bThreeD]);

        SavedDefectImage->Canvas->Pen->Color = clRed;
        SavedDefectImage->Canvas->Pen->Width = 2;
        SavedDefectImage->Canvas->Brush->Style = bsClear;
        SavedDefectImage->Canvas->Rectangle((CurrentDefectStX - 2) * rate[bThreeD], (CurrentDefectStY - 2) * rate[bThreeD], (CurrentDefectEdX + 2) * rate[bThreeD], (CurrentDefectEdY + 2) * rate[bThreeD]);

        SavedDefectImage->Repaint();
      }
    }
  }

  if(ProcessingPCSIM == false)
  {
    ExtractedPrintInfoImage->Visible = false;
    PrintInfoPanel->Visible = false;
  }
}
//---------------------------------------------------------------------------

int __fastcall TDefectInfoForm::GetSideFaceCameraIndex(int cameraIndex)
{
  int retIndex = 0;

  switch(cameraIndex)
  {
    case SD1_2D_SIDE_FACE_P45_CAMERA_INDEX:
      retIndex = 0;
      break;

    case SD1_2D_SIDE_FACE_00_CAMERA_INDEX:
      retIndex = 1;
      break;

    case SD1_2D_SIDE_FACE_M45_CAMERA_INDEX:
      retIndex = 2;
      break;

    case SD1_2D_OTHER_SIDE_FACE_P45_CAMERA_INDEX:
      retIndex = 3;
      break;

    case SD1_2D_OTHER_SIDE_FACE_00_CAMERA_INDEX:
      retIndex = 4;
      break;

    case SD1_2D_OTHER_SIDE_FACE_M45_CAMERA_INDEX:
      retIndex = 5;
      break;

    case SD2_2D_SIDE_FACE_P45_CAMERA_INDEX:
      retIndex = 6;
      break;

    case SD2_2D_SIDE_FACE_00_CAMERA_INDEX:
      retIndex = 7;
      break;

    case SD2_2D_SIDE_FACE_M45_CAMERA_INDEX:
      retIndex = 8;
      break;

    case SD2_2D_OTHER_SIDE_FACE_P45_CAMERA_INDEX:
      retIndex = 9;
      break;

    case SD2_2D_OTHER_SIDE_FACE_00_CAMERA_INDEX:
      retIndex = 10;
      break;

    case SD2_2D_OTHER_SIDE_FACE_M45_CAMERA_INDEX:
      retIndex = 11;
      break;
  }

  return retIndex;
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::TntButton1Click(TObject *Sender)
{
  if(EnableScroll == false ) return;
  
  TTntButton * Btn =(TTntButton *)Sender;
  if(Btn->Tag == 0)
  {
    if(CurrentViewStepCount != 1)
      InitDefectInfo(ProductCode, LOTName,-1,InspectionSataus);
  }
  else
  {
    if(MaxLimitViewStepCount != 0 && CurrentViewStepCount + 1 <= MaxLimitViewStepCount)
      InitDefectInfo(ProductCode, LOTName,1,InspectionSataus);
  }
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::ScrollPageChange(int Direction) // 1 : Up , 2 : Down
{
  if(!InspectionSataus)
  {
    if(Direction == SCROLL_UP)
    {
      TntButton1->Click();
    }
    else if(Direction ==SCROLL_DOWN)
    {
      TntButton2->Click();
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::Button1Click(TObject *Sender)
{
  memcpy(BayerImage, DefectBayerImage, 640 * 480);

  int spbIndex = CameraMapInfo[SavedDefectData.GlobalCameraIndex].SPBIndex;
  int x, y;
  int tempAddress;
  int camnum;
  camnum = CameraMapInfo[SavedDefectData.GlobalCameraIndex].CamIndex;

  BayerImage[0] = camnum;
  BayerImage[1] = spbIndex;
  BayerImage[2] = SavedDefectData.GlobalCameraIndex;
  
  Byte *ptr;
 
  Graphics::TBitmap *img2;
	img2 = new Graphics::TBitmap();
	img2->Width = MAX_IMAGE_WIDTH;
	img2->Height = MAX_IMAGE_HEIGHT;
	img2->PixelFormat = pf24bit;
	for (int y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (byte*)img2->ScanLine[y];
    for (int x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3 * x + 0] = BayerImage[tempAddress];
      ptr[3 * x + 1] = BayerImage[tempAddress];
      ptr[3 * x + 2] = BayerImage[tempAddress];
		}
	}

	SavedDefectImage->Picture->Bitmap->Assign(img2);
	SavedDefectImage->Refresh();

  delete img2;

  SavePictureDialog1->FileName = "";
	if (SavePictureDialog1->Execute())
	{
		SavedDefectImage->Picture->Bitmap->SaveToFile(SavePictureDialog1->FileName);
	}
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::ThreeDLaserInfoViewerCheckBoxClick(TObject *Sender)
{
  if(ThreeDLaserInfoViewerCheckBox->Checked)
  {
    ThreeDResultLabel1->Visible = true;
    ThreeDResultLabel2->Visible = true;
    ThreeDResultLabel3->Visible = true;
  }
  else
  {
    ThreeDResultLabel1->Visible = false;
    ThreeDResultLabel2->Visible = false;
    ThreeDResultLabel3->Visible = false;
  }
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::LoadFrontFace3DDebugData()
{
  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;              
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  int x, y;
  int tempAddress;
  Byte *ptr;

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3*x + 0] = Debug_RealThreeD_Image[tempAddress];
      ptr[3*x + 1] = Debug_RealThreeD_Image[tempAddress];
      ptr[3*x + 2] = Debug_RealThreeD_Image[tempAddress];
    }
  }

  ThreeDDebug_OriginalImage->Picture->Bitmap->Assign(img);
  ThreeDDebug_OriginalImage->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3*x + 0] = Debug_LabelingImage[tempAddress];
      ptr[3*x + 1] = Debug_LabelingImage[tempAddress];
      ptr[3*x + 2] = Debug_LabelingImage[tempAddress];
    }
  }

  ThreeDDebug_MaxLabelingImage->Picture->Bitmap->Assign(img);
  ThreeDDebug_MaxLabelingImage->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3*x + 0] = Debug_LabelingImage[tempAddress];
      ptr[3*x + 1] = Debug_LabelingImage[tempAddress];
      ptr[3*x + 2] = Debug_LabelingImage[tempAddress];

      if(Debug_ProtoShapeArea[HALF_IMAGE_WIDTH * (y / 2) + (x / 2)])
      {
        if(Debug_LabelingImage[tempAddress])
        {
          ptr[3*x + 0] = 0;
          ptr[3*x + 1] = Debug_LabelingImage[tempAddress];
          ptr[3*x + 2] = 0;
        }
        else
        {
          ptr[3*x + 0] = 0;
          ptr[3*x + 1] = 255;
          ptr[3*x + 2] = 0;
        }
      }
    }
  }

  ThreeDDebug_BasicTabletAreaImage->Picture->Bitmap->Assign(img);
  ThreeDDebug_BasicTabletAreaImage->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3*x + 0] = Debug_OvelapRemoveResult[tempAddress];
      ptr[3*x + 1] = Debug_OvelapRemoveResult[tempAddress];
      ptr[3*x + 2] = Debug_OvelapRemoveResult[tempAddress];
    }
  }

  ThreeDDebug_ApplyOverlapRemoveImage->Picture->Bitmap->Assign(img);
  ThreeDDebug_ApplyOverlapRemoveImage->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(DefectSW == 0 || DefectSW == 1)
      {
        ptr[3*x + 0] = Debug_LabelingImage[tempAddress];
        ptr[3*x + 1] = Debug_LabelingImage[tempAddress];
        ptr[3*x + 2] = Debug_LabelingImage[tempAddress];

        if(ThreeDEraseArea[HALF_IMAGE_WIDTH * (y / 2) + (x / 2)])
        {
          ptr[3*x + 0] = Debug_LabelingImage[tempAddress];
          ptr[3*x + 1] = 0;
          ptr[3*x + 2] = 255;
        }

        if(Debug_SatAreaImage[tempAddress])
        {
          ptr[3*x + 0] = Debug_LabelingImage[tempAddress];
          ptr[3*x + 1] = 255;
          ptr[3*x + 2] = 0;
        }
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

  ThreeDDebug_OverlapAreaImage->Picture->Bitmap->Assign(img);
  ThreeDDebug_OverlapAreaImage->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = HALF_IMAGE_WIDTH * (y / 2) + (x / 2);

      ptr[3*x + 0] = Debug_NormalizedThreeDImage[tempAddress];
      ptr[3*x + 1] = Debug_NormalizedThreeDImage[tempAddress];
      ptr[3*x + 2] = Debug_NormalizedThreeDImage[tempAddress];
    }
  }

  ThreeDDebug_ScaleDownImage->Picture->Bitmap->Assign(img);
  ThreeDDebug_ScaleDownImage->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3*x + 0] = AdjustThreeD_Data[tempAddress];
      ptr[3*x + 1] = AdjustThreeD_Data[tempAddress];
      ptr[3*x + 2] = AdjustThreeD_Data[tempAddress];

      if(ThreeDOutlineImage[tempAddress])
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 255;
      }
    }
  }

  ThreeDDebug_RemoveNoiseImage->Picture->Bitmap->Assign(img);
  ThreeDDebug_RemoveNoiseImage->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3*x + 0] = AdjustThreeD_Data[tempAddress];
      ptr[3*x + 1] = AdjustThreeD_Data[tempAddress];
      ptr[3*x + 2] = AdjustThreeD_Data[tempAddress];
    }
  }

  ThreeDDebug_COGResultImage->Picture->Bitmap->Assign(img);

  if(DefectSW == 0 || DefectSW == 1)
  {
    ThreeDDebug_COGResultImage->Canvas->Pen->Width = 2;
    ThreeDDebug_COGResultImage->Canvas->Pen->Color = clYellow;
    ThreeDDebug_COGResultImage->Canvas->Pen->Style = psSolid;
    ThreeDDebug_COGResultImage->Canvas->Brush->Style = bsClear;
    ThreeDDebug_COGResultImage->Canvas->MoveTo(0, AdjustTabletCenterInfo[1]);
    ThreeDDebug_COGResultImage->Canvas->LineTo(MAX_IMAGE_WIDTH, AdjustTabletCenterInfo[1]);
    ThreeDDebug_COGResultImage->Canvas->MoveTo(AdjustTabletCenterInfo[0], 0);
    ThreeDDebug_COGResultImage->Canvas->LineTo(AdjustTabletCenterInfo[0], MAX_IMAGE_HEIGHT);

    ThreeDDebug_COGResultImage->Canvas->Pen->Width = 2;
    ThreeDDebug_COGResultImage->Canvas->Pen->Color = clRed;
    ThreeDDebug_COGResultImage->Canvas->Pen->Style = psDot;
    ThreeDDebug_COGResultImage->Canvas->Brush->Style = bsClear;
    ThreeDDebug_COGResultImage->Canvas->MoveTo(0, ProtoTabletCenterY);
    ThreeDDebug_COGResultImage->Canvas->LineTo(MAX_IMAGE_WIDTH, ProtoTabletCenterY);
    ThreeDDebug_COGResultImage->Canvas->MoveTo(ProtoTabletCenterX, 0);
    ThreeDDebug_COGResultImage->Canvas->LineTo(ProtoTabletCenterX, MAX_IMAGE_HEIGHT);

    ThreeDDebug_COGResultImage->Canvas->Font->Size = 40;
    ThreeDDebug_COGResultImage->Canvas->Font->Color = clBlue;

    TLabel *tempLabel = new TLabel(this);
    tempLabel->Font->Size = 40;

    if(ProtoTabletCenterY > AdjustTabletCenterInfo[1])
    {
      tempLabel->Caption = " ↑";

      ThreeDDebug_COGResultImage->Canvas->TextOutW(MAX_IMAGE_WIDTH / 2 - tempLabel->Width / 2 + 20, (AdjustTabletCenterInfo[1] + ProtoTabletCenterY) / 2 - tempLabel->Height / 2, " ↑");
    }
    else if(ProtoTabletCenterY < AdjustTabletCenterInfo[1])
    {
      tempLabel->Caption = " ↓";

      ThreeDDebug_COGResultImage->Canvas->TextOutW(MAX_IMAGE_WIDTH / 2 - tempLabel->Width / 2 + 20, (AdjustTabletCenterInfo[1] + ProtoTabletCenterY) / 2 - tempLabel->Height / 2, " ↓");
    }

    if(ProtoTabletCenterX > AdjustTabletCenterInfo[0])
    {
      tempLabel->Caption = " ←";

      ThreeDDebug_COGResultImage->Canvas->TextOutW(MAX_IMAGE_WIDTH / 2 - tempLabel->Width / 2 - 20, (AdjustTabletCenterInfo[1] + ProtoTabletCenterY) / 2 - tempLabel->Height / 2, " ←");
    }
    else if(ProtoTabletCenterX < AdjustTabletCenterInfo[0])
    {
      tempLabel->Caption = " →";

      ThreeDDebug_COGResultImage->Canvas->TextOutW(MAX_IMAGE_WIDTH / 2 - tempLabel->Width / 2 - 20, (AdjustTabletCenterInfo[1] + ProtoTabletCenterY) / 2 - tempLabel->Height / 2, " →");
    }

    delete tempLabel;
  }

  ThreeDDebug_COGResultImage->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3*x + 0] = RotationThreeDImage[tempAddress];
      ptr[3*x + 1] = RotationThreeDImage[tempAddress];
      ptr[3*x + 2] = RotationThreeDImage[tempAddress];
    }
  }

  for(int m = 0; m < EdgeLineCountForThreeDImage; m++)
  {
    x = EdgeLineForThreeDImage[m][0];
    y = EdgeLineForThreeDImage[m][1];

    for(int tempY = y - 1; tempY <= y + 1; tempY++)
    {
      for(int tempX = x - 1; tempX <= x + 1; tempX++)
      {
        if(tempX > 0 && tempX < MAX_IMAGE_WIDTH && tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
        {
          ptr = (Byte*)img->ScanLine[tempY];

          ptr[3*tempX + 0] = 0;
          ptr[3*tempX + 1] = 0;
          ptr[3*tempX + 2] = 255;
        }
      }
    }
  }

  if(AdjustTabletCenterX && AdjustTabletCenterY)
  {
    if(ExecutiveSearchingRotationAngle)
    {
      int xyCosValue = CosData[(ProtoTabletRotationAngle + 720) % 720];
		  int xySinValue = SinData[(ProtoTabletRotationAngle + 720) % 720];
    
      for(x = 0; x < MAX_IMAGE_WIDTH; x++)
      {
        int tempX = x;
        int tempY = AdjustTabletCenterY;

        int rotateX, rotateY;
        
        rotateX = ((xyCosValue * (tempX - AdjustTabletCenterX) - xySinValue * (tempY - AdjustTabletCenterY)) / 1024) + AdjustTabletCenterX;
				rotateY = ((xySinValue * (tempX - AdjustTabletCenterX) + xyCosValue * (tempY - AdjustTabletCenterY)) / 1024) + AdjustTabletCenterY;

        if(rotateX > 2 && rotateX < MAX_IMAGE_WIDTH - 2 && rotateY > 2 && rotateY < MAX_IMAGE_HEIGHT - 2)
        {
          for(int tempY = rotateY - 1; tempY <= rotateY + 1; tempY++)
          {
            for(int tempX = rotateX - 1; tempX <= rotateX + 1; tempX++)
            {
              ptr = (Byte*)img->ScanLine[tempY];

              ptr[3*tempX + 0] = 0;
              ptr[3*tempX + 1] = 255;
              ptr[3*tempX + 2] = 0;
            }
          }
        }
      }
    }
  }

  ThreeDDebug_RotationImage->Picture->Bitmap->Assign(img);

  ThreeDDebug_RotationImage->Canvas->Pen->Width = 2;
  ThreeDDebug_RotationImage->Canvas->Pen->Color = clBlue;
  ThreeDDebug_RotationImage->Canvas->Brush->Style = bsClear;
  ThreeDDebug_RotationImage->Canvas->Rectangle(tabletAreaInfo[AREA_INFO_ST_X_ADDRESS], tabletAreaInfo[AREA_INFO_ST_Y_ADDRESS], tabletAreaInfo[AREA_INFO_END_X_ADDRESS], tabletAreaInfo[AREA_INFO_END_Y_ADDRESS]);

  ThreeDDebug_RotationImage->Canvas->Pen->Width = 2;
  ThreeDDebug_RotationImage->Canvas->Pen->Color = clYellow;
  ThreeDDebug_RotationImage->Canvas->Pen->Style = psDashDotDot;
  ThreeDDebug_RotationImage->Canvas->Brush->Style = bsClear;
  ThreeDDebug_RotationImage->Canvas->MoveTo(AdjustTabletCenterX, 0);
  ThreeDDebug_RotationImage->Canvas->LineTo(AdjustTabletCenterX, MAX_IMAGE_HEIGHT);
  ThreeDDebug_RotationImage->Canvas->MoveTo(0, AdjustTabletCenterY);
  ThreeDDebug_RotationImage->Canvas->LineTo(MAX_IMAGE_WIDTH, AdjustTabletCenterY);

  ThreeDDebug_RotationImage->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3*x + 0] = Debug_BeforeRotationResult[tempAddress];
      ptr[3*x + 1] = Debug_BeforeRotationResult[tempAddress];
      ptr[3*x + 2] = Debug_BeforeRotationResult[tempAddress];
    }
  }

  ThreeDDebug_BeforeRotationResult->Picture->Bitmap->Assign(img);
  ThreeDDebug_BeforeRotationResult->Refresh();

  int maxDentedValue = 0;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y+=2)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x+=2)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(maxDentedValue < DentedArea[tempAddress])
      {
        maxDentedValue = DentedArea[tempAddress];
      }
    }
  }
  
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(maxDentedValue)
      {
        ptr[3*x + 0] = min(255, DentedArea[tempAddress] * 255 / maxDentedValue);
        ptr[3*x + 1] = min(255, DentedArea[tempAddress] * 255 / maxDentedValue);
        ptr[3*x + 2] = min(255, DentedArea[tempAddress] * 255 / maxDentedValue);
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

  ThreeDDebug_DentedImage->Picture->Bitmap->Assign(img);
  ThreeDDebug_DentedImage->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3*x + 0] = ThreeD_Image[tempAddress];
      ptr[3*x + 1] = ThreeD_Image[tempAddress];
      ptr[3*x + 2] = ThreeD_Image[tempAddress];

      if(Debug_SatAreaImage[tempAddress])
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 255;
      }
    }
  }

  ThreeDDebug_SaturationArea->Picture->Bitmap->Assign(img);
  ThreeDDebug_SaturationArea->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3*x + 0] = RotationThreeDImage[tempAddress];
      ptr[3*x + 1] = RotationThreeDImage[tempAddress];
      ptr[3*x + 2] = RotationThreeDImage[tempAddress];

      if(realPrintMaskingArea[tempAddress])
      {
        ptr[3*x + 0] = RotationThreeDImage[tempAddress] / realPrintMaskingArea[tempAddress];
        ptr[3*x + 1] = RotationThreeDImage[tempAddress];
        ptr[3*x + 2] = min(255, RotationThreeDImage[tempAddress] * 2);
      }
    }
  }

  ThreeDDebug_PrintMatchingResult->Picture->Bitmap->Assign(img);
  ThreeDDebug_PrintMatchingResult->Refresh();

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      ptr[3*x + 0] = AdjustThreeD_Data[tempAddress];
      ptr[3*x + 1] = AdjustThreeD_Data[tempAddress];
      ptr[3*x + 2] = AdjustThreeD_Data[tempAddress];

      if(threeDShellImage[tempAddress]) // shell info
      {
        ptr[3*x + 0] = (threeDShellImage[tempAddress] * 17) & 0xFF;
        ptr[3*x + 1] = (threeDShellImage[tempAddress] * 41) & 0xFF;
        ptr[3*x + 2] = (threeDShellImage[tempAddress] * 73) & 0xFF;
      }
    }
  }

  ThreeDDebug_ThreeDShellImage->Picture->Bitmap->Assign(img);
  ThreeDDebug_ThreeDShellImage->Refresh();

  int maxDefectValue = 0;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y+=2)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x+=2)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(maxDefectValue < ExpectedThreeDDefectArea[tempAddress])
      {
        maxDefectValue = ExpectedThreeDDefectArea[tempAddress];
      }
    }
  }
  
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*)img->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(maxDefectValue)
      {
        ptr[3*x + 0] = min(255, ExpectedThreeDDefectArea[tempAddress] * 255 / maxDefectValue);
        ptr[3*x + 1] = min(255, ExpectedThreeDDefectArea[tempAddress] * 255 / maxDefectValue);
        ptr[3*x + 2] = min(255, ExpectedThreeDDefectArea[tempAddress] * 255 / maxDefectValue);
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

  ThreeDDebug_ExpecteDefectArea->Picture->Bitmap->Assign(img);
  ThreeDDebug_ExpecteDefectArea->Refresh();
  
  delete img;
}
//---------------------------------------------------------------------------
void __fastcall TDefectInfoForm::ThreeDDebugButtonClick(TObject *Sender)
{
  if (GlobalCameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX - 1 || GlobalCameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX - 1)
  {
    if(ThreeDLaserInfoViewerCheckBox->Checked == false)
    {
      ThreeDDebugInfoPanel->Visible = !ThreeDDebugInfoPanel->Visible;

      if(ThreeDDebugInfoPanel->Visible)
      {
        ThreeDDebugInfoPanel->BringToFront();
        ThreeDDebugButton->Caption = "3D Debug (On)";
      }
      else
      {
        ThreeDDebugButton->Caption = "3D Debug (Off)";
      }
    }
  }
  else
  {
    ThreeDDebugInfoPanel->Visible = false;
    ThreeDDebugButton->Caption = "3D Debug (Off)";
  }
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::GroupBox1DblClick(TObject *Sender)
{
  ThreeDDebugButton->Visible = !ThreeDDebugButton->Visible;
}
//---------------------------------------------------------------------------

TColor __fastcall TDefectInfoForm::ThreeDDepth(int srcValue, int maxValue)
{
  int minColor = 0x000000FF; // red
  int maxColor = 0x00FF0000; // blue

  if(srcValue > maxValue) srcValue = maxValue;

  float value = srcValue / (float)maxValue;

  int nColor;

  if(value <= 0)
  {
    nColor = 0x00000000;
  }
  else if(value >= 1)
  {
    nColor = 0x000000FF;
  }
  else
  {
    if(value < 0.25)
    {
      nColor = (maxColor | (int)(255 * value / 0.25) << 8);
    }
    else if(value > 0.75)
    {
      nColor = (minColor | (int)(255 * (0.25 - (value - 0.75)) / 0.25) << 8);
    }
    else if(value < 0.5)
    {
      nColor = (0x00FF00 | (int)(255 * (0.25 - (value - 0.25)) / 0.25) << 16);
    }
    else
    {
      nColor = (0x00FF00 | (int)(255 * (value - 0.50) / 0.25) << 0);
    }
  }

  TColor returnColor;
  returnColor = (TColor)nColor;

  return returnColor;
}
//--------------------------------------------------------------------------

TColor __fastcall TDefectInfoForm::SetDepthbar()
{
  Graphics::TBitmap *img;
	img = new Graphics::TBitmap();
	img->Width = MAX_IMAGE_WIDTH;
	img->Height = 10;
	img->PixelFormat = pf24bit;

	for (int y = 0; y < 10; y++)
  {
    Byte *ptr = (byte*)img->ScanLine[y];
    for (int x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      TColor value = ThreeDDepth(MAX_IMAGE_WIDTH - x, 640);

      ptr[3*x + 0] = (value & 0x00FF0000) >> 16;
      ptr[3*x + 1] = (value & 0x0000FF00) >> 8;
      ptr[3*x + 2] = (value & 0x000000FF) >> 0;
		}
	}

	DepthRefImage->Picture->Bitmap->Assign(img);
	DepthRefImage->Refresh();

  delete img;
}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::TntPanel2Click(TObject *Sender)
{
	
  TPBCameraSettingForm->Width = 732;
  TPBCameraSettingForm->Height = 620;

  TPBCameraSettingForm->ShowModal();

}
//---------------------------------------------------------------------------

void __fastcall TDefectInfoForm::CheckTPB_BoardExist(void)
{
	ReadTPB_BoardExistInfo();

  if(TPBSystemInfo.boardExist == TPB_BOARD_EXSIT)
  {
    TntPanel2->Visible = true;
  }
  else
  {
    TntPanel2->Visible = false;
  }  
}
