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

#include <vcl.h>
#include <FileCtrl.hpp>
#include <inifiles.hpp>
#include "Mmsystem.h"
#pragma hdrstop

#include <math.h>
#include "RealSizeImage_Form.h"
#include "TabletSimulation_Form.h"
#include "Environment.h"
#include "Bayer.h"
#include "conio.h"
#include "Common_PC.h"
#include "GradeSetting.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "CSPIN"
#pragma link "TntComCtrls"
#pragma link "TntExtCtrls"
#pragma link "TntStdCtrls"
#pragma resource "*.dfm"
TTabletSimulationForm *TabletSimulationForm;

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

#define STUDY_MODE 1
#define INSPECTION_MODE 2

#define UNCOATING  1
#define FILMCOATING  2
#define SUGARCOATING  3

#define ROUND  1
#define OBLONG  2
#define OVAL  3
#define HEXA  4
#define TRIANGLE  5

#define STAMP 1
#define PRINT 2

#define DARK 1
#define BRIGHT 2

#define ONE_FACE 1
#define TWO_FACE_SAME 2
#define TWO_FACE_DIFF 3

#define MAX_IMAGE_WIDTH 640
#define MAX_IMAGE_HEIGHT 480

#define CASE1    1
#define CASE2    2
#define CASE3    3
#define SHAPE_MATCHING_RANGE 10
#define ACCEPTABLE_ROTATION_RANGE 10
#define PRINT_DATA_SIZE 40000

#define PI    3.141592

#define FRONT_FACE 1
#define SIDE_FACE_M45 2
#define SIDE_FACE_0 3
#define SIDE_FACE_P45 4
#define FRONT_FACE_BACKLIGHT 5

#define NORMAL_INPECTION_AREA  1
#define FRONT_SHAPE_EDGE_NEIGHBOR  2
#define FRONT_SHAPE_EDGE  3
#define PRINT_AREA  4
#define PRINT_NEIGHBOR  5


#define CAMERA1_ZOOM 37
#define CAMERA2_ZOOM 37
#define CAMERA3_ZOOM 35
#define CAMERA4_ZOOM 34
#define CAMERA5_ZOOM 34

#define MAX_LABEL_COUNT 5000
#define MAX_DEFECT_POINT_COUNT 10000

#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define GRID_SIZE 20

int DefectSWforCamera[SYSTEM_TOTAL_CAMERA_COUNT] = {0,};
typedef struct
{
  int defectSeries;
  int cameraIndex;
  int defectPositionStartX;
  int defectPositionEndX;
  int defectPositionStartY;
  int defectPositionEndY;
  int size;
}TTempDefectInfo;

TTempDefectInfo TempDefectInfo[SYSTEM_TOTAL_CAMERA_COUNT];
//---------------------------------------------------------------------------
__fastcall TTabletSimulationForm::TTabletSimulationForm(TComponent* Owner)
: TTntForm(Owner)
{


}
//---------------------------------------------------------------------------
bool __fastcall TTabletSimulationForm::SaveBMPImage(int imageIndex, int cameraIndex, bool bThreeD)
{
  bool returnValue = true;
  Graphics::TBitmap *img1;
  img1 = new Graphics::TBitmap();
  Graphics::TBitmap *img2;
  img2 = new Graphics::TBitmap();


  AnsiString filename = GetProductImagePath() + "\\Image" + IntToStr(imageIndex)  + "_" + IntToStr(cameraIndex) + ".bmp";

  if(!bThreeD)
  {
    if (ExtractImage(img1, imageIndex, cameraIndex, TabletSetupData.ImageOffSetSW[cameraIndex - 1], TabletSetupData.referenceImageForOffset[cameraIndex - 1], ProductData.SubSamplingMode))
    {
      img1->SaveToFile(filename);
    }
    else
    {
      returnValue = false;
    }

  }
  else
  {
    if (ExtractImage(img1, imageIndex, cameraIndex, TabletSetupData.ImageOffSetSW[cameraIndex - 1], TabletSetupData.referenceImageForOffset[cameraIndex -1], ProductData.SubSamplingMode))
    {
      img2->Assign(img1);
      img2->Width = img1->Width*2;

			Byte *ptr;
			Byte *tr;
			ExtractBayerImage(BayerImage, imageIndex, cameraIndex);

      for(int y = 0 ; y < ImageHeight; y++)
      {
        ptr = (byte*) img1->ScanLine[y];
        tr = (byte*) img2->ScanLine[y];
        for(int x = 0; x < img1->Width*2; x++)
        {
            tr[x] = ptr[x/2];
        }
      }
      img2->SaveToFile(filename);
    }
  }

  delete img1;
  delete img2;
  return returnValue;

}

//----------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::ImageLoad(int imageIndex, int cameraIndex, int mode)
{
  int x,y;
  int rgb;

  rgb = 1;
  int selectedImageNumber;
  selectedImageNumber = imageIndex;
  Graphics::TBitmap *img1;
  img1 = new Graphics::TBitmap();
  Graphics::TBitmap *img2;
  img2 = new Graphics::TBitmap();
  AnsiString fileName;
  fileName = ImagePathEdit->Text + "\\Image" + IntToStr(selectedImageNumber) + "_" + IntToStr(cameraIndex) + ".bmp";

  if(cameraIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX &&
      cameraIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX)
  {
    if(mode == SIM_SELECT_IMAGE)
    {
      memset(ColorSourceDefectImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3);

      OpenPictureDialog1->FileName = "";

      Graphics::TBitmap *img1;
      img1 = new Graphics::TBitmap();

      if(OpenPictureDialog1->Execute())
      {
        img1->LoadFromFile(OpenPictureDialog1->FileName);

        int width = img1->Width;
        int height = img1->Height;

        int x, y;
        Byte *ptr;
        for (y = 0; y < height; y++)
        {
          ptr = (byte*)img1->ScanLine[y];
          for (x = 0; x < width; x++)
          {
            BayerImage[(width*y + x) * 3] = ptr[3 * x];
            BayerImage[(width*y + x) * 3 + 1] = ptr[3 * x + 1];
            BayerImage[(width*y + x) * 3 + 2] = ptr[3 * x + 2];

            //BayerImage[(width*y + x)] = ptr[3 * x + 1];
          }
        }
      }

      delete img1;
    }
    else
    {
      ExtractBayerImage(BayerImage, selectedImageNumber, cameraIndex);
    }
  }
  else
  {
    if(mode == SIM_SELECT_IMAGE)
    {
      //memset(ColorSourceDefectImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3);

      OpenPictureDialog1->FileName = "";

      Graphics::TBitmap *img1;
      img1 = new Graphics::TBitmap();

      if(OpenPictureDialog1->Execute())
      {
	img1->LoadFromFile(OpenPictureDialog1->FileName);

        int width = img1->Width;
        int height = img1->Height;
        int halfWidth = img1->Width/2;
        int halfHeight = img1->Height/2;

	// convert to bayer image
        ImageConversion_3D_Reverse(img1, IMAGE_WIDTH_3D, IMAGE_HEIGHT_3D, BayerImage, SYSTEM_CAMERA_WIDTH_3D, SYSTEM_CAMERA_HEIGHT_3D);

        img2->Assign(img1);
        img2->Width = img1->Width;

        int x, y;
        Byte *ptr;
        Byte *tr;
        for (y = 0; y < height; y++)
        {
          ptr = (byte*)img1->ScanLine[y];
          tr = (byte*) img2->ScanLine[y];
          for (x = 0; x < width; x++)
          {
            tr[x] = ptr[x];
          }
        }

        ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Picture->Bitmap->Assign(img2);
        ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Refresh();
        ((TTntImage *)FindComponent("Image"+IntToStr(11)))->Picture->Bitmap->Assign(img2);

        ((TTntImage *)FindComponent("Image"+IntToStr(11)))->Refresh();
      }

      delete img1;
    }
    else
    {
      if (ExtractImage(img1, selectedImageNumber, cameraIndex, TabletSetupData.ImageOffSetSW[cameraIndex - 1], TabletSetupData.referenceImageForOffset[cameraIndex - 1], ProductData.SubSamplingMode))
      {
        img2->Assign(img1);
        img2->Width = img1->Width*2;

        Byte *ptr;
        Byte *tr;
        ExtractBayerImage(BayerImage, selectedImageNumber, cameraIndex);

        for(y = 0 ; y < ImageHeight; y++)
        {
          ptr = (byte*) img1->ScanLine[y];
          tr = (byte*) img2->ScanLine[y];
          for(x = 0; x < img1->Width*2; x++)
          {
              tr[x] = ptr[x/2];
          }
        }

        if(mode == SIM_MANUAL_MODE)
        {
          ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Picture->Bitmap->Assign(img2);
          ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Refresh();
          ((TTntImage *)FindComponent("Image"+IntToStr(11)))->Picture->Bitmap->Assign(img2);

          ((TTntImage *)FindComponent("Image"+IntToStr(11)))->Refresh();
        }
        else
        {
          AutoProcessedImage->Picture->Bitmap->Assign(img2);
          AutoProcessedImage->Refresh();
        }
      }
      else
      {
        ShowMessageW("파일이 없습니다.");
      }
    }
  }

  delete(img1);
  delete(img2);
}

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

bool __fastcall TTabletSimulationForm::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
    {
      delete fileStream;
      return false;
    }
  }
  else
  {
    return false;
  }
}
//---------------------------------------------------------------------------
bool __fastcall TTabletSimulationForm::ReadSetupData(TTabletSetupData *tabletSetupData)
{
  AnsiString setupDataFileName = ProgramPath.Product + "\\" + ProductData.ProductCode + "\\" + ProductData.ProductCode + ".sdt";
  if (FileExists(setupDataFileName))
  {
    TFileStream *fileStream  = new TFileStream(setupDataFileName, fmOpenRead);
    if (fileStream)
    {
      fileStream->Read(tabletSetupData, sizeof(TTabletSetupData));
      delete fileStream;
      return true;
    }
    else
    {
      delete fileStream;
      return false;
    }
  }
  else
  {
    return false;
  }
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::FindImageFolderButtonClick(
      TObject *Sender)
{
  AnsiString Dir = ImagePathEdit->Text;
  if (SelectDirectory(Dir, TSelectDirOpts(), 0 ))
  {
    ImagePathEdit->Text = Dir;
  }
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::FormCreate(TObject *Sender)
{
	TIniFile *iniFile = new TIniFile(ProgramPath.Env + "Virtual.ini");

  if (iniFile)
  {
    ImagePathEdit->Text = iniFile->ReadString("Recent", "Image Path", "");
  }

  delete iniFile;

  xAngle = 0;
  yAngle = 0;

  AutoInspectionResultGrid->Cells[0][0] = "구분";
  AutoInspectionResultGrid->Cells[1][0] = "#Img";
  AutoInspectionResultGrid->Cells[2][0] = "#Cam";
  AutoInspectionResultGrid->Cells[3][0] = "#Defect Info";

  bStop = false;

  ImageCount = 1;

  SelectedCameraIndex = -1;

  PagePanel1->BringToFront();

  bMakeMatchingData = false;

  print1MatchingCount = 0;
  print2MatchingCount = 0;

  TabletSimulationForm->DoubleBuffered = true;

  ShowHintByName(this);
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::FormDestroy(TObject *Sender)
{
	TIniFile *iniFile = new TIniFile(ProgramPath.Env + "Virtual.ini");
  if (iniFile)
  {
    iniFile->WriteString("Recent", "Image Path", ImagePathEdit->Text);
  }
  delete iniFile;
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::UpDown2Click(TObject *Sender,
      TUDBtnType Button)
{
  InspectionFlag = 1;

  CameraIndexEdit->Text = "";
  InspectionResultEdit->Text = "";

  ImageCount = UpDown2->Position;
  InspectionOrStudy = INSPECTION_MODE;

  ImageIndexEdit->Text = IntToStr(ImageCount);
  ThreeDImageNumberEdit->Text = IntToStr(ImageCount);

  int cameraNumSetEditValue = StrToInt(cameraNumSetEdit->Text);

  for(int camIndex = 1; camIndex <= SYSTEM_TOTAL_CAMERA_COUNT; camIndex++)
  {
    if(CameraMapInfo[camIndex - 1].CameraInspectPosition != CAMERA_POSITION_DISCONNECT)
    {
      	if(cameraNumSetCheckBox->Checked == true)
        {
        	if(camIndex != cameraNumSetEditValue)
            {
            	continue;
            } 
  		}

      if(camIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX &&
          camIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX)
      {
        DoProcessing(ImageCount, camIndex, SIM_MANUAL_MODE);
      }
      else
      {
        DoProcessingFor3D(ImageCount, camIndex, SIM_MANUAL_MODE);
      }

      Edit1->Text = IntToStr(TabletMatchingResult.TabletSideShapeXTotion);
      Edit2->Text = IntToStr(TabletMatchingResult.TabletSideShapeYTotion);
      Edit3->Text = IntToStr(TabletMatchingResult.TabletSideShapeZTotion);
      Edit4->Text = IntToStr(TabletMatchingResult.AdjustResolution);
      UpDown4->Position = TabletMatchingResult.TabletSideShapeShiftX;
      UpDown5->Position = TabletMatchingResult.TabletSideShapeShiftY;

      UpDown7->Position = TabletMatchingResult.TabletSideShapeXTotion;
      UpDown8->Position = TabletMatchingResult.TabletSideShapeYTotion;
      UpDown9->Position = TabletMatchingResult.TabletSideShapeZTotion;
      UpDown4->Position = TabletMatchingResult.TabletSideShapeShiftX;
      UpDown5->Position = TabletMatchingResult.TabletSideShapeShiftY;

      if(DefectSWforCamera[camIndex-1] == 0)
        ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Pen->Color = clGreen;
      else if(DefectSWforCamera[camIndex-1] == 1)
        ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Pen->Color = clRed;
      else
        ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Pen->Color = clYellow;

      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Picture->Bitmap->PixelFormat = pf24bit;
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Pen->Width = 20;
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Brush->Style = bsClear;
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Rectangle(15, 15, ImageWidth-15, ImageHeight-15);
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm:: ProcessingResultDisplay(int cameraIndex)
{
  int m;
  int  tempX, tempY;
  Byte *ptr;
  int i, j;
  int rotateX,rotateY;

  if((cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX || cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX) && CheckBox3->Checked == false)
  {
    Graphics::TBitmap *img1;
    img1 = new Graphics::TBitmap();
    img1->Width =  MAX_IMAGE_WIDTH;
    img1->Height =  MAX_IMAGE_HEIGHT;
    img1->PixelFormat = pf24bit;
    int tempAddress;
    int areaValue;

    for(i = 10; i < ImageHeight-10; i++)
    {
      ptr = (byte*) img1->ScanLine[i];
      for(j = 10; j < ImageWidth-10; 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];

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

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

    ((TTntImage *)FindComponent("Image12"))->Picture->Bitmap->Assign(img1);
    ((TTntImage *)FindComponent("Image12"))->Refresh();

    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)
          {
            if(1)//DefectInformation.defectSeries == DEFECT_3D_PRINT_ERASE)
            {
              ptr[3*j + 0] = 0;
              ptr[3*j + 1] = 0;
              ptr[3*j + 2] = 255;

              if(InspectionArea[tempAddress] == PRINT_AREA)
              {
                ptr[3*j + 1] = 255;
              }
            }
            else
            {
              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;
            }
          }
        }
      }
    }

    ((TTntImage *)FindComponent("Image11"))->Picture->Bitmap->Assign(img1);
    ((TTntImage *)FindComponent("Image11"))->Refresh();

    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] = ThreeD_Image[tempAddress];
        ptr[3 * j + 1] = ThreeD_Image[tempAddress];
        ptr[3 * j + 2] = ThreeD_Image[tempAddress];
      }
    }

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

    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Picture->Bitmap->Assign(img1);
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Refresh();

    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(TempImage[tempAddress])
        {
          ptr[3 * j + 0] = AdjustThreeD_Data[tempAddress] / 2;
          ptr[3 * j + 1] = AdjustThreeD_Data[tempAddress] / 2;
          ptr[3 * j + 2] = AdjustThreeD_Data[tempAddress] / 2;
        }
      }
    }

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

    delete(img1);
  }
  else if((cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX || cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX) && CheckBox3->Checked == true)
  {
    Graphics::TBitmap *img1;
    img1 = new Graphics::TBitmap();
    img1->Width =  MAX_IMAGE_WIDTH;
    img1->Height =  MAX_IMAGE_HEIGHT;
    img1->PixelFormat = pf24bit;
    int tempAddress;
    int areaValue;

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

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

    ((TTntImage *)FindComponent("Image12"))->Picture->Bitmap->Assign(img1);
    ((TTntImage *)FindComponent("Image12"))->Refresh();

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

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

        if(OneColorImage[tempAddress] == 1)
        {
          ptr[3*j + 1] = 255;
        }
        else if(OneColorImage[tempAddress] == 2)
        {
          ptr[3*j + 2] = 255;
        }
      }
    }

    ((TTntImage *)FindComponent("Image11"))->Picture->Bitmap->Assign(img1);
    ((TTntImage *)FindComponent("Image11"))->Refresh();

    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] = ThreeD_Image[tempAddress];
        ptr[3 * j + 1] = ThreeD_Image[tempAddress];
        ptr[3 * j + 2] = ThreeD_Image[tempAddress];
      }
    }

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

    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Picture->Bitmap->Assign(img1);
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Refresh();

    delete(img1);
  }
  else if(cameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX ||
          cameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
  {
    Graphics::TBitmap *img1;
    img1 = new Graphics::TBitmap();
    img1->Width =  MAX_IMAGE_WIDTH;
    img1->Height =  MAX_IMAGE_HEIGHT;
    img1->PixelFormat = pf24bit;
    Graphics::TBitmap *img2;
    img2 = new Graphics::TBitmap();
    img2->Width =  MAX_IMAGE_WIDTH;
    img2->Height =  MAX_IMAGE_HEIGHT;
    img2->PixelFormat = pf24bit;
    int tempAddress;
    int areaValue; 

    for(int y = 10; y < ImageHeight-10; y++)
    {
      ptr = (byte*) img1->ScanLine[y];
      for(int x = 10; x < ImageWidth-10; x++)
      {
        tempAddress =  MAX_IMAGE_WIDTH*y + x;
        areaValue = InspectionArea[tempAddress];
        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[tempAddress])
            {
              ptr[3*x] = 0;
              ptr[3*x+1] = 0;
              ptr[3*x+2] = 255;
            }
          }
          else
          {
            if(LabelImage_Virtual[tempAddress])
            {
              ptr[3*x] = (LabelImage_Virtual[tempAddress] * 17) & 0xFF;
              ptr[3*x+1] = (LabelImage_Virtual[tempAddress] * 41) & 0xFF;
              ptr[3*x+2] = (LabelImage_Virtual[tempAddress] * 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] ;
        }

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

    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Picture->Bitmap->Assign(img1);
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Refresh();

    ((TTntImage *)FindComponent("Image12"))->Picture->Bitmap->Assign(img1);
    ((TTntImage *)FindComponent("Image12"))->Canvas->Pen->Color = clWhite;
    ((TTntImage *)FindComponent("Image12"))->Canvas->Pen->Width = 1;
    ((TTntImage *)FindComponent("Image12"))->Canvas->Brush->Style = bsClear;
    ((TTntImage *)FindComponent("Image12"))->Refresh();

    for(int y = 10; y < ImageHeight-10; y++)
    {
      ptr = (byte*) img1->ScanLine[y];
      for(int x = 10; x < ImageWidth-10; x++)
      {
        tempAddress =  MAX_IMAGE_WIDTH*y + x;

        if(0)//ExtractedSplitLineImage[tempAddress])
        {
          ptr[3*x] = ColorSourceImage[(tempAddress)*3 + 0];
          ptr[3*x+1] = min(255, ExtractedSplitLineImage[tempAddress] * 4);
          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];
        }
      }
    }

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

        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(AdjustThreeD_Data[tempAddress])
        {
          ptr[3*x + 2] = 255;
        }

        if(TempThreeD_Image[tempAddress])
        {
          ptr[3*x + 1] = 255;
        }
        */
      }
    }
    
    ((TTntImage *)FindComponent("Image11"))->Picture->Bitmap->Assign(img1);

    if(PrintIsSW)
    {
      if(CurrentPrintType == 0)
      {
        Label19->Caption = "A " + IntToStr(PrintMatchingDiff);
      }
      else
      {
        Label19->Caption = "B " + IntToStr(PrintMatchingDiff);
      }
    }
    else
    {
      Label19->Caption = "N/A";
    }

    /*
    for(int y = 10; y < ImageHeight-10; y++)
    {
      ptr = (byte*) img1->ScanLine[y];
      for(int x = 10; x < ImageWidth-10; x++)
      {
        tempAddress =  MAX_IMAGE_WIDTH*y + x;

        if(LabelImage_Virtual[tempAddress])
        {
          ptr[3*x] = (LabelImage_Virtual[tempAddress] * 17) & 0xFF;
          ptr[3*x+1] = (LabelImage_Virtual[tempAddress] * 41) & 0xFF;
          ptr[3*x+2] = (LabelImage_Virtual[tempAddress] * 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];
        }
      }
    }

    ((TTntImage *)FindComponent("Image11"))->Picture->Bitmap->Assign(img1);
    ((TTntImage *)FindComponent("Image11"))->Refresh();
    */

    delete(img1);
    delete(img2);
  }
  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 =  MAX_IMAGE_WIDTH;
    img1->Height =  MAX_IMAGE_HEIGHT;
    img1->PixelFormat = pf24bit;
    int tempAddress;
    int areaValue;

    for(int y = 10; y < ImageHeight-10; y++)
    {
      ptr = (byte*) img1->ScanLine[y];
      for(int x = 10; x < ImageWidth-10; x++)
      {
        tempAddress =  MAX_IMAGE_WIDTH*y + x;
        areaValue = InspectionArea[tempAddress];

        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[tempAddress])
        {
          //ptr[3*x] = (LabelImage_Virtual[tempAddress] * 17) & 0xFF;
          //ptr[3*x+1] = (LabelImage_Virtual[tempAddress] * 41) & 0xFF;
          //ptr[3*x+2] = (LabelImage_Virtual[tempAddress] * 73) & 0xFF;

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

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

    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Picture->Bitmap->Assign(img1);
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Refresh();

    ((TTntImage *)FindComponent("Image12"))->Picture->Bitmap->Assign(img1);
    ((TTntImage *)FindComponent("Image12"))->Refresh();

    for(int y = 10; y < ImageHeight-10; y++)
    {
      ptr = (byte*) img1->ScanLine[y];
      for(int x = 10; x < ImageWidth-10; x++)
      {
        tempAddress =  MAX_IMAGE_WIDTH*y + x;
        /*
        if(TempImage3[tempAddress])
        {
          ptr[3*x] = 0;
          ptr[3*x+1] = max(0, 255 - ColorSourceImage[(tempAddress)*3+1] * 2);
          ptr[3*x+2] = 0;
        }
        else */
        /*
        if(noneGradientArea[tempAddress])
        {
          ptr[3*x] = 0;
          ptr[3*x+1] = 255;
          ptr[3*x+2] = 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(0)//ShapeBinaryImage[tempAddress])
        {
          ptr[3*x] =  ColorSourceImage[ (tempAddress)*3+0] ;
          ptr[3*x+1] = 255;
          ptr[3*x+2] = ColorSourceImage[ (tempAddress)*3+2] ;
        }
      }
    }

    if(0)
    for(int y = 10; y < ImageHeight-10; y++)
    {
      ptr = (byte*) img1->ScanLine[y];
      for(int x = 10; x < ImageWidth-10; x++)
      {
        tempAddress =  MAX_IMAGE_WIDTH*y + x;

        ptr[3*x] = GradientImage[tempAddress];
        ptr[3*x+1] = GradientImage[tempAddress];
        ptr[3*x+2] = GradientImage[tempAddress];
      }
    }
    
    ((TTntImage *)FindComponent("Image11"))->Picture->Bitmap->Assign(img1);

    delete(img1);
  }
}

//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::InspectionCameraClick(TObject *Sender)
{
  TTntImage *tempImage;
  tempImage = (TTntImage*) Sender;

  int cameraIndex = tempImage->Tag;
  SelectedCameraIndex = tempImage->Tag;
  int selectedImageNumber;
  selectedImageNumber = ImageCount;

  if(SaveBMPCheck->Checked)
  {
    for(int imageIndex = 1; imageIndex <= 100; imageIndex++)
    {
      if(!SaveBMPImage(imageIndex, cameraIndex, false))
      {
        ShowMessage("error");
        break;
      }
    }
	ShowMessage("BMP Saved.");
    return;
  }


  if(CameraMapInfo[cameraIndex - 1].CameraInspectPosition == CAMERA_POSITION_DISCONNECT) return;

  CameraIndexEdit->Text = IntToStr(cameraIndex);
  InspectionResultEdit->Text = "";
  DefectInfoEdit->Text = "";
  DefectSizeEdit->Text = "";

  ImageIndexEdit->Text = IntToStr(ImageCount);

  int imageLoadMode = SIM_MANUAL_MODE;
  if(LoadFromBMPCheckBox->Checked)
  {
    imageLoadMode = SIM_SELECT_IMAGE;
  }

  DoProcessing(ImageCount, cameraIndex, imageLoadMode);

  PrintNumEdit->Text = IntToStr(CurrentPrintType);
  
  if(PrintIsSW)
    PrintResultEdit->Text = "인쇄 및 각인 있음";
  else
    PrintResultEdit->Text = "인쇄 및 각인 없음";

  InspectionFlag = 1;

  if(InspectionFlag)
  {
    if(DefectSWforCamera[cameraIndex - 1] == 0)
    {
      InspectionResultEdit->Text = "GOOD";
    }
    else if(DefectSWforCamera[cameraIndex - 1] == 1)
    {
      InspectionResultEdit->Text = "DEFECT";
    }
    else
    {
      InspectionResultEdit->Text = "UN-INSPECTION";
    }

    ThreeDDebugPanel->Visible = false;
    PagePanel1->BringToFront();

    if(InspectionKind == SIDE_FACE_P45 ||
        InspectionKind == SIDE_FACE_M45 ||
        InspectionKind == SIDE_FACE_0)

    {
      Edit1->Text = IntToStr(TabletMatchingResult.TabletSideShapeXTotion);
      Edit2->Text = IntToStr(TabletMatchingResult.TabletSideShapeYTotion);
      Edit3->Text = IntToStr(TabletMatchingResult.TabletSideShapeZTotion);
      Edit4->Text = IntToStr(TabletMatchingResult.AdjustResolution);

      UpDown4->Position = TabletMatchingResult.TabletSideShapeShiftX;
      UpDown5->Position = TabletMatchingResult.TabletSideShapeShiftY;

      UpDown7->Position = TabletMatchingResult.TabletSideShapeXTotion;
      UpDown8->Position = TabletMatchingResult.TabletSideShapeYTotion;
      UpDown9->Position = TabletMatchingResult.TabletSideShapeZTotion;
      UpDown4->Position = TabletMatchingResult.TabletSideShapeShiftX;
      UpDown5->Position = TabletMatchingResult.TabletSideShapeShiftY;

      LoadSideFaceDebugData();
    }
    else if(InspectionKind == FRONT_FACE)
    {
      LoadFrontFaceDebugData();
    }
  }

  if(DefectSWforCamera[cameraIndex - 1])
  {
    AnsiString DefectStr = GetDefectSeriesStr(TempDefectInfo[cameraIndex - 1].defectSeries);

    DefectInfoEdit->Text = DefectStr;

    if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_FRONT_WHITE_ENGRAVE)
    {
      DefectSizeEdit->Text = IntToStr(TempDefectInfo[cameraIndex - 1].size) + " Grade";
    }
    else if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_PRINT_POSITION_ERROR)
    {
      DefectSizeEdit->Text = FloatToStr(TempDefectInfo[cameraIndex - 1].size * 0.04) + " mm";
    }
    else if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_PRINT_ROTATION_ERROR)
    {
      DefectSizeEdit->Text = IntToStr(TempDefectInfo[cameraIndex - 1].size) + " Degree";
    }
    else
    {
      DefectSizeEdit->Text = FloatToStr(DefectSizePixelToMili(TempDefectInfo[cameraIndex - 1].size) / 100.0) + "mm";
    }

    ((TTntImage *)FindComponent("Image11"))->Canvas->Pen->Color = clRed;
    ((TTntImage *)FindComponent("Image11"))->Canvas->Brush->Style = bsClear;
    ((TTntImage *)FindComponent("Image11"))->Canvas->Rectangle(TempDefectInfo[cameraIndex - 1].defectPositionStartX,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionStartY,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionEndX,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionEndY);
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::Inspection3DCamClick(TObject *Sender)
{
  TTntImage *tempImage;
  tempImage = (TTntImage*) Sender;

  int cameraIndex = tempImage->Tag;
  int selectedImageNumber;
  SelectedCameraIndex = cameraIndex;
  selectedImageNumber = ImageCount;

  if(SaveBMPCheck->Checked)
  {
    for(int imageIndex = 1; imageIndex <= 100; imageIndex++)
    {
      if(!SaveBMPImage(imageIndex, cameraIndex, true))
      {
        ShowMessage("error");
        break;
      }
    }
	ShowMessage("BMP Saved.");
    return;
  }

  if(CameraMapInfo[cameraIndex - 1].CameraInspectPosition == CAMERA_POSITION_DISCONNECT) return;
  
  CameraIndexEdit->Text = IntToStr(cameraIndex);
  InspectionResultEdit->Text = "";
  DefectInfoEdit->Text = "";
  DefectSizeEdit->Text = "";

  int imageLoadMode = SIM_MANUAL_MODE;
  if(LoadFromBMPCheckBox->Checked)
  {
    imageLoadMode = SIM_SELECT_IMAGE;
  }

  DoProcessingFor3D(ImageCount, cameraIndex, imageLoadMode);

  PrintNumEdit->Text = IntToStr(CurrentPrintType);

  if(PrintIsSW)
    PrintResultEdit->Text = "인쇄 및 각인 있음";
  else
    PrintResultEdit->Text = "인쇄 및 각인 없음";
                       
  if(InspectionFlag)
  {
    if(DefectSWforCamera[cameraIndex - 1] == 0)
    {
      InspectionResultEdit->Text = "GOOD";
    }
    else if(DefectSWforCamera[cameraIndex - 1] == 1)
    {
      InspectionResultEdit->Text = "DEFECT";
    }
    else
    {
      InspectionResultEdit->Text = "UN-INSPECTION";
    }
  }

  ThreeDDebugPanel->Visible = true;
  ThreeDDebugPanel->BringToFront();

  if(CheckBox3->Checked == false)
  {
    LoadFrontFace3DDebugData();
  }
  else
  {
    if(DefectSW == 0)
    {
      Load3DPositionInfo();
    }
  }

  if(DefectSWforCamera[cameraIndex - 1])
  {
    AnsiString DefectStr = GetDefectSeriesStr(TempDefectInfo[cameraIndex - 1].defectSeries);
    DefectInfoEdit->Text = DefectStr;

    if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_FRONT_WHITE_ENGRAVE)
    {
      DefectSizeEdit->Text = IntToStr(TempDefectInfo[cameraIndex - 1].size) + " Grade";
    }
    else if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_PRINT_POSITION_ERROR)
    {
      DefectSizeEdit->Text = FloatToStr(TempDefectInfo[cameraIndex - 1].size * 0.04) + " mm";
    }
    else if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_PRINT_ROTATION_ERROR)
    {
      DefectSizeEdit->Text = IntToStr(TempDefectInfo[cameraIndex - 1].size) + " Degree";
    }
    else
    {
      DefectSizeEdit->Text = FloatToStr(DefectSizePixelToMili(TempDefectInfo[cameraIndex - 1].size) / 100.0) + "mm";
    }

    ((TTntImage *)FindComponent("Image11"))->Canvas->Pen->Color = clRed;
    ((TTntImage *)FindComponent("Image11"))->Canvas->Brush->Style = bsClear;
    ((TTntImage *)FindComponent("Image11"))->Canvas->Rectangle(TempDefectInfo[cameraIndex - 1].defectPositionStartX,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionStartY,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionEndX,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionEndY);
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::DoProcessing(int imageIndex, int cameraIndex, int mode)
{
	double timeDouble;
    AnsiString tmpString;
    
  if(!SystemLinkCameraInfo[cameraIndex - 1]) return;

  if (!ReadSetupData(&TabletSetupData))
  {
    ShowMessageW("Setup Data 를 읽어올 수 없습니다.");
  }

  if(!ReadStudyData(&TabletStudyData) )
  {
    ShowMessageW("study Data 를 읽어올 수 없습니다.");
  }

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

  TabletGradeData.dummy[0] = 100;

  InspectionOrStudy = INSPECTION_MODE;

  MakeTabletCharacterData(&ProductData, &TabletCharacter, &MachineParams);
  currentBackgroundImage = NULL;

  // CPB Data Initial
  SetSideFaceDataAddress(&tempSideData[0]);

  CPBCommonVariableInitial();

  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(imageIndex, cameraIndex, mode);

  int bViewDefectImageResult = 0;
  if(mode == SIM_SELECT_IMAGE)
    bViewDefectImageResult = 1;

  InitQueryTime(); // 실행 시간 측정을 위한 변수 초기화

  WriteProcessingBeginTime(); // 실행시간 측정 시작

  //unsigned int stTime = GetTickCount();
  switch(cameraIndex)
  {
    case SD1_2D_FRONT_FACE_CAMERA_INDEX :
    case SD2_2D_FRONT_FACE_CAMERA_INDEX :

      InspectionKind = FRONT_FACE;
      ProcessingStartForFrontFace(InspectionOrStudy, cameraIndex, bViewDefectImageResult);
      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, bViewDefectImageResult);
      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, bViewDefectImageResult);
      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, bViewDefectImageResult);
      break;
  }
  //unsigned int endTime = GetTickCount();

  //unsigned int diffTime = endTime - stTime;
  //Edit5->Text = IntToStr(diffTime);

  WriteProcessingEndTime();

// 검사 속도 메모장에 표시
  SpeedCheckDisplay(cameraIndex);

  double duringtime = GetProcessingElapsedTime(); // 총 실행시간 가져옴.
  double duringtime_check_start_end = GetCheckElapsedTime(0); // 중간 체크 타임을 가져옴
  double duringtime_to_check_start = GetCheckElapsedTime(1);
  double duringtime_from_check_end = GetCheckElapsedTime(2);

  Edit5->Text = FloatToStr(duringtime);

  DefectSWforCamera[cameraIndex - 1] = DefectSW;

  if(mode == SIM_SELECT_IMAGE || mode == SIM_MANUAL_MODE || (mode == SIM_AUTO_MODE && DefectSW))
  {
    ProcessingResultDisplay(cameraIndex);

    if(DefectSWforCamera[cameraIndex-1] == 0)
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Pen->Color = clGreen;
    else if(DefectSWforCamera[cameraIndex-1] == 1)
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Pen->Color = clRed;
    else
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Pen->Color = clYellow;

    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Picture->Bitmap->PixelFormat = pf24bit;
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Pen->Width = 20;
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Brush->Style = bsClear;
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Rectangle(15, 15, ImageWidth-15, ImageHeight-15);
  }

  if(DefectSWforCamera[cameraIndex - 1] != 0)
  {
    TempDefectInfo[cameraIndex - 1].defectSeries = DefectInformation.defectSeries;
    TempDefectInfo[cameraIndex - 1].defectPositionStartX = DefectInformation.defectPositionStartX;
    TempDefectInfo[cameraIndex - 1].defectPositionStartY = DefectInformation.defectPositionStartY;
    TempDefectInfo[cameraIndex - 1].defectPositionEndX = DefectInformation.defectPositionEndX;
    TempDefectInfo[cameraIndex - 1].defectPositionEndY = DefectInformation.defectPositionEndY;
    TempDefectInfo[cameraIndex - 1].size = DefectInformation.size;

    ((TTntImage *)FindComponent("Image11"))->Picture->Bitmap->PixelFormat = pf24bit;
    ((TTntImage *)FindComponent("Image11"))->Canvas->Pen->Color = clRed;
    ((TTntImage *)FindComponent("Image11"))->Canvas->Brush->Style = bsClear;
    ((TTntImage *)FindComponent("Image11"))->Canvas->Rectangle(TempDefectInfo[cameraIndex - 1].defectPositionStartX,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionStartY,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionEndX,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionEndY);
  }

  if(InspectionKind == SIDE_FACE_P45 ||
      InspectionKind == SIDE_FACE_0 ||
      InspectionKind == SIDE_FACE_M45)
  {
    ImageRotation(cameraIndex);

  }
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::ImageIndexEditKeyPress(TObject *Sender,
      char &Key)
{
  if(Key == 0x0d)
  {
    ImageCount = StrToInt(ImageIndexEdit->Text);
    UpDown2->Position = ImageCount;
    ThreeDImageUpdown->Position = ImageCount * 2;
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::Image12MouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
  XAxisEdit->Text = IntToStr(X);
  YAxisEdit->Text = IntToStr(Y);

  if(X > 0 && X < Image12->Picture->Bitmap->Width &&
      Y > 0 && Y < Image12->Picture->Bitmap->Height)
  {
    Byte *ptr;
    ptr = (Byte*)Image12->Picture->Bitmap->ScanLine[Y];

    TntEdit1->Text = IntToStr(ptr[3*X + 0]);
    TntEdit2->Text = IntToStr(ptr[3*X + 1]);
    TntEdit3->Text = IntToStr(ptr[3*X + 2]);
  }
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::DoProcessingFor3D(int ImageIndex, int cameraIndex, int mode)
{
  if (!ReadSetupData(&TabletSetupData))
  {
    ShowMessageW("Setup Data 를 읽어올 수 없습니다.");
  }

  if (!Read3DSetupData(&Tablet3DSetupData))
  {
    ShowMessageW("Setup Data 를 읽어올 수 없습니다.");
  }

  if(!ReadStudyData(&TabletStudyData) )
  {
    ShowMessageW("study Data 를 읽어올 수 없습니다.");
  }

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

  TabletGradeData.dummy[0] = 100;

  InspectionOrStudy = INSPECTION_MODE;

  InspectionKind = FRONT_FACE_SPECIAL;

  MakeTabletCharacterData(&ProductData, &TabletCharacter, &MachineParams);
  currentBackgroundImage = NULL;

  int SDNum;
  if(cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
    SDNum = SUCTION_DISK_NUM1;
  else
    SDNum = SUCTION_DISK_NUM2;
    
  CPBCommonVariableInitial();
  SetUpDataTransFormForThreeD(InspectionKind,SDNum);

  ImageLoad(ImageIndex, cameraIndex, mode);

  InitQueryTime(); // 실행 시간 측정을 위한 변수 초기화

  WriteProcessingBeginTime(); // 실행시간 측정 시작

  if(CheckBox3->Checked == false)
  {
    ProcessingStartForFrontFace_3D(InspectionOrStudy, cameraIndex, 0x01);
  }
  else
  {
    GettingThreeDPositionInformationForLaserComplexer(InspectionOrStudy, cameraIndex, 0x01);
  }

  WriteProcessingEndTime();

// 검사 속도 메모장에 표시
  SpeedCheckDisplay(cameraIndex);

  double duringtime = GetProcessingElapsedTime(); // 총 실행시간 가져옴.
  double duringtime_check_start_end = GetCheckElapsedTime(0); // 중간 체크 타임을 가져옴
  double duringtime_to_check_start = GetCheckElapsedTime(1);
  double duringtime_from_check_end = GetCheckElapsedTime(2);

  Edit22->Text = FloatToStr(duringtime);

  DefectSWforCamera[cameraIndex - 1] = DefectSW;
  
  if(mode == SIM_SELECT_IMAGE || mode == SIM_MANUAL_MODE || (mode == SIM_AUTO_MODE && DefectSW))
  {
    ProcessingResultDisplay(cameraIndex);

    if(DefectSWforCamera[cameraIndex-1] == 0)
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Pen->Color = clGreen;
    else if(DefectSWforCamera[cameraIndex-1] == 1)
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Pen->Color = clRed;
    else
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Pen->Color = clYellow;

    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Picture->Bitmap->PixelFormat = pf24bit;
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Pen->Width = 20;
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Brush->Style = bsClear;
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(cameraIndex)))->Canvas->Rectangle(15, 15, ImageWidth-15, ImageHeight-15);
  }

  if(DefectSWforCamera[cameraIndex - 1] != 0)
  {
    TempDefectInfo[cameraIndex - 1].defectSeries = DefectInformation.defectSeries;
    TempDefectInfo[cameraIndex - 1].defectPositionStartX = DefectInformation.defectPositionStartX;
    TempDefectInfo[cameraIndex - 1].defectPositionStartY = DefectInformation.defectPositionStartY;
    TempDefectInfo[cameraIndex - 1].defectPositionEndX = DefectInformation.defectPositionEndX;
    TempDefectInfo[cameraIndex - 1].defectPositionEndY = DefectInformation.defectPositionEndY;
    TempDefectInfo[cameraIndex - 1].size = DefectInformation.size;

    ((TTntImage *)FindComponent("Image11"))->Picture->Bitmap->PixelFormat = pf24bit;
    ((TTntImage *)FindComponent("Image11"))->Canvas->Pen->Color = clRed;
    ((TTntImage *)FindComponent("Image11"))->Canvas->Brush->Style = bsClear;
    ((TTntImage *)FindComponent("Image11"))->Canvas->Rectangle(TempDefectInfo[cameraIndex - 1].defectPositionStartX,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionStartY,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionEndX,
                                                                TempDefectInfo[cameraIndex - 1].defectPositionEndY);
  }
}
//---------------------------------------------------------------------------
bool __fastcall TTabletSimulationForm::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
    {
      delete fileStream;
      return false;
    }
  }
  else
  {
    return false;
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::TntFormActivate(TObject *Sender)
{
  ImageHeight= 480;
	ImageWidth = 640;

  InspectionFlag = 0; 

  AvgHeight = 0;
  AvgHeightCnt = 0;

  if (!ReadSetupData(&TabletSetupData))
  {
    ShowMessageW("Setup Data 를 읽어올 수 없습니다.");
  }

  // For SELMA200, TEST
  // 각 카메라 별로 CameraZoom 값이 존재하지 않아 임의로 넣어줌

  /*
  for(int i = 0; i < 16; i++)
  {
    TabletSetupData.cameraZoom[i] = 440;
  }

  TabletSetupData.cameraZoom[0] = 410;
  TabletSetupData.cameraZoom[4] = 400;
  TabletSetupData.cameraZoom[8] = 410;
  TabletSetupData.cameraZoom[12] = 400;

  //현재 배율이 조금 작음
  TabletSetupData.cameraZoom[1] = 485;
  TabletSetupData.cameraZoom[3] = 485;
  // end

  // SideFace 0
  //TabletSetupData.cameraZoom[2] = 420;
  //TabletSetupData.cameraZoom[6] = 420;
  //TabletSetupData.cameraZoom[10] = 420;
  //TabletSetupData.cameraZoom[14] = 420;
  // end
  */


  if(!ReadStudyData(&TabletStudyData) )
  {
    ShowMessageW("study Data 를 읽어올 수 없습니다.");
  }

  InspectionOrStudy = INSPECTION_MODE;

  MakeTabletCharacterData(&ProductData, &TabletCharacter, &MachineParams);
  currentBackgroundImage = NULL;

  // CPB Data Initial
  CPBCommonVariableInitial();
  
  SideFaceSetUpDataTransForm_For_PCSIM(tempSideData);

  if(0)
  {
    GroupBox1->Visible = false;
    GroupBox3->Visible = false;
    
    AutoInspectionResultGrid->Visible = false;

    Panel1->Enabled = false;

    TTntImage *tempImage;
    tempImage = (TTntImage*) Sender;

    int cameraIndex = GlobalCameraIndexForDefectImage;
    SelectedCameraIndex = GlobalCameraIndexForDefectImage;
    int selectedImageNumber;
    selectedImageNumber = ImageCount;

    if (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 ||
        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)
    {
      GroupBox5->Visible = true;
    }
    else
    {
      GroupBox5->Visible = false;
    }

    if(CameraMapInfo[cameraIndex - 1].CameraInspectPosition == CAMERA_POSITION_DISCONNECT) return;

    CameraIndexEdit->Text = IntToStr(cameraIndex);
    InspectionResultEdit->Text = "";
    DefectInfoEdit->Text = "";
    DefectSizeEdit->Text = "";

    ImageIndexEdit->Text = IntToStr(ImageCount);
  
    DoProcessing(ImageCount, cameraIndex, SIM_MANUAL_MODE);

    PrintNumEdit->Text = IntToStr(CurrentPrintType);
  
    if(PrintIsSW)
      PrintResultEdit->Text = "인쇄 및 각인 있음";
    else
      PrintResultEdit->Text = "인쇄 및 각인 없음";

    InspectionFlag = 1;

    if(InspectionFlag)
    {
      if(DefectSWforCamera[cameraIndex - 1] == 0)
      {
        InspectionResultEdit->Text = "GOOD";
      }
      else if(DefectSWforCamera[cameraIndex - 1] == 1)
      {
        InspectionResultEdit->Text = "DEFECT";
      }
      else
      {
        InspectionResultEdit->Text = "UN-INSPECTION";
      }

      if(InspectionKind == SIDE_FACE_P45 ||
          InspectionKind == SIDE_FACE_M45 ||
          InspectionKind == SIDE_FACE_0)

      {
        Edit1->Text = IntToStr(TabletMatchingResult.TabletSideShapeXTotion);
        Edit2->Text = IntToStr(TabletMatchingResult.TabletSideShapeYTotion);
        Edit3->Text = IntToStr(TabletMatchingResult.TabletSideShapeZTotion);
        Edit4->Text = IntToStr(TabletMatchingResult.AdjustResolution);

        UpDown4->Position = TabletMatchingResult.TabletSideShapeShiftX;
        UpDown5->Position = TabletMatchingResult.TabletSideShapeShiftY;

        UpDown7->Position = TabletMatchingResult.TabletSideShapeXTotion;
        UpDown8->Position = TabletMatchingResult.TabletSideShapeYTotion;
        UpDown9->Position = TabletMatchingResult.TabletSideShapeZTotion;
        UpDown4->Position = TabletMatchingResult.TabletSideShapeShiftX;
        UpDown5->Position = TabletMatchingResult.TabletSideShapeShiftY;

        LoadSideFaceDebugData();
      }
      else if(InspectionKind == FRONT_FACE)
      {
        LoadFrontFaceDebugData();
      }
    }

    if(DefectSWforCamera[cameraIndex - 1])
    {
      AnsiString DefectStr = GetDefectSeriesStr(TempDefectInfo[cameraIndex - 1].defectSeries);
      DefectInfoEdit->Text = DefectStr;

      if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_FRONT_WHITE_ENGRAVE)
      {
        DefectSizeEdit->Text = IntToStr(TempDefectInfo[cameraIndex - 1].size) + " Grade";
      }
      else if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_PRINT_POSITION_ERROR)
      {
        DefectSizeEdit->Text = FloatToStr(TempDefectInfo[cameraIndex - 1].size * 0.04) + " mm";
      }
      else if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_PRINT_ROTATION_ERROR)
      {
        DefectSizeEdit->Text = IntToStr(TempDefectInfo[cameraIndex - 1].size) + " Degree";
      }
      else
      {
        DefectSizeEdit->Text = FloatToStr(DefectSizePixelToMili(TempDefectInfo[cameraIndex - 1].size) / 100.0) + "mm";
      }

      ((TTntImage *)FindComponent("Image11"))->Canvas->Pen->Color = clRed;
      ((TTntImage *)FindComponent("Image11"))->Canvas->Brush->Style = bsClear;
      ((TTntImage *)FindComponent("Image11"))->Canvas->Rectangle(TempDefectInfo[cameraIndex - 1].defectPositionStartX,
                                                                  TempDefectInfo[cameraIndex - 1].defectPositionStartY,
                                                                  TempDefectInfo[cameraIndex - 1].defectPositionEndX,
                                                                  TempDefectInfo[cameraIndex - 1].defectPositionEndY);
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::CameraMaskAllChkBoxClick(
      TObject *Sender)
{
  TCheckBox *tempCheckBox;

  for(int camIndex = 1; camIndex <= SYSTEM_TOTAL_CAMERA_COUNT; camIndex++)
  {
    tempCheckBox = ((TCheckBox *)FindComponent("CameraMaskChkBox"+IntToStr(camIndex)));

    if(tempCheckBox)
    {
      if(CameraMaskAllChkBox->Checked)
      {
        tempCheckBox->Checked = true;
      }
      else
      {
        tempCheckBox->Checked = false;
      }
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::AutoStartBtnClick(TObject *Sender)
{
  bMakeMatchingData = false;

  timeDoubleMin = 9999999;
  imgCntForAvg = 0;
  timeDoubleMax = 0;
  timeDoubleAvg = 0;

  if(CheckBox1->Checked)
  {
    print1MatchingCount = 0;
    print2MatchingCount = 0;
    
    memset(print1MatchingData, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
    memset(print2MatchingData, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
    bMakeMatchingData = true;
  }

  for(int i = 1; i < AutoInspectionResultGrid->RowCount; i++)
  {
    AutoInspectionResultGrid->Cells[0][i] = "";
    AutoInspectionResultGrid->Cells[1][i] = "";
    AutoInspectionResultGrid->Cells[2][i] = "";
    AutoInspectionResultGrid->Cells[3][i] = "";
  }
  AutoInspectionResultGrid->RowCount = 3; 
  
  bStop = false;
  
  Panel3->Enabled = false;
  Panel1->Enabled = false;
  GroupBox1->Enabled = false;


  UpDown4->Enabled = false;
  UpDown5->Enabled = false;
  UpDown2->Enabled = false;
  GroupBox4->Enabled = false;
  AutoStartBtn->Enabled = false;
  
  int cameraMask;
  cameraMask = 0;

  TCheckBox *tempCheckBox;

  for(int camIndex = 1; camIndex <= SYSTEM_TOTAL_CAMERA_COUNT; camIndex++)
  {
    tempCheckBox = ((TCheckBox *)FindComponent("CameraMaskChkBox"+IntToStr(camIndex)));

    if(tempCheckBox)
    {
      if(tempCheckBox->Checked)
      {
        cameraMask |= (0x01 << camIndex - 1);
      }
    }
  }

  InspectionFlag = 1;

  int DefectIndex = 1;
  float currentGoodRate;
  int goodCount = 0;
  GoodRateEdit->Text = "0 %";
  
  bool bGoodTablet;
  AutoInspectionResultGrid->Enabled = false;
  for(int autoImageIndex = 1; autoImageIndex <= 100; autoImageIndex++)
  {
    ProgressBar1->Position = autoImageIndex;
    InspectionOrStudy = INSPECTION_MODE;

    bGoodTablet = true;
    for(int camIndex = 1; camIndex <= SYSTEM_TOTAL_CAMERA_COUNT; camIndex++)
    {
      if(bStop)
        break;

      if(cameraMask & (0x01 << camIndex - 1))
      {
        if(camIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX &&
            camIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX)
        {
          DoProcessing(autoImageIndex, camIndex, SIM_AUTO_MODE);

          if(camIndex == 1 || camIndex == 9)
          {
            if(bMakeMatchingData)
            {
              AccPrintMachingData();
            }
          }
        }
        else
        {
          DoProcessingFor3D(autoImageIndex, camIndex, SIM_AUTO_MODE);
        }

        Application->ProcessMessages();
        
        if(DefectSWforCamera[camIndex-1])
        {
          AutoInspectionResultGrid->Cells[0][DefectIndex] = IntToStr(DefectIndex);
          AutoInspectionResultGrid->Cells[1][DefectIndex] = IntToStr(autoImageIndex);
          AutoInspectionResultGrid->Cells[2][DefectIndex] = IntToStr(camIndex);
          AutoInspectionResultGrid->Cells[3][DefectIndex] = GetDefectSeriesStr(DefectInformation.defectSeries);

          DefectIndex++;

          //AutoInspectionResultGrid->Row = AutoInspectionResultGrid->RowCount - 2;

          AutoInspectionResultGrid->RowCount++;
        }
      }
    }

    for(int camIndex = 1; camIndex <= SYSTEM_TOTAL_CAMERA_COUNT; camIndex++)
    {
      if(DefectSWforCamera[camIndex-1])
      {
        bGoodTablet = false;
        break;
      }
    }

    if(bGoodTablet)
    {
      goodCount++;
    }

    if(goodCount)
    {
      currentGoodRate = (goodCount / (float)autoImageIndex) * 100;
      GoodRateEdit->Text = FloatToStrF(currentGoodRate, ffFixed, 5, 2) + " %";
    }
    else
    {
      GoodRateEdit->Text = "0 %";
    }
  }
  AutoInspectionResultGrid->Enabled = true;

  ShowMessage("완료");

  Panel3->Enabled = true;
  Panel1->Enabled = true;
  GroupBox1->Enabled = true;


  UpDown4->Enabled = true;
  UpDown5->Enabled = true;
  UpDown2->Enabled = true;
  GroupBox4->Enabled = true;
  AutoStartBtn->Enabled = true;

  if(bMakeMatchingData)
  {
    TrackBar7->Max = print1MatchingCount;
    TrackBar8->Max = print2MatchingCount;
  }
  bMakeMatchingData = false;
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::AutoStopBtnClick(TObject *Sender)
{
  bStop = true;
}
//---------------------------------------------------------------------------


void __fastcall TTabletSimulationForm::AutoInspectionResultGridSelectCell(
      TObject *Sender, int ACol, int ARow, bool &CanSelect)
{
  if(ARow < AutoInspectionResultGrid->RowCount - 2)
  {
    int selectedImageNumber = StrToInt(AutoInspectionResultGrid->Cells[1][ARow]);
    int cameraIndex = StrToInt(AutoInspectionResultGrid->Cells[2][ARow]);

    CameraIndexEdit->Text = IntToStr(cameraIndex);
    ImageIndexEdit->Text = IntToStr(selectedImageNumber);
    DefectInfoEdit->Text = "";
    DefectSizeEdit->Text = "";

    if(cameraIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX &&
      cameraIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX)
    {
      DoProcessing(selectedImageNumber, cameraIndex, SIM_MANUAL_MODE);
    }
    else
    {
      DoProcessingFor3D(selectedImageNumber, cameraIndex, SIM_MANUAL_MODE);
    }
    
    PrintNumEdit->Text = IntToStr(CurrentPrintType);

    if(PrintIsSW)
      PrintResultEdit->Text = "인쇄 및 각인 있음";
    else
      PrintResultEdit->Text = "인쇄 및 각인 없음";

    if(InspectionFlag)
    {
      if(DefectSWforCamera[cameraIndex - 1] == 0)
      {
        InspectionResultEdit->Text = "GOOD";
      }
      else if(DefectSWforCamera[cameraIndex - 1] == 1)
      {
        InspectionResultEdit->Text = "DEFECT";
      }
      else
      {
        InspectionResultEdit->Text = "UN-INSPECTION";
      }
    }

    if(DefectSWforCamera[cameraIndex - 1])
    {
      AnsiString DefectStr = GetDefectSeriesStr(TempDefectInfo[cameraIndex - 1].defectSeries);
      DefectInfoEdit->Text = DefectStr;

      if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_FRONT_WHITE_ENGRAVE)
      {
        DefectSizeEdit->Text = IntToStr(TempDefectInfo[cameraIndex - 1].size) + " Grade";
      }
      else if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_PRINT_POSITION_ERROR)
      {
        DefectSizeEdit->Text = FloatToStr(TempDefectInfo[cameraIndex - 1].size * 0.04) + " mm";
      }
      else if(TempDefectInfo[cameraIndex - 1].defectSeries == DEFECT_PRINT_ROTATION_ERROR)
      {
        DefectSizeEdit->Text = IntToStr(TempDefectInfo[cameraIndex - 1].size) + " Degree";
      }
      else
      {
        DefectSizeEdit->Text = FloatToStr(DefectSizePixelToMili(TempDefectInfo[cameraIndex - 1].size) / 100.0) + "mm";
      }

      ((TTntImage *)FindComponent("Image11"))->Canvas->Pen->Color = clRed;
      ((TTntImage *)FindComponent("Image11"))->Canvas->Brush->Style = bsClear;
      ((TTntImage *)FindComponent("Image11"))->Canvas->Rectangle(TempDefectInfo[cameraIndex - 1].defectPositionStartX,
                                                                  TempDefectInfo[cameraIndex - 1].defectPositionStartY,
                                                                  TempDefectInfo[cameraIndex - 1].defectPositionEndX,
                                                                  TempDefectInfo[cameraIndex - 1].defectPositionEndY);
    }

    if(InspectionKind == SIDE_FACE_P45 ||
        InspectionKind == SIDE_FACE_M45 ||
        InspectionKind == SIDE_FACE_0)

    {
      LoadSideFaceDebugData();
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::LoadSideFaceDebugData()
{
  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;

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

  DebugData1->Picture->Bitmap->Assign(img);
  DebugData1->Refresh();
  helpLabel1->Caption = "Shape Binary Image";

  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] = GradientImage[tempAddress];
      ptr[3*x + 1] = GradientImage[tempAddress];
      ptr[3*x + 2] = GradientImage[tempAddress];
    }
  }

  DebugData2->Picture->Bitmap->Assign(img);
  DebugData2->Refresh();
  helpLabel2->Caption = "Gradient Image";

  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(realBinaryArea[tempAddress])
      {
        ptr[3*x + 0] = 255 - ColorSourceImage[tempAddress* 3 + 0];
        ptr[3*x + 1] = 255 - ColorSourceImage[tempAddress* 3 + 1];
        ptr[3*x + 2] = 255 - ColorSourceImage[tempAddress* 3 + 2];
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

  DebugData3->Picture->Bitmap->Assign(img);
  DebugData3->Refresh();
  helpLabel3->Caption = "NULL";

  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] = ColorSourceImage[tempAddress* 3 + 0];
      ptr[3*x + 1] = ColorSourceImage[tempAddress* 3 + 1];
      ptr[3*x + 2] = ColorSourceImage[tempAddress* 3 + 2];

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

      if(TempImage[tempAddress] == 255)
      {
        ptr[3*x + 0] = 255;
      }
      else if(TempImage[tempAddress] == 128)
      {
        ptr[3*x + 2] = 255;
      }
    }
  }

  DebugData4->Picture->Bitmap->Assign(img);
  DebugData4->Refresh();
  helpLabel4->Caption = "Real Binary Image";

  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(TempImage3[tempAddress])
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 255 - ColorSourceImage[tempAddress* 3 + 1];
        ptr[3*x + 2] = 0;
      }
      else
      {
        ptr[3*x + 0] = ColorSourceImage[tempAddress* 3 + 0];
        ptr[3*x + 1] = ColorSourceImage[tempAddress* 3 + 1];
        ptr[3*x + 2] = ColorSourceImage[tempAddress* 3 + 2];
      }
    }
  }

  DebugData5->Picture->Bitmap->Assign(img);
  DebugData5->Refresh();
  helpLabel5->Caption = "Split Line Matching Image";

  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(TempImage[tempAddress])
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 255;
        ptr[3*x + 2] = 255;
      }
      else
      {
        ptr[3*x + 0] = OneColorImage[tempAddress];
        ptr[3*x + 1] = OneColorImage[tempAddress];
        ptr[3*x + 2] = OneColorImage[tempAddress];
      }
    }
  }
  
  DebugData6->Picture->Bitmap->Assign(img);
  DebugData6->Refresh();
  helpLabel6->Caption = "One Color Image";

  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(noneGradientArea[tempAddress])
      {
        ptr[3*x] = 0;
        ptr[3*x+1] = 255;
        ptr[3*x+2] = 255;
      }
      else
      {
        ptr[3*x + 0] = ColorSourceImage[tempAddress* 3 + 0];
        ptr[3*x + 1] = ColorSourceImage[tempAddress* 3 + 1];
        ptr[3*x + 2] = ColorSourceImage[tempAddress* 3 + 2];
      }
    }
  }

  DebugData7->Picture->Bitmap->Assign(img);
  DebugData7->Refresh();
  helpLabel7->Caption = "Out Line Mask Image";

  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(ShapeBinaryImageForPrintArea[tempAddress] == 255)
      {
        ptr[3*x] = 0;
        ptr[3*x+1] = 0;
        ptr[3*x+2] = 255;
      }
      else if(ShapeBinaryImageForPrintArea[tempAddress])
      {
        ptr[3*x] = 0;
        ptr[3*x+1] = 255;
        ptr[3*x+2] = 255;
      }
      else
      {
        ptr[3*x + 0] = ColorSourceImage[tempAddress* 3 + 0];
        ptr[3*x + 1] = ColorSourceImage[tempAddress* 3 + 1];
        ptr[3*x + 2] = ColorSourceImage[tempAddress* 3 + 2];
      }
    }
  }

  DebugData8->Picture->Bitmap->Assign(img);
  DebugData8->Refresh();
  helpLabel8->Caption = "Out Line Matching Image";

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

void __fastcall TTabletSimulationForm::LoadFrontFaceDebugData()
{
  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;

  int maxValue;

  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(ShapeBinaryImage[tempAddress])
      //if(TempImage[tempAddress])
      {
        ptr[3*x + 0] = 255 - ColorSourceImage[tempAddress* 3 + 0];
        ptr[3*x + 1] = 255 - ColorSourceImage[tempAddress* 3 + 1];
        ptr[3*x + 2] = 255 - ColorSourceImage[tempAddress* 3 + 2];

        //ptr[3*x + 0] = (TempImage[tempAddress] * 17) & 0xFF;
        //ptr[3*x + 1] = (TempImage[tempAddress] * 41) & 0xFF;
        //ptr[3*x + 2] = (TempImage[tempAddress] * 73) & 0xFF;
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

  DebugData1->Picture->Bitmap->Assign(img);
  DebugData1->Refresh();
  helpLabel1->Caption = "Shape Binary Image";

  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] = min(255, GradientImage[tempAddress] * 10);
      ptr[3*x + 1] = min(255, GradientImage[tempAddress] * 10);
      ptr[3*x + 2] = min(255, GradientImage[tempAddress] * 10);
    }
  }

  DebugData2->Picture->Bitmap->Assign(img);
  DebugData2->Refresh();
  helpLabel2->Caption = "Gradient Image";

  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] = min(255, DarkPixelNeighborPrint[tempAddress] * 10);
      ptr[3*x + 1] = min(255, DarkPixelNeighborPrint[tempAddress] * 10);
      ptr[3*x + 2] = min(255, DarkPixelNeighborPrint[tempAddress] * 10);
    }
  }

  DebugData3->Picture->Bitmap->Assign(img);
  DebugData3->Refresh();
  helpLabel3->Caption = "Extract Print Area";

  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(PrintLabelArea[tempAddress] & 0xF0)
      {
        ptr[3*x + 0] = 255 / ((PrintLabelArea[tempAddress] & 0xF0) >> 4);
        ptr[3*x + 1] = 255 / ((PrintLabelArea[tempAddress] & 0xF0) >> 4);
        ptr[3*x + 2] = 255 / ((PrintLabelArea[tempAddress] & 0xF0) >> 4);
      }
      else
      */
      {
        ptr[3*x + 0] = min(255, DarkPixelNeighborPrint2[tempAddress]);
        ptr[3*x + 1] = min(255, DarkPixelNeighborPrint2[tempAddress]);
        ptr[3*x + 2] = min(255, DarkPixelNeighborPrint2[tempAddress]);

        //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(DentedArea[tempAddress])
      {
        ptr[3*x + 0] = ColorSourceImage[tempAddress* 3 + 0];
        ptr[3*x + 1] = ColorSourceImage[tempAddress* 3 + 1];
        ptr[3*x + 2] = ColorSourceImage[tempAddress* 3 + 2];
      }
    }
  }

  DebugData4->Picture->Bitmap->Assign(img);
  DebugData4->Refresh();
  helpLabel4->Caption = "Print Label";

  /*
  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(ShapeBinaryImage[tempAddress])
      {
        ptr[3*x + 0] = min(255, 3 * ColorSourceImage[tempAddress* 3 + 0] / ShapeBinaryImage[tempAddress]);
        ptr[3*x + 1] = min(255, 3 * ColorSourceImage[tempAddress* 3 + 1] / ShapeBinaryImage[tempAddress]);
        ptr[3*x + 2] = min(255, 3 * ColorSourceImage[tempAddress* 3 + 2] / ShapeBinaryImage[tempAddress]);
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }
  */

  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] = OneColorImage[tempAddress];
      ptr[3*x + 1] = OneColorImage[tempAddress];
      ptr[3*x + 2] = OneColorImage[tempAddress];
      
      if(AdjustThreeD_Data[tempAddress] & 0x01)
      {
        ptr[3*x + 0] = 255;
      }
      else if(AdjustThreeD_Data[tempAddress] & 0x02)
      {
        ptr[3*x + 0] = 0;
      }
      else if(AdjustThreeD_Data[tempAddress] & 0x04)
      {
        ptr[3*x + 1] = 255;
      }
      else if(AdjustThreeD_Data[tempAddress] & 0x08)
      {
        ptr[3*x + 1] = 0;
      }

      if(BrightPixelNeighborPrint[tempAddress] && AdjustThreeD_Data[tempAddress] == 0)
      {
        ptr[3*x + 2] = 255;
      }
    }
  }

  DebugData5->Picture->Bitmap->Assign(img);
  DebugData5->Refresh();
  helpLabel5->Caption = "Shape Binary Image2";

  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] = OneColorImage[tempAddress];
      ptr[3*x + 1] = OneColorImage[tempAddress];
      ptr[3*x + 2] = OneColorImage[tempAddress];

      if(BrightPixelNeighborPrint[tempAddress])
      {
        ptr[3*x + 0] = ColorSourceImage[tempAddress* 3 + 0] / 2;
        ptr[3*x + 1] = ColorSourceImage[tempAddress* 3 + 1] / 2;
        ptr[3*x + 2] = ColorSourceImage[tempAddress* 3 + 2] / 2;
      }
      else
      {
        ptr[3*x + 0] = ColorSourceImage[tempAddress* 3 + 0];
        ptr[3*x + 1] = ColorSourceImage[tempAddress* 3 + 1];
        ptr[3*x + 2] = ColorSourceImage[tempAddress* 3 + 2];
      }
    }
  }

  DebugData6->Picture->Bitmap->Assign(img);
  DebugData6->Refresh();
  helpLabel6->Caption = "PrintNeighbor_Bright area";

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

  DebugData7->Picture->Bitmap->Assign(img);
  DebugData7->Refresh();
  helpLabel7->Caption = "Shape Area For Print Extraction";

  maxValue = 0;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(ExtractedSplitLineImage[tempAddress])
      {
        if(maxValue < ExtractedSplitLineImage[tempAddress])
        {
          maxValue = ExtractedSplitLineImage[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(DentedArea[tempAddress])
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = ColorSourceImage[tempAddress * 3 + 1];
        ptr[3*x + 2] = 0;
      }
      else
      {
        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(ExtractedSplitLineImage[tempAddress] && maxValue)
      {
        ptr[3*x + 0] = ExtractedSplitLineImage[tempAddress] * 255 / maxValue;
        ptr[3*x + 1] = ExtractedSplitLineImage[tempAddress] * 255 / maxValue;
        ptr[3*x + 2] = ExtractedSplitLineImage[tempAddress] * 255 / maxValue;
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
      */
    }
  }

  DebugData8->Picture->Bitmap->Assign(img);
  DebugData8->Refresh();
  helpLabel8->Caption = "Extracted Print";

  delete img;

  printBColorLabel->Caption = "Print B = " + IntToStr(GlobalPrintColor[0]);
  printGColorLabel->Caption = "Print G = " + IntToStr(GlobalPrintColor[1]);
  printRColorLabel->Caption = "Print R = " + IntToStr(GlobalPrintColor[2]);
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::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;

      TColor depthColor = ThreeDDepth(Debug_RealThreeD_Image[tempAddress], 255);

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

  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(1)//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]);

  if(CheckBox2->Checked)
  {
    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);
  }

  ThreeDXZRotationAngleLabel->Caption = IntToStr(GlobalTabletRotationXZAngle / 2) + "도";
  ThreeDYZRotationAngleLabel->Caption = IntToStr(GlobalTabletRotationYZAngle / 2) + "도";

  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])
      {
		if (realPrintMaskingArea[tempAddress] == PRINT_AREA)
		{
			ptr[3*x + 0] = RotationThreeDImage[tempAddress];
			ptr[3*x + 1] = 255; // 녹색이나 흰색에 가까운 녹색으로 보임.
			ptr[3*x + 2] = RotationThreeDImage[tempAddress];
		}
		else if (realPrintMaskingArea[tempAddress] == EXPANDED_PRINT_AREA) // 가끔 인쇄 확장 영역이 뒤집힌 경우가 있는데 그것은 1차 학습을 안해줘서 그런 것이다.
		{
			ptr[3*x + 0] = RotationThreeDImage[tempAddress];
			ptr[3*x + 1] = 0; // 보라색.
			ptr[3*x + 2] = RotationThreeDImage[tempAddress];
		}
		else if (realPrintMaskingArea[tempAddress] == FRONT_MASKING_AREA)
		{
			ptr[3*x + 0] = RotationThreeDImage[tempAddress];
			ptr[3*x + 1] = RotationThreeDImage[tempAddress];
			ptr[3*x + 2] = 0; // 어두운 cyan 색.
		}
		else
		{
			ptr[3*x + 0] = RotationThreeDImage[tempAddress];
			ptr[3*x + 1] = RotationThreeDImage[tempAddress];
			ptr[3*x + 2] = 255;
		}
      }
    }
  }

  int zeroShiftX, zeroShiftY;
  zeroShiftX = AdjustTabletCenterX - MAX_IMAGE_WIDTH / 2;
  zeroShiftY = AdjustTabletCenterY - MAX_IMAGE_HEIGHT / 2;

  if((TabletCharacter.discriminationDisplay_num == ONE_FACE && PrintMatchingResult.dataNumberWithMaxValue == 0) || TabletCharacter.discriminationDisplay_num == TWO_FACE_SAME || TabletCharacter.discriminationDisplay_num == TWO_FACE_DIFF)
  {
    Label42->Caption = "ShiftX : " + IntToStr(PrintMatchingResult.PrintShiftX - zeroShiftX);
    Label43->Caption = "ShiftY : " + IntToStr(PrintMatchingResult.PrintShiftY - zeroShiftY);
  }
  else
  {
    Label42->Caption = "ShiftX : N/A";
    Label43->Caption = "ShiftY : N/A";
  }

  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();

  int maxEdgeDefectValue = 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(maxEdgeDefectValue < PlanariztionThreeDEdgeImage[tempAddress])
      {
        maxEdgeDefectValue = PlanariztionThreeDEdgeImage[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(maxEdgeDefectValue)
      {
        ptr[3*x + 0] = min(255, PlanariztionThreeDEdgeImage[tempAddress] * 255 / maxEdgeDefectValue);
        ptr[3*x + 1] = min(255, PlanariztionThreeDEdgeImage[tempAddress] * 255 / maxEdgeDefectValue);
        ptr[3*x + 2] = min(255, PlanariztionThreeDEdgeImage[tempAddress] * 255 / maxEdgeDefectValue);
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

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

  delete img;

  unsigned char realYSliceImage[MAX_IMAGE_HEIGHT * 256];
  unsigned char adjustYSliceImage[MAX_IMAGE_HEIGHT * 256];
  
  memset(realYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);
  memset(adjustYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);

  SliceResult1->Picture->Bitmap->Width = 256;
  SliceResult1->Picture->Bitmap->Height = MAX_IMAGE_HEIGHT;
  SliceResult1->Picture->Bitmap->PixelFormat = pf24bit;

  SliceResult2->Picture->Bitmap->Width = 256;
  SliceResult2->Picture->Bitmap->Height = MAX_IMAGE_HEIGHT;
  SliceResult2->Picture->Bitmap->PixelFormat = pf24bit;

  int value;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    value = AdjustThreeD_Data[MAX_IMAGE_WIDTH * y + AdjustTabletCenterX];

    if(value)
    {
      for(int tempY = y - 1; tempY <= y + 1; tempY++)
      {
        for(int tempX = value - 1; tempX <= value + 1; tempX++)
        {
          if(tempX > 0 && tempX < 256 && tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
          {
            realYSliceImage[256 * tempY + tempX] = 255;
          }
        }
      }
    }
  }

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    value = RotationThreeDImage[MAX_IMAGE_WIDTH * y + AdjustTabletCenterX];

    if(value)
    {
      for(int tempY = y - 1; tempY <= y + 1; tempY++)
      {
        for(int tempX = value - 1; tempX <= value + 1; tempX++)
        {
          if(tempX > 0 && tempX < 256 && tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
          {
            adjustYSliceImage[256 * tempY + tempX] = 255;
          }
        }
      }
    }
  }

  Graphics::TBitmap *img2 = new Graphics::TBitmap;
  img2->Width = 256;
  img2->Height = MAX_IMAGE_HEIGHT;
  img2->PixelFormat = pf24bit;

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    Byte *ptr = (Byte *)img2->ScanLine[y];

    for(x = 0; x < 256; x++)
    {
      ptr[3 * x + 0] = 0;
      ptr[3 * x + 1] = 0;
      ptr[3 * x + 2] = 0;

      tempAddress = 256 * y + x;

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

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

  SliceResult1->Picture->Bitmap->Assign(img2);
  SliceResult1->Refresh();
  
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    Byte *ptr = (Byte *)img2->ScanLine[y];

    for(x = 0; x < 256; x++)
    {
      ptr[3 * x + 0] = 0;
      ptr[3 * x + 1] = 0;
      ptr[3 * x + 2] = 0;

      tempAddress = 256 * y + x;

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

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

  memset(realYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);
  memset(adjustYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);

  SliceResult3->Picture->Bitmap->Width = 256;
  SliceResult3->Picture->Bitmap->Height = MAX_IMAGE_HEIGHT;
  SliceResult3->Picture->Bitmap->PixelFormat = pf24bit;

  SliceResult4->Picture->Bitmap->Width = 256;
  SliceResult4->Picture->Bitmap->Height = MAX_IMAGE_HEIGHT;
  SliceResult4->Picture->Bitmap->PixelFormat = pf24bit;

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    value = AdjustThreeD_Data[MAX_IMAGE_WIDTH * y + AdjustTabletCenterX];

    if(value)
    {
      for(int tempY = y - 1; tempY <= y + 1; tempY++)
      {
        for(int tempX = value - 1; tempX <= value + 1; tempX++)
        {
          if(tempX > 0 && tempX < 256 && tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
          {
            realYSliceImage[256 * tempY + tempX] = 255;
          }
        }
      }
    }
  }

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    value = Debug_BeforeRotationResult[MAX_IMAGE_WIDTH * y + AdjustTabletCenterX];

    if(value)
    {
      for(int tempY = y - 1; tempY <= y + 1; tempY++)
      {
        for(int tempX = value - 1; tempX <= value + 1; tempX++)
        {
          if(tempX > 0 && tempX < 256 && tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
          {
            adjustYSliceImage[256 * tempY + tempX] = 255;
          }
        }
      }
    }
  }

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    Byte *ptr = (Byte *)img2->ScanLine[y];

    for(x = 0; x < 256; x++)
    {
      ptr[3 * x + 0] = 0;
      ptr[3 * x + 1] = 0;
      ptr[3 * x + 2] = 0;

      tempAddress = 256 * y + x;

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

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

  SliceResult3->Picture->Bitmap->Assign(img2);
  SliceResult3->Refresh();
  
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    Byte *ptr = (Byte *)img2->ScanLine[y];

    for(x = 0; x < 256; x++)
    {
      ptr[3 * x + 0] = 0;
      ptr[3 * x + 1] = 0;
      ptr[3 * x + 2] = 0;

      tempAddress = 256 * y + x;

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

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

  delete img2;
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::TrackBar1Change(TObject *Sender)
{
  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;

      if(GradientImage[tempAddress] > TrackBar1->Position)
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 255;
        ptr[3*x + 2] = 0;
      }
      else
      {
        ptr[3*x + 0] = 25;
        ptr[3*x + 1] = 25;
        ptr[3*x + 2] = 0;
      }
    }
  }

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

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


void __fastcall TTabletSimulationForm::tSideFaceSetUpDataTransForm()
{
  /*
  int m, x, y;
	unsigned short sizeTransform[2000][2];

	unsigned short firstTransformForFace1[2000][3];
	unsigned short firstTransformForFace2[2000][3];

	unsigned short SecondTransformForFace1[2000][3];
	unsigned short SecondTransformForFace2[2000][3];

	unsigned short transfarentEdgeDataPoint[2000][3];
	unsigned short transfarentEdgeDataPoint2[2000][3];
	unsigned char unVisibleEdgeLineCheck[2000];
	unsigned char weightCheck[2000];
	int tAngleX;
	int tAngleY;
  int tAngleZ;
	int tempX, tempY;
	int tabletCenterX, tabletCenterY, tabletCenterZ;
	int startX1, startY1, endX1, endY1;
	int startX2, startY2, endX2, endY2;
	int start_Number, end_Number;
	int face1Height, face2Height;
	int weightValue;
	unsigned short tempRotationCheckPosition[2000][2];
	int sysCameraIndex;
	int diffColor[3];
	int shiftMinX, shiftMaxX;
	int dataLength;
	int edgeMinX, edgeMaxX, edgeMinY;
	int tShiftX;
	int sX;
	int shiftLimit;
	int tempIndex;
  int cameraIndex;
  int shapeEndY;

  unsigned short testpoint1[2000][3];
  unsigned short testpoint2[2000][3];


	// For SELMA200, Rev by moon. (20180209) Camera Index
	const int HALF_CAMERA_INDEX = 9;
	const int MODULE1_2D_CAM_INDEX = 1;
	const int MODULE1_3D_CAM_INDEX = 5;
	const int MODULE2_2D_CAM_INDEX = 9;
	const int MODULE2_3D_CAM_INDEX = 13;

	int FrontFaceCameraResolution;
	int SideFaceCameraResolution;
  int adjustMiddleHeight;
  int adjustTabletHeight; 

	weightValue = 4;
	if (TabletSetupData.protoStudyColorR != 0
		&& TabletSetupData.protoStudyColorG != 0
		&& TabletSetupData.protoStudyColorB != 0)
	{
		if (TabletSetupData.protoStudyColorR > TabletSetupData.protoStudyColorG * 8 / 10)
			weightValue = 2;
	}

	if (TabletCharacter.middle_height != 0)
	{
    cameraIndex = 4;

    FrontFaceCameraResolution = TabletSetupData.cameraZoom[0];
    SideFaceCameraResolution = TabletSetupData.cameraZoom[cameraIndex - 1];

    for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
    {
      sizeTransform[m][0] = (TabletSetupData.FrontShapeEdgePoint[m][0] - MAX_IMAGE_WIDTH / 2) * FrontFaceCameraResolution / SideFaceCameraResolution + MAX_IMAGE_WIDTH / 2;
      sizeTransform[m][1] = (TabletSetupData.FrontShapeEdgePoint[m][1] - MAX_IMAGE_HEIGHT / 2) * FrontFaceCameraResolution / SideFaceCameraResolution + MAX_IMAGE_HEIGHT / 2;
    }

    adjustMiddleHeight = TabletCharacter.middle_height * FrontFaceCameraResolution / SideFaceCameraResolution;
    adjustTabletHeight = TabletCharacter.height * FrontFaceCameraResolution / SideFaceCameraResolution;

    tAngleZ = UpDown7->Position;
    tAngleX = MAX_ANGLE1_RANGE * 2 + UpDown8->Position;
    tAngleY = UpDown9->Position;

    memset(RotationEdgeImage, 0, MAX_IMAGE_WIDTH*MAX_IMAGE_WIDTH * 2);
    memset(unVisibleEdgeLineCheck, 0, 2000);

    memset(testpoint1, 0, sizeof(unsigned short) * 2000 * 3);
    memset(testpoint2, 0, sizeof(unsigned short) * 2000 * 3);

    tabletCenterX = 320;
    tabletCenterY = 240;
    tabletCenterZ = TabletSetupData.DiskBaseHeightPosition[cameraIndex - 1];

    face1Height = tabletCenterZ - adjustMiddleHeight - (adjustTabletHeight - adjustMiddleHeight) / 2;
    face2Height = tabletCenterZ - (adjustTabletHeight - adjustMiddleHeight) / 2;

    for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
    {
      firstTransformForFace1[m][0] = sizeTransform[m][0];
      if (tAngleX < 0)
      {
        firstTransformForFace1[m][1] = ((sizeTransform[m][1] - tabletCenterY)*CosData[-tAngleX] + (face1Height - tabletCenterZ)*SinData[-tAngleX]) / 1024 + tabletCenterY;
        firstTransformForFace1[m][2] = (-(sizeTransform[m][1] - tabletCenterY)*SinData[-tAngleX] + (face1Height - tabletCenterZ)*CosData[-tAngleX]) / 1024 + tabletCenterZ;
      }
      else
      {
        firstTransformForFace1[m][1] = ((sizeTransform[m][1] - tabletCenterY)*CosData[tAngleX] - (face1Height - tabletCenterZ)*SinData[tAngleX]) / 1024 + tabletCenterY;
        firstTransformForFace1[m][2] = ((sizeTransform[m][1] - tabletCenterY)*SinData[tAngleX] + (face1Height - tabletCenterZ)*CosData[tAngleX]) / 1024 + tabletCenterZ;
      }
    }

    for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
    {
      firstTransformForFace2[m][0] = sizeTransform[m][0];
      if (tAngleX < 0)
      {
        firstTransformForFace2[m][1] = ((sizeTransform[m][1] - tabletCenterY)*CosData[-tAngleX] + (face2Height - tabletCenterZ)*SinData[-tAngleX]) / 1024 + tabletCenterY;
        firstTransformForFace2[m][2] = (-(sizeTransform[m][1] - tabletCenterY)*SinData[-tAngleX] + (face2Height - tabletCenterZ)*CosData[-tAngleX]) / 1024 + tabletCenterZ;
      }
      else
      {
        firstTransformForFace2[m][1] = ((sizeTransform[m][1] - tabletCenterY)*CosData[tAngleX] - (face2Height - tabletCenterZ)*SinData[tAngleX]) / 1024 + tabletCenterY;
        firstTransformForFace2[m][2] = ((sizeTransform[m][1] - tabletCenterY)*SinData[tAngleX] + (face2Height - tabletCenterZ)*CosData[tAngleX]) / 1024 + tabletCenterZ;
      }
    }
    //y축 회전////
    for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
    {
      SecondTransformForFace1[m][1] = firstTransformForFace1[m][1];
      if (tAngleY < 0)
      {
        SecondTransformForFace1[m][0] = ((firstTransformForFace1[m][0] - tabletCenterX)*CosData[-tAngleY] + (firstTransformForFace1[m][2] - tabletCenterZ)*SinData[-tAngleY]) / 1024 + tabletCenterX;
        SecondTransformForFace1[m][2] = (-(firstTransformForFace1[m][0] - tabletCenterX)*SinData[-tAngleY] + (firstTransformForFace1[m][2] - tabletCenterZ)*CosData[-tAngleY]) / 1024 + tabletCenterZ;
      }
      else
      {
        SecondTransformForFace1[m][0] = ((firstTransformForFace1[m][0] - tabletCenterX)*CosData[tAngleY] - (firstTransformForFace1[m][2] - tabletCenterZ)*SinData[tAngleY]) / 1024 + tabletCenterX;
        SecondTransformForFace1[m][2] = ((firstTransformForFace1[m][0] - tabletCenterX)*SinData[tAngleY] + (firstTransformForFace1[m][2] - tabletCenterZ)*CosData[tAngleY]) / 1024 + tabletCenterZ;
      }
    }

    for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
    {
      SecondTransformForFace2[m][1] = firstTransformForFace2[m][1];
      if (tAngleY < 0)
      {
        SecondTransformForFace2[m][0] = ((firstTransformForFace2[m][0] - tabletCenterX)*CosData[-tAngleY] + (firstTransformForFace2[m][2] - tabletCenterZ)*SinData[-tAngleY]) / 1024 + tabletCenterX;
        SecondTransformForFace2[m][2] = (-(firstTransformForFace2[m][0] - tabletCenterX)*SinData[-tAngleY] + (firstTransformForFace2[m][2] - tabletCenterZ)*CosData[-tAngleY]) / 1024 + tabletCenterZ;
      }
      else
      {
        SecondTransformForFace2[m][0] = ((firstTransformForFace2[m][0] - tabletCenterX)*CosData[tAngleY] - (firstTransformForFace2[m][2] - tabletCenterZ)*SinData[tAngleY]) / 1024 + tabletCenterX;
        SecondTransformForFace2[m][2] = ((firstTransformForFace2[m][0] - tabletCenterX)*SinData[tAngleY] + (firstTransformForFace2[m][2] - tabletCenterZ)*CosData[tAngleY]) / 1024 + tabletCenterZ;
      }
    }

    // For SELMA200, Rev by moon. (20180209) Camera Index
    if (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)
    {
      for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
      {
          if (tAngleZ < 0)
          {
            transfarentEdgeDataPoint[m][0] = ((SecondTransformForFace1[m][0] - tabletCenterX)*CosData[-tAngleZ * 2] - (SecondTransformForFace1[m][1] - tabletCenterY)*SinData[-tAngleZ * 2]) / 1024 + tabletCenterX;
            transfarentEdgeDataPoint[m][1] = ((SecondTransformForFace1[m][0] - tabletCenterX)*SinData[-tAngleZ * 2] + (SecondTransformForFace1[m][1] - tabletCenterY)*CosData[-tAngleZ * 2]) / 1024 + tabletCenterY;
            transfarentEdgeDataPoint[m][2] = SecondTransformForFace1[m][2];
          }
          else
          {
            transfarentEdgeDataPoint[m][0] = ((SecondTransformForFace1[m][0] - tabletCenterX)*CosData[tAngleZ * 2] + (SecondTransformForFace1[m][1] - tabletCenterY)*SinData[tAngleZ * 2]) / 1024 + tabletCenterX;
            transfarentEdgeDataPoint[m][1] = (-(SecondTransformForFace1[m][0] - tabletCenterX)*SinData[tAngleZ * 2] + (SecondTransformForFace1[m][1] - tabletCenterY)*CosData[tAngleZ * 2]) / 1024 + tabletCenterY;
            transfarentEdgeDataPoint[m][2] = SecondTransformForFace1[m][2];
          }
      }
      for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
      {
          if (tAngleZ < 0)
          {
            transfarentEdgeDataPoint2[m][0] = ((SecondTransformForFace2[m][0] - tabletCenterX)*CosData[-tAngleZ * 2] - (SecondTransformForFace2[m][1] - tabletCenterY)*SinData[-tAngleZ * 2]) / 1024 + tabletCenterX;
            transfarentEdgeDataPoint2[m][1] = ((SecondTransformForFace2[m][0] - tabletCenterX)*SinData[-tAngleZ * 2] + (SecondTransformForFace2[m][1] - tabletCenterY)*CosData[-tAngleZ * 2]) / 1024 + tabletCenterY;
            transfarentEdgeDataPoint2[m][2] = SecondTransformForFace2[m][2];
          }
          else
          {
            transfarentEdgeDataPoint2[m][0] = ((SecondTransformForFace2[m][0] - tabletCenterX)*CosData[tAngleZ * 2] + (SecondTransformForFace2[m][1] - tabletCenterY)*SinData[tAngleZ * 2]) / 1024 + tabletCenterX;
            transfarentEdgeDataPoint2[m][1] = (-(SecondTransformForFace2[m][0] - tabletCenterX)*SinData[tAngleZ * 2] + (SecondTransformForFace2[m][1] - tabletCenterY)*CosData[tAngleZ * 2]) / 1024 + tabletCenterY;
            transfarentEdgeDataPoint2[m][2] = SecondTransformForFace2[m][2];
          }
      }
    }
    else if (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)
    {
      for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
      {
        transfarentEdgeDataPoint[m][0] = ((SecondTransformForFace1[m][0] - tabletCenterX)*CosData[0] + (SecondTransformForFace1[m][1] - tabletCenterY)*SinData[0]) / 1024 + tabletCenterX;
        transfarentEdgeDataPoint[m][1] = (-(SecondTransformForFace1[m][0] - tabletCenterX)*SinData[0] + (SecondTransformForFace1[m][1] - tabletCenterY)*CosData[0]) / 1024 + tabletCenterY;
        transfarentEdgeDataPoint[m][2] = SecondTransformForFace1[m][2];
      }
      for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
      {
        transfarentEdgeDataPoint2[m][0] = ((SecondTransformForFace2[m][0] - tabletCenterX)*CosData[0] + (SecondTransformForFace2[m][1] - tabletCenterY)*SinData[0]) / 1024 + tabletCenterX;
        transfarentEdgeDataPoint2[m][1] = (-(SecondTransformForFace2[m][0] - tabletCenterX)*SinData[0] + (SecondTransformForFace2[m][1] - tabletCenterY)*CosData[0]) / 1024 + tabletCenterY;
        transfarentEdgeDataPoint2[m][2] = SecondTransformForFace2[m][2];
      }
    }
    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)
    {
      for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
      {
          if (tAngleZ < 0)
          {
            transfarentEdgeDataPoint[m][0] = ((SecondTransformForFace1[m][0] - tabletCenterX)*CosData[-tAngleZ * 2] + (SecondTransformForFace1[m][1] - tabletCenterY)*SinData[-tAngleZ * 2]) / 1024 + tabletCenterX;
            transfarentEdgeDataPoint[m][1] = (-(SecondTransformForFace1[m][0] - tabletCenterX)*SinData[-tAngleZ * 2] + (SecondTransformForFace1[m][1] - tabletCenterY)*CosData[-tAngleZ * 2]) / 1024 + tabletCenterY;
            transfarentEdgeDataPoint[m][2] = SecondTransformForFace1[m][2];
          }
          else
          {
            transfarentEdgeDataPoint[m][0] = ((SecondTransformForFace1[m][0] - tabletCenterX)*CosData[tAngleZ * 2] - (SecondTransformForFace1[m][1] - tabletCenterY)*SinData[tAngleZ * 2]) / 1024 + tabletCenterX;
            transfarentEdgeDataPoint[m][1] = ((SecondTransformForFace1[m][0] - tabletCenterX)*SinData[tAngleZ * 2] + (SecondTransformForFace1[m][1] - tabletCenterY)*CosData[tAngleZ * 2]) / 1024 + tabletCenterY;
            transfarentEdgeDataPoint[m][2] = SecondTransformForFace1[m][2];
          }
      }
      for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
      {
          if (tAngleZ < 0)
          {
            transfarentEdgeDataPoint2[m][0] = ((SecondTransformForFace2[m][0] - tabletCenterX)*CosData[-tAngleZ * 2] + (SecondTransformForFace2[m][1] - tabletCenterY)*SinData[-tAngleZ * 2]) / 1024 + tabletCenterX;
            transfarentEdgeDataPoint2[m][1] = (-(SecondTransformForFace2[m][0] - tabletCenterX)*SinData[-tAngleZ * 2] + (SecondTransformForFace2[m][1] - tabletCenterY)*CosData[-tAngleZ * 2]) / 1024 + tabletCenterY;
            transfarentEdgeDataPoint2[m][2] = SecondTransformForFace2[m][2];
          }
          else
          {
            transfarentEdgeDataPoint2[m][0] = ((SecondTransformForFace2[m][0] - tabletCenterX)*CosData[tAngleZ * 2] - (SecondTransformForFace2[m][1] - tabletCenterY)*SinData[tAngleZ * 2]) / 1024 + tabletCenterX;
            transfarentEdgeDataPoint2[m][1] = ((SecondTransformForFace2[m][0] - tabletCenterX)*SinData[tAngleZ * 2] + (SecondTransformForFace2[m][1] - tabletCenterY)*CosData[tAngleZ * 2]) / 1024 + tabletCenterY;
            transfarentEdgeDataPoint2[m][2] = SecondTransformForFace2[m][2];
          }
      }
    }

    //45도 상에서 실제로 보이는 에지 라인만 추출////////////
    startX1 = 1000;
    endX1 = -1;
    for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
    {
      tempX = transfarentEdgeDataPoint[m][0];
      tempY = transfarentEdgeDataPoint[m][1];

      if (startX1 > tempX)
      {
        start_Number = m;
        startX1 = tempX;
        startY1 = tempY;
      }
      else if (startX1 == tempX)
      {
        if (startY1 > tempY)
        {
          start_Number = m;
          startX1 = tempX;
          startY1 = tempY;
        }
      }
      if (endX1 <= tempX)
      {
        end_Number = m;
        endX1 = tempX;
        endY1 = tempY;
      }
      else if (endX1 == tempX)
      {
        if (endY1 > tempY)
        {
          start_Number = m;
          endX1 = tempX;
          endY1 = tempY;
        }
      }

      if(tempX > 0 && tempX < MAX_IMAGE_WIDTH && tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
      {
        RotationEdgeImage[tempY*MAX_IMAGE_WIDTH + tempX] = m;
      }
    }

    for (x = 1; x < MAX_IMAGE_WIDTH - 1; x++)
    {
      for (y = MAX_IMAGE_WIDTH - 1; y >= 1; y--)
      {
        if (RotationEdgeImage[y * 640 + x])
        {
          unVisibleEdgeLineCheck[RotationEdgeImage[y*MAX_IMAGE_WIDTH + x]] = 1;
          break;
        }
        if (RotationEdgeImage[y * 640 + x - 1])
        {
          unVisibleEdgeLineCheck[RotationEdgeImage[y*MAX_IMAGE_WIDTH + x - 1]] = 1;
          break;
        }
        if (RotationEdgeImage[y * 640 + x + 1])
        {
          unVisibleEdgeLineCheck[RotationEdgeImage[y*MAX_IMAGE_WIDTH + x + 1]] = 1;
          break;
        }
      }
    }

    for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
    {
      if(!unVisibleEdgeLineCheck[m])
      {
        testpoint1[m][0] = transfarentEdgeDataPoint[m][0];
        testpoint1[m][1] = transfarentEdgeDataPoint[m][1];
        testpoint1[m][2] = transfarentEdgeDataPoint[m][2];
      }
    }
    for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
    {
      if(!unVisibleEdgeLineCheck[m])
      {
        testpoint2[m][0] = transfarentEdgeDataPoint2[m][0];
        testpoint2[m][1] = transfarentEdgeDataPoint2[m][1];
        testpoint2[m][2] = transfarentEdgeDataPoint2[m][2];
      }
    }
  }

  Graphics::TBitmap *img1;
  img1 = new Graphics::TBitmap();
  img1->Width =  MAX_IMAGE_WIDTH;
  img1->Height =  MAX_IMAGE_HEIGHT;
  img1->PixelFormat = pf24bit;
  int i, j;
  Byte *ptr;
  int tempAddress;
  int tempAddress1;
  int tempX2, tempY2;
  int ShiftX, ShiftY;

  ShiftX = UpDown10->Position;
  ShiftY = UpDown11->Position;

  for(i = 1; i < MAX_IMAGE_HEIGHT - 1; i++)
  {
    ptr = (byte*) img1->ScanLine[i];
    for(j = 1; j < MAX_IMAGE_WIDTH - 1; j++)
    {
      tempAddress1 = MAX_IMAGE_WIDTH * (i) + (j);

      ptr[3*j+0] = ColorSourceImage[tempAddress1 *3 + 0];
      ptr[3*j+1] = GradientImage[tempAddress1] * 4;
      ptr[3*j+2] = ColorSourceImage[tempAddress1 *3 + 2];
    }
  }

  memset(OutlineData, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
  {
    tempX2 = transfarentEdgeDataPoint[m][0];
    tempY2 = transfarentEdgeDataPoint[m][1];

    if(tempX2 + ShiftX > 0 && tempX2 + ShiftX < 640 &&
        tempY2 + ShiftY > 0 && tempY2 + ShiftY < 480)
    {
      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;
    }
  }

  for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
  {
    tempX2 = transfarentEdgeDataPoint2[m][0];
    tempY2 = transfarentEdgeDataPoint2[m][1];

    if(tempX2 + ShiftX > 0 && tempX2 + ShiftX < 640 &&
        tempY2 + ShiftY > 0 && tempY2 + ShiftY < 480)
    {
      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 255;
      ptr[3*(tempX2 + ShiftX) + 2] = 0;
    }
  }

  for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
  {
    if (!unVisibleEdgeLineCheck[m])
    {
      tempX2 = testpoint1[m][0];
      tempY2 = testpoint1[m][1];

      if(tempX2 + ShiftX > 0 && tempX2 + ShiftX < 640 &&
        tempY2 + ShiftY > 0 && tempY2 + ShiftY < 480)
      {
        ptr = (byte*) img1->ScanLine[tempY2 + ShiftY];
        ptr[3*(tempX2 + ShiftX) + 0] = 255;
        ptr[3*(tempX2 + ShiftX) + 1] = 0;
        ptr[3*(tempX2 + ShiftX) + 2] = 0;
      }

      tempX2 = testpoint2[m][0];
      tempY2 = testpoint2[m][1];
    
      if(tempX2 + ShiftX > 0 && tempX2 + ShiftX < 640 &&
        tempY2 + ShiftY > 0 && tempY2 + ShiftY < 480)
      {
        ptr = (byte*) img1->ScanLine[tempY2 + ShiftY];
        ptr[3*(tempX2 + ShiftX) + 0] = 255;
        ptr[3*(tempX2 + ShiftX) + 1] = 0;
        ptr[3*(tempX2 + ShiftX) + 2] = 0;
      }
    }
  }

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

  delete img1;
  */
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::MakeRotationTabletShapeData()
{
  
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::UpDown8Click(TObject *Sender,
      TUDBtnType Button)
{
  int tAngleZ;
  int tAngleY;
  int tAngleX;
  int tempX2, tempY2;
  int cameraIndex;
  int m;
  int ShiftX, ShiftY;
  int tempIndex;
  const int HALF_CAMERA_INDEX = 9;
  const int MODULE1_2D_CAM_INDEX = 1;
	const int MODULE1_3D_CAM_INDEX = 5;
	const int MODULE2_2D_CAM_INDEX = 9;
	const int MODULE2_3D_CAM_INDEX = 13;

  int SideAngle;

  cameraIndex = SelectedCameraIndex;

  if (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)
  {
    SideAngle = MINUS_45_ANGLE_CAM;
  }
  else if (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)
  {
    SideAngle = ZERO_ANGLE_CAM;
  }
  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)
  {
    SideAngle = PLUS_45_ANGLE_CAM;
  }
  
  if(UpDown7->Position < 0) UpDown7->Position = 0;
  if(UpDown7->Position > MAX_ANGLE1_RANGE * 2) UpDown7->Position = MAX_ANGLE1_RANGE * 2;

  if(UpDown8->Position < 0) UpDown8->Position = 0;
  if(UpDown8->Position > MAX_ANGLE2_RANGE * 2) UpDown8->Position = MAX_ANGLE2_RANGE * 2;

  tAngleX = UpDown7->Position;
	tAngleY = UpDown8->Position;
  tAngleZ = UpDown9->Position;
  ShiftX = 0;
  ShiftY = 0;

  Edit1->Text = IntToStr(UpDown7->Position);
  Edit2->Text = IntToStr(UpDown8->Position);
  Edit3->Text = IntToStr(UpDown9->Position);
  Edit4->Text = IntToStr(TabletMatchingResult.AdjustResolution);

  Graphics::TBitmap *img1;
  img1 = new Graphics::TBitmap();
  img1->Width =  MAX_IMAGE_WIDTH;
  img1->Height =  MAX_IMAGE_HEIGHT;
  img1->PixelFormat = pf24bit;
  int i, j;
  Byte *ptr;
  int tempAddress;
  int tempAddress1;

  for(i = 1; i < MAX_IMAGE_HEIGHT - 1; i++)
  {
    ptr = (byte*) img1->ScanLine[i];
    for(j = 1; j < MAX_IMAGE_WIDTH - 1; j++)
    {
      tempAddress1 = MAX_IMAGE_WIDTH * (i) + (j);

      ptr[3*j+0] = ColorSourceImage[tempAddress1 *3 + 0];
      ptr[3*j+1] = ColorSourceImage[tempAddress1 *3 + 1];
      ptr[3*j+2] = ColorSourceImage[tempAddress1 *3 + 2];
    }
  }

  ShiftX = UpDown4->Position;
  ShiftY = UpDown5->Position;

  for(m = 0; m < SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointCountLeft; m++)
  {
    tempX2 = SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointLeft[m*2];
    tempY2 = SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointLeft[m*2+1];

    if(tempX2 + ShiftX > 0 && tempX2 + ShiftX < 640 &&
        tempY2 + ShiftY > 0 && tempY2 + ShiftY < 480)
    {
      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;

      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY - 1];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;

      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY + 1];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;
    }
  }

  for(m = 0; m < SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointCountRight; m++)
  {
    tempX2 = SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointRight[m*2];
    tempY2 = SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointRight[m*2+1];

    if(tempX2 + ShiftX > 0 && tempX2 + ShiftX < 640 &&
        tempY2 + ShiftY > 0 && tempY2 + ShiftY < 480)
    {
      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;

      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY - 1];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;

      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY + 1];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;
    }
  }

  /*
  for(m = 0; m < SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointCountTop; m++)
  {
    tempX2 = SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointTop[m*2];
    tempY2 = SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointTop[m*2+1];

    if(tempX2 + ShiftX > 0 && tempX2 + ShiftX < 640 &&
        tempY2 + ShiftY > 0 && tempY2 + ShiftY < 480)
    {
      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY];
      ptr[3*(tempX2 + ShiftX) + 0] = 255;
      ptr[3*(tempX2 + ShiftX) + 1] = 255;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;
    }
  }
  */

  for(m = 0; m < SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointCountBottom; m++)
  {
    tempX2 = SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointBottom[m*2];
    tempY2 = SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointBottom[m*2+1];

    if(tempX2 + ShiftX > 0 && tempX2 + ShiftX < 640 &&
        tempY2 + ShiftY > 0 && tempY2 + ShiftY < 480)
    {
      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;

      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY - 1];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;

      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY + 1];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;
    }
  }

  /*
  ShiftX += TabletMatchingResult.TabletSideShapeTopLineShiftX;
  ShiftY += TabletMatchingResult.TabletSideShapeTopLineShiftY;

  for(m = 0; m < SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointCountBottom; m++)
  {
    tempX2 = SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointBottom[m*2];
    tempY2 = SideData[SideAngle].SideShapeData[tAngleY][tAngleX].SideShapeEdgePointBottom[m*2+1];

    if(tempX2 + ShiftX > 0 && tempX2 + ShiftX < 640 &&
        tempY2 + ShiftY > 0 && tempY2 + ShiftY < 480)
    {
      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;

      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY - 1];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;

      ptr = (byte*) img1->ScanLine[tempY2 + ShiftY + 1];
      ptr[3*(tempX2 + ShiftX) + 0] = 0;
      ptr[3*(tempX2 + ShiftX) + 1] = 0;
      ptr[3*(tempX2 + ShiftX) + 2] = 255;

      ptr[3*(tempX2 + ShiftX - 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX - 1) + 2] = 255;

      ptr[3*(tempX2 + ShiftX + 1) + 0] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 1] = 0;
      ptr[3*(tempX2 + ShiftX + 1) + 2] = 255;
    }
  }
  */


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

  delete img1;
}
//---------------------------------------------------------------------------


void __fastcall TTabletSimulationForm::ImageRotation(int cameraIndex)
{
  return;
  
  int x, y;
  int tempAddress;
  int CenterX, CenterY;
  int maxGradientPosition[MAX_IMAGE_WIDTH];
  int maxValue;

  memset(maxGradientPosition, 0, sizeof(int) * MAX_IMAGE_WIDTH);

  CenterX = ProtoTabletCenterX;
  CenterY = ProtoTabletCenterY;

  for(x = 0; x < MAX_IMAGE_WIDTH; x++)
  {
    maxValue = 0;
    for(y = CenterY; y < MAX_IMAGE_HEIGHT; y++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;
      if(GradientImage[tempAddress] && ShapeBinaryImage[tempAddress])
      {
        if(maxValue < GradientImage[tempAddress])
        {
          maxGradientPosition[x] = y;
          maxValue = GradientImage[tempAddress];
        }
      }
    }
  }

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

  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;

      if(ShapeBinaryImage[tempAddress])
      {
        ptr[3*x + 0] = ColorSourceImage[tempAddress * 3 + 0];
        ptr[3*x + 1] = ColorSourceImage[tempAddress * 3 + 1];
        ptr[3*x + 2] = ColorSourceImage[tempAddress * 3 + 2];
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

  memset(bottomLine, 0, sizeof(short) * 2000 * 2);
  bottomLineCount = 0;
  for(x = 0; x < MAX_IMAGE_WIDTH; x++)
  {
    y = maxGradientPosition[x];

    if(x > 2 && x < MAX_IMAGE_WIDTH - 2 && y > 2 && y < MAX_IMAGE_HEIGHT - 2)
    {
      if(bottomLineCount < 2000)
      {
        bottomLine[bottomLineCount][0] = x;
        bottomLine[bottomLineCount][1] = y;
        bottomLineCount++;
      }

      for(int j = y - 2; j <= y + 2; j++)
      {
        ptr = (Byte*)img1->ScanLine[j];
        for(int i = x - 2; i <= x + 2; i++)
        {
          ptr[3*i + 0] = 0;
          ptr[3*i + 1] = 255;
          ptr[3*i + 2] = 0;
        }
      }
    }
  }

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


  delete img1;


  /*
  // make side wall
  int sideWallLength = (TabletCharacter.middle_height * TabletSetupData.cameraZoom[0] / TabletSetupData.cameraZoom[cameraIndex - 1]) * 2;
  unsigned short SideWallData[150 * 2];
  unsigned short RotateSideWallData[150 * 2];
  int SideWallDataCount;
  memset(SideWallData, 0, sizeof(unsigned short) * 150 * 2);
  SideWallDataCount = 0;

  int x, y;
  int tempX, tempY;

  for(y = MAX_IMAGE_HEIGHT / 2 - sideWallLength / 2; y <= MAX_IMAGE_HEIGHT / 2 + sideWallLength / 2; y++)
  {
    if(SideWallDataCount < 150)
    {
      SideWallData[SideWallDataCount * 2 + 0] = MAX_IMAGE_WIDTH / 2;
      SideWallData[SideWallDataCount * 2 + 1] = y;
      SideWallDataCount++;
    }
  }

  int SideWallCenterX = MAX_IMAGE_WIDTH / 2;
  int SideWallCenterY = MAX_IMAGE_HEIGHT / 2;

  int shiftX;
  int shiftY;

  int gradSum;
  int maxValue;

  maxValue = -1;

  int matchingAngle;
  int matchingShiftX;
  int matchingShiftY;

  int tempAddress;
  
  for(int angle = -90; angle <= 90; angle++)
  {
    for(int m = 0; m < SideWallDataCount; m++)
    {
      if(angle < 0)
      {
        tempX = ((SideWallData[m * 2 + 0] - SideWallCenterX)*CosData[-angle] + (SideWallData[m * 2 + 1] - SideWallCenterY)*SinData[-angle]) / 1024 + SideWallCenterX;
        tempY = (-(SideWallData[m * 2 + 0] - SideWallCenterX)*SinData[-angle] + (SideWallData[m * 2 + 1] - SideWallCenterY)*CosData[-angle]) / 1024 + SideWallCenterY;
      }
      else
      {
        tempX = ((SideWallData[m * 2 + 0] - SideWallCenterX)*CosData[angle] - (SideWallData[m * 2 + 1] - SideWallCenterY)*SinData[angle]) / 1024 + SideWallCenterX;
        tempY = ((SideWallData[m * 2 + 0] - SideWallCenterX)*SinData[angle] + (SideWallData[m * 2 + 1] - SideWallCenterY)*CosData[angle]) / 1024 + SideWallCenterY;
      }

      RotateSideWallData[m * 2 + 0] = tempX;
      RotateSideWallData[m * 2 + 1] = tempY;
    }

    shiftX = TabletMatchingResult.SearchStartXForSideShape - SideWallCenterX;
    shiftY = ProtoTabletCenterY - SideWallCenterY;

    for(int i = shiftX - 10; i <= shiftX + 10; i++)
    {
      for(int j = shiftY - 20; j <= shiftY + 20; j++)
      {
        gradSum = 0;
        for(int m = 0; m < SideWallDataCount; m++)
        {
          tempX = RotateSideWallData[m * 2 + 0] + i;
          tempY = RotateSideWallData[m * 2 + 1] + j;

          if(tempX > 0 && tempX < MAX_IMAGE_WIDTH && tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
          {
            tempAddress = MAX_IMAGE_WIDTH * tempY + tempX;

            gradSum += GradientImage[tempAddress];
          }
        }

        if(maxValue < gradSum)
        {
          maxValue = gradSum;

          matchingAngle = angle;
          matchingShiftX = i;
          matchingShiftY = j;
        }
      }
    }
  }


  int startPoint[2];
  int endPoint[2];

  int minY, maxY;
  minY = MAX_IMAGE_HEIGHT;
  maxY = 0; 
  for(int m = 0; m < SideWallDataCount; m++)
  {
    if(matchingAngle < 0)
    {
      tempX = ((SideWallData[m * 2 + 0] - SideWallCenterX)*CosData[-matchingAngle] + (SideWallData[m * 2 + 1] - SideWallCenterY)*SinData[-matchingAngle]) / 1024 + SideWallCenterX;
      tempY = (-(SideWallData[m * 2 + 0] - SideWallCenterX)*SinData[-matchingAngle] + (SideWallData[m * 2 + 1] - SideWallCenterY)*CosData[-matchingAngle]) / 1024 + SideWallCenterY;
    }
    else
    {
      tempX = ((SideWallData[m * 2 + 0] - SideWallCenterX)*CosData[matchingAngle] - (SideWallData[m * 2 + 1] - SideWallCenterY)*SinData[matchingAngle]) / 1024 + SideWallCenterX;
      tempY = ((SideWallData[m * 2 + 0] - SideWallCenterX)*SinData[matchingAngle] + (SideWallData[m * 2 + 1] - SideWallCenterY)*CosData[matchingAngle]) / 1024 + SideWallCenterY;
    }

    RotateSideWallData[m * 2 + 0] = tempX + matchingShiftX;
    RotateSideWallData[m * 2 + 1] = tempY + matchingShiftY;

    if(ShapeBinaryImage[RotateSideWallData[m * 2 + 1] * MAX_IMAGE_WIDTH + RotateSideWallData[m * 2 + 0]])
    {
      if(minY > RotateSideWallData[m * 2 + 1])
      {
        minY = RotateSideWallData[m * 2 + 1];

        startPoint[0] = RotateSideWallData[m * 2 + 0];
        startPoint[1] = RotateSideWallData[m * 2 + 1];
      }

      if(maxY < RotateSideWallData[m * 2 + 1])
      {
        maxY = RotateSideWallData[m * 2 + 1];

        endPoint[0] = RotateSideWallData[m * 2 + 0];
        endPoint[1] = RotateSideWallData[m * 2 + 1];
      }
    }
  } 

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

  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;

      if(ShapeBinaryImage[tempAddress])
      {
        ptr[3*x + 0] = ColorSourceImage[tempAddress * 3 + 0];
        ptr[3*x + 1] = ColorSourceImage[tempAddress * 3 + 1];
        ptr[3*x + 2] = ColorSourceImage[tempAddress * 3 + 2];
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

  for(int m = 0; m < SideWallDataCount; m++)
  {
    tempX = RotateSideWallData[m * 2 + 0];
    tempY = RotateSideWallData[m * 2 + 1];

    ptr = (Byte*)img1->ScanLine[tempY];

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

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

  DebugData5->Canvas->Pen->Color = clGreen;
  DebugData5->Canvas->Pen->Width = 1;
  DebugData5->Canvas->Brush->Style = bsClear;
  DebugData5->Canvas->Rectangle(startPoint[0] - 2, startPoint[1] - 2, startPoint[0] + 2, startPoint[1] + 2);
  DebugData5->Canvas->Rectangle(endPoint[0] - 2, endPoint[1] - 2, endPoint[0] + 2, endPoint[1] + 2);

  int SideAngle;
  if (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)
  {
    SideAngle = MINUS_45_ANGLE_CAM;
  }
  else if (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)
  {
    SideAngle = ZERO_ANGLE_CAM;
  }
  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)
  {
    SideAngle = PLUS_45_ANGLE_CAM;
  }

  int nextShiftX;
  int nextShiftY;
  int cShiftY;
  int qqq, rrr;
  int diffX, diffY;
  if(SideAngle == PLUS_45_ANGLE_CAM)
  {
    cShiftY = endPoint[1];
    for(int j = 1; j < MAX_IMAGE_WIDTH; j++)
    {
      gradSum = 0;
      nextShiftX = nextShiftY = 0;

      if(j < 30)
      {
        qqq = 0;
        rrr = 10;
      }
      else
      {
        qqq = -5;
        rrr = 5;
      }
      for(int i = qqq; i < rrr; i++)
      {
        tempX = endPoint[0] - j;
        tempY = cShiftY + i;

        if(tempX > 0 && tempX < MAX_IMAGE_WIDTH && tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
        {
          if(gradSum < GradientImage[MAX_IMAGE_WIDTH * tempY + tempX])
          {
            gradSum = GradientImage[MAX_IMAGE_WIDTH * tempY + tempX];

            nextShiftX = tempX;
            nextShiftY = tempY;
          }
        }
      }

      DebugData5->Canvas->Rectangle(nextShiftX - 1, nextShiftY - 1, nextShiftX + 1, nextShiftY + 1);

      cShiftY = nextShiftY;
    }
  }

  

  DebugData5->Refresh();
  

  delete img1;
  */
}

void __fastcall TTabletSimulationForm::TrackBar2Change(TObject *Sender)
{
  /*
  unsigned char tempColorSourceImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3];
  unsigned char GrayValueImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  unsigned char binImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];

  memcpy(tempColorSourceImage, ColorSourceImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3);
  memset(GrayValueImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
  memset(binImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int x, y;
  int tempAddress;
  int grayValue;

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

      grayValue = (tempColorSourceImage[tempAddress * 3 + 0] + tempColorSourceImage[tempAddress * 3 + 1] + tempColorSourceImage[tempAddress * 3 + 2]) / 3;

      GrayValueImage[tempAddress] = min(255, max(0, grayValue));
    }
  }

  int selfValue;
  int left, right, top, bottom;
  int tempAddress2;
  int colorDiff;
  int threshold = TrackBar2->Position;
  int leftSW, rightSW, topSW, bottomSW;

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

      selfValue = GrayValueImage[tempAddress];

      if(selfValue > 30)
      {
        leftSW = rightSW = topSW = bottomSW = 0;

        for(left = 4; left < 320; left += 4)
        {
          tempAddress2 = tempAddress - left;

          if(x - left < 0) break;

          colorDiff = GrayValueImage[tempAddress2] - grayValue;
          if(colorDiff > threshold)
          {
            leftSW = 1;
            break;
          }
        }

        if(!leftSW) continue;

        for(right = 4; right < 320; right += 4)
        {
          tempAddress2 = tempAddress + right;

          if(x + right > 640) break;

          colorDiff = GrayValueImage[tempAddress2] - grayValue;
          if(colorDiff > threshold)
          {
            rightSW = 1;
            break;
          }
        }

        if(!rightSW) continue;

        for(top = 4; top < 240; top += 4)
        {
          tempAddress2 = tempAddress - top * MAX_IMAGE_WIDTH;

          if(y - top < 0) break;

          colorDiff = GrayValueImage[tempAddress2] - grayValue;
          if(colorDiff > threshold)
          {
            topSW = 1;
            break;
          }
        }

        if(!topSW) continue;

        for(bottom = 4; bottom < 240; bottom += 4)
        {
          tempAddress2 = tempAddress + bottom * MAX_IMAGE_WIDTH;

          if(y + bottom > 480) break;

          colorDiff = GrayValueImage[tempAddress2] - grayValue;
          if(colorDiff > threshold)
          {
            bottomSW = 1;
            break;
          }
        }

        if(!bottomSW) continue;

        if(topSW && bottomSW && leftSW && rightSW)
        {
          binImage[tempAddress] = 1; 
        }
      }
    }
  }

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  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;

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

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

  delete img;
  */

  /*
  unsigned char tempColorSourceImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3];
  unsigned char GrayValueImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  unsigned char binImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];

  memcpy(tempColorSourceImage, ColorSourceImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3);
  memset(GrayValueImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
  memset(binImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int x, y;
  int tempAddress;
  int grayValue;
  int normalizedValue;
  int totalValue;

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

      if(tempColorSourceImage[tempAddress * 3 + selectedRGB] > 30)
      {
        totalValue = (tempColorSourceImage[tempAddress * 3 + 0] + tempColorSourceImage[tempAddress * 3 + 1] + tempColorSourceImage[tempAddress * 3 + 2]);
        normalizedValue = tempColorSourceImage[tempAddress * 3 + selectedRGB] * 255 / totalValue;


        GrayValueImage[tempAddress] = normalizedValue;
      }
    }
  }

  int threshold = TrackBar2->Position;

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  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;

      if(GrayValueImage[tempAddress] > threshold)
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = GrayValueImage[tempAddress];
        ptr[3*x + 2] = 0;
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

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

  delete img;

  유사한 색상끼리 그룹화를한다... 오?!
  */

  unsigned char GrayValueImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  unsigned char binImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];

  memset(GrayValueImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
  memset(binImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int x, y;
  int tempAddress;
  int grayValue;
  int normalizedValue;
  int totalValue;

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;
      GrayValueImage[tempAddress] = ColorSourceImage[tempAddress * 3 + 1];//(ColorSourceImage[tempAddress * 3 + 0] + ColorSourceImage[tempAddress * 3 + 1] + ColorSourceImage[tempAddress * 3 + 2]) / 3;
    }
  }

  memcpy(binImage, GrayValueImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

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

      if(binImage[tempAddress] < 40)
        GrayValueImage[tempAddress] = 0;
    }
  }

  memcpy(binImage, GradientImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int nX, nY;
  int i, j;
  for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
	{
		for (x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
		{
			tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(binImage[tempAddress] > 8)
      {
        for (i = y - 2; i <= y + 2; i++)
        {
          for (j = x - 2; j <= x + 2; j++)
          {
            tempAddress = MAX_IMAGE_WIDTH * i + j;

            GrayValueImage[tempAddress] = 0;
          }
        }
      }
    }
  }
  
  short *LabelingImage;
  unsigned short labelGroup[100000 * 2];

  int currentLabelNum;
  int maxLabelNum;
  int PixelCountInGroup;
  int PixelIndex;
  int breakSW;

  int MaxDefectGroupSize;
  int tempColor;
  int range;

  LabelingImage = RotationEdgeImage;
  MaxDefectGroupSize = 120000;

  memset(LabelingImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 2);
  maxLabelNum = 3000;
  currentLabelNum = 0;
  int labelMinColor, labelMaxColor;
  int colorDiff;
  int neighborLabelN;
  int tempAddress2;

  int maskLabelN;
  int reAssignLabelNum;
  int tempX, tempY;

  int labelMinX[3000];
  int labelMinY[3000];

  short CollisionArray[3000];

  for(int m = 0; m < 3000; m++)
  {
    labelMinX[m] = 640;
    labelMinY[m] = 480;
  }

  range = 8;

  for (i = 0; i < 3000; i++)
	{
		CollisionArray[i] = i;
  }

  /*
  for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
	{
		for (x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
		{
			tempAddress = MAX_IMAGE_WIDTH * y + x;
      if(GrayValueImage[tempAddress])
      {
        if (*(LabelingImage + tempAddress - MAX_IMAGE_WIDTH) == 0)
        {
          // up is background
          if (*(LabelingImage + tempAddress - 1) == 0)
          {
            // left is also background
            if (currentLabelNum < 3000 - 1)
            {
              currentLabelNum++;
              *(LabelingImage + tempAddress) = currentLabelNum; // first label number is '1'
            }
          }
          else
          {
            // left is not background
            *(LabelingImage + tempAddress) = *(LabelingImage + tempAddress - 1);
          }
        }
        else
        {
          // up is not background
          if (*(LabelingImage + tempAddress - 1) == 0)
          {
            // left is background
            *(LabelingImage + tempAddress) = *(LabelingImage + tempAddress - MAX_IMAGE_WIDTH);
          }
          else
          {
            // left is not background
            if (*(LabelingImage + tempAddress - MAX_IMAGE_WIDTH) == *(LabelingImage + tempAddress - 1))
            {
              *(LabelingImage + tempAddress) = *(LabelingImage + tempAddress - MAX_IMAGE_WIDTH);
            }
            else
            {
              CollisionArray[max(*(LabelingImage + tempAddress - 1), *(LabelingImage + tempAddress - MAX_IMAGE_WIDTH))] = min(*(LabelingImage + tempAddress - 1), *(LabelingImage + tempAddress - MAX_IMAGE_WIDTH));
              *(LabelingImage + tempAddress) = CollisionArray[*(LabelingImage + tempAddress - MAX_IMAGE_WIDTH)];
            }
          }
        }
      }
    }
	}
  */


    int leftLabelN;
    int topLabelN;
    int topleftLabelN;
    for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
    {
      for (x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
      {
        tempAddress = MAX_IMAGE_WIDTH * y + x;

        if(GrayValueImage[tempAddress])
        {
          if(!LabelingImage[tempAddress])
          {
            leftLabelN = LabelingImage[tempAddress - 1];
            topLabelN = LabelingImage[tempAddress - MAX_IMAGE_WIDTH];

            if(leftLabelN && topLabelN)
            {
              //상단 Label을 우선순위를 둠
              LabelingImage[tempAddress] = topLabelN;
              
              if(labelMinX[topLabelN] > x) labelMinX[topLabelN] = x;
              if(labelMinY[topLabelN] > y) labelMinY[topLabelN] = y;

              /*
              //서로다른 라벨이 인접해있는경우 좌측Label 값 다시 부여
              reAssignLabelNum = leftLabelN;
              for(j = y; j >= labelMinY[reAssignLabelNum]; j--)
              {
                for(i = x; i >= labelMinX[reAssignLabelNum]; i--)
                {
                  tempAddress2 = MAX_IMAGE_WIDTH * j + i;

                  if(LabelingImage[tempAddress2] == reAssignLabelNum)
                  {
                    LabelingImage[tempAddress2] = topLabelN;

                    if(labelMinX[topLabelN] > i) labelMinX[topLabelN] = i;
                    if(labelMinY[topLabelN] > j) labelMinY[topLabelN] = j;
                  }
                }
              }
              */
            }
            else if(leftLabelN)
            {
              LabelingImage[tempAddress] = leftLabelN;

              if(labelMinX[leftLabelN] > x) labelMinX[leftLabelN] = x;
              if(labelMinY[leftLabelN] > y) labelMinY[leftLabelN] = y;
            }
            else if(topLabelN)
            {
              LabelingImage[tempAddress] = topLabelN;

              if(labelMinX[topLabelN] > x) labelMinX[topLabelN] = x;
              if(labelMinY[topLabelN] > y) labelMinY[topLabelN] = y;
            }
            else
            {
              if(currentLabelNum < 3000 - 1)
              {
                currentLabelNum++;
                LabelingImage[tempAddress] = currentLabelNum;

                if(labelMinX[currentLabelNum] > x) labelMinX[currentLabelNum] = x;
                if(labelMinY[currentLabelNum] > y) labelMinY[currentLabelNum] = y;
              }
            }
          }
        }
      }
    }

  /*
  for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
	{
		for (x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
		{
			tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(GrayValueImage[tempAddress])
      {
        if(!LabelingImage[tempAddress])
        {
          if(LabelingImage[tempAddress - 1] && LabelingImage[tempAddress - MAX_IMAGE_WIDTH])
          {
            //상단 Label을 우선순위를 둠
            LabelingImage[tempAddress] = LabelingImage[tempAddress - MAX_IMAGE_WIDTH];

            //서로다른 라벨이 인접해있는경우 좌측Label 값 다시 부여
            reAssignLabelNum = LabelingImage[tempAddress - 1];
            for(j = y; j >= labelMinY[reAssignLabelNum]; j--)
            {
              for(i = x; i >= labelMinX[reAssignLabelNum]; i--)
              {
                tempAddress2 = MAX_IMAGE_WIDTH * j + i;

                if(LabelingImage[tempAddress2] == reAssignLabelNum)
                  LabelingImage[tempAddress2] = LabelingImage[tempAddress];
              }
            }
          }
          else if(LabelingImage[tempAddress - 1])
          {
            LabelingImage[tempAddress] = LabelingImage[tempAddress - 1];
          }
          else if(LabelingImage[tempAddress - MAX_IMAGE_WIDTH])
          {
            LabelingImage[tempAddress] = LabelingImage[tempAddress - MAX_IMAGE_WIDTH];
          }
          else
          {
            if(currentLabelNum < 3000 - 1)
            {
              currentLabelNum++;
              LabelingImage[tempAddress] = currentLabelNum;

              labelMinX[currentLabelNum] = x;
              labelMinY[currentLabelNum] = y;
            }
          }
        }
      }
    }
  }
  */

  /*
  for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
	{
		for (x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
		{
			tempAddress = MAX_IMAGE_WIDTH * y + x;

			if (GrayValueImage[tempAddress] && LabelingImage[tempAddress] == 0)
			{
        labelMinColor = labelMaxColor = GrayValueImage[tempAddress];

				memset(labelGroup, 0, sizeof(short) * 100000 * 2);
				PixelCountInGroup = 0;
				PixelIndex = 0;

				if (currentLabelNum < maxLabelNum)
				{
					currentLabelNum++;

					labelGroup[PixelCountInGroup * 2 + 0] = x;
					labelGroup[PixelCountInGroup * 2 + 1] = y;

					breakSW = 0;

					while (1)
					{
						nX = labelGroup[PixelIndex * 2 + 0];
						nY = labelGroup[PixelIndex * 2 + 1];

						for (i = nY - 2; i <= nY + 2; i++)
						{
							for (j = nX - 2; j <= nX + 2; j++)
							{
                tempAddress = MAX_IMAGE_WIDTH * i + j;

								if (GrayValueImage[tempAddress] && LabelingImage[tempAddress] == 0)
								{
									LabelingImage[tempAddress] = currentLabelNum;

									if (PixelCountInGroup < MaxDefectGroupSize)
									{
										PixelCountInGroup++;

										labelGroup[PixelCountInGroup * 2 + 0] = j;
										labelGroup[PixelCountInGroup * 2 + 1] = i;
									}
									else
									{
										breakSW = 1;
										break;
									}
								}
							}
              if (breakSW) break;
						}

						if (breakSW) break;
						if (PixelCountInGroup == PixelIndex) break;

						PixelIndex++;
					}
				}
			}
		}
	}
  */

  int threshold = TrackBar2->Position;

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  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;

      if(LabelingImage[tempAddress])
      {
        ptr[3*x] = (LabelingImage[tempAddress] * 17) & 0xFF;
        ptr[3*x+1] = (LabelingImage[tempAddress] * 41) & 0xFF;
        ptr[3*x+2] = (LabelingImage[tempAddress] * 73) & 0xFF;
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

  //DebugData5->Picture->Bitmap->Assign(img);
  //DebugData5->Refresh();


  // histogram
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;
      GrayValueImage[tempAddress] = GradientImage[tempAddress];//ColorSourceImage[tempAddress * 3 + 1];//(ColorSourceImage[tempAddress * 3 + 0] + ColorSourceImage[tempAddress * 3 + 1] + ColorSourceImage[tempAddress * 3 + 2]) / 3;
    }
  }

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

      if(ColorSourceImage[tempAddress * 3 + selectedRGB] > 30)
      {
        totalValue = (ColorSourceImage[tempAddress * 3 + 0] + ColorSourceImage[tempAddress * 3 + 1] + ColorSourceImage[tempAddress * 3 + 2]);
        normalizedValue = ColorSourceImage[tempAddress * 3 + selectedRGB] * 255 / totalValue;


        GrayValueImage[tempAddress] = normalizedValue;
      }
    }
  }
  
  int histo[256];
  int sum_histo[256];
  memset(histo, 0, sizeof(int) * 256);
  memset(sum_histo, 0, sizeof(int) * 256);

  int totalPixelCount = 0;
  for(y = 20; y < MAX_IMAGE_HEIGHT - 20; y++)
  {
    for(x = 20; x < MAX_IMAGE_WIDTH - 20; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(GrayValueImage[tempAddress])
      {
        histo[GrayValueImage[tempAddress]]++;
        totalPixelCount++;
      }
    }
  }

  int sum = 0;
  for(i = 0; i < 256; i++)
  {
    sum += histo[i];
    sum_histo[i] = sum;
  }

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;
      GrayValueImage[tempAddress] = sum_histo[GrayValueImage[tempAddress]] * 255 / totalPixelCount;
    }
  }


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

      if(GrayValueImage[tempAddress] > threshold)
      {
        ptr[3*x] = GrayValueImage[tempAddress];
        ptr[3*x+1] = GrayValueImage[tempAddress];
        ptr[3*x+2] = GrayValueImage[tempAddress];
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

  memset(GradientImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int g1, g2, g3;
  int compareWidth = 4;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(ColorSourceImage[(tempAddress - compareWidth) * 3 + 1] && ColorSourceImage[(tempAddress + compareWidth) * 3 + 1])
      {
        g1 = abs(ColorSourceImage[(tempAddress - compareWidth) * 3 + 0] - ColorSourceImage[(tempAddress + compareWidth) * 3 + 0]);
        g2 = abs(ColorSourceImage[(tempAddress - compareWidth) * 3 + 1] - ColorSourceImage[(tempAddress + compareWidth) * 3 + 1]);
        g3 = abs(ColorSourceImage[(tempAddress - compareWidth) * 3 + 2] - ColorSourceImage[(tempAddress + compareWidth) * 3 + 2]);

        GradientImage[tempAddress] = max(g1, max(g2, g3));
      }
    }
  }

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

      if(ColorSourceImage[(tempAddress - compareWidth * MAX_IMAGE_WIDTH) * 3 + 1] && ColorSourceImage[(tempAddress + compareWidth * MAX_IMAGE_WIDTH) * 3 + 1])
      {
        g1 = abs(ColorSourceImage[(tempAddress - compareWidth * MAX_IMAGE_WIDTH) * 3 + 0] - ColorSourceImage[(tempAddress + compareWidth * MAX_IMAGE_WIDTH) * 3 + 0]);
        g2 = abs(ColorSourceImage[(tempAddress - compareWidth * MAX_IMAGE_WIDTH) * 3 + 1] - ColorSourceImage[(tempAddress + compareWidth * MAX_IMAGE_WIDTH) * 3 + 1]);
        g3 = abs(ColorSourceImage[(tempAddress - compareWidth * MAX_IMAGE_WIDTH) * 3 + 2] - ColorSourceImage[(tempAddress + compareWidth * MAX_IMAGE_WIDTH) * 3 + 2]);

        int maxValue = max(g1, max(g2, g3));

        GradientImage[tempAddress] = max(GradientImage[tempAddress], maxValue);
      }
    }
  }

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

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


  DebugData5->Picture->Bitmap->Assign(img);
  DebugData5->Refresh();
  delete img;

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

void __fastcall TTabletSimulationForm::Button2Click(TObject *Sender)
{
  /*
  OpenPictureDialog1->FileName = "";

  Graphics::TBitmap *img1;
	img1 = new Graphics::TBitmap();

  if(OpenPictureDialog1->Execute())
  {
    img1->LoadFromFile(OpenPictureDialog1->FileName);

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

    unsigned char GrayValueImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
    unsigned char binImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];

    memset(GrayValueImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
    memset(binImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

    int tempAddress;
    int grayValue;
    int normalizedValue;
    int totalValue;

    for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
    {
      for(x = 0; x < MAX_IMAGE_WIDTH; x++)
      {
        tempAddress = MAX_IMAGE_WIDTH * y + x;
        GrayValueImage[tempAddress] = ColorSourceImage[tempAddress * 3 + 1];//(ColorSourceImage[tempAddress * 3 + 0] + ColorSourceImage[tempAddress * 3 + 1] + ColorSourceImage[tempAddress * 3 + 2]) / 3;
      }
    }

    memcpy(binImage, GrayValueImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

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

        if(binImage[tempAddress] < 40)
          GrayValueImage[tempAddress] = 0;
      }
    }

    memcpy(binImage, GradientImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

    int nX, nY;
    int i, j;
    for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
    {
      for (x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
      {
        tempAddress = MAX_IMAGE_WIDTH * y + x;

        if(binImage[tempAddress] > 8)
        {
          for (i = y - 2; i <= y + 2; i++)
          {
            for (j = x - 2; j <= x + 2; j++)
            {
              tempAddress = MAX_IMAGE_WIDTH * i + j;

              GrayValueImage[tempAddress] = 0;
            }
          }
        }
      }
    }
  
    short *LabelingImage;
    unsigned short labelGroup[100000 * 2];

    int currentLabelNum;
    int maxLabelNum;
    int PixelCountInGroup;
    int PixelIndex;
    int breakSW;

    int MaxDefectGroupSize;
    int tempColor;
    int range;

    LabelingImage = RotationEdgeImage;
    MaxDefectGroupSize = 120000;

    memset(LabelingImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 2);
    maxLabelNum = 3000;
    currentLabelNum = 0;
    int labelMinColor, labelMaxColor;
    int colorDiff;
    int neighborLabelN;
    int tempAddress2;

    int maskLabelN;
    int reAssignLabelNum;
    int tempX, tempY;

    int labelMinX[3000];
    int labelMinY[3000];

    short CollisionArray[3000];

    for(int m = 0; m < 3000; m++)
    {
      labelMinX[m] = 640;
      labelMinY[m] = 480;
    }
    range = 8;
    */


    /*
    for (i = 0; i < MAX_LABEL_COUNT; i++)
    {
      CollisionArray[i] = i;
    }

    for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
    {
      for (x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
      {
        tempAddress = MAX_IMAGE_WIDTH * y + x;
        if(GrayValueImage[tempAddress])
        {
          if (*(LabelingImage + tempAddress - MAX_IMAGE_WIDTH) == 0)
          {
            // up is background
            if (*(LabelingImage + tempAddress - 1) == 0)
            {
              // left is also background
              if (currentLabelNum < 3000 - 1)
              {
                currentLabelNum++;
                *(LabelingImage + tempAddress) = currentLabelNum; // first label number is '1'
              }
            }
            else
            {
              // left is not background
              *(LabelingImage + tempAddress) = *(LabelingImage + tempAddress - 1);
            }
          }
          else
          {
            // up is not background
            if (*(LabelingImage + tempAddress - 1) == 0)
            {
              // left is background
              *(LabelingImage + tempAddress) = *(LabelingImage + tempAddress - MAX_IMAGE_WIDTH);
            }
            else
            {
              // left is not background
              if (*(LabelingImage + tempAddress - MAX_IMAGE_WIDTH) == *(LabelingImage + tempAddress - 1))
              {
                *(LabelingImage + tempAddress) = *(LabelingImage + tempAddress - MAX_IMAGE_WIDTH);
              }
              else
              {
                CollisionArray[max(*(LabelingImage + tempAddress - 1), *(LabelingImage + tempAddress - MAX_IMAGE_WIDTH))] = min(*(LabelingImage + tempAddress - 1), *(LabelingImage + tempAddress - MAX_IMAGE_WIDTH));
                *(LabelingImage + tempAddress) = CollisionArray[*(LabelingImage + tempAddress - MAX_IMAGE_WIDTH)];
              }
            }
          }
        }
      }
    }
    */

    /*
    int leftLabelN;
    int topLabelN;
    int topleftLabelN;
    for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
    {
      for (x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
      {
        tempAddress = MAX_IMAGE_WIDTH * y + x;

        if(GrayValueImage[tempAddress])
        {
          if(!LabelingImage[tempAddress])
          {
            leftLabelN = LabelingImage[tempAddress - 1];
            topLabelN = LabelingImage[tempAddress - MAX_IMAGE_WIDTH]; 

            if(leftLabelN && topLabelN)
            {
              //상단 Label을 우선순위를 둠
              LabelingImage[tempAddress] = topLabelN;

              if(labelMinX[topLabelN] > x) labelMinX[topLabelN] = x;
              if(labelMinY[topLabelN] > y) labelMinY[topLabelN] = y;

              //서로다른 라벨이 인접해있는경우 좌측Label 값 다시 부여
              reAssignLabelNum = leftLabelN;
              for(j = y; j >= labelMinY[reAssignLabelNum]; j--)
              {
                for(i = x; i >= labelMinX[reAssignLabelNum]; i--)
                {
                  tempAddress2 = MAX_IMAGE_WIDTH * j + i;

                  if(LabelingImage[tempAddress2] == reAssignLabelNum)
                  {
                    LabelingImage[tempAddress2] = topLabelN;

                    if(labelMinX[topLabelN] > i) labelMinX[topLabelN] = i;
                    if(labelMinY[topLabelN] > j) labelMinY[topLabelN] = j;
                  }
                }
              }
            }
            else if(leftLabelN)
            {
              LabelingImage[tempAddress] = leftLabelN;

              if(labelMinX[leftLabelN] > x) labelMinX[leftLabelN] = x;
              if(labelMinY[leftLabelN] > y) labelMinY[leftLabelN] = y;
            }
            else if(topLabelN)
            {
              LabelingImage[tempAddress] = topLabelN;

              if(labelMinX[topLabelN] > x) labelMinX[topLabelN] = x;
              if(labelMinY[topLabelN] > y) labelMinY[topLabelN] = y;
            }
            else
            {
              if(currentLabelNum < 3000 - 1)
              {
                currentLabelNum++;
                LabelingImage[tempAddress] = currentLabelNum;

                if(labelMinX[currentLabelNum] > x) labelMinX[currentLabelNum] = x;
                if(labelMinY[currentLabelNum] > y) labelMinY[currentLabelNum] = y;
              }
            }
          }
        }
      }
    }

    int threshold = TrackBar2->Position;

    Graphics::TBitmap *img = new Graphics::TBitmap;
    img->Width = MAX_IMAGE_WIDTH;
    img->Height = MAX_IMAGE_HEIGHT;
    img->PixelFormat = pf24bit;

    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(LabelingImage[tempAddress])
        {
          ptr[3*x] = (LabelingImage[tempAddress] * 17) & 0xFF;
          ptr[3*x+1] = (LabelingImage[tempAddress] * 41) & 0xFF;
          ptr[3*x+2] = (LabelingImage[tempAddress] * 73) & 0xFF;
        }
        else
        {
          ptr[3*x + 0] = 0;
          ptr[3*x + 1] = 0;
          ptr[3*x + 2] = 0;
        }
      }
    }

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

    delete img;
  }

  delete img1;
  */
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::Button3Click(TObject *Sender)
{
  /*
  int x, y;
	int protoThrshold;
	int gradX, gradY;
	int tempCount;
	int i, j;
	int tempSum;
	int startX, endX, startY, endY;
  int halfStartX, halfEndX, halfStartY, halfEndY;
	int tempAddress;
	int maxLabelN;

  int space;
  int tabletColorFactorDiff;

	short *tempLabelImage;
  unsigned char *tempBinaryImage;
  int minX, maxX, minY, maxY;
  int option;
  int cameraIndex = SelectedCameraIndex;
  unsigned char tempHalfShapeBinaryImage[(MAX_IMAGE_WIDTH / 2)*(MAX_IMAGE_HEIGHT / 2)];
  int ProtoTabletRotationAngle;

  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)
  {
    option = CASE2;
  }
  else
  {
    option = CASE1;
  }

  startX = TabletSetupData.ImageCutStartX[cameraIndex - 1] + 10;
	endX = TabletSetupData.ImageCutEndX[cameraIndex - 1] - 10;
	startY = TabletSetupData.ImageCutStartY[cameraIndex - 1] + 10;
	endY = TabletSetupData.ImageCutEndY[cameraIndex - 1] - 10;

  if (startX < 4) startX = 4;
	if (endX > ImageWidth - 4) endX = ImageWidth - 4;
	if (startY < 4) startY = 4;
	if (endY > ImageHeight - 4) endY = ImageHeight - 4;

  halfStartX = startX / 2;
	halfEndX = endX / 2;
	halfStartY = startY / 2;
	halfEndY = endY / 2; 

  tempBinaryImage = BrightPixelNeighborPrint;
  
  tempLabelImage = HalfLabelImage;
  memset(tempLabelImage, 0, HALF_IMAGE_WIDTH * HALF_IMAGE_HEIGHT * 2);
  memset(tempHalfShapeBinaryImage, 0, HALF_IMAGE_WIDTH * HALF_IMAGE_HEIGHT);

	protoThrshold = 40;
  ProtoTabletRotationAngle = 0;

  for (y = startY; y < endY; y++)
	{
		for (x = startX; x < endX; x++)
		{
			tempAddress = y * MAX_IMAGE_WIDTH + x;
			tempSum = (OneColorImage[tempAddress] + OneColorImage[tempAddress - 1] + OneColorImage[tempAddress + 1]
				+ OneColorImage[tempAddress - MAX_IMAGE_WIDTH] + OneColorImage[tempAddress + MAX_IMAGE_WIDTH]) / 5;

			MeanOneColorImage[tempAddress] = tempSum;
    }
  }

  if(selectedRGB == 2)
  {
    if(ProcessingModeGlobal == INSPECTION_MODE)
      tabletColorFactorDiff = (TabletStudyData.tabletColorR_ForCamera1  - TabletStudyData.tabletColorB_ForCamera1) / 2;
    else
      tabletColorFactorDiff = (TabletSetupData.protoStudyColorR  - TabletSetupData.protoStudyColorB) / 2;

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

        if(OneColorImage[tempAddress] > protoThrshold &&
            ColorSourceImage[tempAddress * 3 + 2] - ColorSourceImage[tempAddress * 3 + 0] > tabletColorFactorDiff)
        {
          tempHalfShapeBinaryImage[(y / 2) * HALF_IMAGE_WIDTH + (x / 2)] = 1;
        }
      }
    }
  }
  else
  {
    for (y = startY; y < endY; y++)
    {
      for (x = startX; x < endX; x++)
      {
        tempAddress = y * MAX_IMAGE_WIDTH + x;

        if(OneColorImage[tempAddress] > protoThrshold)
        {
          tempHalfShapeBinaryImage[(y / 2) * HALF_IMAGE_WIDTH + (x / 2)] = 1;
        }
      }
    }
  }

  // 확장
  memcpy(HalfShapeBinaryImage, tempHalfShapeBinaryImage, HALF_IMAGE_WIDTH * HALF_IMAGE_HEIGHT);
  for (y = halfStartY; y < halfEndY; y++)
  {
    for (x = halfStartX; x < halfEndX; x++)
    {
      tempAddress = y * HALF_IMAGE_WIDTH + x;

      if(x > 4 && x < HALF_IMAGE_WIDTH - 4 && y > 4 && y < HALF_IMAGE_HEIGHT - 4)
      {
        if(!tempHalfShapeBinaryImage[tempAddress])
        {
          if(tempHalfShapeBinaryImage[tempAddress - 4])
          {
            HalfShapeBinaryImage[tempAddress] = 1;
          }
          else if(tempHalfShapeBinaryImage[tempAddress + 4])
          {
            HalfShapeBinaryImage[tempAddress] = 1;
          }
          else if(tempHalfShapeBinaryImage[tempAddress - 4 * HALF_IMAGE_WIDTH])
          {
            HalfShapeBinaryImage[tempAddress] = 1;
          }
          else if(tempHalfShapeBinaryImage[tempAddress + 4 * HALF_IMAGE_WIDTH])
          {
            HalfShapeBinaryImage[tempAddress] = 1;
          }
        }
      }
    }
  }
  memcpy(tempHalfShapeBinaryImage, HalfShapeBinaryImage, HALF_IMAGE_WIDTH * HALF_IMAGE_HEIGHT);

  maxLabelN = LabellingForTabletImage(tempLabelImage, tempHalfShapeBinaryImage, halfStartX, halfEndX, halfStartY, halfEndY, HALF_IMAGE_WIDTH, HALF_IMAGE_HEIGHT);

  ProtoTabletCenterX = ProtoTabletCenterY = tempCount = 0;
  for (y = startY; y < endY; y++)
  {
    for (x = startX; x < endX; x++)
    {
      tempAddress = (y / 2) * HALF_IMAGE_WIDTH + (x / 2);
        
      if (tempLabelImage[tempAddress] == maxLabelN)
      {
        ShapeBinaryImage[MAX_IMAGE_WIDTH * y + x] = 1;

        ProtoTabletCenterX += x;
        ProtoTabletCenterY += y;
        tempCount++;
      }
    }
  }

  if(tempCount)
  {
    ProtoTabletCenterX /= tempCount;
    ProtoTabletCenterY /= tempCount;
  }

  memset(GradientImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int g1, g2, g3;
  int compareSize = 8;

  int labelNum;
  int labelCheckSW;

  unsigned char ExpectedBinaryImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  unsigned char BottomGradientData[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  memset(ExpectedBinaryImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
  memset(BottomGradientData, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int extraCheckWSize = 0;
  int extraCheckHSize = 0;

  protoThrshold = 20;

  for (y = startY; y < endY; y++)
  {
    labelCheckSW = 0;
    for (x = endX; x > ProtoTabletCenterX - extraCheckWSize; x--)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(ShapeBinaryImage[tempAddress])
      {
        g1 = ColorSourceImage[(tempAddress) * 3 + 0] - ColorSourceImage[(tempAddress + compareSize) * 3 + 0];
        g2 = ColorSourceImage[(tempAddress) * 3 + 1] - ColorSourceImage[(tempAddress + compareSize) * 3 + 1];
        g3 = ColorSourceImage[(tempAddress) * 3 + 2] - ColorSourceImage[(tempAddress + compareSize) * 3 + 2];

        int maxValue = max(g1, max(g2, g3));

        GradientImage[tempAddress] = max(GradientImage[tempAddress], maxValue);

        if(labelCheckSW)
        {
          ExpectedBinaryImage[tempAddress]++;
        }
        else if(maxValue > protoThrshold)
        {
          labelCheckSW = 1;
          ExpectedBinaryImage[tempAddress]++;
        }
      }
    }
  }

  for (y = startY; y < endY; y++)
  {
    labelCheckSW = 0;
    for (x = startX; x <= ProtoTabletCenterX + extraCheckWSize; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(ShapeBinaryImage[tempAddress])
      {
        g1 = ColorSourceImage[(tempAddress) * 3 + 0] - ColorSourceImage[(tempAddress - compareSize) * 3 + 0];
        g2 = ColorSourceImage[(tempAddress) * 3 + 1] - ColorSourceImage[(tempAddress - compareSize) * 3 + 1];
        g3 = ColorSourceImage[(tempAddress) * 3 + 2] - ColorSourceImage[(tempAddress - compareSize) * 3 + 2];

        int maxValue = max(g1, max(g2, g3));

        GradientImage[tempAddress] = max(GradientImage[tempAddress], maxValue);

        if(labelCheckSW)
        {
          ExpectedBinaryImage[tempAddress]++;
        }
        else if(maxValue > protoThrshold)
        {
          labelCheckSW = 1;
          ExpectedBinaryImage[tempAddress]++;
        }
      }
    }
  }

  for (x = startX; x < endX; x++)
  {
    labelCheckSW = 0;
    for (y = endY; y >= ProtoTabletCenterY - extraCheckHSize; y--)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(ShapeBinaryImage[tempAddress])
      {
        g1 = ColorSourceImage[(tempAddress) * 3 + 0] - ColorSourceImage[(tempAddress + compareSize * MAX_IMAGE_WIDTH) * 3 + 0];
        g2 = ColorSourceImage[(tempAddress) * 3 + 1] - ColorSourceImage[(tempAddress + compareSize * MAX_IMAGE_WIDTH) * 3 + 1];
        g3 = ColorSourceImage[(tempAddress) * 3 + 2] - ColorSourceImage[(tempAddress + compareSize * MAX_IMAGE_WIDTH) * 3 + 2];

        int maxValue = max(g1, max(g2, g3));

        GradientImage[tempAddress] = max(GradientImage[tempAddress], maxValue);
        BottomGradientData[tempAddress] = maxValue;

        if(labelCheckSW)
        {
          ExpectedBinaryImage[tempAddress]++;
        }
        else if(maxValue > protoThrshold)
        {
          labelCheckSW = 1;
          ExpectedBinaryImage[tempAddress]++;
        }
      }
    }
  }

  for (x = startX; x < endX; x++)
  {
    labelCheckSW = 0;
    for (y = startY; y < ProtoTabletCenterY + extraCheckHSize; y++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(ShapeBinaryImage[tempAddress])
      {
        g1 = ColorSourceImage[(tempAddress) * 3 + 0] - ColorSourceImage[(tempAddress - compareSize * MAX_IMAGE_WIDTH) * 3 + 0];
        g2 = ColorSourceImage[(tempAddress) * 3 + 1] - ColorSourceImage[(tempAddress - compareSize * MAX_IMAGE_WIDTH) * 3 + 1];
        g3 = ColorSourceImage[(tempAddress) * 3 + 2] - ColorSourceImage[(tempAddress - compareSize * MAX_IMAGE_WIDTH) * 3 + 2];

        int maxValue = max(g1, max(g2, g3));

        GradientImage[tempAddress] = max(GradientImage[tempAddress], maxValue);

        if(labelCheckSW)
        {
          ExpectedBinaryImage[tempAddress]++;
        }
        else if(maxValue > protoThrshold)
        {
          labelCheckSW = 1;
          ExpectedBinaryImage[tempAddress]++;
        }
      }
    }
  }

  int histo[128];
  memset(histo, 0, sizeof(int) * 128);

  memset(ShapeBinaryImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

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

      //if(ExpectedBinaryImage[tempAddress])
      {
        //if(ExpectedBinaryImage[tempAddress + 4 * MAX_IMAGE_WIDTH] == 0)
        {
          histo[ColorSourceImage[(tempAddress) * 3 + 1] / 2]++;

          ShapeBinaryImage[tempAddress] = 1;
        }
      }
    }
  }

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

      if(!ShapeBinaryImage[tempAddress])
      {
        GradientImage[tempAddress] = 0;
      }
    }
  }

  int k = 0;
  */

  /*
  // Binary 유효한지 검증
  CopyBuffer(ShapeBinaryImage, tempBinaryImage, cameraIndex, sizeof(unsigned char));
  for (y = startY; y < endY; y++)
  {
    for (x = startX; x < endX; x++)
    {
      tempAddress = y * MAX_IMAGE_WIDTH + x;

      if(x > 10 && x < MAX_IMAGE_WIDTH - 10 && y > 10 && y < MAX_IMAGE_HEIGHT - 10)
      {
        if (!ShapeBinaryImage[tempAddress] && OneColorImage[tempAddress] > protoThrshold)
        {
          if(ShapeBinaryImage[tempAddress - 10])
          {
            tempBinaryImage[tempAddress] = 1;
          }
          else if(ShapeBinaryImage[tempAddress + 10])
          {
            tempBinaryImage[tempAddress] = 1;
          }
          else if(ShapeBinaryImage[tempAddress - 10 * MAX_IMAGE_WIDTH])
          {
            tempBinaryImage[tempAddress] = 1;
          }
          else if(ShapeBinaryImage[tempAddress + 10 * MAX_IMAGE_WIDTH])
          {
            tempBinaryImage[tempAddress] = 1;
          }
        }
      }
    }
  }

  // 확대
  CopyBuffer(tempBinaryImage, ShapeBinaryImage, cameraIndex, sizeof(unsigned char));
  for (y = startY; y < endY; y++)
  {
    for (x = startX; x < endX; x++)
    {
      tempAddress = y * MAX_IMAGE_WIDTH + x;

      if(x > 2 && x < MAX_IMAGE_WIDTH - 2 && y > 2 && y < MAX_IMAGE_HEIGHT - 2)
      {
        if (!ShapeBinaryImage[tempAddress])
        {
          if(ShapeBinaryImage[tempAddress - 2])
          {
            tempBinaryImage[tempAddress] = 1;
          }
          else if(ShapeBinaryImage[tempAddress + 2])
          {
            tempBinaryImage[tempAddress] = 1;
          }
          else if(ShapeBinaryImage[tempAddress - 2 * MAX_IMAGE_WIDTH])
          {
            tempBinaryImage[tempAddress] = 1;
          }
          else if(ShapeBinaryImage[tempAddress + 2 * MAX_IMAGE_WIDTH])
          {
            tempBinaryImage[tempAddress] = 1;
          }
        }
      }
    }
  }
  CopyBuffer(ShapeBinaryImage, tempBinaryImage, cameraIndex, sizeof(unsigned char)); 

  minX = MAX_IMAGE_WIDTH;
  maxX = 0;
  minY = MAX_IMAGE_HEIGHT;
  maxY = 0;
  ProtoTabletCenterX = ProtoTabletCenterY = tempCount = 0;
  for (y = startY; y < endY; y++)
  {
    for (x = startX; x < endX; x++)
    {
      if (ShapeBinaryImage[MAX_IMAGE_WIDTH * y + x])
      {
        ProtoTabletCenterX += x;
        ProtoTabletCenterY += y;
        tempCount++;

        if(minY > y) minY = y;
        if(maxY < y) maxY = y;
        if(minX > x) minX = x;
        if(maxX < x) maxX = x;
      }
    }
  }

  if (tempCount)
  {
    ProtoTabletCenterX /= tempCount;
    ProtoTabletCenterY /= tempCount;
  }

  if(option == CASE1)
  {
    TabletMatchingResult.SearchStartXForSideShape = minX;

    if(TabletMatchingResult.SearchStartXForSideShape <= startX + 6)
    {
      TabletMatchingResult.SearchStartXForSideShape = startX;
      DefectSW = 2;
    }
  }
  if(option == CASE2)
  {
    TabletMatchingResult.SearchStartXForSideShape = maxX;

    if(TabletMatchingResult.SearchStartXForSideShape >= endX - 6)
    {
      TabletMatchingResult.SearchStartXForSideShape = endX;
      DefectSW = 2;
    }
  }
  TabletMatchingResult.SideShapeEndY = maxY;

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

      if(ShapeBinaryImage[tempAddress])
      {
        if (x < ProtoTabletCenterX)
          gradX = OneColorImage[tempAddress + 2] - OneColorImage[tempAddress - 2];
        else
          gradX = OneColorImage[tempAddress - 2] - OneColorImage[tempAddress + 2];

        gradY = OneColorImage[tempAddress - 640] - OneColorImage[tempAddress + 1920];

        if (gradX > abs(gradY))
        {
          GradientImage[tempAddress] = gradX;
        }
      }
    }
  }

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

      if(ShapeBinaryImage[tempAddress])
      {
        gradY = OneColorImage[tempAddress - 640] - OneColorImage[tempAddress + 1920];

        if (gradY > 0)
        {
          GradientImage[tempAddress] = max(GradientImage[tempAddress], gradY);
        }
      }
    }
  }

  tabletStartXArea = minX - 10;
  tabletEndXArea = maxX + 10;
  tabletStartYArea = minY - 10;
  tabletEndYArea = maxY + 10;

  tabletStartXArea = max(startX, tabletStartXArea);
  tabletEndXArea = min(endX, tabletEndXArea);
  tabletStartYArea = max(startY, tabletStartYArea);
  tabletEndYArea = min(endY, tabletEndYArea);
  */

  /*
  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = 500;
  img->Height = 512;
  img->PixelFormat = pf24bit;
  Byte *ptr;

  int maxCount = 0;
  int normalizedHisto[128];
  for(int m = 0; m < 128; m++)
  {
    if(histo[m] > maxCount)
      maxCount = histo[m];
  }

  if(maxCount)
  {
    for(int m = 0; m < 128; m++)
    {
      normalizedHisto[m] = (histo[m] * 500 / maxCount);
    }

    int value;
    for(y = 0; y < 512; y++)
    {
      ptr = (Byte*)img->ScanLine[y];
      for(x = 0; x < 500; x++)
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }

      if(y % 4)
      {
        value = normalizedHisto[y / 4];

        for(x = 0; x < value; x++)
        {
          ptr[3*x + 0] = 0;
          ptr[3*x + 1] = 255;
          ptr[3*x + 2] = 255;
        }
      }
    }

    histoImage->Picture->Bitmap->Assign(img);
    histoImage->Refresh();
  }

  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;

  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(ExpectedBinaryImage[tempAddress])
      {
        ptr[3*x] = (ExpectedBinaryImage[tempAddress] * 30) & 0xFF;
        ptr[3*x+1] = (ExpectedBinaryImage[tempAddress] * 30) & 0xFF;
        ptr[3*x+2] = (ExpectedBinaryImage[tempAddress] * 30) & 0xFF;
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

  DebugData5->Picture->Bitmap->Assign(img);
  DebugData5->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(ShapeBinaryImage[tempAddress])
      {
        ptr[3*x + 0] = 255;
        ptr[3*x + 1] = 255;
        ptr[3*x + 2] = 255;
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

  DebugData1->Picture->Bitmap->Assign(img);
  DebugData1->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] = GradientImage[tempAddress];
      ptr[3*x + 1] = GradientImage[tempAddress];
      ptr[3*x + 2] = GradientImage[tempAddress];
    }
  }

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

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

void __fastcall TTabletSimulationForm::histoImageMouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
  /*
  int threshold = Y / 2;

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;
  Byte *ptr; 

  int x, y;
  int 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(ColorSourceImage[(tempAddress) * 3 + 1])
      {
        if(ColorSourceImage[(tempAddress) * 3 + 1] >= threshold)
        {
          ptr[3*x + 0] = 0;
          ptr[3*x + 1] = 255;
          ptr[3*x + 2] = 255;
        }
        else
        {
          ptr[3*x + 0] = 0;
          ptr[3*x + 1] = 0;
          ptr[3*x + 2] = 255;
        }
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

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

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

void __fastcall TTabletSimulationForm::Button4Click(TObject *Sender)
{
  /*
  unsigned char tempColorSourceImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3];
  unsigned char GrayValueImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  unsigned char binImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];

  memcpy(tempColorSourceImage, ColorSourceImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3);
  memset(GrayValueImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
  memset(binImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int x, y;
  int tempAddress;
  int grayValue;
  int normalizedValue;
  int totalValue;

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

      if(ShapeBinaryImage[tempAddress])
      {
        totalValue = (tempColorSourceImage[tempAddress * 3 + 0] + tempColorSourceImage[tempAddress * 3 + 1] + tempColorSourceImage[tempAddress * 3 + 2]);
        normalizedValue = tempColorSourceImage[tempAddress * 3 + selectedRGB] * 255 / totalValue;


        GrayValueImage[tempAddress] = normalizedValue;
      }
    }
  }

  int threshold = TrackBar2->Position;

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  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;

      if(GrayValueImage[tempAddress] > threshold)
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = GrayValueImage[tempAddress];
        ptr[3*x + 2] = 0;
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

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

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

void __fastcall TTabletSimulationForm::TrackBar3Change(TObject *Sender)
{
  unsigned char tempColorSourceImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3];
  unsigned char GrayValueImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  unsigned char binImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];

  memcpy(tempColorSourceImage, ColorSourceImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3);
  memset(GrayValueImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
  memset(binImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int x, y;
  int tempAddress;
  int grayValue;
  int normalizedValue;
  int totalValue;

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

      if(ShapeBinaryImage[tempAddress])
      {
        totalValue = (tempColorSourceImage[tempAddress * 3 + 0] + tempColorSourceImage[tempAddress * 3 + 1] + tempColorSourceImage[tempAddress * 3 + 2]);
        normalizedValue = tempColorSourceImage[tempAddress * 3 + selectedRGB] * 255 / totalValue;


        GrayValueImage[tempAddress] = normalizedValue;
      }
    }
  }

  int threshold = TrackBar3->Position;

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  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;

      if(GrayValueImage[tempAddress] > threshold)
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = GrayValueImage[tempAddress];
        ptr[3*x + 2] = 0;
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

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

  delete img;

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

void __fastcall TTabletSimulationForm::Button5Click(TObject *Sender)
{
  /*
  int x, y;
  int tempAddress;
  int histo[256];
  int sum_histo[256];
  unsigned char GrayValueImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  memset(histo, 0, sizeof(int) * 256);
  memset(sum_histo, 0, sizeof(int) * 256);

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

      if(ColorSourceImage[tempAddress * 3 + 1] > 30)
      {
        histo[ColorSourceImage[tempAddress * 3 + 1]]++;
        totalPixelCount++;
      }
    }
  }

  int sum = 0;
  for(int m = 0; m < 256; m++)
  {
    sum += histo[m];
    sum_histo[m] = sum;
  }

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;
      GrayValueImage[tempAddress] = sum_histo[ColorSourceImage[tempAddress * 3 + 1]] * 255 / totalPixelCount;
    }
  }

  int threshold = TrackBar3->Position;

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  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;

      if(GrayValueImage[tempAddress] > threshold)
      {
        ptr[3*x + 0] = GrayValueImage[tempAddress];
        ptr[3*x + 1] = GrayValueImage[tempAddress];
        ptr[3*x + 2] = GrayValueImage[tempAddress];
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

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

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

void __fastcall TTabletSimulationForm::TrackBar4Change(TObject *Sender)
{
  int x, y;
  int tempAddress;
  int histo[256];
  int sum_histo[256];
  unsigned char GrayValueImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  memset(histo, 0, sizeof(int) * 256);
  memset(sum_histo, 0, sizeof(int) * 256);

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

      if(ColorSourceImage[tempAddress * 3 + 1] > 0)
      {
        histo[ColorSourceImage[tempAddress * 3 + 1]]++;
        totalPixelCount++;
      }
    }
  }

  int sum = 0;
  for(int m = 0; m < 256; m++)
  {
    sum += histo[m];
    sum_histo[m] = sum;
  }

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;
      GrayValueImage[tempAddress] = sum_histo[ColorSourceImage[tempAddress * 3 + 1]] * 255 / totalPixelCount;
    }
  }

  int threshold = TrackBar4->Position;

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  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;

      if(GrayValueImage[tempAddress] > threshold)
      {
        ptr[3*x + 0] = GrayValueImage[tempAddress];
        ptr[3*x + 1] = GrayValueImage[tempAddress];
        ptr[3*x + 2] = GrayValueImage[tempAddress];
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

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

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

void __fastcall TTabletSimulationForm::Button6Click(TObject *Sender)
{
  /*
  int x, y;
  int tempAddress;
  unsigned char GrayValueImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  memset(GrayValueImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int value[3];
  int fstColorFactor;
  int secColorFactor;
  int maxColor;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(ColorSourceImage[tempAddress * 3 + 1] > 30)
      {
        value[0] = ColorSourceImage[tempAddress * 3 + 0];
        value[1] = ColorSourceImage[tempAddress * 3 + 1];
        value[2] = ColorSourceImage[tempAddress * 3 + 2];

        maxColor = max(value[0], max(value[1], value[2]));

        for(int m = 0; m < 3; m++)
        {
          if(maxColor == value[m])
          {
            fstColorFactor = m;
            break;
          }
        }

        if(fstColorFactor == 0)
        {
          maxColor = max(value[1], value[2]);

          if(maxColor == value[1])
          {
            secColorFactor = 1;
          }
          else
          {
            secColorFactor = 2;
          }
        }
        else if(fstColorFactor == 1)
        {
          maxColor = max(value[0], value[2]);

          if(maxColor == value[0])
          {
            secColorFactor = 0;
          }
          else
          {
            secColorFactor = 2;
          }
        }
        else if(fstColorFactor == 2)
        {
          maxColor = max(value[0], value[1]);

          if(maxColor == value[0])
          {
            secColorFactor = 0;
          }
          else
          {
            secColorFactor = 1;
          }
        }

        if((fstColorFactor == 1 && secColorFactor == 2) || (fstColorFactor == 2 && secColorFactor == 1))
        {
          GrayValueImage[tempAddress] = 255;
        }
      }
    }
  }

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  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;

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

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

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





void __fastcall TTabletSimulationForm::UpDown12Click(TObject *Sender,
      TUDBtnType Button)
{
  int tempX2, tempY2;
  int rotationValue;

  rotationValue = UpDown12->Position;

  Graphics::TBitmap *img1;
  img1 = new Graphics::TBitmap();
  img1->Width =  MAX_IMAGE_WIDTH;
  img1->Height =  MAX_IMAGE_HEIGHT;
  img1->PixelFormat = pf24bit;
  Byte *ptr;
  
  int tempAddress;
  for(int y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (byte*) img1->ScanLine[y];
    for(int x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      ptr[3*x + 0] = 0;
      ptr[3*x + 1] = 0;
      ptr[3*x + 2] = 0;
    }
  }


  for(int m = 0; m < SideWallMatchingData.SideWallData[rotationValue].SideWallPxDataCount; m++)
  {
    tempX2 = SideWallMatchingData.SideWallData[rotationValue].SideWallPxData[m * 2 + 0];
    tempY2 = SideWallMatchingData.SideWallData[rotationValue].SideWallPxData[m * 2 + 1];

    ptr = (byte*) img1->ScanLine[tempY2];
    ptr[3*tempX2 + 0] = 0;
    ptr[3*tempX2 + 1] = 0;
    ptr[3*tempX2 + 2] = 255;
  }

  ((TTntImage *)FindComponent("Image11"))->Picture->Bitmap->Assign(img1);
  ((TTntImage *)FindComponent("Image11"))->Refresh();

  delete img1;
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::UpDown15Click(TObject *Sender,
      TUDBtnType Button)
{
  int cameraIndex;
  int SideAngle;

  if(SelectedCameraIndex == 1 || SelectedCameraIndex == 5 || SelectedCameraIndex == 9 || SelectedCameraIndex == 13)
  {
    cameraIndex = 2;
  }
  else
  {
    cameraIndex = SelectedCameraIndex;
  }

  if (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)
  {
    SideAngle = MINUS_45_ANGLE_CAM;
  }
  else if (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)
  {
    SideAngle = ZERO_ANGLE_CAM;
  }
  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)
  {
    SideAngle = PLUS_45_ANGLE_CAM;
  }

  if(UpDown13->Position < 0) UpDown13->Position = 0;
  if(UpDown13->Position > SMALL_SIZE_ANGLE3_RANGE * 2) UpDown13->Position = SMALL_SIZE_ANGLE3_RANGE * 2;

  if(UpDown14->Position < 0) UpDown14->Position = 0;
  if(UpDown14->Position > SMALL_SIZE_ANGLE2_RANGE * 2) UpDown14->Position = SMALL_SIZE_ANGLE2_RANGE * 2;

  if(UpDown15->Position < 0) UpDown15->Position = 0;
  if(UpDown15->Position > SMALL_SIZE_ANGLE1_RANGE * 2) UpDown15->Position = SMALL_SIZE_ANGLE1_RANGE * 2;


  int XAngle, YAngle, ZAngle;
  int tempAddress;
  int tempX, tempY;

  ZAngle = UpDown13->Position;
  YAngle = UpDown14->Position;
  XAngle = UpDown15->Position;
  memset(TempImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
  
  for(int m = 0; m < SmallSizeSideData[SideAngle].SideShapeData[ZAngle][XAngle].SideShapeEdgePointCountBottom; m++)
  {
    tempX = SmallSizeSideData[SideAngle].SideShapeData[ZAngle][XAngle].SideShapeEdgePointBottom[m * 2 + 0];
    tempY = SmallSizeSideData[SideAngle].SideShapeData[ZAngle][XAngle].SideShapeEdgePointBottom[m * 2 + 1];

    tempAddress = SMALL_WIDTH * tempY + tempX;

    TempImage[tempAddress] = 1;
  }

  for(int m = 0; m < SmallSizeSideData[SideAngle].SideShapeData[ZAngle][XAngle].SideShapeEdgePointCountSideWall; m++)
  {
    tempX = SmallSizeSideData[SideAngle].SideShapeData[ZAngle][XAngle].SideShapeEdgePointSideWall[m * 2 + 0];
    tempY = SmallSizeSideData[SideAngle].SideShapeData[ZAngle][XAngle].SideShapeEdgePointSideWall[m * 2 + 1];

    tempAddress = SMALL_WIDTH * tempY + tempX;

    TempImage[tempAddress] = 1;    
  }

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = SMALL_WIDTH;
  img->Height = SMALL_HEIGHT;
  img->PixelFormat = pf24bit;

  Byte *ptr;

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

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

  DebugData1->Picture->Bitmap->Assign(img);
  DebugData1->Refresh();
  helpLabel1->Caption = "Shape Binary Image";

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

void  __fastcall TTabletSimulationForm::SideFaceShapeMatchingForETC(int cameraIndex)
{
	int tempShiftMean;
	int tempShiftMeanCount;
	int gradSum;
	int tAngleZ, tAngleY, tAngleX;
	int i, j, m, x, y;
	int maxValue;
	int maxV;
	int shiftX, shiftY;
	int tempX, tempY;
	int tempX2, tempY2;
	int tempShfit;
	int tempShiftX, tempShiftY;

	int temp_TabletshiftX;
	int temp_TabletshiftY;
	int temp_TabletXTotion;
	int temp_TabletYTotion;

	int topEdgeLinePosition;
	int alpha;
	int beta;
	int gamma;
	int delta;
	int topLineEndSearchRange;
	int tempCount;
	int totalCount;
	int yShiftRange;
	int diskBaseAdjustValue;
	int angle1Range;
	int angle2Range;
	int angle3Range;
	int tempAddress;
	int topLineStartSearchRange;
	int meanColorCountForExceptMiddle;
	int meanColorCountForMiddle;
	int boundaryTheshold;
	int startX, endX, startY, endY;
	int areaValue;
	int bColorDiff, gColorDiff, rColorDiff;
	int fstBColor, fstGColor, fstRColor;
	int secBColor, secGColor, secRColor;

	int inspectionAreaStartX, inspectionAreaEndX;

#ifdef PC_SIM
	int minY = 480;
	int maxY = 0;
#endif

	int brightNormalization[256];
	int histo[256];

	unsigned short meanColorRForTop[640];
	unsigned short meanColorRForBottom[640];
	unsigned short meanColorRForMiddle[640];
	unsigned short meanColorGForTop[640];
	unsigned short meanColorGForBottom[640];
	unsigned short meanColorGForMiddle[640];
	unsigned short meanColorBForTop[640];
	unsigned short meanColorBForBottom[640];
	unsigned short meanColorBForMiddle[640];

	unsigned char tempGradientImage[MAX_IMAGE_HEIGHT*MAX_IMAGE_WIDTH];
	int MultiLayerTabletBoundaryPoint1[MAX_IMAGE_WIDTH];
	int MultiLayerTabletBoundaryPoint2[MAX_IMAGE_WIDTH];
	int AvgShiftBoundaryY;
	int AvgShiftBoundaryYCnt;
	int tempY1;
	int grayColor1, grayColor2;
	int areaMinX, areaMaxX, areaMinY, areaMaxY;
	int selectedRGBForDoubleLayer;
	int limitInspectionStartX, limitInspectionEndX;
	int binarySW;
	int normalCaptureSW1, normalCaptureSW2;
	int Space;

	int maxShiftX;
	int minShiftY, maxShiftY;
	int angleAddStep;
	int centerY;
	int centerX;

	int tempTabletMatchingRes;
	int tempTabletMatchingShiftX;
	int tempTabletMatchingShiftY;
	int tempTabletMatchingTotionX;
	int tempTabletMatchingTotionY;
	int tempTabletMatchingTotionZ;
	int tempTabletMatchingTopLineShiftX;
	int tempTabletMatchingTopLineShiftY;
	int matchingSW;

	int gradientDataThreshold;
	int shiftYHisto[MAX_IMAGE_HEIGHT];
	int topLineBColor, topLineGColor, topLineRColor, accCount;
	int frontBColorRate, frontGColorRate, frontRColorRate;
	int rearBColorRate, rearGColorRate, rearRColorRate;
	int currentBColorRate, currentGColorRate, currentRColorRate;
	int BrightnessFace;
	int SideFaceDirectionForMultiLayerTablet;
	unsigned short tempSideShapeEdgePointTop[520 * 2];
	unsigned short tempSideShapeEdgePointBottom[520 * 2];
	short topLineCorrectionValue[MAX_IMAGE_WIDTH];
	short bottomLineCorrectionValue[MAX_IMAGE_WIDTH];

	int topColor, bottomColor;
	unsigned char brightnessDistribution[MAX_IMAGE_WIDTH];
	int topIsMoreBrightness;
	int bottomIsMoreBrightness;


	int multiLayerMaskSize;
	int tempCount2;
	int minX, maxX;
	int gradValue;
	unsigned short MultiTabletShapeInformationForWaveDefect[MAX_IMAGE_WIDTH];
	int avgThickness;
	int limitY;
	unsigned short SingleLayerThick[MAX_IMAGE_WIDTH];
	unsigned short thicknessHistogram[MAX_IMAGE_HEIGHT / 2];
	unsigned short waveDefectGroup[MAX_IMAGE_WIDTH];
	int tempThick;
	int defectSize;
	int maxDefectSize;
	int plusToleranceWave, minusToleranceWave;
	int defectStartX, defectEndX;
	unsigned char *defectAreaImage;
	int tempMaxY;
	int breakSW;
	int topShiftMinXAngle, topShiftMaxXAngle;
	int topShiftMinYAngle, topShiftMaxYAngle;
	int topMatchingXAngle, topMatchingYAngle, topMatchingZAngle;
	int shiftXAngle, shiftYAngle;
	int gradX, gradY;
	int tripleTabletSelectedRGB;
	int shiftCenterPositionInfo;
	int colorDiff;
	int tempAddress2;
	int topShiftSizeForTripleTablet;
	int bottomShiftSizeForTripleTablet;
	int j2;
	int TripleTabletEdgeLine[MAX_IMAGE_WIDTH][2];
	int topLinePixelShift[520];
	int tempLinePixelShift[520];
	int angleIndex;
	int SideAngle;
	int SideWallGradValue;
	int k;
	int sideWallSlope;

	TTabletMatchingResult tempTabletMatchingResult;
	TTabletMatchingResult fstTabletMatchingResult;
	int topLineMatchingValue;
	int bottomLineMatchingValue;
	int shiftMatchingValue;
	int sideWallMaxMatchingValue;
	int shiftTopLineCount;
	int n;
	int width, height;
	int edgeAreaShiftX;
	int zAngle;
	int sideWallMatchingXAngle;
	int sideWallMatchingYAngle;
	int sideWallMatchingZAngle;

	int sideWallMatchingShiftX;
	int sideWallMatchingShiftY;
	int sideWallMatchingStRange;
	int sideWallMatchingEdRange;

	int TabletShapeEdgeX, TabletShapeEdgeY;

	int SideShapeMatchingXAngleStRange;
	int SideShapeMatchingXAngleEdRange;
	int SideShapeMatchingZAngleStRange;
	int SideShapeMatchingZAngleEdRange;

	// For SELMA200, Rev by moon. (20180209) Camera Index
	const int HALF_CAMERA_INDEX = 9;
	const int MODULE1_2D_CAM_INDEX = 1;
	const int MODULE1_3D_CAM_INDEX = 5;
	const int MODULE2_2D_CAM_INDEX = 9;
	const int MODULE2_3D_CAM_INDEX = 13;

	int maxNeighborPxValue;
	int z, l;
	int binSW;

	int maxAdjustLinePosSize;
	int startN, endN;
  unsigned char halfSizeGradientImage[HALF_IMAGE_WIDTH * HALF_IMAGE_HEIGHT];

  int option;

	if (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)
	{
		sideWallMatchingStRange = MAX_SIDE_WALL_ROT_RANGE;
		sideWallMatchingEdRange = MAX_SIDE_WALL_ROT_RANGE * 2;

		SideAngle = MINUS_45_ANGLE_CAM;

    option = CASE1;
	}
	else if (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)
	{
		sideWallMatchingStRange = MAX_SIDE_WALL_ROT_RANGE - 5;//MAX_SIDE_WALL_ROT_RANGE / 2;
		sideWallMatchingEdRange = MAX_SIDE_WALL_ROT_RANGE + 5;//MAX_SIDE_WALL_ROT_RANGE / 2;

		SideAngle = ZERO_ANGLE_CAM;

    option = CASE1;
	}
	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)
	{
		sideWallMatchingStRange = 0;
		sideWallMatchingEdRange = MAX_SIDE_WALL_ROT_RANGE;

		SideAngle = PLUS_45_ANGLE_CAM;

    option = CASE2;
	}

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

	// 하단부의 Grad 값만을 활용하기 위함
	// BrightPixelNeighborPrint, TempImage -> 임시 버퍼
	memset(BrightPixelNeighborPrint, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
	for (y = startY; y < endY; y++)
	{
		for (x = startX; x < endX; x++)
		{
			tempAddress = MAX_IMAGE_WIDTH * y + x;
			if (ShapeBinaryImage[tempAddress])
			{
				if (OneColorImage[tempAddress] > TabletSetupData.SideFaceShapeExtractThreshold)
				{
					BrightPixelNeighborPrint[tempAddress] = 1;
				}
			}
		}
	}

	memset(TempImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
	for (x = startX; x < endX; x++)
	{
		binSW = 0;
		for (y = endY; y >= startY; y--)
		{
			tempAddress = MAX_IMAGE_WIDTH * y + x;
			if (BrightPixelNeighborPrint[tempAddress])
			{
				tempX = x;
				tempY = y;
				binSW = 1;
				break;
			}
		}

		if (binSW)
		{
			for (tempY2 = tempY - 8; tempY2 <= tempY + 8; tempY2++)
			{
				for (tempX2 = tempX - 3; tempX2 <= tempX + 3; tempX2++)
				{
					if (tempX2 > startX && tempX2 < endX && tempY2 > startY && tempY2 < endY)
						TempImage[MAX_IMAGE_WIDTH * tempY2 + tempX2] = 1;
				}
			}
		}
	}

  memset(halfSizeGradientImage, 0, HALF_IMAGE_WIDTH * HALF_IMAGE_HEIGHT);

  for(y = startY; y < endY; y++)
  {
    for(x = startX; x < endX; x++)
    {
      if(TempImage[MAX_IMAGE_WIDTH * y + x])
      {
        halfSizeGradientImage[HALF_IMAGE_WIDTH * (y / 2) + (x / 2)] = GradientImage[MAX_IMAGE_WIDTH * y + x];
      }
    }
  }

	centerX = ProtoTabletCenterX / 2;
	centerY = ProtoTabletCenterY / 2;

	alpha = TabletGradeData.side_Edge_Top_Neighbor_Intensity;
	beta = TabletGradeData.side_Edge_Bottom_Neighbor_Intensity;
	gamma = TabletGradeData.SideFaceEdgeAreaSize * 2;
	delta = TabletGradeData.SideFaceEdgeUnInsAreaSize;

	angle3Range = 0;

	angle1Range = SMALL_SIZE_ANGLE1_RANGE;
  angle2Range = SMALL_SIZE_ANGLE3_RANGE / 3;

	memcpy(&tempTabletMatchingResult, &TabletMatchingResult, sizeof(TTabletMatchingResult));

	SideShapeMatchingXAngleStRange = SMALL_SIZE_ANGLE1_RANGE - angle1Range;
	SideShapeMatchingXAngleEdRange = SMALL_SIZE_ANGLE1_RANGE + angle1Range;
	SideShapeMatchingZAngleStRange = SMALL_SIZE_ANGLE3_RANGE - angle2Range;
	SideShapeMatchingZAngleEdRange = SMALL_SIZE_ANGLE3_RANGE + angle2Range;

  maxShiftX = 32 / 2;
  maxShiftY = 24 / 2;

	gradientDataThreshold = 0;

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

	maxValue = -1;
	for (tAngleZ = SideShapeMatchingZAngleStRange; tAngleZ <= SideShapeMatchingZAngleEdRange; tAngleZ++)
	{
    for(tAngleY = - SMALL_SIZE_ANGLE2_RANGE; tAngleY <= SMALL_SIZE_ANGLE2_RANGE; tAngleY += 2)
    {
      for (tAngleX = SideShapeMatchingXAngleStRange; tAngleX <= SideShapeMatchingXAngleEdRange; tAngleX++)
      {
        if (SideAngle == PLUS_45_ANGLE_CAM)
        {
          tempShiftX = TabletMatchingResult.SearchStartXForSideShape / 2 - SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].endX2;
        }
        else
        {
          tempShiftX = TabletMatchingResult.SearchStartXForSideShape / 2 - SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].startX2;
        }

        tempShiftY = TabletMatchingResult.SideShapeEndY / 2 - SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].ShapeEndY;

        shiftMatchingValue = 0;
        for (i = tempShiftY - maxShiftY; i <= tempShiftY + maxShiftY; i+=2)
        {
          for (j = tempShiftX - maxShiftX; j <= tempShiftX + maxShiftX; j+=2)
          {
            gradSum = 0;
            for (m = 0; m < SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointCountBottom; m += 2)
            {
              tempX2 = SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointBottom[m * 2] + j;
              tempY2 = SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointBottom[m * 2 + 1] + i;

              if (tAngleY < 0)
              {
                tempX = ((tempX2 - centerX)*CosData[-tAngleY * 2] + (tempY2 - centerY)*SinData[-tAngleY * 2]) / 1024 + centerX;
                tempY = (-(tempX2 - centerX)*SinData[-tAngleY * 2] + (tempY2 - centerY)*CosData[-tAngleY * 2]) / 1024 + centerY;
              }
              else
              {
                tempX = ((tempX2 - centerX)*CosData[tAngleY * 2] - (tempY2 - centerY)*SinData[tAngleY * 2]) / 1024 + centerX;
                tempY = ((tempX2 - centerX)*SinData[tAngleY * 2] + (tempY2 - centerY)*CosData[tAngleY * 2]) / 1024 + centerY;
              }
                  
              if (tempX > startX && tempX < endX && tempY > startY && tempY < endY)
              {
                tempAddress = tempY * HALF_IMAGE_WIDTH + tempX;
                gradSum += halfSizeGradientImage[tempAddress];

                /*
                SideWallGradValue = 0;
                for (k = -2; k <= 2; k++)
                {
                  if (SideWallGradValue < halfSizeGradientImage[tempAddress + k * HALF_IMAGE_WIDTH])
                    SideWallGradValue = halfSizeGradientImage[tempAddress + k * HALF_IMAGE_WIDTH];
                }

                gradSum += SideWallGradValue;
                */
              }
            }

            if (maxValue < gradSum)
            {
              maxValue = gradSum;

              tempTabletMatchingResult.TabletSideShapeShiftX = j;
              tempTabletMatchingResult.TabletSideShapeShiftY = i;
              tempTabletMatchingResult.TabletSideShapeXTotion = tAngleX;
              tempTabletMatchingResult.TabletSideShapeYTotion = tAngleY;
              tempTabletMatchingResult.TabletSideShapeZTotion = tAngleZ;

              memcpy(&TabletMatchingResult, &tempTabletMatchingResult, sizeof(TTabletMatchingResult));
            }
          }
        }
      }
    }
	}

  /*
	maxValue = -1;
	for (tAngleZ = tempTabletMatchingResult.TabletSideShapeZTotion - 4; tAngleZ <= tempTabletMatchingResult.TabletSideShapeZTotion + 4; tAngleZ++)
	{
		if (tAngleZ < 0 || tAngleZ >= SMALL_SIZE_ANGLE3_RANGE * 2 + 1) continue;
    for(tAngleY = tempTabletMatchingResult.TabletSideShapeYTotion - 2; tAngleY <= tempTabletMatchingResult.TabletSideShapeYTotion + 2; tAngleY++)
    {
      for (tAngleX = tempTabletMatchingResult.TabletSideShapeXTotion - 4; tAngleX <= tempTabletMatchingResult.TabletSideShapeXTotion + 4; tAngleX++)
      {
        if (tAngleX < 0 || tAngleX >= SMALL_SIZE_ANGLE1_RANGE * 2 + 1) continue;

        shiftMatchingValue = 0;
        for (i = tempTabletMatchingResult.TabletSideShapeShiftY - 2; i <= tempTabletMatchingResult.TabletSideShapeShiftY + 2; i++)
        {
          for (j = tempTabletMatchingResult.TabletSideShapeShiftX - 2; j <= tempTabletMatchingResult.TabletSideShapeShiftX + 2; j++)
          {
            gradSum = 0;
            if(0)
            for (m = 0; m < SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointCountSideWall; m += 2)
            {
              tempX = SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointSideWall[m * 2] + j;
              tempY = SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointSideWall[m * 2 + 1] + i;

              if (tempX > startX && tempX < endX && tempY > startY && tempY < endY)
              {
                tempAddress = tempY * HALF_IMAGE_WIDTH + tempX;

                SideWallGradValue = 0;
                for (k = -4; k <= 4; k++)
                {
                  if (SideWallGradValue < halfSizeGradientImage[tempAddress + k])
                    SideWallGradValue = halfSizeGradientImage[tempAddress + k];
                }

                gradSum += SideWallGradValue;
              }
            }

            if (gradSum < gradientDataThreshold) continue;

            for (m = 0; m < SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointCountBottom; m += 2)
            {
              tempX2 = SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointBottom[m * 2] + j;
              tempY2 = SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointBottom[m * 2 + 1] + i;

              if (tAngleY < 0)
              {
                tempX = ((tempX2 - centerX)*CosData[-tAngleY * 2] + (tempY2 - centerY)*SinData[-tAngleY * 2]) / 1024 + centerX;
                tempY = (-(tempX2 - centerX)*SinData[-tAngleY * 2] + (tempY2 - centerY)*CosData[-tAngleY * 2]) / 1024 + centerY;
              }
              else
              {
                tempX = ((tempX2 - centerX)*CosData[tAngleY * 2] - (tempY2 - centerY)*SinData[tAngleY * 2]) / 1024 + centerX;
                tempY = ((tempX2 - centerX)*SinData[tAngleY * 2] + (tempY2 - centerY)*CosData[tAngleY * 2]) / 1024 + centerY;
              }
              
              if (tempX > startX && tempX < endX && tempY > startY && tempY < endY)
              {
                tempAddress = tempY * HALF_IMAGE_WIDTH + tempX;

                gradSum += halfSizeGradientImage[tempAddress];
              }
            }

            if (maxValue < gradSum)
            {
              maxValue = gradSum;

              TabletMatchingResult.TabletSideShapeShiftX = j;
              TabletMatchingResult.TabletSideShapeShiftY = i;
              TabletMatchingResult.TabletSideShapeXTotion = tAngleX;
              TabletMatchingResult.TabletSideShapeYTotion = tAngleY;
              TabletMatchingResult.TabletSideShapeZTotion = tAngleZ;
            }
          }
        }
      }
    }
	}
  */

	bottomLineMatchingValue = 0;
	shiftX = shiftY = 0;
	for (i = -4; i <= 4; i += 2)
	{
		for (j = -6; j <= 6; j += 2)
		{
			gradSum = 0;
			for (m = 0; m < SmallSizeSideData[SideAngle].SideShapeData[TabletMatchingResult.TabletSideShapeZTotion][TabletMatchingResult.TabletSideShapeXTotion].SideShapeEdgePointCountBottom; m++)
			{
				tempX = SmallSizeSideData[SideAngle].SideShapeData[TabletMatchingResult.TabletSideShapeZTotion][TabletMatchingResult.TabletSideShapeXTotion].SideShapeEdgePointBottom[m * 2] + TabletMatchingResult.TabletSideShapeShiftX + i;
				tempY = SmallSizeSideData[SideAngle].SideShapeData[TabletMatchingResult.TabletSideShapeZTotion][TabletMatchingResult.TabletSideShapeXTotion].SideShapeEdgePointBottom[m * 2 + 1] + TabletMatchingResult.TabletSideShapeShiftY + j;

				if (tempX > startX && tempX < endX && tempY > startY && tempY < endY)
				{
					tempAddress = tempY * HALF_IMAGE_WIDTH + tempX;

					gradSum += (halfSizeGradientImage[tempAddress] + halfSizeGradientImage[tempAddress + HALF_IMAGE_WIDTH] + halfSizeGradientImage[tempAddress - HALF_IMAGE_WIDTH]);
				}
			}

			if (bottomLineMatchingValue < gradSum)
			{
				bottomLineMatchingValue = gradSum;

				shiftX = i;
				shiftY = j;
			}
		}
	}

	TabletMatchingResult.TabletSideShapeShiftX += shiftX;
	TabletMatchingResult.TabletSideShapeShiftY += shiftY;

  tAngleZ = TabletMatchingResult.TabletSideShapeZTotion;
  tAngleY = TabletMatchingResult.TabletSideShapeYTotion;
  tAngleX = TabletMatchingResult.TabletSideShapeXTotion;

  memset(TempImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);


  for(int m = 0; m < SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointCountBottom; m++)
  {
    tempX2 = SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointBottom[m * 2 + 0] + TabletMatchingResult.TabletSideShapeShiftX;
    tempY2 = SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointBottom[m * 2 + 1] + TabletMatchingResult.TabletSideShapeShiftY;

    if (tAngleY < 0)
    {
      tempX = ((tempX2 - centerX)*CosData[-tAngleY * 2] + (tempY2 - centerY)*SinData[-tAngleY * 2]) / 1024 + centerX;
      tempY = (-(tempX2 - centerX)*SinData[-tAngleY * 2] + (tempY2 - centerY)*CosData[-tAngleY * 2]) / 1024 + centerY;
    }
    else
    {
      tempX = ((tempX2 - centerX)*CosData[tAngleY * 2] - (tempY2 - centerY)*SinData[tAngleY * 2]) / 1024 + centerX;
      tempY = ((tempX2 - centerX)*SinData[tAngleY * 2] + (tempY2 - centerY)*CosData[tAngleY * 2]) / 1024 + centerY;
    }
    
    tempAddress = SMALL_WIDTH * tempY + tempX;

    TempImage[tempAddress] = 1;
  }

  if(0)
  for(int m = 0; m < SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointCountSideWall; m++)
  {
    tempX2 = SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointSideWall[m * 2 + 0] + TabletMatchingResult.TabletSideShapeShiftX;
    tempY2 = SmallSizeSideData[SideAngle].SideShapeData[tAngleZ][tAngleX].SideShapeEdgePointSideWall[m * 2 + 1] + TabletMatchingResult.TabletSideShapeShiftY;

    if (tAngleY < 0)
    {
      tempX = ((tempX2 - centerX)*CosData[-tAngleY * 2] + (tempY2 - centerY)*SinData[-tAngleY * 2]) / 1024 + centerX;
      tempY = (-(tempX2 - centerX)*SinData[-tAngleY * 2] + (tempY2 - centerY)*CosData[-tAngleY * 2]) / 1024 + centerY;
    }
    else
    {
      tempX = ((tempX2 - centerX)*CosData[tAngleY * 2] - (tempY2 - centerY)*SinData[tAngleY * 2]) / 1024 + centerX;
      tempY = ((tempX2 - centerX)*SinData[tAngleY * 2] + (tempY2 - centerY)*CosData[tAngleY * 2]) / 1024 + centerY;
    }
              
    tempAddress = SMALL_WIDTH * tempY + tempX;

    TempImage[tempAddress] = 1;    
  }

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = SMALL_WIDTH;
  img->Height = SMALL_HEIGHT;
  img->PixelFormat = pf24bit;

  Byte *ptr;

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

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

  DebugData1->Picture->Bitmap->Assign(img);
  DebugData1->Refresh();
  helpLabel1->Caption = "Shape Binary Image";

  delete img;

  /*
	topLineMatchingValue = 0;
	for (n = 0; n < MAX_SHIFT_HEIGHT_COUNT; n++)
	{
		shiftX = SmallSizeSideData[SideAngle].SideShapeData[TabletMatchingResult.TabletSideShapeZTotion][TabletMatchingResult.TabletSideShapeXTotion].shiftTopLineX[n];
		shiftY = SmallSizeSideData[SideAngle].SideShapeData[TabletMatchingResult.TabletSideShapeZTotion][TabletMatchingResult.TabletSideShapeXTotion].shiftTopLineY[n];

		if (shiftY)
		{
			for (k = -6; k <= 6; k += 2)
			{
				gradSum = 0;
				for (m = 0; m < SmallSizeSideData[SideAngle].SideShapeData[TabletMatchingResult.TabletSideShapeZTotion][TabletMatchingResult.TabletSideShapeXTotion].SideShapeEdgePointCountBottom; m++)
				{
					tempX = SmallSizeSideData[SideAngle].SideShapeData[TabletMatchingResult.TabletSideShapeZTotion][TabletMatchingResult.TabletSideShapeXTotion].SideShapeEdgePointBottom[m * 2] + TabletMatchingResult.TabletSideShapeShiftX + shiftX + k;
					tempY = SmallSizeSideData[SideAngle].SideShapeData[TabletMatchingResult.TabletSideShapeZTotion][TabletMatchingResult.TabletSideShapeXTotion].SideShapeEdgePointBottom[m * 2 + 1] + TabletMatchingResult.TabletSideShapeShiftY + shiftY;

					if (tempX > startX && tempX < endX && tempY > startY && tempY < endY)
					{
						tempAddress = tempY * HALF_IMAGE_WIDTH + tempX;

						gradSum += (halfSizeGradientImage[tempAddress] + halfSizeGradientImage[tempAddress + HALF_IMAGE_WIDTH] + halfSizeGradientImage[tempAddress - HALF_IMAGE_WIDTH]);
					}
				}

				if (topLineMatchingValue < gradSum)
				{
					topLineMatchingValue = gradSum;

					TabletMatchingResult.TabletSideShapeTopLineShiftX = shiftX + k;
					TabletMatchingResult.TabletSideShapeTopLineShiftY = shiftY;
				}
			}
		}
	}
  */
}

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

void __fastcall TTabletSimulationForm::Button7Click(TObject *Sender)
{
  SideFaceShapeMatchingForETC(SelectedCameraIndex);
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::Button8Click(TObject *Sender)
{
  int m, x, y;
	unsigned short sizeTransform[2000][2];
  unsigned short rotateTransform[2000][2];
  unsigned short eraseEdgeLine[2000];

	unsigned short firstTransformForFace1[2000][3];
	unsigned short firstTransformForFace2[2000][3];

	unsigned short SecondTransformForFace1[2000][3];
	unsigned short SecondTransformForFace2[2000][3];

	unsigned short transfarentEdgeDataPoint[2000][3];
	unsigned short transfarentEdgeDataPoint2[2000][3];
	unsigned char unVisibleEdgeLineCheck[2000];

	int tAngleX;
	int tAngleY;

	int tempX, tempY;
	int tabletCenterX, tabletCenterY, tabletCenterZ;

	int startX1, startY1, endX1, endY1;
	int startX2, startY2, endX2, endY2;
	int start_Number, end_Number;

	int face1Height, face2Height;
	int sysCameraIndex;

	int tempIndex;
  int cameraIndex;
  int shapeEndY;

	const int HALF_CAMERA_INDEX = 9;
	const int MODULE1_2D_CAM_INDEX = 1;
	const int MODULE1_3D_CAM_INDEX = 5;
	const int MODULE2_2D_CAM_INDEX = 9;
	const int MODULE2_3D_CAM_INDEX = 13;

	int FrontFaceCameraResolution;
	int SideFaceCameraResolution;
  int adjustMiddleHeight;
  int adjustTabletHeight;

  int AngleXZeroPos;
  int AngleYZeroPos;

  int XAxisDataMakeCount;
  int YAxisDataMakeCount;

  int tempAddress;

  int SideAngle;
  int ProcessingSW;
  int tempCount;

  unsigned char *tempImage;

  int lineMinX, lineMaxX, lineMinY, lineMaxY;
  int width, height;
  int SideWallLength;
  int halfSideWallLength;
  int shiftCount;
  int shapeMinX, shapeMaxX;
  int ShapeWidth;
  int tAngleZ;
  int ZAxisDataMakeCount;
  int AngleZZeroPos;
  int tempSideWallDataCount;
  int convCamIndex;

  // 측면 카메라에서 분할선 매칭에 필요한 데이터 생성
  int tabletLength;
  int avgResolution;
  unsigned short protoLineData[SIDE_FACE_ROTATION_LINE_DATA_COUNT * 2];
  int r;

  unsigned char smallSizeImage[SMALL_WIDTH * SMALL_HEIGHT];

  memset(smallSizeImage, 0, SMALL_WIDTH * SMALL_HEIGHT);
  tempImage = OneColorImage;

  AngleXZeroPos = 60;
  AngleYZeroPos = 0;
  AngleZZeroPos = 0;

	if (TabletCharacter.middle_height != 0)
	{
    tAngleY = 0;

    // PC상에서 Side Camera 12대를 고려하기에는 데이터양이 너무 방대해짐. 일단 해상도를 430으로 통일하고 데이터 이니셜
    for (cameraIndex = 1; cameraIndex <= 4; cameraIndex++)
    {
      ProcessingSW = 0;
      switch(cameraIndex)
      {
        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:
          SideAngle = MINUS_45_ANGLE_CAM;
          ProcessingSW = 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:
          SideAngle = ZERO_ANGLE_CAM;
          ProcessingSW = 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:
          SideAngle = PLUS_45_ANGLE_CAM;
          ProcessingSW = 1;
          break;
      }
  
      if (ProcessingSW)
      {
        memset(SmallSizeSideData[SideAngle].SideShapeData, 0, sizeof(TSideSmallSizeShapeData) * (SMALL_SIZE_ANGLE3_RANGE*2 + 1) * (SMALL_SIZE_ANGLE1_RANGE * 2 + 1));
          
        FrontFaceCameraResolution = TabletSetupData.cameraZoom[0];
        SideFaceCameraResolution = 430;// 해상도는 430으로 통일

        ZAxisDataMakeCount = 0;
        for(tAngleZ = AngleZZeroPos - SMALL_SIZE_ANGLE3_RANGE; tAngleZ <= AngleZZeroPos + SMALL_SIZE_ANGLE3_RANGE; tAngleZ++)
        {
          shapeMinX = MAX_IMAGE_WIDTH;
          shapeMaxX = 0;

          for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
          {
            sizeTransform[m][0] = (TabletSetupData.FrontShapeEdgePoint[m][0] - MAX_IMAGE_WIDTH / 2) * FrontFaceCameraResolution / SideFaceCameraResolution + MAX_IMAGE_WIDTH / 2;
            sizeTransform[m][1] = (TabletSetupData.FrontShapeEdgePoint[m][1] - MAX_IMAGE_HEIGHT / 2) * FrontFaceCameraResolution / SideFaceCameraResolution + MAX_IMAGE_HEIGHT / 2;

            if(tAngleZ < 0)
            {
              rotateTransform[m][0] = ((sizeTransform[m][0] - MAX_IMAGE_WIDTH / 2)*CosData[-tAngleZ * 4] + (sizeTransform[m][1] - MAX_IMAGE_HEIGHT / 2)*SinData[-tAngleZ * 4]) / 1024 + MAX_IMAGE_WIDTH / 2;
              rotateTransform[m][1] = (-(sizeTransform[m][0] - MAX_IMAGE_WIDTH / 2)*SinData[-tAngleZ * 4] + (sizeTransform[m][1] - MAX_IMAGE_HEIGHT / 2)*CosData[-tAngleZ * 4]) / 1024 + MAX_IMAGE_HEIGHT / 2;
            }
            else
            {
              rotateTransform[m][0] = ((sizeTransform[m][0] - MAX_IMAGE_WIDTH / 2)*CosData[tAngleZ * 4] - (sizeTransform[m][1] - MAX_IMAGE_HEIGHT / 2)*SinData[tAngleZ * 4]) / 1024 + MAX_IMAGE_WIDTH / 2;
              rotateTransform[m][1] = ((sizeTransform[m][0] - MAX_IMAGE_WIDTH / 2)*SinData[tAngleZ * 4] + (sizeTransform[m][1] - MAX_IMAGE_HEIGHT / 2)*CosData[tAngleZ * 4]) / 1024 + MAX_IMAGE_HEIGHT / 2;
            }

            if (rotateTransform[m][0] < shapeMinX)
              shapeMinX = rotateTransform[m][0];
            if (rotateTransform[m][0] > shapeMaxX)
              shapeMaxX = rotateTransform[m][0];
          }

          ShapeWidth = abs(shapeMaxX - shapeMinX);

          adjustMiddleHeight = (TabletCharacter.middle_height * 1.1) * FrontFaceCameraResolution / SideFaceCameraResolution;
          adjustTabletHeight = (TabletCharacter.height * 1.1) * FrontFaceCameraResolution / SideFaceCameraResolution;

          memset(smallSizeImage, 0, SMALL_WIDTH * SMALL_HEIGHT);
          memset(tempImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
          memset(RotationEdgeImage, 0, MAX_IMAGE_WIDTH*MAX_IMAGE_WIDTH * 2);
          memset(unVisibleEdgeLineCheck, 0, 2000);
          memset(eraseEdgeLine, 0, 2000 * 2);

          //45도 상에서 실제로 보이는 에지 라인만 추출////////////
          startX1 = 1000;
          endX1 = -1;
          for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
          {
            if(SideAngle == MINUS_45_ANGLE_CAM)
            {
              tempX = ((rotateTransform[m][0] - MAX_IMAGE_WIDTH / 2)*CosData[SIDE_CAMERA_ANGLE * 2] + (rotateTransform[m][1] - MAX_IMAGE_WIDTH / 2)*SinData[SIDE_CAMERA_ANGLE * 2]) / 1024 + MAX_IMAGE_WIDTH / 2;
              tempY = (-(rotateTransform[m][0] - MAX_IMAGE_WIDTH / 2)*SinData[SIDE_CAMERA_ANGLE * 2] + (rotateTransform[m][1] - MAX_IMAGE_WIDTH / 2)*CosData[SIDE_CAMERA_ANGLE * 2]) / 1024 + MAX_IMAGE_WIDTH / 2;
            }
            else if(SideAngle == ZERO_ANGLE_CAM)
            {
              tempX = ((rotateTransform[m][0] - MAX_IMAGE_WIDTH / 2)*CosData[0] - (rotateTransform[m][1] - MAX_IMAGE_WIDTH / 2)*SinData[0]) / 1024 + MAX_IMAGE_WIDTH / 2;
              tempY = ((rotateTransform[m][0] - MAX_IMAGE_WIDTH / 2)*SinData[0] + (rotateTransform[m][1] - MAX_IMAGE_WIDTH / 2)*CosData[0]) / 1024 + MAX_IMAGE_WIDTH / 2;
            }
            else if(SideAngle == PLUS_45_ANGLE_CAM)
            {
              tempX = ((rotateTransform[m][0] - MAX_IMAGE_WIDTH / 2)*CosData[SIDE_CAMERA_ANGLE * 2] - (rotateTransform[m][1] - MAX_IMAGE_WIDTH / 2)*SinData[SIDE_CAMERA_ANGLE * 2]) / 1024 + MAX_IMAGE_WIDTH / 2;
              tempY = ((rotateTransform[m][0] - MAX_IMAGE_WIDTH / 2)*SinData[SIDE_CAMERA_ANGLE * 2] + (rotateTransform[m][1] - MAX_IMAGE_WIDTH / 2)*CosData[SIDE_CAMERA_ANGLE * 2]) / 1024 + MAX_IMAGE_WIDTH / 2;
            }
            
            if (startX1 > tempX)
            {
              start_Number = m;
              startX1 = tempX;
              startY1 = tempY;
            }
            else if (startX1 == tempX)
            {
              if (startY1 > tempY)
              {
                start_Number = m;
                startX1 = tempX;
                startY1 = tempY;
              }
            }
            if (endX1 <= tempX)
            {
              end_Number = m;
              endX1 = tempX;
              endY1 = tempY;
            }
            else if (endX1 == tempX)
            {
              if (endY1 > tempY)
              {
                start_Number = m;
                endX1 = tempX;
                endY1 = tempY;
              }
            }

            if(tempX > 0 && tempX < MAX_IMAGE_WIDTH && tempY > 0 && tempY < MAX_IMAGE_WIDTH)
            {
              RotationEdgeImage[tempY*MAX_IMAGE_WIDTH + tempX] = m;
            }
          }

          /*
          if(SideAngle == MINUS_45_ANGLE_CAM)
          {
            for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
            {
              if(rotateTransform[m][0] > shapeMaxX - ShapeWidth / 2)
              {
                eraseEdgeLine[m] = 1;
              }
            }
          }
          else if(SideAngle == PLUS_45_ANGLE_CAM)
          {
            for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
            {
              if(rotateTransform[m][0] < shapeMinX + ShapeWidth / 2)
              {
                eraseEdgeLine[m] = 1;
              }
            }
          }
          else
          {
            for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
            {
              if(rotateTransform[m][0] > shapeMaxX - ShapeWidth / 10)
              {
                eraseEdgeLine[m] = 1;
              }
            }
          }
          */

          for (x = 1; x < MAX_IMAGE_WIDTH - 1; x++)
          {
            for (y = MAX_IMAGE_WIDTH - 1; y >= 1; y--)
            {
              if (RotationEdgeImage[y * MAX_IMAGE_WIDTH + x])
              {
                unVisibleEdgeLineCheck[RotationEdgeImage[y*MAX_IMAGE_WIDTH + x]] = 1;
                break;
              }
              if (RotationEdgeImage[y * MAX_IMAGE_WIDTH + x - 1])
              {
                unVisibleEdgeLineCheck[RotationEdgeImage[y*MAX_IMAGE_WIDTH + x - 1]] = 1;
                break;
              }
              if (RotationEdgeImage[y * MAX_IMAGE_WIDTH + x + 1])
              {
                unVisibleEdgeLineCheck[RotationEdgeImage[y*MAX_IMAGE_WIDTH + x + 1]] = 1;
                break;
              }
            }
          }

          tabletCenterX = 320;
          tabletCenterY = 240;
          tabletCenterZ = 240;

          face1Height = tabletCenterZ - adjustMiddleHeight;
          face2Height = tabletCenterZ;

          XAxisDataMakeCount = 0;
          for(tAngleX = - SMALL_SIZE_ANGLE1_RANGE; tAngleX <= SMALL_SIZE_ANGLE1_RANGE; tAngleX++)
          {
            for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
            {
              firstTransformForFace1[m][0] = rotateTransform[m][0];
              firstTransformForFace1[m][1] = ((rotateTransform[m][1] - tabletCenterY)*CosData[AngleXZeroPos + tAngleX * 2] - (face1Height - tabletCenterZ)*SinData[AngleXZeroPos + tAngleX * 2]) / 1024 + tabletCenterY;
              firstTransformForFace1[m][2] = ((rotateTransform[m][1] - tabletCenterY)*SinData[AngleXZeroPos + tAngleX * 2] + (face1Height - tabletCenterZ)*CosData[AngleXZeroPos + tAngleX * 2]) / 1024 + tabletCenterZ;
            }

            for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
            {
              firstTransformForFace2[m][0] = rotateTransform[m][0];
              firstTransformForFace2[m][1] = ((rotateTransform[m][1] - tabletCenterY)*CosData[AngleXZeroPos + tAngleX * 2] - (face2Height - tabletCenterZ)*SinData[AngleXZeroPos + tAngleX * 2]) / 1024 + tabletCenterY;
              firstTransformForFace2[m][2] = ((rotateTransform[m][1] - tabletCenterY)*SinData[AngleXZeroPos + tAngleX * 2] + (face2Height - tabletCenterZ)*CosData[AngleXZeroPos + tAngleX * 2]) / 1024 + tabletCenterZ;
            }

            for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
            {
              SecondTransformForFace1[m][1] = firstTransformForFace1[m][1];
              if (tAngleY < 0)
              {
                SecondTransformForFace1[m][0] = ((firstTransformForFace1[m][0] - tabletCenterX)*CosData[-tAngleY * 2] + (firstTransformForFace1[m][2] - tabletCenterZ)*SinData[-tAngleY * 2]) / 1024 + tabletCenterX;
                SecondTransformForFace1[m][2] = (-(firstTransformForFace1[m][0] - tabletCenterX)*SinData[-tAngleY * 2] + (firstTransformForFace1[m][2] - tabletCenterZ)*CosData[-tAngleY * 2]) / 1024 + tabletCenterZ;
              }
              else
              {
                SecondTransformForFace1[m][0] = ((firstTransformForFace1[m][0] - tabletCenterX)*CosData[tAngleY * 2] - (firstTransformForFace1[m][2] - tabletCenterZ)*SinData[tAngleY * 2]) / 1024 + tabletCenterX;
                SecondTransformForFace1[m][2] = ((firstTransformForFace1[m][0] - tabletCenterX)*SinData[tAngleY * 2] + (firstTransformForFace1[m][2] - tabletCenterZ)*CosData[tAngleY * 2]) / 1024 + tabletCenterZ;
              }
            }

            for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
            {
              SecondTransformForFace2[m][1] = firstTransformForFace2[m][1];
              if (tAngleY < 0)
              {
                SecondTransformForFace2[m][0] = ((firstTransformForFace2[m][0] - tabletCenterX)*CosData[-tAngleY * 2] + (firstTransformForFace2[m][2] - tabletCenterZ)*SinData[-tAngleY * 2]) / 1024 + tabletCenterX;
                SecondTransformForFace2[m][2] = (-(firstTransformForFace2[m][0] - tabletCenterX)*SinData[-tAngleY * 2] + (firstTransformForFace2[m][2] - tabletCenterZ)*CosData[-tAngleY * 2]) / 1024 + tabletCenterZ;
              }
              else
              {
                SecondTransformForFace2[m][0] = ((firstTransformForFace2[m][0] - tabletCenterX)*CosData[tAngleY * 2] - (firstTransformForFace2[m][2] - tabletCenterZ)*SinData[tAngleY * 2]) / 1024 + tabletCenterX;
                SecondTransformForFace2[m][2] = ((firstTransformForFace2[m][0] - tabletCenterX)*SinData[tAngleY * 2] + (firstTransformForFace2[m][2] - tabletCenterZ)*CosData[tAngleY * 2]) / 1024 + tabletCenterZ;
              }
            }

            if(SideAngle == MINUS_45_ANGLE_CAM)
            {
              for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
              {
                transfarentEdgeDataPoint[m][0] = ((SecondTransformForFace1[m][0] - tabletCenterX)*CosData[SIDE_CAMERA_ANGLE * 2] + (SecondTransformForFace1[m][1] - tabletCenterY)*SinData[SIDE_CAMERA_ANGLE * 2]) / 1024 + tabletCenterX;
                transfarentEdgeDataPoint[m][1] = (-(SecondTransformForFace1[m][0] - tabletCenterX)*SinData[SIDE_CAMERA_ANGLE * 2] + (SecondTransformForFace1[m][1] - tabletCenterY)*CosData[SIDE_CAMERA_ANGLE * 2]) / 1024 + tabletCenterY;
                transfarentEdgeDataPoint[m][2] = SecondTransformForFace1[m][2];
              }
              for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
              {
                transfarentEdgeDataPoint2[m][0] = ((SecondTransformForFace2[m][0] - tabletCenterX)*CosData[SIDE_CAMERA_ANGLE * 2] + (SecondTransformForFace2[m][1] - tabletCenterY)*SinData[SIDE_CAMERA_ANGLE * 2]) / 1024 + tabletCenterX;
                transfarentEdgeDataPoint2[m][1] = (-(SecondTransformForFace2[m][0] - tabletCenterX)*SinData[SIDE_CAMERA_ANGLE * 2] + (SecondTransformForFace2[m][1] - tabletCenterY)*CosData[SIDE_CAMERA_ANGLE * 2]) / 1024 + tabletCenterY;
                transfarentEdgeDataPoint2[m][2] = SecondTransformForFace2[m][2];
              }
            }
            else if(SideAngle == ZERO_ANGLE_CAM)
            {
              for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
              {
                transfarentEdgeDataPoint[m][0] = ((SecondTransformForFace1[m][0] - tabletCenterX)*CosData[0] - (SecondTransformForFace1[m][1] - tabletCenterY)*SinData[0]) / 1024 + tabletCenterX;
                transfarentEdgeDataPoint[m][1] = ((SecondTransformForFace1[m][0] - tabletCenterX)*SinData[0] + (SecondTransformForFace1[m][1] - tabletCenterY)*CosData[0]) / 1024 + tabletCenterY;

                transfarentEdgeDataPoint[m][2] = SecondTransformForFace1[m][2];
              }
              for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
              {
                transfarentEdgeDataPoint2[m][0] = ((SecondTransformForFace2[m][0] - tabletCenterX)*CosData[0] - (SecondTransformForFace2[m][1] - tabletCenterY)*SinData[0]) / 1024 + tabletCenterX;
                transfarentEdgeDataPoint2[m][1] = ((SecondTransformForFace2[m][0] - tabletCenterX)*SinData[0] + (SecondTransformForFace2[m][1] - tabletCenterY)*CosData[0]) / 1024 + tabletCenterY;

                transfarentEdgeDataPoint2[m][2] = SecondTransformForFace2[m][2];
              }
            }
            else if(SideAngle == PLUS_45_ANGLE_CAM)
            {
              for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
              {
                transfarentEdgeDataPoint[m][0] = ((SecondTransformForFace1[m][0] - tabletCenterX)*CosData[SIDE_CAMERA_ANGLE * 2] - (SecondTransformForFace1[m][1] - tabletCenterY)*SinData[SIDE_CAMERA_ANGLE * 2]) / 1024 + tabletCenterX;
                transfarentEdgeDataPoint[m][1] = ((SecondTransformForFace1[m][0] - tabletCenterX)*SinData[SIDE_CAMERA_ANGLE * 2] + (SecondTransformForFace1[m][1] - tabletCenterY)*CosData[SIDE_CAMERA_ANGLE * 2]) / 1024 + tabletCenterY;
                transfarentEdgeDataPoint[m][2] = SecondTransformForFace1[m][2];
              }
              for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
              {
                transfarentEdgeDataPoint2[m][0] = ((SecondTransformForFace2[m][0] - tabletCenterX)*CosData[SIDE_CAMERA_ANGLE * 2] - (SecondTransformForFace2[m][1] - tabletCenterY)*SinData[SIDE_CAMERA_ANGLE * 2]) / 1024 + tabletCenterX;
                transfarentEdgeDataPoint2[m][1] = ((SecondTransformForFace2[m][0] - tabletCenterX)*SinData[SIDE_CAMERA_ANGLE * 2] + (SecondTransformForFace2[m][1] - tabletCenterY)*CosData[SIDE_CAMERA_ANGLE * 2]) / 1024 + tabletCenterY;
                transfarentEdgeDataPoint2[m][2] = SecondTransformForFace2[m][2];
              }
            }

            startX1 = transfarentEdgeDataPoint[start_Number][0];
            startY1 = transfarentEdgeDataPoint[start_Number][2];
            startX2 = transfarentEdgeDataPoint2[start_Number][0];
            startY2 = transfarentEdgeDataPoint2[start_Number][2];

            endX1 = transfarentEdgeDataPoint[end_Number][0];
            endY1 = transfarentEdgeDataPoint[end_Number][2];
            endX2 = transfarentEdgeDataPoint2[end_Number][0];
            endY2 = transfarentEdgeDataPoint2[end_Number][2];

            SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startX1 = startX1 / 2;
            SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startY1 = startY1 / 2;
            SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startX2 = startX2 / 2;
            SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startY2 = startY2 / 2;

            SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endX1 = endX1 / 2;
            SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endY1 = endY1 / 2;
            SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endX2 = endX2 / 2;
            SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endY2 = endY2 / 2;

            shapeEndY = 0;

            lineMinX = MAX_IMAGE_WIDTH;
            lineMaxX = 0;
            lineMinY = MAX_IMAGE_HEIGHT;
            lineMaxY = 0;                                     
            for (m = 0; m < TabletSetupData.FrontShapeEdgePointCount; m++)
            {
              if (1)//unVisibleEdgeLineCheck[m])
              {
                tempX = transfarentEdgeDataPoint2[m][0];
                tempY = transfarentEdgeDataPoint2[m][2];

                if(tempX > 0 && tempX < MAX_IMAGE_WIDTH && tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
                {
                  if(!eraseEdgeLine[m])
                    tempImage[MAX_IMAGE_WIDTH * tempY + tempX] = 1;

                  if(shapeEndY < transfarentEdgeDataPoint2[m][2])
                    shapeEndY = transfarentEdgeDataPoint2[m][2];

                  if(lineMinX > tempX) lineMinX = tempX;
                  if(lineMaxX < tempX) lineMaxX = tempX;
                  if(lineMinY > tempY) lineMinY = tempY;
                  if(lineMaxY < tempY) lineMaxY = tempY;
                }
              }
            }

            tempCount = 0;
            for(y = lineMinY; y <= lineMaxY; y++)
            {
              for(x = lineMinX; x <= lineMaxX; x++)
              {
                if(tempImage[MAX_IMAGE_WIDTH * y + x] == 1)
                {
                  if(tempCount < 480)
                  {
                    smallSizeImage[SMALL_WIDTH * (y / 2) + (x / 2)] = 1;

                    tempCount++;
                  }

                  tempImage[MAX_IMAGE_WIDTH * y + x] = 0;
                }
              }
            }

            tempCount = 0;
            for(y = lineMinY / 2; y <= lineMaxY / 2; y++)
            {
              for(x = lineMinX / 2; x <= lineMaxX / 2; x++)
              {
                if(smallSizeImage[SMALL_WIDTH * y + x] == 1)
                {
                  if(tempCount < 240)
                  {
                    SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointBottom[tempCount * 2 + 0] = x;
                    SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointBottom[tempCount * 2 + 1] = y;

                    tempCount++;
                  }

                  smallSizeImage[SMALL_WIDTH * y + x] = 0;
                }
              }
            }

            SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointCountBottom = tempCount;
            SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].ShapeEndY = shapeEndY / 2;

            if(SideAngle == PLUS_45_ANGLE_CAM)
            {
              lineMinX = MAX_IMAGE_WIDTH;
              lineMaxX = 0;
              lineMinY = MAX_IMAGE_HEIGHT;
              lineMaxY = 0;
              for (y = endY1; y <= endY2; y++)
              {
                if((endY1 - endY2))
                {
                  tempX = (endX1 - endX2)*(y - endY1) / (endY1 - endY2) + endX1;

                  if(tempX > 0 && tempX < MAX_IMAGE_WIDTH && y > 0 && y < MAX_IMAGE_HEIGHT)
                  { 
                    tempImage[MAX_IMAGE_WIDTH * y + tempX] = 2;

                    if(lineMinX > tempX) lineMinX = tempX;
                    if(lineMaxX < tempX) lineMaxX = tempX;
                    if(lineMinY > y) lineMinY = y;
                    if(lineMaxY < y) lineMaxY = y;
                  }
                }
              }

              tempCount = 0;
              for(y = lineMinY; y <= lineMaxY; y++)
              {
                for(x = lineMinX; x <= lineMaxX; x++)
                {
                  if(tempImage[MAX_IMAGE_WIDTH * y + x] == 2)
                  {
                    if(tempCount < 480)
                    {
                      smallSizeImage[SMALL_WIDTH * (y / 2) + (x / 2)] = 2;

                      tempCount++;
                    }

                    tempImage[MAX_IMAGE_WIDTH * y + x] = 0;
                  }
                }
              }

              for(y = lineMinY / 2; y <= lineMaxY / 2; y++)
              {
                for(x = lineMinX / 2; x <= lineMaxX / 2; x++)
                {
                  if(smallSizeImage[SMALL_WIDTH * y + x] == 2)
                  {
                    if(SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointCountSideWall < MAX_TABLET_HEIGHT / 2)
                    {
                      SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointSideWall[SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointCountSideWall * 2 + 0] = x;
                      SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointSideWall[SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointCountSideWall * 2 + 1] = y;
                      SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointCountSideWall++;
                    }

                    smallSizeImage[SMALL_WIDTH * y + x] = 0;
                  }
                }
              }
            }
            else
            {
              lineMinX = MAX_IMAGE_WIDTH;
              lineMaxX = 0;
              lineMinY = MAX_IMAGE_HEIGHT;
              lineMaxY = 0;
              for (y = startY1; y <= startY2; y++)
              {
                if((startY1 - startY2))
                {
                  tempX = (startX1 - startX2)*(y - startY1) / (startY1 - startY2) + startX1;

                  if(tempX > 0 && tempX < MAX_IMAGE_WIDTH && y > 0 && y < MAX_IMAGE_HEIGHT)
                  {
                    tempImage[MAX_IMAGE_WIDTH * y + tempX]  = 3;

                    if(lineMinX > tempX) lineMinX = tempX;
                    if(lineMaxX < tempX) lineMaxX = tempX;
                    if(lineMinY > y) lineMinY = y;
                    if(lineMaxY < y) lineMaxY = y;
                  }
                }
              }

              tempCount = 0;
              for(y = lineMinY; y <= lineMaxY; y++)
              {
                for(x = lineMinX; x <= lineMaxX; x++)
                {
                  if(tempImage[MAX_IMAGE_WIDTH * y + x] == 3)
                  {
                    if(tempCount < 480)
                    {
                      smallSizeImage[SMALL_WIDTH * (y / 2) + (x / 2)] = 3;

                      tempCount++;
                    }

                    tempImage[MAX_IMAGE_WIDTH * y + x] = 0;
                  }
                }
              }

              for(y = lineMinY / 2; y <= lineMaxY / 2; y++)
              {
                for(x = lineMinX / 2; x <= lineMaxX / 2; x++)
                {
                  if(smallSizeImage[SMALL_WIDTH * y + x] == 3)
                  {
                    if(SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointCountSideWall < MAX_TABLET_HEIGHT / 2)
                    {
                      SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointSideWall[SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointCountSideWall * 2 + 0] = x;
                      SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointSideWall[SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointCountSideWall * 2 + 1] = y;
                      SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointCountSideWall++;
                    }

                    smallSizeImage[SMALL_WIDTH * y + x] = 0;
                  }
                }
              }
            }

            if(SideAngle == PLUS_45_ANGLE_CAM)
            {
              width = abs(SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endX1 - SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endX2);
              height = abs(SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endY1 - SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endY2);
            }
            else
            {
              width = abs(SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startX1 - SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startX2);
              height = abs(SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startY1 - SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startY2);
            }
            SideWallLength = sqrt((double)width * width + (double)height * height);

            if(MAX_TABLET_HEIGHT / 2 < SideWallLength)
              SideWallLength = MAX_TABLET_HEIGHT / 2;

            halfSideWallLength = SideWallLength / 2;

            shiftCount = 0;
            if(SideAngle == PLUS_45_ANGLE_CAM)
            {
              for(y = SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endY2 - SideWallLength; y <= SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endY2 - halfSideWallLength; y++)
              {
                tempX = 0;

                for(m = 0; m < SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointCountSideWall; m++)
                {
                  if(y == SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointSideWall[m*2+1])
                  {
                    tempX = SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointSideWall[m*2+0];
                    break;
                  }
                }

                if(tempX)
                {
                  SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].shiftTopLineX[shiftCount] = tempX - SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endX2;
                  SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].shiftTopLineY[shiftCount] = y - SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].endY2;
                  shiftCount++;
                }
              }
            }
            else
            {
              for(y = SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startY2 - SideWallLength; y <= SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startY2 - halfSideWallLength; y++)
              {
                tempX = 0;

                for(m = 0; m < SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointCountSideWall; m++)
                {
                  if(y == SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointSideWall[m*2+1])
                  {
                    tempX = SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].SideShapeEdgePointSideWall[m*2+0];
                    break;
                  }
                }

                if(tempX)
                {
                  SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].shiftTopLineX[shiftCount] = tempX - SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startX2;
                  SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].shiftTopLineY[shiftCount] = y - SmallSizeSideData[SideAngle].SideShapeData[ZAxisDataMakeCount][XAxisDataMakeCount].startY2;
                  shiftCount++;
                }
              }
            }

            XAxisDataMakeCount++;
          }

          ZAxisDataMakeCount++;
        }
      }
    }
  }
}
//---------------------------------------------------------------------------



void __fastcall TTabletSimulationForm::DebugData1DblClick(TObject *Sender)
{
  TRealSizeImageForm *RealSizeImageForm = new  TRealSizeImageForm(this);
  TTntImage *Image = (TTntImage*)Sender;
  RealSizeImageForm->SetImage(Image);
  RealSizeImageForm->ShowModal();
  delete RealSizeImageForm;
}
//---------------------------------------------------------------------------

void MakeINVMatrix(double *input[], double *output[], int size)
{
  // 이론 : 가우스-소거법 적용
  // 첨가행렬을 만든뒤, 첨가행렬을 역행렬으로만듬
  // 역행렬을 만들고자하는 행렬값을 단위행렬로 만들어주면됨
  // 단위행렬로 만드는과정에서 가우스-소거법을 활용

  int i,j,x,k,dim,A;
  double tmp;
  A = size;
  dim = A;

  double **mat = new double *[size];
  for(int i = 0; i < size; i++)
  {
    mat[i] = new double[size*2];
    memset(mat[i], 0, sizeof(double)*size*2);
  }

  for(i = 0; i < size; i++)
  {
    for(j = 0; j < size; j++)
    {
      mat[i][j] = input[i][j];
    }
  }


  for(i = 0; i < size; i++)    // 첨가행렬
  {
    for(j = dim; j < size*2; j++)
    {
      if(i == (j%size))  mat[i][j] = 1;
      else mat[i][j] = 0;
    }
  }

  for(i = 0; i < size; i++)
  {
    x = i;

    // i번쩨 열중에서 가장 큰 원소를 남아있는 n-i개 행중에서 구함
    for(j = i+1; j < size; j++)
    {
      if(mat[j][i] > mat[x][i]) x = j;

    }

    // x에는 가장 큰 원소를 가진 행의 위치정보가 담김
    // 가장 큰 원소를 가진행과 i번쨰 행을 서로 바꿈
    if(x != i)
    {
      for(k = 0; k < size*2; k++)
      {
        tmp = mat[i][k];
        mat[i][k] = mat[x][k];
        mat[x][k] = tmp;
      }
    }


    // 소거연산
    for(j = 0; j < size; j++)
    {
      if(j != i)
      {
        tmp = mat[j][i];
        for(k = 0; k < size * 2; k++)
        {
          mat[j][k] -= (mat[i][k] / mat[i][i]) * tmp;
        }
      }

      else
      {
        tmp = mat[j][i];
        for(k = 0; k < dim + dim; k++)
        {
          mat[j][k] /= tmp;
        }
      }

    }

  }

  for(i = 0; i < size; i++)
  {
    for(j = A; j < size*2; j++)
    {
      output[i][j-A] = mat[i][j];
    }
  }

  
  //동적 메모리 해제
  for(int i = 0; i < size; i++)
  {
    delete[] mat;
  }

}

void __fastcall TTabletSimulationForm::Image11MouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
  XAxisEdit->Text = IntToStr(X);
  YAxisEdit->Text = IntToStr(Y);

  if(X > 0 && X < Image11->Picture->Bitmap->Width &&
      Y > 0 && Y < Image11->Picture->Bitmap->Height)
  {
    Byte *ptr;
    ptr = (Byte*)Image11->Picture->Bitmap->ScanLine[Y];

    TntEdit1->Text = IntToStr(ptr[3*X + 0]);
    TntEdit2->Text = IntToStr(ptr[3*X + 1]);
    TntEdit3->Text = IntToStr(ptr[3*X + 2]);
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::TrackBar5Change(TObject *Sender)
{
  int threshold = TrackBar5->Position;

  int x, y;
  int tempAddress;
  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  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;

      if(OneColorImage[tempAddress] < threshold)
      {
        ptr[3*x + 0] = OneColorImage[tempAddress];
        ptr[3*x + 1] = OneColorImage[tempAddress];
        ptr[3*x + 2] = OneColorImage[tempAddress];
      }
      else
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 0;
      }
    }
  }

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

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

void __fastcall TTabletSimulationForm::Button9Click(TObject *Sender)
{
  int x, y;
  int tempAddress;

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  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] = ColorSourceImage[tempAddress * 3 + 0];
      ptr[3*x + 1] = ColorSourceImage[tempAddress * 3 + 1];
      ptr[3*x + 2] = ColorSourceImage[tempAddress * 3 + 2];
    }
  }

  for(int m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    int tempX = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 0];
    int tempY = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 1];

    ptr = (Byte*)img->ScanLine[tempY];
    ptr[3*tempX + 0] = 0;
    ptr[3*tempX + 1] = 0;
    ptr[3*tempX + 2] = 255;
  }

  /*
  double **multipleMat = new double*[3];
  double **inverseMat = new double*[3];
  for(int i = 0; i < 3; i++)
  {
    multipleMat[i] = new double[3];
    inverseMat[i] = new double[3];
    memset(multipleMat[i],0,sizeof(double)* 3);
    memset(inverseMat[i],0,sizeof(double)* 3);
  }
  */

  double srcMat[MAX_IMAGE_WIDTH][3];
  double srcTransMat[3][MAX_IMAGE_WIDTH];
  double dstMat[MAX_IMAGE_WIDTH];
  double multipleMat2[3][MAX_IMAGE_WIDTH];
  double multipleMat[3][3];
  double inverseMat[3][3];

  memset(srcMat, 0, sizeof(double) * MAX_IMAGE_WIDTH * 3);
  memset(srcTransMat, 0, sizeof(double) * MAX_IMAGE_WIDTH * 3);
  memset(dstMat, 0, sizeof(double) * MAX_IMAGE_WIDTH);
  memset(multipleMat2, 0, sizeof(double) * MAX_IMAGE_WIDTH * 3);

  memset(multipleMat, 0, sizeof(double) * 3 * 3);
  memset(inverseMat, 0, sizeof(double) * 3 * 3);

  for(int m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    int tempX = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 0];
    int tempY = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 1];

    srcMat[m][0] = tempX * tempX;
    srcMat[m][1] = tempX;
    srcMat[m][2] = 1;

    srcTransMat[0][m] = tempX * tempX;
    srcTransMat[1][m] = tempX;
    srcTransMat[2][m] = 1;

    dstMat[m] = tempY;
  }

  for(int m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    multipleMat[0][0] += srcTransMat[0][m] * srcMat[m][0];
    multipleMat[0][1] += srcTransMat[0][m] * srcMat[m][1];
    multipleMat[0][2] += srcTransMat[0][m] * srcMat[m][2];

    multipleMat[1][0] += srcTransMat[1][m] * srcMat[m][0];
    multipleMat[1][1] += srcTransMat[1][m] * srcMat[m][1];
    multipleMat[1][2] += srcTransMat[1][m] * srcMat[m][2];

    multipleMat[2][0] += srcTransMat[2][m] * srcMat[m][0];
    multipleMat[2][1] += srcTransMat[2][m] * srcMat[m][1];
    multipleMat[2][2] += srcTransMat[2][m] * srcMat[m][2];
  }

  double detA;
  detA =   multipleMat[0][0] * (multipleMat[1][1] * multipleMat[2][2] - multipleMat[1][2] * multipleMat[2][1])
         - multipleMat[0][1] * (multipleMat[1][0] * multipleMat[2][2] - multipleMat[1][2] * multipleMat[2][0])
         + multipleMat[0][2] * (multipleMat[1][0] * multipleMat[2][1] - multipleMat[1][1] * multipleMat[2][0]);

  inverseMat[0][0] = (multipleMat[1][1] * multipleMat[2][2] - multipleMat[2][1] * multipleMat[1][2]) / detA;
  inverseMat[0][1] = (multipleMat[0][2] * multipleMat[2][1] - multipleMat[0][1] * multipleMat[2][2]) / detA;
  inverseMat[0][2] = (multipleMat[0][1] * multipleMat[1][2] - multipleMat[0][2] * multipleMat[1][1]) / detA;

  inverseMat[1][0] = (multipleMat[1][2] * multipleMat[2][0] - multipleMat[1][0] * multipleMat[2][2]) / detA;
  inverseMat[1][1] = (multipleMat[0][0] * multipleMat[2][2] - multipleMat[0][2] * multipleMat[2][0]) / detA;
  inverseMat[1][2] = (multipleMat[1][0] * multipleMat[0][2] - multipleMat[0][0] * multipleMat[1][2]) / detA;

  inverseMat[2][0] = (multipleMat[1][0] * multipleMat[2][1] - multipleMat[2][0] * multipleMat[1][1]) / detA;
  inverseMat[2][1] = (multipleMat[2][0] * multipleMat[0][1] - multipleMat[0][0] * multipleMat[2][1]) / detA;
  inverseMat[2][2] = (multipleMat[0][0] * multipleMat[1][1] - multipleMat[1][0] * multipleMat[0][1]) / detA;

  //MakeINVMatrix(multipleMat, inverseMat, 3);

  for(int m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    multipleMat2[0][m] += (inverseMat[0][0] * srcTransMat[0][m] + inverseMat[0][1] * srcTransMat[1][m] + inverseMat[0][2] * srcTransMat[2][m]);
    multipleMat2[1][m] += (inverseMat[1][0] * srcTransMat[0][m] + inverseMat[1][1] * srcTransMat[1][m] + inverseMat[1][2] * srcTransMat[2][m]);
    multipleMat2[2][m] += (inverseMat[2][0] * srcTransMat[0][m] + inverseMat[2][1] * srcTransMat[1][m] + inverseMat[2][2] * srcTransMat[2][m]);
  }

  double a, b, c;
  a = b = c = 0;

  for(int m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    a += multipleMat2[0][m] * dstMat[m];
    b += multipleMat2[1][m] * dstMat[m];
    c += multipleMat2[2][m] * dstMat[m];
  }

  for(int m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    int tempX = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 0];
    int tempY = a * tempX * tempX + b * tempX + c;

    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] = 255;
      ptr[3*tempX + 2] = 0;
    }
  }

  Image11->Picture->Bitmap->Assign(img);
  Image11->Refresh();
  
  delete img;

  //delete multipleMat;
  //delete inverseMat;
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::Button10Click(TObject *Sender)
{
  int x, y;
  int tempAddress;

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  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] = ColorSourceImage[tempAddress * 3 + 0];
      ptr[3*x + 1] = ColorSourceImage[tempAddress * 3 + 1];
      ptr[3*x + 2] = ColorSourceImage[tempAddress * 3 + 2];
    }
  }

  for(int m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    int tempX = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 0];
    int tempY = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 1];

    ptr = (Byte*)img->ScanLine[tempY];
    ptr[3*tempX + 0] = 0;
    ptr[3*tempX + 1] = 0;
    ptr[3*tempX + 2] = 255;
  }

  int minX, minY;
  minX = MAX_IMAGE_WIDTH;
  minY = MAX_IMAGE_HEIGHT;

  for(int m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    int tempX = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 0];
    int tempY = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 1];

    if(tempX < minX) minX = tempX;
    if(tempY < minY) minY = tempY;
  }                                       

  unsigned char smallSizeBinaryImage[HALF_IMAGE_WIDTH * HALF_IMAGE_HEIGHT];
  memset(smallSizeBinaryImage, 0, HALF_IMAGE_WIDTH * HALF_IMAGE_HEIGHT);

  for(int m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    int tempX = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 0];
    int tempY = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 1];

    int shiftX = tempX - minX;
    int shiftY = tempY - minY;

    tempAddress = HALF_IMAGE_WIDTH * (shiftY / 2) + (shiftX / 2);

    smallSizeBinaryImage[tempAddress] = 1;
  }

  int smallSizeShapeBottomLine[HALF_IMAGE_WIDTH][2];
  int smallSizeShapeBottomLineCount;

  smallSizeShapeBottomLineCount = 0;
  for(x = 0; x < HALF_IMAGE_WIDTH; x++)
  {
    for(y = 0; y < HALF_IMAGE_HEIGHT; y++)
    {
      tempAddress = HALF_IMAGE_WIDTH * y + x;

      if(smallSizeBinaryImage[tempAddress])
      {
        if(smallSizeShapeBottomLineCount < HALF_IMAGE_WIDTH)
        {
          smallSizeShapeBottomLine[smallSizeShapeBottomLineCount][0] = x;
          smallSizeShapeBottomLine[smallSizeShapeBottomLineCount][1] = y;
          smallSizeShapeBottomLineCount++;
        }
        break;
      }
    }
  }

  /*
  double xPositionMat[HALF_IMAGE_WIDTH][3];
  double xPositionTransMat[3][HALF_IMAGE_WIDTH];
  double yPositionMat[HALF_IMAGE_WIDTH];
  double squareMultipleMat[3][3];
  double inverseMat[3][3];
  double resultMultipleMat[3][HALF_IMAGE_WIDTH];
  double detA;

  memset(xPositionMat, 0, sizeof(double) * HALF_IMAGE_WIDTH * 3);
  memset(xPositionTransMat, 0, sizeof(double) * HALF_IMAGE_WIDTH * 3);
  memset(yPositionMat, 0, sizeof(double) * HALF_IMAGE_WIDTH);
  memset(squareMultipleMat, 0, sizeof(double) * 3 * 3);
  memset(inverseMat, 0, sizeof(double) * 3 * 3);
  memset(resultMultipleMat, 0, sizeof(double) * 3 * HALF_IMAGE_WIDTH);

  for(int m = 0; m < smallSizeShapeBottomLineCount; m++)
  {
    int tempX = smallSizeShapeBottomLine[m][0];
    int tempY = smallSizeShapeBottomLine[m][1];

    xPositionMat[m][0] = tempX * tempX;
    xPositionMat[m][1] = tempX;
    xPositionMat[m][2] = 1;

    xPositionTransMat[0][m] = tempX * tempX;
    xPositionTransMat[1][m] = tempX;
    xPositionTransMat[2][m] = 1;

    yPositionMat[m] = tempY;
  }

  for(int m = 0; m < smallSizeShapeBottomLineCount; m++)
  {
    squareMultipleMat[0][0] += xPositionTransMat[0][m] * xPositionMat[m][0];
    squareMultipleMat[0][1] += xPositionTransMat[0][m] * xPositionMat[m][1];
    squareMultipleMat[0][2] += xPositionTransMat[0][m] * xPositionMat[m][2];

    squareMultipleMat[1][0] += xPositionTransMat[1][m] * xPositionMat[m][0];
    squareMultipleMat[1][1] += xPositionTransMat[1][m] * xPositionMat[m][1];
    squareMultipleMat[1][2] += xPositionTransMat[1][m] * xPositionMat[m][2];

    squareMultipleMat[2][0] += xPositionTransMat[2][m] * xPositionMat[m][0];
    squareMultipleMat[2][1] += xPositionTransMat[2][m] * xPositionMat[m][1];
    squareMultipleMat[2][2] += xPositionTransMat[2][m] * xPositionMat[m][2];
  }
  
  detA =   squareMultipleMat[0][0] * (squareMultipleMat[1][1] * squareMultipleMat[2][2] - squareMultipleMat[1][2] * squareMultipleMat[2][1])
         - squareMultipleMat[0][1] * (squareMultipleMat[1][0] * squareMultipleMat[2][2] - squareMultipleMat[1][2] * squareMultipleMat[2][0])
         + squareMultipleMat[0][2] * (squareMultipleMat[1][0] * squareMultipleMat[2][1] - squareMultipleMat[1][1] * squareMultipleMat[2][0]);

  inverseMat[0][0] = (squareMultipleMat[1][1] * squareMultipleMat[2][2] - squareMultipleMat[2][1] * squareMultipleMat[1][2]) / detA;
  inverseMat[0][1] = (squareMultipleMat[0][2] * squareMultipleMat[2][1] - squareMultipleMat[0][1] * squareMultipleMat[2][2]) / detA;
  inverseMat[0][2] = (squareMultipleMat[0][1] * squareMultipleMat[1][2] - squareMultipleMat[0][2] * squareMultipleMat[1][1]) / detA;

  inverseMat[1][0] = (squareMultipleMat[1][2] * squareMultipleMat[2][0] - squareMultipleMat[1][0] * squareMultipleMat[2][2]) / detA;
  inverseMat[1][1] = (squareMultipleMat[0][0] * squareMultipleMat[2][2] - squareMultipleMat[0][2] * squareMultipleMat[2][0]) / detA;
  inverseMat[1][2] = (squareMultipleMat[1][0] * squareMultipleMat[0][2] - squareMultipleMat[0][0] * squareMultipleMat[1][2]) / detA;

  inverseMat[2][0] = (squareMultipleMat[1][0] * squareMultipleMat[2][1] - squareMultipleMat[2][0] * squareMultipleMat[1][1]) / detA;
  inverseMat[2][1] = (squareMultipleMat[2][0] * squareMultipleMat[0][1] - squareMultipleMat[0][0] * squareMultipleMat[2][1]) / detA;
  inverseMat[2][2] = (squareMultipleMat[0][0] * squareMultipleMat[1][1] - squareMultipleMat[1][0] * squareMultipleMat[0][1]) / detA;

  for(int m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    resultMultipleMat[0][m] += (inverseMat[0][0] * xPositionTransMat[0][m] + inverseMat[0][1] * xPositionTransMat[1][m] + inverseMat[0][2] * xPositionTransMat[2][m]);
    resultMultipleMat[1][m] += (inverseMat[1][0] * xPositionTransMat[0][m] + inverseMat[1][1] * xPositionTransMat[1][m] + inverseMat[1][2] * xPositionTransMat[2][m]);
    resultMultipleMat[2][m] += (inverseMat[2][0] * xPositionTransMat[0][m] + inverseMat[2][1] * xPositionTransMat[1][m] + inverseMat[2][2] * xPositionTransMat[2][m]);
  }

  double a, b, c;
  a = b = c = 0;

  for(int m = 0; m < smallSizeShapeBottomLineCount; m++)
  {
    a += resultMultipleMat[0][m] * yPositionMat[m];
    b += resultMultipleMat[1][m] * yPositionMat[m];
    c += resultMultipleMat[2][m] * yPositionMat[m];
  }

  for(int m = 0; m < smallSizeShapeBottomLineCount; m++)
  {
    int tempX = smallSizeShapeBottomLine[m][0];
    int tempY = a * tempX * tempX + b * tempX + c;

    int tempX2 = tempX * 2 + minX;
    int tempY2 = tempY * 2 + minY;

    if(tempX2 > 0 && tempX2 < MAX_IMAGE_WIDTH && tempY2 > 0 && tempY2 < MAX_IMAGE_HEIGHT)
    {
      ptr = (Byte*)img->ScanLine[tempY2];
      ptr[3*tempX2 + 0] = 0;
      ptr[3*tempX2 + 1] = 255;
      ptr[3*tempX2 + 2] = 0;
    }
  }

  Image11->Picture->Bitmap->Assign(img);
  Image11->Refresh();
  */

  /*
  int xPositionMat[HALF_IMAGE_WIDTH][3];
  int xPositionTransMat[3][HALF_IMAGE_WIDTH];
  int yPositionMat[HALF_IMAGE_WIDTH];
  int squareMultipleMat[3][3];
  int inverseMat[3][3];
  int resultMultipleMat[3][HALF_IMAGE_WIDTH];
  int detA;

  int stPoint;
  int endPoint;
  for(int m = 0; m < smallSizeShapeBottomLineCount; m++)
  {
    stPoint = max(0, m - 5);
    endPoint = min(smallSizeShapeBottomLineCount - 1, m + 5);
    
    memset(xPositionMat, 0, sizeof(int) * HALF_IMAGE_WIDTH * 3);
    memset(xPositionTransMat, 0, sizeof(int) * HALF_IMAGE_WIDTH * 3);
    memset(yPositionMat, 0, sizeof(int) * HALF_IMAGE_WIDTH);
    memset(squareMultipleMat, 0, sizeof(int) * 3 * 3);
    memset(inverseMat, 0, sizeof(int) * 3 * 3);
    memset(resultMultipleMat, 0, sizeof(int) * 3 * HALF_IMAGE_WIDTH);

    for(int k = stPoint; k < endPoint; k++)
    {
      int tempX = smallSizeShapeBottomLine[k][0];
      int tempY = smallSizeShapeBottomLine[k][1];

      xPositionMat[k][0] = tempX * tempX;
      xPositionMat[k][1] = tempX;
      xPositionMat[k][2] = 1;

      xPositionTransMat[0][k] = tempX * tempX;
      xPositionTransMat[1][k] = tempX;
      xPositionTransMat[2][k] = 1;

      yPositionMat[k] = tempY;
    }

    for(int k = stPoint; k < endPoint; k++)
    {
      squareMultipleMat[0][0] += xPositionTransMat[0][k] * xPositionMat[k][0];
      squareMultipleMat[0][1] += xPositionTransMat[0][k] * xPositionMat[k][1];
      squareMultipleMat[0][2] += xPositionTransMat[0][k] * xPositionMat[k][2];

      squareMultipleMat[1][0] += xPositionTransMat[1][k] * xPositionMat[k][0];
      squareMultipleMat[1][1] += xPositionTransMat[1][k] * xPositionMat[k][1];
      squareMultipleMat[1][2] += xPositionTransMat[1][k] * xPositionMat[k][2];

      squareMultipleMat[2][0] += xPositionTransMat[2][k] * xPositionMat[k][0];
      squareMultipleMat[2][1] += xPositionTransMat[2][k] * xPositionMat[k][1];
      squareMultipleMat[2][2] += xPositionTransMat[2][k] * xPositionMat[k][2];
    }
  
    detA =   squareMultipleMat[0][0] * (squareMultipleMat[1][1] * squareMultipleMat[2][2] - squareMultipleMat[1][2] * squareMultipleMat[2][1])
           - squareMultipleMat[0][1] * (squareMultipleMat[1][0] * squareMultipleMat[2][2] - squareMultipleMat[1][2] * squareMultipleMat[2][0])
           + squareMultipleMat[0][2] * (squareMultipleMat[1][0] * squareMultipleMat[2][1] - squareMultipleMat[1][1] * squareMultipleMat[2][0]);

    inverseMat[0][0] = (squareMultipleMat[1][1] * squareMultipleMat[2][2] - squareMultipleMat[2][1] * squareMultipleMat[1][2]);
    inverseMat[0][1] = (squareMultipleMat[0][2] * squareMultipleMat[2][1] - squareMultipleMat[0][1] * squareMultipleMat[2][2]);
    inverseMat[0][2] = (squareMultipleMat[0][1] * squareMultipleMat[1][2] - squareMultipleMat[0][2] * squareMultipleMat[1][1]);

    inverseMat[1][0] = (squareMultipleMat[1][2] * squareMultipleMat[2][0] - squareMultipleMat[1][0] * squareMultipleMat[2][2]);
    inverseMat[1][1] = (squareMultipleMat[0][0] * squareMultipleMat[2][2] - squareMultipleMat[0][2] * squareMultipleMat[2][0]);
    inverseMat[1][2] = (squareMultipleMat[1][0] * squareMultipleMat[0][2] - squareMultipleMat[0][0] * squareMultipleMat[1][2]);

    inverseMat[2][0] = (squareMultipleMat[1][0] * squareMultipleMat[2][1] - squareMultipleMat[2][0] * squareMultipleMat[1][1]);
    inverseMat[2][1] = (squareMultipleMat[2][0] * squareMultipleMat[0][1] - squareMultipleMat[0][0] * squareMultipleMat[2][1]);
    inverseMat[2][2] = (squareMultipleMat[0][0] * squareMultipleMat[1][1] - squareMultipleMat[1][0] * squareMultipleMat[0][1]);

    for(int k = stPoint; k < endPoint; k++)
    {
      resultMultipleMat[0][k] += (inverseMat[0][0] * xPositionTransMat[0][k] + inverseMat[0][1] * xPositionTransMat[1][k] + inverseMat[0][2] * xPositionTransMat[2][k]);
      resultMultipleMat[1][k] += (inverseMat[1][0] * xPositionTransMat[0][k] + inverseMat[1][1] * xPositionTransMat[1][k] + inverseMat[1][2] * xPositionTransMat[2][k]);
      resultMultipleMat[2][k] += (inverseMat[2][0] * xPositionTransMat[0][k] + inverseMat[2][1] * xPositionTransMat[1][k] + inverseMat[2][2] * xPositionTransMat[2][k]);
    }

    int a, b, c;
    a = b = c = 0;

    for(int k = stPoint; k < endPoint; k++)
    {
      a += resultMultipleMat[0][k] * yPositionMat[k];
      b += resultMultipleMat[1][k] * yPositionMat[k];
      c += resultMultipleMat[2][k] * yPositionMat[k];
    }

    for(int k = stPoint; k < endPoint; k++)
    {
      int tempX = smallSizeShapeBottomLine[k][0];
      int tempY = (a * tempX * tempX + b * tempX + c) / detA;

      int tempX2 = tempX * 2 + minX;
      int tempY2 = tempY * 2 + minY;

      if(tempX2 > 0 && tempX2 < MAX_IMAGE_WIDTH && tempY2 > 0 && tempY2 < MAX_IMAGE_HEIGHT)
      {
        ptr = (Byte*)img->ScanLine[tempY2];
        ptr[3*tempX2 + 0] = 0;
        ptr[3*tempX2 + 1] = 255;
        ptr[3*tempX2 + 2] = 0;
      }
    }

    Image11->Picture->Bitmap->Assign(img);
    Image11->Refresh();
  }
  */

  long long xPositionMat[MAX_IMAGE_WIDTH][3];
  long long xPositionTransMat[3][MAX_IMAGE_WIDTH];
  long long yPositionMat[MAX_IMAGE_WIDTH];
  long long squareMultipleMat[3][3];
  long long inverseMat[3][3];
  long long resultMultipleMat[3][MAX_IMAGE_WIDTH];
  long long detA;

  int stPoint;
  int endPoint;

  for(int m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    stPoint = max(0, m - 20);
    endPoint = min(TabletETCMatchingResult.tabletShapeBottomLineCount - 1, m + 20);

    memset(xPositionMat, 0, sizeof(long long) * MAX_IMAGE_WIDTH * 3);
    memset(xPositionTransMat, 0, sizeof(long long) * MAX_IMAGE_WIDTH * 3);
    memset(yPositionMat, 0, sizeof(long long) * MAX_IMAGE_WIDTH);
    memset(squareMultipleMat, 0, sizeof(long long) * 3 * 3);
    memset(inverseMat, 0, sizeof(long long) * 3 * 3);
    memset(resultMultipleMat, 0, sizeof(long long) * 3 * MAX_IMAGE_WIDTH);

    for(int k = stPoint; k < endPoint; k++)
    {
      int tempX = TabletETCMatchingResult.tabletShapeBottomLine[k * 2 + 0] - minX;
      int tempY = TabletETCMatchingResult.tabletShapeBottomLine[k * 2 + 1] - minY;

      xPositionMat[k][0] = tempX * tempX;
      xPositionMat[k][1] = tempX;
      xPositionMat[k][2] = 1;

      xPositionTransMat[0][k] = tempX * tempX;
      xPositionTransMat[1][k] = tempX;
      xPositionTransMat[2][k] = 1;

      yPositionMat[k] = tempY;
    }

    for(int k = stPoint; k < endPoint; k++)
    {
      squareMultipleMat[0][0] += xPositionTransMat[0][k] * xPositionMat[k][0];
      squareMultipleMat[0][1] += xPositionTransMat[0][k] * xPositionMat[k][1];
      squareMultipleMat[0][2] += xPositionTransMat[0][k] * xPositionMat[k][2];

      squareMultipleMat[1][0] += xPositionTransMat[1][k] * xPositionMat[k][0];
      squareMultipleMat[1][1] += xPositionTransMat[1][k] * xPositionMat[k][1];
      squareMultipleMat[1][2] += xPositionTransMat[1][k] * xPositionMat[k][2];

      squareMultipleMat[2][0] += xPositionTransMat[2][k] * xPositionMat[k][0];
      squareMultipleMat[2][1] += xPositionTransMat[2][k] * xPositionMat[k][1];
      squareMultipleMat[2][2] += xPositionTransMat[2][k] * xPositionMat[k][2];
    }
  
    detA =   squareMultipleMat[0][0] * (squareMultipleMat[1][1] * squareMultipleMat[2][2] - squareMultipleMat[1][2] * squareMultipleMat[2][1])
           - squareMultipleMat[0][1] * (squareMultipleMat[1][0] * squareMultipleMat[2][2] - squareMultipleMat[1][2] * squareMultipleMat[2][0])
           + squareMultipleMat[0][2] * (squareMultipleMat[1][0] * squareMultipleMat[2][1] - squareMultipleMat[1][1] * squareMultipleMat[2][0]);

    inverseMat[0][0] = (squareMultipleMat[1][1] * squareMultipleMat[2][2] - squareMultipleMat[2][1] * squareMultipleMat[1][2]);
    inverseMat[0][1] = (squareMultipleMat[0][2] * squareMultipleMat[2][1] - squareMultipleMat[0][1] * squareMultipleMat[2][2]);
    inverseMat[0][2] = (squareMultipleMat[0][1] * squareMultipleMat[1][2] - squareMultipleMat[0][2] * squareMultipleMat[1][1]);

    inverseMat[1][0] = (squareMultipleMat[1][2] * squareMultipleMat[2][0] - squareMultipleMat[1][0] * squareMultipleMat[2][2]);
    inverseMat[1][1] = (squareMultipleMat[0][0] * squareMultipleMat[2][2] - squareMultipleMat[0][2] * squareMultipleMat[2][0]);
    inverseMat[1][2] = (squareMultipleMat[1][0] * squareMultipleMat[0][2] - squareMultipleMat[0][0] * squareMultipleMat[1][2]);

    inverseMat[2][0] = (squareMultipleMat[1][0] * squareMultipleMat[2][1] - squareMultipleMat[2][0] * squareMultipleMat[1][1]);
    inverseMat[2][1] = (squareMultipleMat[2][0] * squareMultipleMat[0][1] - squareMultipleMat[0][0] * squareMultipleMat[2][1]);
    inverseMat[2][2] = (squareMultipleMat[0][0] * squareMultipleMat[1][1] - squareMultipleMat[1][0] * squareMultipleMat[0][1]);

    for(int k = stPoint; k < endPoint; k++)
    {
      resultMultipleMat[0][k] += (inverseMat[0][0] * xPositionTransMat[0][k] + inverseMat[0][1] * xPositionTransMat[1][k] + inverseMat[0][2] * xPositionTransMat[2][k]);
      resultMultipleMat[1][k] += (inverseMat[1][0] * xPositionTransMat[0][k] + inverseMat[1][1] * xPositionTransMat[1][k] + inverseMat[1][2] * xPositionTransMat[2][k]);
      resultMultipleMat[2][k] += (inverseMat[2][0] * xPositionTransMat[0][k] + inverseMat[2][1] * xPositionTransMat[1][k] + inverseMat[2][2] * xPositionTransMat[2][k]);
    }

    long long a, b, c;
    a = b = c = 0;

    for(int k = stPoint; k < endPoint; k++)
    {
      a += resultMultipleMat[0][k] * yPositionMat[k];
      b += resultMultipleMat[1][k] * yPositionMat[k];
      c += resultMultipleMat[2][k] * yPositionMat[k];
    }

    for(int k = stPoint; k < endPoint; k++)
    {
      int tempX = TabletETCMatchingResult.tabletShapeBottomLine[k * 2 + 0] - minX;

      if(detA == 0)
      {
        continue;
      }
      int tempY = (a * tempX * tempX + b * tempX + c) / detA;

      int tempX2 = tempX + minX;
      int tempY2 = tempY + minY;

      if(tempX2 > 0 && tempX2 < MAX_IMAGE_WIDTH && tempY2 > 0 && tempY2 < MAX_IMAGE_HEIGHT)
      {
        ptr = (Byte*)img->ScanLine[tempY2];
        ptr[3*tempX2 + 0] = 0;
        ptr[3*tempX2 + 1] = 255;
        ptr[3*tempX2 + 2] = 0;
      }
    }

    Image11->Picture->Bitmap->Assign(img);
    Image11->Refresh();
  }

  delete img;

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


void __fastcall TTabletSimulationForm::UpDown6Click(TObject *Sender,
      TUDBtnType Button)
{
  int rEdgeData[4000][2];
  int edgeData[4000][2];
  int edgeDataCount;
  int cosData[720];              //3k
  int sinData[720];              //3k
  
  for(int m = 0 ; m < 720; m++)
  {
    cosData[m] = cos((float)m/2.0*PI/180.0)*1024.0;
    sinData[m] = sin((float)m/2.0*PI/180.0)*1024.0;
  }
  
  int angle;
  int z = 1;

  angle = UpDown6->Position;

  int x, y;

  unsigned char rotationImage[640 * 480 * 3];
  memset(rotationImage, 0, 640 * 480 * 3);

  int cX, cY;
  int rX, rY;
  int tempAddress1, tempAddress2;

  cX = 320;
  cY = 240;

  memset(rEdgeData, 0, sizeof(int) * 4000 * 2);

  int tempCosV, tempSinV;
  tempCosV = cosData[(angle + 720) % 720];
  tempSinV = sinData[(angle + 720) % 720];
    
  int m;
  int tempX, tempY;

  int shapeCenterX, shapeCenterY;
  int tempCount;
  tempCount = shapeCenterX = shapeCenterY = 0;
  for(m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    x = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 0];
    y = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 1];

    tempCount++;
    shapeCenterX += x;
    shapeCenterY += y;
  }

  if(tempCount)
  {
    shapeCenterX /= tempCount;
    shapeCenterY /= tempCount;  
  }
    
  for(m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    x = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 0];
    y = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 1];

    rX =  x;
    rY =  (((y - cY) * tempSinV + (z) * tempCosV) / 1024) + cY;

    if(rX >= 0 && rX < 640 && rY >= 0 && rY < 480)
    {
      rEdgeData[m][0] = rX;
      rEdgeData[m][1] = rY;
    }
  }

  for(m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    x = rEdgeData[m][0];
    y = rEdgeData[m][1];

    if(x > 0 && x < 640 && y > 0 && y < 480)
    {
      tempAddress2 = 640 * y + x;

      rotationImage[tempAddress2 * 3 + 0] = 0;
      rotationImage[tempAddress2 * 3 + 1] = 255;
      rotationImage[tempAddress2 * 3 + 2] = 255;
    }
  }

  for(m = 0; m < TabletETCMatchingResult.tabletShapeBottomLineCount; m++)
  {
    x = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 0];
    y = TabletETCMatchingResult.tabletShapeBottomLine[m * 2 + 1];

    if(x > 0 && x < 640 && y > 0 && y < 480)
    {
      tempAddress2 = 640 * y + x;

      rotationImage[tempAddress2 * 3 + 0] = 0;
      rotationImage[tempAddress2 * 3 + 1] = 255;
      rotationImage[tempAddress2 * 3 + 2] = 0;
    }
  }

  Graphics::TBitmap *tempImage = new Graphics::TBitmap;
  tempImage->Width = 640;
  tempImage->Height = 480;
  tempImage->PixelFormat = pf24bit;

  Byte *ptr;

  for(y = 0; y < 480; y++)
  {
    ptr = (Byte*)tempImage->ScanLine[y];
    for(x = 0; x < 640; x++)
    {
      tempAddress1 = 640 * y + x;

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

  Image11->Picture->Bitmap->Assign(tempImage);
  Image11->Refresh();

  delete tempImage;
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::TntUpDown1Click(TObject *Sender,
      TUDBtnType Button)
{
  int pageIndex;
  pageIndex = TntUpDown1->Position;

  TPanel *tempPanel;
  tempPanel = ((TPanel *)FindComponent("PagePanel"+IntToStr(pageIndex)));

  if(tempPanel)
  {
    tempPanel->BringToFront();
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::BitBtn1Click(TObject *Sender)
{
  AnsiString ImagePath = ImageRootEdit->Text;

  bool bError = false;
  if (!DirectoryExists(ImagePath))
  {
    ShowMessage("fail");
    bError = true;
  }

  ImagePath += "\\Background";

  if (!DirectoryExists(ImagePath))
  {
    ShowMessage("fail");
    bError = true;
  }


  if(!bError)
  {
    AnsiString filename;

    Graphics::TBitmap *img1;
    img1 = new Graphics::TBitmap();

    memset(testBackgroundImage, 0, SYSTEM_TOTAL_CAMERA_COUNT * MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3 * sizeof(int));
    memset(stdCount, 0, sizeof(int) * SYSTEM_TOTAL_CAMERA_COUNT);
    
    for(int imageIndex = 1; imageIndex <= 100; imageIndex++)
    {
      for(int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
      {
        if(CameraMapInfo[globalCameraIndex].CameraInspectPosition != CAMERA_POSITION_DISCONNECT &&
            CameraMapInfo[globalCameraIndex].CameraInspectPosition != CAMERA_POSITION_3D)
        {
          filename = ImagePath + "\\Image" + IntToStr(imageIndex) + "_C" + IntToStr(globalCameraIndex + 1) + ".bmp";

          if(FileExists(filename))
          {
            img1->LoadFromFile(filename);

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

            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;

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

            stdCount[globalCameraIndex]++;
            
            TImage *tempImage = (TImage *)FindComponent("BackGroundImage"+IntToStr(globalCameraIndex + 1));

            if(tempImage)
            {
              tempImage->Picture->Bitmap->Assign(img1);
              tempImage->Refresh();
            }
          }
        }

        Application->ProcessMessages();
      }
    }

    for(int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
    {
      if(CameraMapInfo[globalCameraIndex].CameraInspectPosition != CAMERA_POSITION_DISCONNECT &&
          CameraMapInfo[globalCameraIndex].CameraInspectPosition != CAMERA_POSITION_3D)
      {
        if(stdCount[globalCameraIndex])
        {
          int x, y;
          Byte *ptr;
          int tempAddress;

          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;

              testBackgroundImage[globalCameraIndex][tempAddress * 3 + 0] /= stdCount[globalCameraIndex];
              testBackgroundImage[globalCameraIndex][tempAddress * 3 + 1] /= stdCount[globalCameraIndex];
              testBackgroundImage[globalCameraIndex][tempAddress * 3 + 2] /= stdCount[globalCameraIndex];

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

        TImage *tempImage = (TImage *)FindComponent("BackGroundImage"+IntToStr(globalCameraIndex + 1));

        if(tempImage)
        {
          tempImage->Picture->Bitmap->Assign(img1);
          tempImage->Refresh();
        }
      }

      Application->ProcessMessages();
    }

    delete img1;
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::TntUpDown2Click(TObject *Sender,
      TUDBtnType Button)
{
  AnsiString ImagePath = ImageRootEdit->Text;

  bool bError = false;
  if (!DirectoryExists(ImagePath))
  {
    ShowMessage("fail");
    bError = true;
  }

  /*
  ImagePath += "\\Background";

  if (!DirectoryExists(ImagePath))
  {
    ShowMessage("fail");
    bError = true;
  }
  */

  ImagePath += "\\Object";

  if (!DirectoryExists(ImagePath))
  {
    ShowMessage("fail");
    bError = true;
  }

  int existDataCameraCount = 0;
  for(int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
  {
    if(CameraMapInfo[globalCameraIndex].CameraInspectPosition != CAMERA_POSITION_DISCONNECT &&
          CameraMapInfo[globalCameraIndex].CameraInspectPosition != CAMERA_POSITION_3D)
    {
      if(stdCount[globalCameraIndex])
      {
        existDataCameraCount++;
      }
    }
  }

  if(existDataCameraCount == 0)
  {
    bError = true;
  }

  memset(objStartNum, 0, sizeof(int) * SYSTEM_TOTAL_CAMERA_COUNT);
  memset(objEndNum, 0, sizeof(int) * SYSTEM_TOTAL_CAMERA_COUNT);

  AnsiString filename;
  
  for(int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
  {
    if(CameraMapInfo[globalCameraIndex].CameraInspectPosition != CAMERA_POSITION_DISCONNECT &&
        CameraMapInfo[globalCameraIndex].CameraInspectPosition != CAMERA_POSITION_3D)
    {
      if(stdCount[globalCameraIndex])
      {
        int minN = 10000;
        int maxN = 0;

        for(int imageIndex = 1; imageIndex <= 100; imageIndex++)
        {
          filename = ImagePath + "\\Image" + IntToStr(imageIndex) + "_C" + IntToStr(globalCameraIndex + 1) + ".bmp";

          if(FileExists(filename))
          {
            if(minN >= imageIndex)
            {
              minN = imageIndex;
            }

            if(maxN <= imageIndex)
            {
              maxN = imageIndex;
            }
          }
        }

        objStartNum[globalCameraIndex] = minN;
        objEndNum[globalCameraIndex] = maxN;
      }
    }
  }

  if(!bError)
  {
    int imagePos = TntUpDown2->Position;

    Graphics::TBitmap *img1;
    img1 = new Graphics::TBitmap();

    unsigned char *objectAreaImage = new unsigned char[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];

    for(int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
    {
      if(CameraMapInfo[globalCameraIndex].CameraInspectPosition != CAMERA_POSITION_DISCONNECT &&
          CameraMapInfo[globalCameraIndex].CameraInspectPosition != CAMERA_POSITION_3D)
      {
        if(stdCount[globalCameraIndex])
        {
          int imageIndex = objStartNum[globalCameraIndex] + (imagePos - 1);
          
          filename = ImagePath + "\\Image" + IntToStr(imageIndex) + "_C" + IntToStr(globalCameraIndex + 1) + ".bmp";

          if(FileExists(filename))
          {
            memset(ColorSourceImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3);
            memset(objectAreaImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
            img1->LoadFromFile(filename);

            int x, y;
            Byte *ptr;
            int tempAddress, tempAddress2;
            int colorDiff[3];
            int beltShiftSize = 32;
            int threshold;

            threshold = 40;
            for(y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
            {
              ptr = (Byte*) img1->ScanLine[y];
              for(x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
              {
                tempAddress = MAX_IMAGE_WIDTH * y + x;

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

                if(ColorSourceImage[tempAddress * 3 + 0] > 40 ||
                    ColorSourceImage[tempAddress * 3 + 1] > 40 ||
                    ColorSourceImage[tempAddress * 3 + 2] > 40)
                {
                  objectAreaImage[tempAddress] = 1;
                }
              }
            }

            threshold = 20;
            for(y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
            {
              ptr = (Byte*) img1->ScanLine[y];
              for(x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
              {
                tempAddress = MAX_IMAGE_WIDTH * y + x;

                if(objectAreaImage[tempAddress])
                {
                  colorDiff[0] = abs(testBackgroundImage[globalCameraIndex][tempAddress * 3 + 0] - ColorSourceImage[tempAddress * 3 + 0]);
                  colorDiff[1] = abs(testBackgroundImage[globalCameraIndex][tempAddress * 3 + 1] - ColorSourceImage[tempAddress * 3 + 1]);
                  colorDiff[2] = abs(testBackgroundImage[globalCameraIndex][tempAddress * 3 + 2] - ColorSourceImage[tempAddress * 3 + 2]);

                  if(!(colorDiff[0] > threshold || colorDiff[1] > threshold || colorDiff[2] > threshold))
                  {
                    objectAreaImage[tempAddress] = 2;
                  }
                }
              }
            }


            beltShiftSize = 16;
            for(y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
            {
              ptr = (Byte*) img1->ScanLine[y];
              for(x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
              {
                tempAddress = MAX_IMAGE_WIDTH * y + x;

                if(objectAreaImage[tempAddress] == 1)
                {
                  if(x > beltShiftSize && x < MAX_IMAGE_WIDTH - beltShiftSize && y > beltShiftSize && y < MAX_IMAGE_HEIGHT - beltShiftSize)
                  {
                    int searchingCount = 0;
                    int binCount = 0;
                    for(int tempY = y - beltShiftSize; tempY <= y + beltShiftSize; tempY += 4)
                    {
                      for(int tempX = x - beltShiftSize; tempX <= x + beltShiftSize; tempX += 4)
                      {
                        searchingCount++;

                        int tempAddress2 = MAX_IMAGE_WIDTH * tempY + tempX;

                        colorDiff[0] = abs(ptr[3 * x + 0] - testBackgroundImage[globalCameraIndex][tempAddress2 * 3 + 0]);
                        colorDiff[1] = abs(ptr[3 * x + 1] - testBackgroundImage[globalCameraIndex][tempAddress2 * 3 + 1]);
                        colorDiff[2] = abs(ptr[3 * x + 2] - testBackgroundImage[globalCameraIndex][tempAddress2 * 3 + 2]);

                        if(colorDiff[0] > threshold || colorDiff[1] > threshold || colorDiff[2] > threshold)
                        {
                          binCount++;
                        }
                      }
                    }

                    if(searchingCount)
                    {
                      if(searchingCount * 4 / 5 >= binCount)
                      {
                        objectAreaImage[tempAddress] = 3;
                      }
                    }
                  }
                  else
                  {
                    objectAreaImage[tempAddress] = 3;
                  }
                }
              }
            }

            beltShiftSize = 32;
            int topEndSW, bottomEndSW;
            memset(TempImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
            for(y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
            {
              for(x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
              {
                tempAddress = y * MAX_IMAGE_WIDTH + x;

                if(objectAreaImage[tempAddress] == 1)
                {
                  topEndSW = bottomEndSW = 0;
                  for(int r = 4; r <= beltShiftSize; r += 4)
                  {
                    if(y - r > 10)
                    {
                      if(objectAreaImage[tempAddress - r * MAX_IMAGE_WIDTH] != 1)
                      {
                        topEndSW = 1;
                        break;
                      }
                    }
                  }

                  if(!topEndSW) continue;

                  for(int r = 4; r <= beltShiftSize; r += 4)
                  {
                    if(y + r < MAX_IMAGE_HEIGHT - 10)
                    {
                      if(objectAreaImage[tempAddress + r * MAX_IMAGE_WIDTH] != 1)
                      {
                        bottomEndSW = 1;
                        break;
                      }
                    }
                  }

                  if(topEndSW && bottomEndSW)
                  {
                    TempImage[tempAddress] = 1;
                  }
                }
              }
            }
            // end

            // 벨트예상군 제거
            for(y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
            {
              for(x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
              {
                tempAddress = y * MAX_IMAGE_WIDTH + x;

                if (TempImage[tempAddress])
                {
                  objectAreaImage[tempAddress] = 4;
                }
              }
            }

            // 제거된 영역 중 정제로 예상되는 부분 복원
            for(y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
            {
              for(x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
              {
                tempAddress = y * MAX_IMAGE_WIDTH + x;

                if (TempImage[tempAddress])
                {
                  topEndSW = bottomEndSW = 0;

                  for(int r = 4; r <= beltShiftSize; r += 4)
                  {
                    if(y - r > 10)
                    {
                      if(objectAreaImage[tempAddress - r * MAX_IMAGE_WIDTH] == 1)
                      {
                        TempImage[tempAddress] = 2;
                        topEndSW = 1;
                        break;
                      }
                    }
                  }

                  if(!topEndSW)
                  {
                    for(int r = 4; r <= beltShiftSize; r += 4)
                    {
                      if(y + r < MAX_IMAGE_HEIGHT - 10)
                      {
                        if(objectAreaImage[tempAddress + r * MAX_IMAGE_WIDTH] == 1)
                        {
                          TempImage[tempAddress] = 2;
                          break;
                        }
                      }
                    }
                  }
                }
              }
            }

            for(y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
            {
              for(x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
              {
                tempAddress = y * MAX_IMAGE_WIDTH + x;

                if (TempImage[tempAddress] == 2)
                {
                  objectAreaImage[tempAddress] = 1;
                }
              }
            }

            int binSW = 0;
            for(y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
            {
              for(x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
              {
                tempAddress = y * MAX_IMAGE_WIDTH + x;

                if (objectAreaImage[tempAddress] == 1)
                {
                  binSW = 1;
                  break;
                }
              }

              if(binSW)
              {
                break;
              }
            }

            int minRGBCount[3], maxRGBCount[3];
            int maxValue, minValue;

            int maxRGBFactor;
            int minRGBFactor;

            if(binSW)
            {
              memset(minRGBCount, 0, sizeof(int) * 3);
              memset(maxRGBCount, 0, sizeof(int) * 3);

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

                  if(objectAreaImage[tempAddress] == 1)
                  {
                    maxValue = max(ptr[3 * x + 0], max(ptr[3 * x + 1], ptr[3 * x + 2]));

                    if(maxValue == ptr[3 * x + 0])
                    {
                      maxRGBCount[0]++;
                    }
                    else if(maxValue == ptr[3 * x + 1])
                    {
                      maxRGBCount[1]++;
                    }
                    else if(maxValue == ptr[3 * x + 2])
                    {
                      maxRGBCount[2]++;
                    }
                  }
                }
              }

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

                  if(objectAreaImage[tempAddress] == 1)
                  {
                    minValue = min(ptr[3 * x + 0], min(ptr[3 * x + 1], ptr[3 * x + 2]));

                    if(minValue == ptr[3 * x + 0])
                    {
                      minRGBCount[0]++;
                    }
                    else if(minValue == ptr[3 * x + 1])
                    {
                      minRGBCount[1]++;
                    }
                    else if(minValue == ptr[3 * x + 2])
                    {
                      minRGBCount[2]++;
                    }
                  }
                }
              }

              minValue = 640 * 480;
              for(int rgb = 0; rgb < 3; rgb++)
              {
                if(minValue > maxRGBCount[rgb])
                {
                  minValue = maxRGBCount[rgb];
                  minRGBFactor = rgb;
                }
              }

              maxValue = 0;
              for(int rgb = 0; rgb < 3; rgb++)
              {
                if(maxValue < maxRGBCount[rgb])
                {
                  maxValue = maxRGBCount[rgb];
                  maxRGBFactor = rgb;
                }
              }
            }

            int colorRate[3];
            int tempCount;
            int colorSum;

            memset(colorRate, 0, sizeof(int) * 3);
            tempCount = 0;

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

                if(objectAreaImage[tempAddress] == 1)
                {
                  colorSum = ptr[3 * x + 0] + ptr[3 * x + 1] + ptr[3 * x + 2];

                  if(colorSum)
                  {
                    colorRate[0] += ptr[3 * x + 0] * 1000 / colorSum;
                    colorRate[1] += ptr[3 * x + 1] * 1000 / colorSum;
                    colorRate[2] += ptr[3 * x + 2] * 1000 / colorSum;
                    tempCount++;
                  }
                }
              }
            }

            if(tempCount)
            {
              colorRate[0] /= tempCount;
              colorRate[1] /= tempCount;
              colorRate[2] /= tempCount;

              colorSum = colorRate[0] + colorRate[1] + colorRate[2];
              if(colorSum)
              {
                int tabletColorRate = colorRate[maxRGBFactor] * 100 / (colorRate[0] + colorRate[1] + colorRate[2]);
                int temptabletColorRate; 

                if(tabletColorRate >= 38)
                {
                  for(y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
                  {
                    ptr = (Byte*) img1->ScanLine[y];
                    for(x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
                    {
                      tempAddress = MAX_IMAGE_WIDTH  * y + x;

                      if(objectAreaImage[tempAddress] == 1)
                      {
                        maxValue = max(ptr[3 * x + 0], max(ptr[3 * x + 1], ptr[3 * x + 2]));

                        if(maxValue != ptr[3 * x + maxRGBFactor])
                        {
                          objectAreaImage[tempAddress] = 4;
                        }
                        else
                        {
                          colorSum = ptr[3 * x + 0] + ptr[3 * x + 1] + ptr[3 * x + 2];

                          if(colorSum)
                          {
                            colorRate[0] = ptr[3 * x + 0] * 1000 / colorSum;
                            colorRate[1] = ptr[3 * x + 1] * 1000 / colorSum;
                            colorRate[2] = ptr[3 * x + 2] * 1000 / colorSum;

                            if(colorRate[0] + colorRate[1] + colorRate[2])
                            {
                              temptabletColorRate = colorRate[maxRGBFactor] * 100 / (colorRate[0] + colorRate[1] + colorRate[2]);

                              if(temptabletColorRate < 38)
                              {
                                objectAreaImage[tempAddress] = 5;
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }

            int startX, endX, startY, endY;
            startX = 4;
            endX = MAX_IMAGE_WIDTH - 4;
            startY = 4;
            endY = MAX_IMAGE_HEIGHT - 4;

            memset(HalfLabelImage, 0, (MAX_IMAGE_WIDTH / 2) * (MAX_IMAGE_HEIGHT / 2) * sizeof(short));
            memset(smallBinaryImage, 0, (MAX_IMAGE_WIDTH / 2) * (MAX_IMAGE_HEIGHT / 2));

            for(y = 4; y < MAX_IMAGE_HEIGHT - 4; y++)
            {
              for(x = 4; x < MAX_IMAGE_WIDTH - 4; x++)
              {
                tempAddress = MAX_IMAGE_WIDTH * y + x;
                tempAddress2 = (MAX_IMAGE_WIDTH / 2) * (y / 2) + (x / 2);

                if(objectAreaImage[tempAddress] == 1)
                {
                  smallBinaryImage[tempAddress2] = 1;
                }
              }
            }

            int maxLabelN = LabellingForTabletImage(HalfLabelImage, smallBinaryImage, startX / 2, endX / 2, startY / 2, endY / 2, MAX_IMAGE_WIDTH / 2, MAX_IMAGE_HEIGHT / 2);

            if(maxLabelN)
            {
              for(y = 4; y < MAX_IMAGE_HEIGHT - 4; y++)
              {
                for(x = 4; x < MAX_IMAGE_WIDTH - 4; x++)
                {
                  tempAddress = MAX_IMAGE_WIDTH * y + x;
                  tempAddress2 = (MAX_IMAGE_WIDTH / 2) * (y / 2) + (x / 2);

                  if(objectAreaImage[tempAddress] == 1)
                  {
                    if(HalfLabelImage[tempAddress2] != maxLabelN)
                    {
                      objectAreaImage[tempAddress] = 2;
                    }
                  }
                }
              }
            }

            if(!(globalCameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX - 1 || globalCameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX - 1))
            {
              if(binSW)
              {
                short binaryTopEndPosition[MAX_IMAGE_WIDTH];
                short binaryBottomEndPosition[MAX_IMAGE_WIDTH];

                for(int m = 0; m < MAX_IMAGE_WIDTH; m++)
                {
                  binaryTopEndPosition[m] = MAX_IMAGE_HEIGHT;
                  binaryBottomEndPosition[m] = 0;
                }

                int startBinX, endBinX;
                startBinX = MAX_IMAGE_WIDTH;
                endBinX = 0;

                for(y = 4; y < MAX_IMAGE_HEIGHT - 4; y++)
                {
                  for(x = 4; x < MAX_IMAGE_WIDTH - 4; x++)
                  {
                    tempAddress = MAX_IMAGE_WIDTH * y + x;

                    if(objectAreaImage[tempAddress] == 1)
                    {
                      if(binaryTopEndPosition[x] >= y)
                      {
                        binaryTopEndPosition[x] = y;
                      }

                      if(binaryBottomEndPosition[x] <= y)
                      {
                        binaryBottomEndPosition[x] = y;
                      }

                      if(startBinX >= x)
                      {
                        startBinX = x;
                      }

                      if(endBinX <= x)
                      {
                        endBinX = x;
                      }
                    }
                  }
                }

                threshold = 10;
                for(x = startBinX; x <= endBinX; x++)
                {
                  if(binaryBottomEndPosition[x] && binaryTopEndPosition[x] != MAX_IMAGE_HEIGHT)
                  {
                    startY = binaryBottomEndPosition[x];
                    endY = binaryTopEndPosition[x];

                    for(y = startY; y >= endY; y--)
                    {
                      tempAddress = MAX_IMAGE_WIDTH * y + x;

                      int edgeSW = 0;
                      for(int range = 20; range >= 4; range -= 4)
                      {
                        tempAddress2 = tempAddress + range * MAX_IMAGE_WIDTH;

                        colorDiff[0] = ColorSourceImage[tempAddress * 3 + 0] - ColorSourceImage[tempAddress2 * 3 + 0];
                        colorDiff[1] = ColorSourceImage[tempAddress * 3 + 1] - ColorSourceImage[tempAddress2 * 3 + 1];
                        colorDiff[2] = ColorSourceImage[tempAddress * 3 + 2] - ColorSourceImage[tempAddress2 * 3 + 2];

                        if(colorDiff[0] > threshold || colorDiff[1] > threshold || colorDiff[2] > threshold)
                        {
                          edgeSW = 1;
                          break;
                        }

                        tempAddress2 = tempAddress + range * MAX_IMAGE_WIDTH - range;

                        colorDiff[0] = ColorSourceImage[tempAddress * 3 + 0] - ColorSourceImage[tempAddress2 * 3 + 0];
                        colorDiff[1] = ColorSourceImage[tempAddress * 3 + 1] - ColorSourceImage[tempAddress2 * 3 + 1];
                        colorDiff[2] = ColorSourceImage[tempAddress * 3 + 2] - ColorSourceImage[tempAddress2 * 3 + 2];

                        if(colorDiff[0] > threshold || colorDiff[1] > threshold || colorDiff[2] > threshold)
                        {
                          edgeSW = 1;
                          break;
                        }

                        tempAddress2 = tempAddress + range * MAX_IMAGE_WIDTH + range;

                        colorDiff[0] = ColorSourceImage[tempAddress * 3 + 0] - ColorSourceImage[tempAddress2 * 3 + 0];
                        colorDiff[1] = ColorSourceImage[tempAddress * 3 + 1] - ColorSourceImage[tempAddress2 * 3 + 1];
                        colorDiff[2] = ColorSourceImage[tempAddress * 3 + 2] - ColorSourceImage[tempAddress2 * 3 + 2];

                        if(colorDiff[0] > threshold || colorDiff[1] > threshold || colorDiff[2] > threshold)
                        {
                          edgeSW = 1;
                          break;
                        }
                      }

                      if(edgeSW == 0)
                      {
                        objectAreaImage[tempAddress] = 4;
                      }
                      else
                      {
                        break;
                      }
                    }
                  }
                }
              }
            }

            startX = 4;
            endX = MAX_IMAGE_WIDTH - 4;
            startY = 4;
            endY = MAX_IMAGE_HEIGHT - 4;
            
            int minX, maxX;
            for (y = startY; y < endY; y++)
            {
              minX = MAX_IMAGE_WIDTH;
              maxX = 0;

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

                if(objectAreaImage[tempAddress] == 1)
                {
                  if(minX > x) minX = x;
                  if(maxX < x) maxX = x;
                }
              }

              for (x = minX; x <= maxX; x++)
              {
                tempAddress = y * MAX_IMAGE_WIDTH + x;
                objectAreaImage[tempAddress] = 1;
              }
            }

            int minY, maxY;
            for (x = startX; x < endX; x++)
            {
              minY = MAX_IMAGE_HEIGHT;
              maxY = 0;

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

                if(objectAreaImage[tempAddress] == 1)
                {
                  if(minY > y) minY = y;
                  if(maxY < y) maxY = y;
                }
              }

              for (y = minY; y <= maxY; y++)
              {
                tempAddress = y * MAX_IMAGE_WIDTH + x;
                objectAreaImage[tempAddress] = 1;
              }
            }

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

                if(objectAreaImage[tempAddress] == 1)
                {
                  if(objectAreaImage[tempAddress - 4] != 1 ||
                      objectAreaImage[tempAddress + 4] != 1 ||
                      objectAreaImage[tempAddress - 4 * MAX_IMAGE_WIDTH] != 1 ||
                      objectAreaImage[tempAddress + 4 * MAX_IMAGE_WIDTH] != 1)
                  {
                    ptr[3 * x + 0] = 0;//min(255, ptr[3 * x + 0] * 3);
                    ptr[3 * x + 1] = 0;//min(255, ptr[3 * x + 1] * 3);
                    ptr[3 * x + 2] = 255;//min(255, ptr[3 * x + 2] * 2);
                  }
                }
                /*
                else if(objectAreaImage[tempAddress] == 2)
                {
                  ptr[3 * x + 0] = 0;
                  ptr[3 * x + 1] = 255;
                  ptr[3 * x + 2] = 0;
                }
                else if(objectAreaImage[tempAddress] == 3)
                {
                  ptr[3 * x + 0] = 255;
                  ptr[3 * x + 1] = 0;
                  ptr[3 * x + 2] = 0;
                }
                else if(objectAreaImage[tempAddress] == 4)
                {
                  ptr[3 * x + 0] = 0;
                  ptr[3 * x + 1] = 255;
                  ptr[3 * x + 2] = 255;
                }
                else if(objectAreaImage[tempAddress] == 5)
                {
                  ptr[3 * x + 0] = 255;
                  ptr[3 * x + 1] = 0;
                  ptr[3 * x + 2] = 255;
                }
                */
              }
            }

            TImage *tempImage = (TImage *)FindComponent("BackGroundImage"+IntToStr(globalCameraIndex + 1));

            if(tempImage)
            {
              tempImage->Picture->Bitmap->Assign(img1);
              tempImage->Refresh();
            }
          }
        }
      }

      Application->ProcessMessages();
    }

    delete objectAreaImage;
    delete img1;
  }
}
//---------------------------------------------------------------------------

int __fastcall TTabletSimulationForm::LabellingForTabletImage(short *label_Image, unsigned char *smallSizeBinaryImage, int startX, int endX, int startY, int endY, int imageWidth, int imageHeight)
{
	int i, x, y;
	int temp_address;
	int currentLabel;
	int new_count;
	int newLval;
	int temp;
	int tempAddress;
	int maxLabelN;
	int maxLabelCount;
	int breakSW;

  short CollisionArray[MAX_LABEL_COUNT];
  unsigned short Pixel_N_Of_Label[MAX_LABEL_COUNT];
  short StartX_Label[MAX_LABEL_COUNT];
  short EndX_Label[MAX_LABEL_COUNT];
  short StartY_Label[MAX_LABEL_COUNT];
  short EndY_Label[MAX_LABEL_COUNT];

	currentLabel = 0;

	for (i = 0; i < MAX_LABEL_COUNT; i++)
	{
		CollisionArray[i] = i;
		Pixel_N_Of_Label[i] = 0;
		StartX_Label[i] = 640;
		EndX_Label[i] = 0;
		StartY_Label[i] = 640;
		EndY_Label[i] = 0;
	}

	breakSW = 0;
	for (y = startY; y < endY; y++)
	{
		for (x = startX; x < endX; x++)
		{
			temp_address = imageWidth * (y)+x;
			if (*(smallSizeBinaryImage + temp_address))
			{
				if (*(label_Image + temp_address - imageWidth) == 0)     // up is background
				{
					if (*(label_Image + temp_address - 1) == 0)       // left is also background
					{
						currentLabel++;
						*(label_Image + temp_address) = currentLabel; // first label number is '1'
					}
					else                        // left is not background
					{
						*(label_Image + temp_address) = *(label_Image + temp_address - 1);
					}
				}
				else                // up is not background
				{
					if (*(label_Image + temp_address - 1) == 0)       // left is background
					{
						*(label_Image + temp_address) = *(label_Image + temp_address - imageWidth);
					}
					else                        // left is not background
					{
						if (*(label_Image + temp_address - imageWidth) == *(label_Image + temp_address - 1))
						{
							*(label_Image + temp_address) = *(label_Image + temp_address - imageWidth);
						}
						else        // collision detected
						{           // Left label이 Up label보다 항상 크다
							CollisionArray[max(*(label_Image + temp_address - 1), *(label_Image + temp_address - imageWidth))] =
								min(*(label_Image + temp_address - 1), *(label_Image + temp_address - imageWidth));
							*(label_Image + temp_address) = CollisionArray[*(label_Image + temp_address - imageWidth)];
						}
					}
				}
				if (currentLabel >= MAX_LABEL_COUNT - 1)
				{
					breakSW = 1;
					break;
				}
			}
		}
		if (breakSW == 1)
			break;
	}

	newLval = 1;
	for (i = 1; i <= currentLabel; i++)
	{
		if (CollisionArray[CollisionArray[i]] > newLval)
		{
			newLval++;
			CollisionArray[i] = newLval;
		}
		else
		{
			CollisionArray[i] = CollisionArray[CollisionArray[i]];
		}
	}

	if (newLval > 500)  newLval = 499;
	new_count = newLval;

	for (y = startY; y < endY; y++)
	{
		for (x = startX; x < endX; x++)
		{
			tempAddress = imageWidth * (y)+x;
			if (*(smallSizeBinaryImage + tempAddress))
			{
				temp = *(label_Image + tempAddress);
				temp = CollisionArray[temp];
				*(label_Image + tempAddress) = temp;
				Pixel_N_Of_Label[temp]++;
				if (StartX_Label[temp] > x)  StartX_Label[temp] = x;
				if (StartY_Label[temp] > y)  StartY_Label[temp] = y;
				if (EndX_Label[temp] < x)  EndX_Label[temp] = x;
				if (EndY_Label[temp] < y)  EndY_Label[temp] = y;
			}
		}
	}

	maxLabelN = 0;
	maxLabelCount = 0;
	for (i = 1; i <= new_count; i++)
	{
		if (Pixel_N_Of_Label[i] > maxLabelCount)
		{
			maxLabelN = i;
			maxLabelCount = Pixel_N_Of_Label[i];
		}
	}
  
	return(maxLabelN);
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::Button12Click(TObject *Sender)
{
  int angle, shiftX, shiftY;

  angle = - PrintMatchingResult.PrintRotationAngle;
  shiftX = PrintMatchingResult.PrintShiftX;
	shiftY = PrintMatchingResult.PrintShiftY;

  int centerX, centerY;
  centerX = TabletMatchingResult.AdjustCenterXInImage + shiftX;
  centerY = TabletMatchingResult.AdjustCenterYInImage + shiftY;

  memset(TempImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
  if(PrintMatchingResult.dataNumberWithMaxValue == 0)
  {
    for(int m = 0; m < TabletSetupData.printData1Count; m++)
    {
      int tempX = TabletSetupData.position_printData1[m][0];
      int tempY = TabletSetupData.position_printData1[m][1];

      TempImage[MAX_IMAGE_WIDTH * tempY + tempX] = 0x10;
    }
  }
  else
  {
    for(int m = 0; m < TabletSetupData.printData2Count; m++)
    {
      int tempX = TabletSetupData.position_printData2[m][0];
      int tempY = TabletSetupData.position_printData2[m][1];

      TempImage[MAX_IMAGE_WIDTH * tempY + tempX] = 0x10;
    }
  }

  int x, y;
  int tempAddress;
  int rotateX, rotateY;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(DarkPixelNeighborPrint[tempAddress])
      {
        if(angle >= 0)
				{
					rotateX = ((x - centerX)*CosData[angle] - (y - centerY)*SinData[angle]) / 1024 + MAX_IMAGE_WIDTH / 2;
					rotateY = ((x - centerX)*SinData[angle] + (y - centerY)*CosData[angle]) / 1024 + MAX_IMAGE_HEIGHT / 2;
				}
				else
				{
					rotateX = ((x - centerX)*CosData[-angle] + (y - centerY)*SinData[-angle]) / 1024 + MAX_IMAGE_WIDTH / 2;
					rotateY = (-(x - centerX)*SinData[-angle] + (y - centerY)*CosData[-angle]) / 1024 + MAX_IMAGE_HEIGHT / 2;
				}

        //rotateX = rotateX - shiftX;
        //rotateY = rotateY - shiftY;

        if(rotateX > 10 && rotateX < MAX_IMAGE_HEIGHT - 10 && rotateY > 10 && rotateY < MAX_IMAGE_HEIGHT - 10)
        {
          TempImage[MAX_IMAGE_WIDTH * rotateY + rotateX] |= 0x01;
        }
      }
    }
  }

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

  Byte *ptr;

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*) img1->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      if(TempImage[MAX_IMAGE_WIDTH * y + x] == 0x11)
      {
        ptr[3 * x + 0] = 255;
        ptr[3 * x + 1] = 255;
        ptr[3 * x + 2] = 255;
      }
      else if(TempImage[MAX_IMAGE_WIDTH * y + x] == 0x10)
      {
        ptr[3 * x + 0] = 0;
        ptr[3 * x + 1] = 255;
        ptr[3 * x + 2] = 0;
      }
      else if(TempImage[MAX_IMAGE_WIDTH * y + x] == 0x01)
      {
        ptr[3 * x + 0] = 0;
        ptr[3 * x + 1] = 0;
        ptr[3 * x + 2] = 255;
      }
      else
      {
        ptr[3 * x + 0] = 0;
        ptr[3 * x + 1] = 0;
        ptr[3 * x + 2] = 0;
      }
    }
  }

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

  delete img1;
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::AccPrintMachingData()
{
  int angle, shiftX, shiftY;

  angle = - PrintMatchingResult.PrintRotationAngle;
  shiftX = PrintMatchingResult.PrintShiftX;
	shiftY = PrintMatchingResult.PrintShiftY;

  int centerX, centerY;
  centerX = TabletMatchingResult.AdjustCenterXInImage + shiftX;
  centerY = TabletMatchingResult.AdjustCenterYInImage + shiftY;

  unsigned char *dstImage;

  if(PrintMatchingResult.dataNumberWithMaxValue == 0)
  {
    dstImage = print1MatchingData;
    print1MatchingCount++;
  }
  else
  {
    dstImage = print2MatchingData;
    print2MatchingCount++;
  }

  int x, y;
  int tempAddress;
  int rotateX, rotateY;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(DarkPixelNeighborPrint[tempAddress])
      {
        if(angle >= 0)
				{
					rotateX = ((x - centerX)*CosData[angle] - (y - centerY)*SinData[angle]) / 1024 + MAX_IMAGE_WIDTH / 2;
					rotateY = ((x - centerX)*SinData[angle] + (y - centerY)*CosData[angle]) / 1024 + MAX_IMAGE_HEIGHT / 2;
				}
				else
				{
					rotateX = ((x - centerX)*CosData[-angle] + (y - centerY)*SinData[-angle]) / 1024 + MAX_IMAGE_WIDTH / 2;
					rotateY = (-(x - centerX)*SinData[-angle] + (y - centerY)*CosData[-angle]) / 1024 + MAX_IMAGE_HEIGHT / 2;
				}

        if(rotateX > 10 && rotateX < MAX_IMAGE_WIDTH - 10 && rotateY > 10 && rotateY < MAX_IMAGE_HEIGHT - 10)
        {
          dstImage[MAX_IMAGE_WIDTH * rotateY + rotateX]++;
        }
      }
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::TrackBar7Change(TObject *Sender)
{
  Graphics::TBitmap *img1;
  img1 = new Graphics::TBitmap();
  img1->Width =  MAX_IMAGE_WIDTH;
  img1->Height =  MAX_IMAGE_HEIGHT;
  img1->PixelFormat = pf24bit;

  Byte *ptr;

  for(int y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*) img1->ScanLine[y];
    for(int x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      if(print1MatchingData[MAX_IMAGE_WIDTH * y + x] >= TrackBar7->Position)
      {
        ptr[3 * x + 0] = 255;
        ptr[3 * x + 1] = 255;
        ptr[3 * x + 2] = 255;
      }
      else
      {
        ptr[3 * x + 0] = 0;
        ptr[3 * x + 1] = 0;
        ptr[3 * x + 2] = 0;
      }
    }
  }

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

  delete img1;
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::TrackBar8Change(TObject *Sender)
{
  Graphics::TBitmap *img1;
  img1 = new Graphics::TBitmap();
  img1->Width =  MAX_IMAGE_WIDTH;
  img1->Height =  MAX_IMAGE_HEIGHT;
  img1->PixelFormat = pf24bit;

  Byte *ptr;

  for(int y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte*) img1->ScanLine[y];
    for(int x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      if(print2MatchingData[MAX_IMAGE_WIDTH * y + x] >= TrackBar8->Position)
      {
        ptr[3 * x + 0] = 255;
        ptr[3 * x + 1] = 255;
        ptr[3 * x + 2] = 255;
      }
      else
      {
        ptr[3 * x + 0] = 0;
        ptr[3 * x + 1] = 0;
        ptr[3 * x + 2] = 0;
      }
    }
  }

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

  delete img1;
}
//---------------------------------------------------------------------------


void __fastcall TTabletSimulationForm::Button17Click(TObject *Sender)
{
  int shiftX;
  int shiftY;
  int rotateAngle;
  int tempshiftX;
  int tempshiftY;
  int temprotateAngle;

  int tempAddress;
  int matchingValue;
  int maxValue;
  int a, b, c;

  unsigned char *printArea;
  printArea = TempImage;
  memset(printArea, 0, 640 * 480);

  maxValue = 0;
  for(rotateAngle = 0; rotateAngle < 720; rotateAngle += 4)
  {
    for(shiftY = - 32; shiftY <= 32; shiftY += 4)
    {
      for(shiftX = - 32; shiftX <= 32; shiftX += 4)
      {
        matchingValue = 0;
        for (int m = 0; m < SmallPrintCoreData1CountFor3D; m+=2)
        {
          tempAddress = detailedCorePrintRotationAddress1For3D[rotateAngle][m] + shiftX + shiftY * MAX_IMAGE_WIDTH;

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

          matchingValue += realPrintMaskingArea[tempAddress];
          matchingValue += realPrintMaskingArea[tempAddress - 1];
          matchingValue += realPrintMaskingArea[tempAddress + 1];
          matchingValue += realPrintMaskingArea[tempAddress - MAX_IMAGE_WIDTH];
          matchingValue += realPrintMaskingArea[tempAddress + MAX_IMAGE_WIDTH];
        }

        if(maxValue < matchingValue)
        {
          maxValue = matchingValue;

          a = rotateAngle;
          b = shiftX;
          c = shiftY;
        }
      }
    }
  }

  temprotateAngle = a;
  tempshiftX = b;
  tempshiftY = c;

  maxValue = 0;
  for(rotateAngle = temprotateAngle - 4; rotateAngle < temprotateAngle + 4; rotateAngle++)
  {
    if(rotateAngle < 0 || rotateAngle >= 720) continue;
    
    for(shiftY = tempshiftY - 4; shiftY <= tempshiftY + 4; shiftY++)
    {
      for(shiftX = tempshiftX - 4; shiftX <= tempshiftX + 4; shiftX++)
      {
        matchingValue = 0;
        for (int m = 0; m < SmallPrintCoreData1CountFor3D; m+=2)
        {
          tempAddress = detailedCorePrintRotationAddress1For3D[rotateAngle][m] + shiftX + shiftY * MAX_IMAGE_WIDTH;

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

          matchingValue += realPrintMaskingArea[tempAddress];
          matchingValue += realPrintMaskingArea[tempAddress - 1];
          matchingValue += realPrintMaskingArea[tempAddress + 1];
          matchingValue += realPrintMaskingArea[tempAddress - MAX_IMAGE_WIDTH];
          matchingValue += realPrintMaskingArea[tempAddress + MAX_IMAGE_WIDTH];
        }

        if(maxValue < matchingValue)
        {
          maxValue = matchingValue;

          a = rotateAngle;
          b = shiftX;
          c = shiftY;
        }
      }
    }
  }

  rotateAngle = a;
  shiftX = b;
  shiftY = c;

  for (int m = 0; m < SmallPrintCoreData1CountFor3D; m++)
  {
	  tempAddress = detailedCorePrintRotationAddress1For3D[rotateAngle][m] + shiftX + shiftY * MAX_IMAGE_WIDTH;

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

    printArea[tempAddress] = 1;
  }

  Edit9->Text = IntToStr(rotateAngle);
  Edit10->Text = IntToStr(shiftX);
  Edit11->Text = IntToStr(shiftY);

  Edit8->Text = IntToStr(maxValue);

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;              
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

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

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

      ptr[3*x + 0] = realPrintMaskingArea[tempAddress] * 255 / maxValue;
      ptr[3*x + 1] = realPrintMaskingArea[tempAddress] * 255 / maxValue;
      ptr[3*x + 2] = realPrintMaskingArea[tempAddress] * 255 / maxValue;

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

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

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

void __fastcall TTabletSimulationForm::RealThreeDImageMouseMove(
      TObject *Sender, TShiftState Shift, int X, int Y)
{
  if(SelectedCameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX || SelectedCameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
  {
    int x, y;
    int tempAddress;

    unsigned char tempYSliceImage[MAX_IMAGE_HEIGHT * 256];
    unsigned char adjustYSliceImage[MAX_IMAGE_HEIGHT * 256];
    unsigned char RotationYSliceImage[MAX_IMAGE_HEIGHT * 256];
    unsigned char tempXSliceImage[MAX_IMAGE_WIDTH * 256];

    memset(RotationYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);
    memset(adjustYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);
    memset(tempYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);
    memset(tempXSliceImage, 0, MAX_IMAGE_WIDTH * 256);

    RealThreeDImage->Picture->Bitmap->Width = MAX_IMAGE_WIDTH;
    RealThreeDImage->Picture->Bitmap->Height = MAX_IMAGE_HEIGHT;
    RealThreeDImage->Picture->Bitmap->PixelFormat = pf24bit;

    ySliceThreeDImage->Picture->Bitmap->Width = 256;
    ySliceThreeDImage->Picture->Bitmap->Height = MAX_IMAGE_HEIGHT;
    ySliceThreeDImage->Picture->Bitmap->PixelFormat = pf24bit;

    xSliceThreeDImage->Picture->Bitmap->Width = MAX_IMAGE_WIDTH;
    xSliceThreeDImage->Picture->Bitmap->Height = 256;
    xSliceThreeDImage->Picture->Bitmap->PixelFormat = pf24bit;

    int value;
    for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
    {
      value = AdjustThreeD_Data[MAX_IMAGE_WIDTH * y + X];

      if(value)
      {
        tempYSliceImage[256 * y + value] = 255;
      }
    }

    for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
    {
      value = RotationThreeDImage[MAX_IMAGE_WIDTH * y + X];

      if(value)
      {
        adjustYSliceImage[256 * y + value] = 255;
      }
    }

    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      Byte *ptr = (Byte *)RealThreeDImage->Picture->Bitmap->ScanLine[Y];

      value = ptr[3 * x + 1];

      if(value)
      {
        tempXSliceImage[MAX_IMAGE_WIDTH * (255 - value) + x] = 255;
      }
    }
  
    int minY = MAX_IMAGE_HEIGHT;
    int maxY = 0;

    for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y+=2)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + X;

      if(AdjustThreeD_Data[tempAddress] && ThreeDOutlineImage[tempAddress] == 0)
      {
        minY = y;
        break;
      }
    }

    for (y = MAX_IMAGE_HEIGHT - 10; y >= 10; y-=2)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + X;

      if(AdjustThreeD_Data[tempAddress] && ThreeDOutlineImage[tempAddress] == 0)
      {
        maxY = y;
        break;
      }
    }

    int sinV;
    int tiltR = 0;
    int ProtoTabletCenterInfo[2];
    int realCenterPosition;
    int tempX;
    int CenterOfGravity, splitValue;
    int AvgShiftCOGY = 0;
    int heightDiff = 0;
    int CenterHeight = 0;
    if(minY != MAX_IMAGE_HEIGHT && maxY != 0)
    {
      int tempLength = abs(minY - maxY);

      if(tempLength > 30)
      {
        int upperPos[2];
        int lowerPos[2];

        upperPos[0] = minY;
        upperPos[1] = AdjustThreeD_Data[MAX_IMAGE_WIDTH * minY + X];

        lowerPos[0] = maxY;
        lowerPos[1] = AdjustThreeD_Data[MAX_IMAGE_WIDTH * maxY + X];

        heightDiff = abs(upperPos[1] - lowerPos[1]);
        CenterHeight = (upperPos[1] + lowerPos[1]) / 2;

        realCenterPosition = (minY + maxY) / 2; // 초기값 설정, heightdiff 가 존재하지 않거나 length에 에러가 발생한 경우 minY, maxY의 중간 지점이 real center

        if(heightDiff > 0) // 틸팅이 발생하는 경우 정제의 위 아래의 최소 높이차
        {
          int pX = upperPos[0] - lowerPos[0];
          int pY = upperPos[1] - lowerPos[1];

          int uLength = pX * pX + pY * pY;

          if (uLength < 90000)
          {
            uLength = SqrtData[uLength];
            sinV = 1280000 * pY / uLength;

            if (sinV > 10000) sinV = 10000;

            // x2 : 삼각함수 array의 비율 조정, x1.2 : 실제 보정수치에 가중 적용
            if (pY <= 0)
              tiltR = ArcSinData[-sinV] * 2;
            else
              tiltR = -ArcSinData[sinV] * 2;

            ProtoTabletCenterInfo[0] = realCenterPosition;
            ProtoTabletCenterInfo[1] = AdjustThreeD_Data[MAX_IMAGE_WIDTH * realCenterPosition + X];

            if(tiltR < 0)
            {
              tempX = (ProtoTabletCenterInfo[1] - CenterHeight) * SinData[-tiltR] / 1024 + ProtoTabletCenterInfo[0];
            }
            else
            {
              tempX = -(ProtoTabletCenterInfo[1] - CenterHeight) * SinData[tiltR] / 1024 + ProtoTabletCenterInfo[0];
            }

            realCenterPosition = tempX;

            CenterOfGravity = splitValue = 0;
            for(y = minY; y <= maxY; y+=2)
            {
              tempAddress = MAX_IMAGE_WIDTH * y + X;

              if(AdjustThreeD_Data[tempAddress] && ThreeDOutlineImage[tempAddress] == 0)
              {
                CenterOfGravity += y * AdjustThreeD_Data[tempAddress];
                splitValue += AdjustThreeD_Data[tempAddress];
              }
            }

            if(splitValue)
            {
              CenterOfGravity /= splitValue;

              AvgShiftCOGY = (realCenterPosition - CenterOfGravity);
            }
          }
        }
      }
    }

    memset(adjustYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);

    //AvgShiftCOGY = TrackBar9->Position;
    int zeroYZAngle = -tiltR;
  
    int minHeight, maxHeight;
  
    minHeight = 256;
    maxHeight = 0;

    int yzCosValue = CosData[(zeroYZAngle + 720) % 720];
    int yzSinValue = SinData[(zeroYZAngle + 720) % 720];

    int rX2, rY2, rZ2;

    for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + X;

      int z = AdjustThreeD_Data[tempAddress];

      if(z)
      {
        rX2 = X;
        rY2 = (((y - ProtoTabletCenterY) * yzCosValue - (z - ProtoTabletCenterZ) * yzSinValue) / 1024) + ProtoTabletCenterY;
        rZ2 = (((y - ProtoTabletCenterY) * yzSinValue + (z - ProtoTabletCenterZ) * yzCosValue) / 1024) + ProtoTabletCenterZ;

        if(rZ2 < 0) rZ2 = 0;
        if(rZ2 > 255) rZ2 = 255;

        if(rY2 > 0 && rY2 < MAX_IMAGE_HEIGHT)
        {
          RotationYSliceImage[256 * rY2 + rZ2] = 255;

          if(minHeight > rZ2) minHeight = rZ2;
          if(maxHeight < rZ2) maxHeight = rZ2;
        }
      }
    }

    if(minY != MAX_IMAGE_HEIGHT && maxY != 0)
    {
      for (y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
      {
        tempAddress = MAX_IMAGE_WIDTH * y + X;

        int z = AdjustThreeD_Data[tempAddress];

        if(z > 0)
        {
          int tempY;

          rZ2 = (((y - ProtoTabletCenterY) * yzSinValue + (z - ProtoTabletCenterZ) * yzCosValue) / 1024) + ProtoTabletCenterZ;
          tempY = y + (AvgShiftCOGY * (rZ2 - minHeight)) / (maxHeight - minHeight);

          if(tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
          {
            adjustYSliceImage[256 * tempY + z] |= 0xF0;
          }

          /*
          tempY = y + (AvgShiftCOGY * (z - minHeight)) / (maxHeight - minHeight);

          if(tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
          {
            //adjustYSliceImage[256 * tempY + z] |= 0x0F;
          }
          */
        }
      }
    }
    
    Graphics::TBitmap *img = new Graphics::TBitmap;
    img->Width = 256;              
    img->Height = MAX_IMAGE_HEIGHT;
    img->PixelFormat = pf24bit;

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

      for(x = 0; x < 256; x++)
      {
        ptr[3 * x + 0] = 0;
        ptr[3 * x + 1] = 0;
        ptr[3 * x + 2] = 0;

        tempAddress = 256 * y + x;

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

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

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

    /*
    CenterOfGravity = splitValue = 0;
    for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + X;

      if(AdjustThreeD_Data[tempAddress] && TempImage2[tempAddress] == 0)
      {
        CenterOfGravity += y * AdjustThreeD_Data[tempAddress];
        splitValue += AdjustThreeD_Data[tempAddress];
      }
    }

    if(splitValue)
    {
      CenterOfGravity /= splitValue;
    }
    */

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

    ySliceThreeDImage->Canvas->Pen->Color = clYellow;
    ySliceThreeDImage->Canvas->Brush->Style = bsClear;
    ySliceThreeDImage->Canvas->MoveTo(0, CenterOfGravity);
    ySliceThreeDImage->Canvas->LineTo(256, CenterOfGravity);
    //ySliceThreeDImage->Canvas->MoveTo(CenterOfGravity, 0);
    //ySliceThreeDImage->Canvas->LineTo(CenterOfGravity, MAX_IMAGE_HEIGHT);

    ySliceThreeDImage->Canvas->Pen->Color = clRed;
    ySliceThreeDImage->Canvas->MoveTo(0, realCenterPosition);
    ySliceThreeDImage->Canvas->LineTo(256, realCenterPosition);
    //ySliceThreeDImage->Canvas->MoveTo(realCenterPosition, 0);
    //ySliceThreeDImage->Canvas->LineTo(realCenterPosition, MAX_IMAGE_HEIGHT);

    ySliceThreeDImage->Canvas->Pen->Color = clBlue;
    ySliceThreeDImage->Canvas->MoveTo(CenterHeight, 0);
    ySliceThreeDImage->Canvas->LineTo(CenterHeight, MAX_IMAGE_HEIGHT);


    ySliceThreeDImage->Canvas->Pen->Color = clGray;
    ySliceThreeDImage->Canvas->MoveTo(0, minY);
    ySliceThreeDImage->Canvas->LineTo(256, minY);
    ySliceThreeDImage->Canvas->MoveTo(0, maxY);
    ySliceThreeDImage->Canvas->LineTo(256, maxY);
    ySliceThreeDImage->Canvas->MoveTo(0, (minY + maxY) / 2);
    ySliceThreeDImage->Canvas->LineTo(256, (minY + maxY) / 2);

    ySliceThreeDImage->Refresh();

    img->Width = MAX_IMAGE_WIDTH;              
    img->Height = 256;
    img->PixelFormat = pf24bit;

    for(y = 0; y < 256; y++)
    {
      Byte *ptr = (Byte *)img->ScanLine[y];

      for(x = 0; x < MAX_IMAGE_WIDTH; x++)
      {
        ptr[3 * x + 0] = 0;
        ptr[3 * x + 1] = 0;
        ptr[3 * x + 2] = 0;

        tempAddress = MAX_IMAGE_WIDTH * y + x;

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

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

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

void __fastcall TTabletSimulationForm::Button13Click(TObject *Sender)
{
  int n, m;
  int tempX, tempY;

  memset(TempImage, 0, 640 * 480);

  for (n = 0; n < TabletSetupData.printLabelCount[0]; n++)
  {
    for (m = 0; m < TabletSetupData.printLabelDataCnt[0][n]; m++)
    {
      tempX = TabletSetupData.printLabelData[0][n][m][0];
      tempY = TabletSetupData.printLabelData[0][n][m][1];

      TempImage[MAX_IMAGE_WIDTH * tempY + tempX] = n + 1;
    }
  }
      
  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;

      if(TabletSetupData.printLabelCount[0])
      {
        ptr[3*x + 0] = (TempImage[tempAddress] * 17) & 0xFF;
        ptr[3*x + 1] = (TempImage[tempAddress] * 41) & 0xFF;
        ptr[3*x + 2] = (TempImage[tempAddress] * 73) & 0xFF;
      }
    }
  }

  DebugData1->Picture->Bitmap->Assign(img);
  DebugData1->Refresh();
  helpLabel1->Caption = "Shape Binary Image";

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

void __fastcall TTabletSimulationForm::threeDRotation_PC(unsigned char *srcImage, int xyR, int xzR, int yzR)
{
  int x, y, z;
  int tempAddress, tempAddress2;
  int cosValue, sinValue;
  int centerX, centerY, centerZ;
  int rX, rY, rZ;
  int CosX, CosY, CosZ;
  int SinX, SinY, SinZ;
  int heightDiff;
  int tempHeight;
  int tempCount;
  unsigned char tempThreeDImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  unsigned char tranformedThreeDImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];

  centerX = centerY = centerZ = tempCount = 0;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(srcImage[tempAddress])
      {
        centerX += x;
        centerY += y;
        centerZ += srcImage[tempAddress];
        tempCount++;
      }
    }
  }

  if(tempCount)
  {
    centerX /= tempCount;
    centerY /= tempCount;
    centerZ /= tempCount; 
  }
  else
  {
    centerX = MAX_IMAGE_WIDTH / 2;
    centerY = MAX_IMAGE_HEIGHT / 2;
    centerZ = 128;
  }

  memset(tempThreeDImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  cosValue = CosData[(xyR + 720) % 720];
  sinValue = SinData[(xyR + 720) % 720];

  //z축 기준 회전
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      rX = (cosValue * (x - centerX) - sinValue * (y - centerY)) / 1024 + centerX;
      rY = (sinValue * (x - centerX) + cosValue * (y - centerY)) / 1024 + centerY;

      tempAddress = MAX_IMAGE_WIDTH * rY + rX;
      tempAddress2 = MAX_IMAGE_WIDTH * y + x;

      if(rX > 0 && rX < MAX_IMAGE_WIDTH && rY > 0 && rY < MAX_IMAGE_HEIGHT)
        tempThreeDImage[tempAddress] = max(tempThreeDImage[tempAddress], srcImage[tempAddress2]);
    }
  }

  memcpy(tranformedThreeDImage, tempThreeDImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
  memset(tempThreeDImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  cosValue = CosData[(xzR + 720) % 720];
  sinValue = SinData[(xzR + 720) % 720];

  // y축 기준 회전
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      z = tranformedThreeDImage[tempAddress];

      if(z > 0)
      {
        rX = (((x - centerX) * cosValue + (z - centerZ) * sinValue) / 1024) + centerX;
        rY = y;
        rZ = (( - (x - centerX) * sinValue + (z - centerZ) * cosValue) / 1024) + centerZ;

        if(rZ < 0) rZ = 0;
        if(rZ > 255) rZ = 255;

        tempAddress = MAX_IMAGE_WIDTH * rY + rX;

        if(rX > 0 && rX < MAX_IMAGE_WIDTH && rY > 0 && rY < MAX_IMAGE_HEIGHT)
          tempThreeDImage[tempAddress] = max(tempThreeDImage[tempAddress], rZ);
      }
    }
  }

  memcpy(tranformedThreeDImage, tempThreeDImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
  memset(tempThreeDImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  cosValue = CosData[(yzR + 720) % 720];
  sinValue = SinData[(yzR + 720) % 720];
  
  // x축 기준 회전
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      z = tranformedThreeDImage[tempAddress];

      if(z > 0)
      {
        rX = x;
        rY = (((y - centerY) * cosValue - (z - centerZ) * sinValue) / 1024) + centerY;
        rZ = (((y - centerY) * sinValue + (z - centerZ) * cosValue) / 1024) + centerZ;

        if(rZ < 0) rZ = 0;
        if(rZ > 255) rZ = 255;

        tempAddress = MAX_IMAGE_WIDTH * rY + rX;

        if(rX > 0 && rX < MAX_IMAGE_WIDTH && rY > 0 && rY < MAX_IMAGE_HEIGHT)
          tempThreeDImage[tempAddress] = max(tempThreeDImage[tempAddress], rZ);
      } 
    }
  }

  memcpy(tranformedThreeDImage, tempThreeDImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int r = 0;
  int upBinarySW, downBinarySW, leftBinarySW, rightBinarySW;
  int upThreeDHeight, downThreeDHeight, leftThreeDHeight, rightThreeDHeight;

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

      z = tranformedThreeDImage[tempAddress];

      if(z == 0)
      {
        upBinarySW = downBinarySW = leftBinarySW = rightBinarySW = 0;
        upThreeDHeight = downThreeDHeight = leftThreeDHeight = rightThreeDHeight = 0;

        tempCount = 0;
        for(r = 4; r >= 0; r--)
        {
          if(tranformedThreeDImage[tempAddress - r])
          {
            leftBinarySW = 1;
            leftThreeDHeight += tranformedThreeDImage[tempAddress - r];
            tempCount++;
          }
        }

        if(tempCount)
        {
          leftThreeDHeight /= tempCount;
        }

        tempCount = 0;
        for(r = 4; r >= 0; r--)
        {
          if(tranformedThreeDImage[tempAddress + r])
          {
            rightBinarySW = 1;
            rightThreeDHeight += tranformedThreeDImage[tempAddress + r];
            tempCount++;
          }
        }

        if(tempCount)
        {
          rightThreeDHeight /= tempCount;
        }

        tempCount = 0;
        for(r = 4; r >= 0; r--)
        {
          if(tranformedThreeDImage[tempAddress - r * MAX_IMAGE_WIDTH])
          {
            upBinarySW = 1;
            upThreeDHeight += tranformedThreeDImage[tempAddress - r * MAX_IMAGE_WIDTH];
            tempCount++;
          }
        }

        if(tempCount)
        {
          upThreeDHeight /= tempCount;
        }

        tempCount = 0;
        for(r = 4; r >= 0; r--)
        {
          if(tranformedThreeDImage[tempAddress + r * MAX_IMAGE_WIDTH])
          {
            downBinarySW = 1;
            downThreeDHeight += tranformedThreeDImage[tempAddress + r * MAX_IMAGE_WIDTH];
            tempCount++;
          }
        }

        if(tempCount)
        {
          downThreeDHeight /= tempCount;
        }

        if(upBinarySW && downBinarySW)
        {
          tempThreeDImage[tempAddress] = (upThreeDHeight + downThreeDHeight) / 2;

        }
        else if(leftBinarySW && rightBinarySW)
        {
          tempThreeDImage[tempAddress] = (leftThreeDHeight + rightThreeDHeight) / 2;
        }
      } 
    }
  }

  int nX, nY;

  Graphics::TBitmap *tempImage = new Graphics::TBitmap;
  tempImage->Width = MAX_IMAGE_WIDTH;
  tempImage->Height = MAX_IMAGE_HEIGHT;
  tempImage->PixelFormat = pf24bit;

  Byte *ptr;

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

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

  ThreeDRotationImage->Picture->Bitmap->Assign(tempImage);
  ThreeDRotationImage->Refresh();

  delete tempImage;
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::Disk1RotationAngle1Click(
      TObject *Sender, TUDBtnType Button)
{
  //threeDRotation(ThreeD_Image, Disk1RotationAngle1->Position, Disk1RotationAngle2->Position, Disk1RotationAngle3->Position);

  Label22->Caption = "X : " + IntToStr(Disk1RotationAngle1->Position);
  Label20->Caption = "Y : " + IntToStr(Disk1RotationAngle2->Position);
  Label21->Caption = "Z : " + IntToStr(Disk1RotationAngle3->Position);

  threeDRotation2(ThreeD_Image, Disk1RotationAngle1->Position, Disk1RotationAngle2->Position, Disk1RotationAngle3->Position);
}
//---------------------------------------------------------------------------


void __fastcall TTabletSimulationForm::threeDRotation2(unsigned char *srcImage, int xyR, int xzR, int yzR)
{
  int x, y, z;
  int tempAddress, tempAddress2;
  int xzCosValue, xzSinValue;
  int yzCosValue, yzSinValue;
  int centerX, centerY, centerZ;
  int rX, rY, rZ;
  int rX2, rY2, rZ2;
  int CosX, CosY, CosZ;
  int SinX, SinY, SinZ;
  int heightDiff;
  int tempHeight;
  int tempCount;
  unsigned char tempThreeDImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  unsigned char tranformedThreeDImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  

  memset(shiftInfoArray_PC, 0, sizeof(short) * 3 * MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  centerX = centerY = centerZ = tempCount = 0;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      if(srcImage[tempAddress])
      {
        centerX += x;
        centerY += y;
        centerZ += srcImage[tempAddress];
        tempCount++;
      }
    }
  }

  if(tempCount)
  {
    centerX /= tempCount;
    centerY /= tempCount;
    centerZ /= tempCount; 
  }
  else
  {
    centerX = MAX_IMAGE_WIDTH / 2;
    centerY = MAX_IMAGE_HEIGHT / 2;
    centerZ = 128;
  }

  memset(tempThreeDImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  xzCosValue = CosData[(xzR + 720) % 720];
  xzSinValue = SinData[(xzR + 720) % 720];

  yzCosValue = CosData[(yzR + 720) % 720];
  yzSinValue = SinData[(yzR + 720) % 720];

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

      z = srcImage[tempAddress];

      if(z > 0)
      {
        rX = (((x - centerX) * xzCosValue + (z - centerZ) * xzSinValue) / 1024) + centerX;
        rY = y;
        rZ = (( - (x - centerX) * xzSinValue + (z - centerZ) * xzCosValue) / 1024) + centerZ;

        if(rZ < 0) rZ = 0;
        if(rZ > 255) rZ = 255;

        rX2 = rX;
        rY2 = (((rY - centerY) * yzCosValue - (rZ - centerZ) * yzSinValue) / 1024) + centerY;
        rZ2 = (((rY - centerY) * yzSinValue + (rZ - centerZ) * yzCosValue) / 1024) + centerZ;

        if(rZ2 < 0) rZ2 = 0;
        if(rZ2 > 255) rZ2 = 255;

        tempAddress = MAX_IMAGE_WIDTH * rY2 + rX2;

        if(rX2 > 0 && rX2 < MAX_IMAGE_WIDTH && rY2 > 0 && rY2 < MAX_IMAGE_HEIGHT)
        {
          tempThreeDImage[tempAddress] = max(tempThreeDImage[tempAddress], rZ2);
          shiftInfoArray_PC[MAX_IMAGE_WIDTH * y + x][0] = rX2;
          shiftInfoArray_PC[MAX_IMAGE_WIDTH * y + x][1] = rY2;
          shiftInfoArray_PC[MAX_IMAGE_WIDTH * y + x][2] = rZ2;
        }
      }
    }
  }

  memcpy(tranformedThreeDImage, tempThreeDImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int r = 0;
  int upBinarySW, downBinarySW, leftBinarySW, rightBinarySW;
  int upThreeDHeight, downThreeDHeight, leftThreeDHeight, rightThreeDHeight;

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

      z = tranformedThreeDImage[tempAddress];

      if(z == 0)
      {
        upBinarySW = downBinarySW = leftBinarySW = rightBinarySW = 0;
        upThreeDHeight = downThreeDHeight = leftThreeDHeight = rightThreeDHeight = 0;

        tempCount = 0;
        for(r = 4; r >= 0; r--)
        {
          if(tranformedThreeDImage[tempAddress - r])
          {
            leftBinarySW = 1;
            leftThreeDHeight += tranformedThreeDImage[tempAddress - r];
            tempCount++;
          }
        }

        if(tempCount)
        {
          leftThreeDHeight /= tempCount;
        }

        tempCount = 0;
        for(r = 4; r >= 0; r--)
        {
          if(tranformedThreeDImage[tempAddress + r])
          {
            rightBinarySW = 1;
            rightThreeDHeight += tranformedThreeDImage[tempAddress + r];
            tempCount++;
          }
        }

        if(tempCount)
        {
          rightThreeDHeight /= tempCount;
        }

        tempCount = 0;
        for(r = 4; r >= 0; r--)
        {
          if(tranformedThreeDImage[tempAddress - r * MAX_IMAGE_WIDTH])
          {
            upBinarySW = 1;
            upThreeDHeight += tranformedThreeDImage[tempAddress - r * MAX_IMAGE_WIDTH];
            tempCount++;
          }
        }

        if(tempCount)
        {
          upThreeDHeight /= tempCount;
        }

        tempCount = 0;
        for(r = 4; r >= 0; r--)
        {
          if(tranformedThreeDImage[tempAddress + r * MAX_IMAGE_WIDTH])
          {
            downBinarySW = 1;
            downThreeDHeight += tranformedThreeDImage[tempAddress + r * MAX_IMAGE_WIDTH];
            tempCount++;
          }
        }

        if(tempCount)
        {
          downThreeDHeight /= tempCount;
        }

        if(upBinarySW && downBinarySW)
        {
          tempThreeDImage[tempAddress] = (upThreeDHeight + downThreeDHeight) / 2;

        }
        else if(leftBinarySW && rightBinarySW)
        {
          tempThreeDImage[tempAddress] = (leftThreeDHeight + rightThreeDHeight) / 2;
        }
      } 
    }
  }

  memset(TempImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);

  int shiftX, shiftY, shiftZ;
  int rotateHeight;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;

      z = srcImage[tempAddress];

      if(z)
      {
        shiftX = shiftInfoArray_PC[tempAddress][0];
        shiftY = shiftInfoArray_PC[tempAddress][1];
        shiftZ = shiftInfoArray_PC[tempAddress][2];

        rotateHeight = tempThreeDImage[MAX_IMAGE_WIDTH * shiftY + shiftX];

        if(rotateHeight - shiftZ > 6)
        {
          TempImage[tempAddress] = 1;
        }
      }
    }
  }

  int nX, nY;

  Graphics::TBitmap *tempImage = new Graphics::TBitmap;
  tempImage->Width = MAX_IMAGE_WIDTH;
  tempImage->Height = MAX_IMAGE_HEIGHT;
  tempImage->PixelFormat = pf24bit;

  Byte *ptr;

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

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

  Image11->Picture->Bitmap->Assign(tempImage);
  Image11->Refresh();

  ThreeDRotationImage->Picture->Bitmap->Assign(tempImage);
  ThreeDRotationImage->Refresh();
  
  RealThreeDImage->Picture->Bitmap->Assign(tempImage);
  RealThreeDImage->Refresh();

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

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

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

  Image12->Picture->Bitmap->Assign(tempImage);
  Image12->Refresh();

  delete tempImage;
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::ThreeDDebug_RotationImageMouseMove(
      TObject *Sender, TShiftState Shift, int X, int Y)
{
  int x, y;
  int tempAddress;

  unsigned char realYSliceImage[MAX_IMAGE_HEIGHT * 256];
  unsigned char adjustYSliceImage[MAX_IMAGE_HEIGHT * 256];

  int shiftX; 

  memset(realYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);
  memset(adjustYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);

  ThreeDDebug_RotationImage->Picture->Bitmap->Width = MAX_IMAGE_WIDTH;
  ThreeDDebug_RotationImage->Picture->Bitmap->Height = MAX_IMAGE_HEIGHT;
  ThreeDDebug_RotationImage->Picture->Bitmap->PixelFormat = pf24bit;

  SliceResult1->Picture->Bitmap->Width = 256;
  SliceResult1->Picture->Bitmap->Height = MAX_IMAGE_HEIGHT;
  SliceResult1->Picture->Bitmap->PixelFormat = pf24bit;

  SliceResult2->Picture->Bitmap->Width = 256;
  SliceResult2->Picture->Bitmap->Height = MAX_IMAGE_HEIGHT;
  SliceResult2->Picture->Bitmap->PixelFormat = pf24bit;

  shiftX = X * MAX_IMAGE_WIDTH / ThreeDDebug_RotationImage->Width;

  int value;
  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    value = AdjustThreeD_Data[MAX_IMAGE_WIDTH * y + shiftX];

    if(value)
    {
      for(int tempY = y - 1; tempY <= y + 1; tempY++)
      {
        for(int tempX = value - 1; tempX <= value + 1; tempX++)
        {
          if(tempX > 0 && tempX < 256 && tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
          {
            realYSliceImage[256 * tempY + tempX] = 255;
          }
        }
      }
    }
  }

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    value = RotationThreeDImage[MAX_IMAGE_WIDTH * y + shiftX];

    if(value)
    {
      for(int tempY = y - 1; tempY <= y + 1; tempY++)
      {
        for(int tempX = value - 1; tempX <= value + 1; tempX++)
        {
          if(tempX > 0 && tempX < 256 && tempY > 0 && tempY < MAX_IMAGE_HEIGHT)
          {
            adjustYSliceImage[256 * tempY + tempX] = 255;
          }
        }
      }
    }
  }

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = 256;              
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

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

    for(x = 0; x < 256; x++)
    {
      ptr[3 * x + 0] = 0;
      ptr[3 * x + 1] = 0;
      ptr[3 * x + 2] = 0;

      tempAddress = 256 * y + x;

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

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

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

  SliceResult1->Canvas->Pen->Width = 2;
  SliceResult1->Canvas->Pen->Color = clRed;
  SliceResult1->Canvas->Brush->Style = bsClear;
  SliceResult1->Canvas->MoveTo(ProtoTabletCenterZ, 0);
  SliceResult1->Canvas->LineTo(ProtoTabletCenterZ, MAX_IMAGE_HEIGHT);

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

    for(x = 0; x < 256; x++)
    {
      ptr[3 * x + 0] = 0;
      ptr[3 * x + 1] = 0;
      ptr[3 * x + 2] = 0;

      tempAddress = 256 * y + x;

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

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

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

void __fastcall TTabletSimulationForm::ThreeDImageUpdownClick(TObject *Sender,
      TUDBtnType Button)
{
  InspectionFlag = 1;

  CameraIndexEdit->Text = "";
  InspectionResultEdit->Text = "";

  ImageCount = ThreeDImageUpdown->Position / 2;
  InspectionOrStudy = INSPECTION_MODE;

  ImageIndexEdit->Text = IntToStr(ImageCount);
  ThreeDImageNumberEdit->Text = IntToStr(ImageCount);

  int camIndex;
  if(ThreeDImageUpdown->Position % 2 == 0)
  {
    camIndex = SD1_3D_FRONT_FACE_CAMERA_INDEX;
  }
  else
  {
    camIndex = SD2_3D_FRONT_FACE_CAMERA_INDEX;
  }

  SelectedCameraIndex = camIndex;

  ThreeDCameraNumberEdit->Text = IntToStr(camIndex);

  if(CameraMapInfo[camIndex - 1].CameraInspectPosition != CAMERA_POSITION_DISCONNECT)
  {
    DoProcessingFor3D(ImageCount, camIndex, SIM_MANUAL_MODE);

    if(DefectSWforCamera[camIndex-1] == 0)
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Pen->Color = clGreen;
    else if(DefectSWforCamera[camIndex-1] == 1)
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Pen->Color = clRed;
    else
      ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Pen->Color = clYellow;

    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Picture->Bitmap->PixelFormat = pf24bit;
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Pen->Width = 20;
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Brush->Style = bsClear;
    ((TTntImage *)FindComponent("InspectionCam"+IntToStr(camIndex)))->Canvas->Rectangle(15, 15, ImageWidth-15, ImageHeight-15);
  }

  if(CheckBox3->Checked == false)
  {
    LoadFrontFace3DDebugData();
  }
  else
  {
    Load3DPositionInfo();
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::TrackBar9Change(TObject *Sender)
{
  int x, y;
  int tempAddress;

  Graphics::TBitmap *tempImage = new Graphics::TBitmap;
  tempImage->Width = MAX_IMAGE_WIDTH;
  tempImage->Height = MAX_IMAGE_HEIGHT;
  tempImage->PixelFormat = pf24bit;

  Byte *ptr;

  int threshold;
  threshold = TrackBar9->Position;

  memset(TempImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
  for(y = 10; y < MAX_IMAGE_HEIGHT - 10; y++)
  {
    for(x = 10; x < MAX_IMAGE_WIDTH - 10; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;
      
      int height = AdjustThreeD_Data[tempAddress];

      if(height < threshold && height)
      {
        /*
        if(AdjustThreeD_Data[tempAddress - 1] <= threshold ||
            AdjustThreeD_Data[tempAddress + 1] <= threshold ||
            AdjustThreeD_Data[tempAddress - MAX_IMAGE_WIDTH] <= threshold ||
            AdjustThreeD_Data[tempAddress + MAX_IMAGE_WIDTH] <= threshold)
        */
        {
          TempImage[tempAddress] = 1;
        }
      }
    }
  }

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    ptr = (Byte *) tempImage->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(TempImage[tempAddress])
      {
        ptr[3 * x + 0] = 0;
        ptr[3 * x + 1] = 0;
        ptr[3 * x + 2] = 255;
      }
    }
  }

  RealThreeDImage->Picture->Bitmap->Assign(tempImage);
  RealThreeDImage->Refresh();

  delete tempImage;
}
//---------------------------------------------------------------------------

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

  int x, y, color;
  int tempAddress, tempAddress2;
  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] = ThreeD_Image[tempAddress];
      ptr[3 * x + 1] = ThreeD_Image[tempAddress];
      ptr[3 * x + 2] = ThreeD_Image[tempAddress];
    }
  }

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

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

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

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

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

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

  int tempData[MAX_IMAGE_WIDTH][2];
  int angleViewer[MAX_IMAGE_WIDTH][3];
  memset(tempData, 0, sizeof(int) * MAX_IMAGE_WIDTH * 2);
  memset(angleViewer, 0, sizeof(int) * MAX_IMAGE_WIDTH * 3);
  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 % 720;
  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;
      angleViewer[tempCount][2] = 255 * m / MAX_IMAGE_WIDTH;
      tempCount++;
    }
  }

  Byte *ptr2;
  for(int m = 0; m < tempCount; m++)
  {
    x = angleViewer[m][0];
    y = angleViewer[m][1];
    color = angleViewer[m][2];

    ptr = (Byte *)Image11->Picture->Bitmap->ScanLine[y];
    ptr2 = (Byte *)Image12->Picture->Bitmap->ScanLine[y];

    ptr[3 * x + 0] = color;
    ptr[3 * x + 1] = 128;
    ptr[3 * x + 2] = 0;

    ptr2[3 * x + 0] = color;
    ptr2[3 * x + 1] = 128;
    ptr2[3 * x + 2] = 0;
  }

  Image11->Refresh();
  Image12->Refresh();
  Label50->Caption = "X : "+ IntToStr(ThreeDPositionInfo_CPB.TabletCenterX);
  Label51->Caption = "Y : "+ IntToStr(ThreeDPositionInfo_CPB.TabletCenterY);
  Label52->Caption = "Z : "+ IntToStr(ThreeDPositionInfo_CPB.TabletRotationAngle);

  if(CheckBox4->Checked)
  {
    AnsiString path = GetProductImagePath() + "\\Rotataion Test Image";
    if (!DirectoryExists(path))
    {
      CreateDir(path);
    }

    AnsiString filename = path + "\\Camera_" + IntToStr(SelectedCameraIndex)  + "_" + IntToStr(ImageCount) + ".bmp";

    Image12->Picture->Bitmap->SaveToFile(filename);
  }

  delete img;
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::Button14Click(TObject *Sender)
{
  ExtractBayerImage(BayerImage, ImageCount, SelectedCameraIndex);

  unsigned char *shiftBayerAddress;

  if(CameraMapInfo[SelectedCameraIndex - 1].CameraInspectPosition == CAMERA_POSITION_3D)
  {
    shiftBayerAddress = BayerImage + 1;
  }
  else
  {
    shiftBayerAddress = BayerImage; 
  }

  unsigned char testSmallImage[(MAX_IMAGE_WIDTH / 4) * (MAX_IMAGE_HEIGHT / 4)];
  memset(testSmallImage, 0, (MAX_IMAGE_WIDTH / 4) * (MAX_IMAGE_HEIGHT / 4));

  int smallWidth = MAX_IMAGE_WIDTH / 4;
  int smallHeight = MAX_IMAGE_HEIGHT / 4;

  Image1->Picture->Bitmap->Width = smallWidth;
  Image1->Picture->Bitmap->Height = smallHeight;
  Image1->Picture->Bitmap->PixelFormat = pf24bit;

  Image2->Picture->Bitmap->Width = smallWidth;
  Image2->Picture->Bitmap->Height = smallHeight;
  Image2->Picture->Bitmap->PixelFormat = pf24bit;

  for(int y = 0; y < smallHeight; y++)
  {
    Byte *ptr = (Byte*)Image1->Picture->Bitmap->ScanLine[y];
    for(int x = 0; x < smallWidth; x++)
    {
      testSmallImage[smallWidth * y + x] = shiftBayerAddress[MAX_IMAGE_WIDTH * (y * 4) + (x * 4)];

      ptr[3*x + 0] = testSmallImage[smallWidth * y + x];
      ptr[3*x + 1] = testSmallImage[smallWidth * y + x];
      ptr[3*x + 2] = testSmallImage[smallWidth * y + x];
    }
  }

  Image1->Refresh();

  if(CameraMapInfo[SelectedCameraIndex - 1].CameraInspectPosition == CAMERA_POSITION_3D)
  {
    Graphics::TBitmap *tempBitmap = new Graphics::TBitmap;
    tempBitmap->Width = IMAGE_WIDTH_3D / 4;
    tempBitmap->Height = IMAGE_HEIGHT_3D / 4;
    tempBitmap->PixelFormat = pf8bit;

    ImageConversion_3D(tempBitmap, IMAGE_WIDTH_3D / 4, IMAGE_HEIGHT_3D / 4, testSmallImage, SYSTEM_CAMERA_WIDTH_3D / 4, SYSTEM_CAMERA_HEIGHT_3D / 4);

    for (int y = 0; y < (IMAGE_HEIGHT_3D / 4); y++)
    {
      byte *pBitmap = (byte *)Image2->Picture->Bitmap->ScanLine[y];
      byte *pSrc = (byte *)tempBitmap->ScanLine[y];

      for (int x = 0; x < (IMAGE_WIDTH_3D / 4) * 2; x++)
      {
        if(y == 0 || (x / 2) == 0 || y == (IMAGE_HEIGHT_3D / 4) - 1 || (x / 2) == (IMAGE_WIDTH_3D / 4) - 1)
        {
          pBitmap[3 * x + 0] = 0;
          pBitmap[3 * x + 1] = 0;
          pBitmap[3 * x + 2] = 0;
        }
        else
        {
          pBitmap[3 * x + 0] = min(255, pSrc[x / 2] * 2);
          pBitmap[3 * x + 1] = min(255, pSrc[x / 2] * 2);
          pBitmap[3 * x + 2] = min(255, pSrc[x / 2] * 2);
        }
      }
    }

    Image2->Refresh();

    delete tempBitmap;
  }
  else
  {
    Graphics::TBitmap *tempImage = new Graphics::TBitmap;
    tempImage->Width = smallWidth;
    tempImage->Height = smallHeight;
    tempImage->PixelFormat = pf24bit;

    //Bayer_Conversion_GBRG(tempImage, testSmallImage, smallWidth, smallHeight, 2);
    //ApplyWhiteBalance(SD1_2D_FRONT_FACE_CAMERA_INDEX - 1, tempImage, Image2->Picture->Bitmap);

    for(int y = 0; y < smallHeight; y++)
    {
      Byte *ptr = (Byte*)Image2->Picture->Bitmap->ScanLine[y];
      for(int x = 0; x < smallWidth; x++)
      {
        if(y == 0 || x == 0 || y == smallHeight - 1 || x == smallWidth - 1)
        {
          ptr[3*x + 0] = 0;
          ptr[3*x + 1] = 0;
          ptr[3*x + 2] = 0;
        }
        else
        {
          ptr[3*x + 0] = testSmallImage[smallWidth * y + x];
          ptr[3*x + 1] = testSmallImage[smallWidth * y + x];
          ptr[3*x + 2] = testSmallImage[smallWidth * y + x];
        }
      }
    }

    Image2->Repaint();

    delete tempImage;
  }
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::TrackBar10Change(TObject *Sender)
{
  TColor tempColor;
  tempColor = 0x00FF0000;
  tempColor = 0x000000FF;

  int minColor = 0x000000FF; // red
  int maxColor = 0x00FF0000; // blue

  float value = (255 - TrackBar10->Position) / 255.0;

  int nColor;

  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);
  }

  Shape1->Brush->Color = (TColor)nColor;

  Label47->Caption = IntToStr((nColor & 0x00FF0000) >> 16);
  Label48->Caption = IntToStr((nColor & 0x0000FF00) >> 8);
  Label49->Caption = IntToStr((nColor & 0x000000FF) >> 0);
}
//---------------------------------------------------------------------------

TColor __fastcall TTabletSimulationForm::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;
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::RealThreeDImageDblClick(
      TObject *Sender)
{
  ModelingTestImage->Picture->Bitmap->Assign(xSliceThreeDImage->Picture->Bitmap);
  ModelingTestImage->Refresh();
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::ModelingTestImageMouseDown(
      TObject *Sender, TMouseButton Button, TShiftState Shift, int X,
      int Y)
{
  unsigned char tempXSliceImage[MAX_IMAGE_WIDTH * 256];
  memset(tempXSliceImage, 0, MAX_IMAGE_WIDTH * 256);

  int x, y;
  int tempAddress;

  for(y = 0; y < 256; y++)
  {
    Byte *ptr = (Byte*) ModelingTestImage->Picture->Bitmap->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      if(ptr[3*x + 1])
      {
        tempXSliceImage[MAX_IMAGE_WIDTH * (256 - y) + x] = 255;
      }
    }
  }

  unsigned char SectionModelingResult[MAX_IMAGE_WIDTH * 256];
  memset(SectionModelingResult, 0, MAX_IMAGE_WIDTH * 256);


  int SelectedX, SelectedY;
  int CheckPointX1, CheckPointY1;
  int CheckPointX2, CheckPointY2;

  int ModelingSW = 0;
  for(y = 0; y < 256; y++)
  {
    tempAddress = MAX_IMAGE_WIDTH * y + X;

    if(X > 10 && X < MAX_IMAGE_WIDTH - 10)
    {
      if(tempXSliceImage[tempAddress])
      {
        SelectedX = X;
        SelectedY = y;

        ModelingSW = 1;
        break;
      }
    }
  }

  if(ModelingSW)
  {
    ModelingSW = 0;
    for(y = 0; y < 256; y++)
    {
      for(int tempX = SelectedX - 10; tempX >= SelectedX - 20; tempX--)
      {
        tempAddress = MAX_IMAGE_WIDTH * y + tempX;

        if(tempX > 10 && tempX < MAX_IMAGE_WIDTH - 10)
        {
          int c = abs(y - SelectedY);
          if(tempXSliceImage[tempAddress] && c)
          {
            CheckPointX1 = tempX;
            CheckPointY1 = y;

            ModelingSW = 1;
            break;
          }
        }
      }

      if(ModelingSW)
      {
        break;
      }
    }

    if(ModelingSW)
    {
      ModelingSW = 0;
      for(y = 0; y < 256; y++)
      {
        for(int tempX = SelectedX + 10; tempX <= SelectedX + 20; tempX++)
        {
          tempAddress = MAX_IMAGE_WIDTH * y + tempX;

          if(tempX > 10 && tempX < MAX_IMAGE_WIDTH - 10)
          {
            int c = abs(y - SelectedY);
            if(tempXSliceImage[tempAddress] && c)
            {
              CheckPointX2 = tempX;
              CheckPointY2 = y;

              ModelingSW = 1;
              break;
            }
          }
        }

        if(ModelingSW)
        {
          break;
        }
      }

      if(ModelingSW)
      {
        for(y = SelectedY - 2; y <= SelectedY + 2; y++)
        {
          for(x = SelectedX - 2; x <= SelectedX + 2; x++)
          {
            tempAddress = MAX_IMAGE_WIDTH * y + x;
            SectionModelingResult[tempAddress] = 255;
          }
        }

        for(y = CheckPointY1 - 2; y <= CheckPointY1 + 2; y++)
        {
          for(x = CheckPointX1 - 2; x <= CheckPointX1 + 2; x++)
          {
            tempAddress = MAX_IMAGE_WIDTH * y + x;
            SectionModelingResult[tempAddress] = 255;
          }
        }

        for(y = CheckPointY2 - 2; y <= CheckPointY2 + 2; y++)
        {
          for(x = CheckPointX2 - 2; x <= CheckPointX2 + 2; x++)
          {
            tempAddress = MAX_IMAGE_WIDTH * y + x;
            SectionModelingResult[tempAddress] = 255;
          }
        }

        float d1, d2;

        if(SelectedY - CheckPointY1)
        {
          d1 = (SelectedX - CheckPointX1) / (float)(SelectedY - CheckPointY1);
        }
        else
        {
          d1 = 0;
        }

        if(CheckPointY2 - SelectedY)
        {
          d2 = (CheckPointX2 - SelectedX) / (float)(CheckPointY2 - SelectedY);
        }
        else
        {
          d2 = 0;
        }

        float cX, cY;

        if(d2 - d1)
        {
          cX = ((CheckPointY2 - CheckPointY1) + (SelectedX + CheckPointX2) * d2 - (SelectedX + CheckPointX1) * d1) / (2 * (d2 - d1));

          cY = -d1 * (cX - (CheckPointX1 + SelectedX) / 2) + (SelectedY + CheckPointY1) / 2;

          float r;
          r = sqrt((CheckPointX1 - cX) * (CheckPointX1 - cX) + (CheckPointY1 - cY) * (CheckPointY1 - cY));

          for(x = 0; x < MAX_IMAGE_WIDTH; x++)
          {
            if(x > 0 && x < MAX_IMAGE_WIDTH)
            {
              if(r * r >= (x - cX) * (x - cX))
              {
                y = sqrt(r * r - (x - cX) * (x - cX)) + cY;

                if(y > 0 && y < 256)
                {
                  tempAddress = MAX_IMAGE_WIDTH * y + x;
                  SectionModelingResult[tempAddress] = 128;
                }
              }
            }
          }
        }
      }
    }
  }

  Graphics::TBitmap *img1;
  img1 = new Graphics::TBitmap();

  img1->Width = MAX_IMAGE_WIDTH;
  img1->Height = 256;
  img1->PixelFormat = pf24bit;
 
  for(y = 0; y < 256; y++)
  {
    Byte *ptr = (Byte*) img1->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      ptr[3*x + 0] = tempXSliceImage[MAX_IMAGE_WIDTH * y + x];
      ptr[3*x + 1] = tempXSliceImage[MAX_IMAGE_WIDTH * y + x];
      ptr[3*x + 2] = tempXSliceImage[MAX_IMAGE_WIDTH * y + x];

      if(SectionModelingResult[MAX_IMAGE_WIDTH * y + x])
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 255;

        if(SectionModelingResult[MAX_IMAGE_WIDTH * y + x] == 128)
        {
          ptr[3*x + 0] = 0;
          ptr[3*x + 1] = 255;
          ptr[3*x + 2] = 0;
        }
      }
    }
  }

  ModelingResultImage->Picture->Bitmap->Assign(img1);
  ModelingResultImage->Refresh();
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::TrackBar11Change(TObject *Sender)
{
  int X = TrackBar11->Position;
  
  unsigned char tempXSliceImage[MAX_IMAGE_WIDTH * 256];
  memset(tempXSliceImage, 0, MAX_IMAGE_WIDTH * 256);

  int x, y;
  int tempAddress;

  for(y = 0; y < 256; y++)
  {
    Byte *ptr = (Byte*) ModelingTestImage->Picture->Bitmap->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      if(ptr[3*x + 1])
      {
        tempXSliceImage[MAX_IMAGE_WIDTH * (256 - y) + x] = 255;
      }
    }
  }

  unsigned char SectionModelingResult[MAX_IMAGE_WIDTH * 256];
  memset(SectionModelingResult, 0, MAX_IMAGE_WIDTH * 256);


  int SelectedX, SelectedY;
  int CheckPointX1, CheckPointY1;
  int CheckPointX2, CheckPointY2;

  int ModelingSW = 0;
  for(y = 0; y < 256; y++)
  {
    tempAddress = MAX_IMAGE_WIDTH * y + X;

    if(X > 10 && X < MAX_IMAGE_WIDTH - 10)
    {
      if(tempXSliceImage[tempAddress])
      {
        SelectedX = X;
        SelectedY = y;

        ModelingSW = 1;
        break;
      }
    }
  }

  if(ModelingSW)
  {
    ModelingSW = 0;
    for(y = 0; y < 256; y++)
    {
      for(int tempX = SelectedX - 50; tempX <= SelectedX - 20; tempX++)
      {
        tempAddress = MAX_IMAGE_WIDTH * y + tempX;

        if(tempX > 10 && tempX < MAX_IMAGE_WIDTH - 10)
        {
          int c = abs(y - SelectedY);
          if(tempXSliceImage[tempAddress] && c)
          {
            CheckPointX1 = tempX;
            CheckPointY1 = y;

            ModelingSW = 1;
            break;
          }
        }
      }

      if(ModelingSW)
      {
        break;
      }
    }

    if(ModelingSW)
    {
      ModelingSW = 0;
      for(y = 0; y < 256; y++)
      {
        for(int tempX = SelectedX + 50; tempX >= SelectedX + 20; tempX--)
        {
          tempAddress = MAX_IMAGE_WIDTH * y + tempX;

          if(tempX > 10 && tempX < MAX_IMAGE_WIDTH - 10)
          {
            int c = abs(y - SelectedY);
            if(tempXSliceImage[tempAddress] && c)
            {
              if((SelectedX - CheckPointX1) * (y - SelectedY) != (tempX - SelectedX) * (SelectedY - CheckPointY1))
              {
                CheckPointX2 = tempX;
                CheckPointY2 = y;

                ModelingSW = 1;
                break;
              }
            }
          }
        }

        if(ModelingSW)
        {
          break;
        }
      }

      if(ModelingSW)
      {
        for(y = SelectedY - 2; y <= SelectedY + 2; y++)
        {
          for(x = SelectedX - 2; x <= SelectedX + 2; x++)
          {
            tempAddress = MAX_IMAGE_WIDTH * y + x;
            SectionModelingResult[tempAddress] = 255;
          }
        }

        for(y = CheckPointY1 - 2; y <= CheckPointY1 + 2; y++)
        {
          for(x = CheckPointX1 - 2; x <= CheckPointX1 + 2; x++)
          {
            tempAddress = MAX_IMAGE_WIDTH * y + x;
            SectionModelingResult[tempAddress] = 255;
          }
        }

        for(y = CheckPointY2 - 2; y <= CheckPointY2 + 2; y++)
        {
          for(x = CheckPointX2 - 2; x <= CheckPointX2 + 2; x++)
          {
            tempAddress = MAX_IMAGE_WIDTH * y + x;
            SectionModelingResult[tempAddress] = 255;
          }
        }

        float d1, d2;

        if(SelectedY - CheckPointY1)
        {
          d1 = (SelectedX - CheckPointX1) / (float)(SelectedY - CheckPointY1);
        }
        else
        {
          d1 = 0;
        }

        if(CheckPointY2 - SelectedY)
        {
          d2 = (CheckPointX2 - SelectedX) / (float)(CheckPointY2 - SelectedY);
        }
        else
        {
          d2 = 0;
        }

        float cX, cY;

        if(d2 - d1)
        {
          cX = ((CheckPointY2 - CheckPointY1) + (SelectedX + CheckPointX2) * d2 - (SelectedX + CheckPointX1) * d1) / (2 * (d2 - d1));

          cY = -d1 * (cX - (CheckPointX1 + SelectedX) / 2) + (SelectedY + CheckPointY1) / 2;

          float r;
          r = sqrt((CheckPointX1 - cX) * (CheckPointX1 - cX) + (CheckPointY1 - cY) * (CheckPointY1 - cY));

          for(x = 0; x < MAX_IMAGE_WIDTH; x++)
          {
            if(x > 0 && x < MAX_IMAGE_WIDTH)
            {
              if(r * r >= (x - cX) * (x - cX))
              {
                y = sqrt(r * r - (x - cX) * (x - cX)) + cY;

                if(y > 0 && y < 256)
                {
                  tempAddress = MAX_IMAGE_WIDTH * y + x;
                  SectionModelingResult[tempAddress] = 128;
                }
              }
            }
          }
        }

        long long id1, id2;

        if(SelectedY - CheckPointY1)
        {
          id1 = ((SelectedX - CheckPointX1) * 100000) / (SelectedY - CheckPointY1);
        }
        else
        {
          id1 = 0;
        }

        if(CheckPointY2 - SelectedY)
        {
          id2 = ((CheckPointX2 - SelectedX) * 100000) / (CheckPointY2 - SelectedY);
        }
        else
        {
          id2 = 0;
        }

        if(id2 - id1)
        {
          cX = ((CheckPointY2 - CheckPointY1) * 100000 + (SelectedX + CheckPointX2) * id2 - (SelectedX + CheckPointX1) * id1) * 100 / (2 * (id2 - id1));
          cY = (-id1 * (cX - ((CheckPointX1 + SelectedX) / 2) * 100)) / 10000000 + (SelectedY + CheckPointY1) / 2;

          cX /= 100;

          int distance;
          distance = (CheckPointX1 - cX) * (CheckPointX1 - cX) + (CheckPointY1 - cY) * (CheckPointY1 - cY);

          if(distance < MAX_SHAPE_RADIAL * MAX_SHAPE_RADIAL)
          {
            int r = sqrtTable[distance] / 1000;

            for(x = 0; x < MAX_IMAGE_WIDTH; x++)
            {
              if(x > 0 && x < MAX_IMAGE_WIDTH)
              {
                if(r * r >= (x - cX) * (x - cX))
                {
                  distance = r * r - (x - cX) * (x - cX);
                  
                  y = sqrtTable[distance] / 1000 + cY;

                  if(y > 0 && y < 256)
                  {
                    tempAddress = MAX_IMAGE_WIDTH * y + x;
                    SectionModelingResult[tempAddress] = 192;
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  Graphics::TBitmap *img1;
  img1 = new Graphics::TBitmap();

  img1->Width = MAX_IMAGE_WIDTH;
  img1->Height = 256;
  img1->PixelFormat = pf24bit;
 
  for(y = 0; y < 256; y++)
  {
    Byte *ptr = (Byte*) img1->ScanLine[y];
    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      ptr[3*x + 0] = tempXSliceImage[MAX_IMAGE_WIDTH * y + x];
      ptr[3*x + 1] = tempXSliceImage[MAX_IMAGE_WIDTH * y + x];
      ptr[3*x + 2] = tempXSliceImage[MAX_IMAGE_WIDTH * y + x];

      if(SectionModelingResult[MAX_IMAGE_WIDTH * y + x])
      {
        ptr[3*x + 0] = 0;
        ptr[3*x + 1] = 0;
        ptr[3*x + 2] = 255;

        if(SectionModelingResult[MAX_IMAGE_WIDTH * y + x] == 128)
        {
          ptr[3*x + 0] = 0;
          ptr[3*x + 1] = 255;
          ptr[3*x + 2] = 0;
        }

        if(SectionModelingResult[MAX_IMAGE_WIDTH * y + x] == 192)
        {
          ptr[3*x + 0] = 255;
          ptr[3*x + 1] = 0;
          ptr[3*x + 2] = 0;
        }
      }
    }
  }

  ModelingResultImage->Picture->Bitmap->Assign(img1);
  ModelingResultImage->Refresh();
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::SugarCoatingTestImageMouseMove(
      TObject *Sender, TShiftState Shift, int X, int Y)
{
  if(SelectedCameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX || SelectedCameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
  {
    int x, y;
    int tempAddress;

    unsigned char srcXSliceImage[MAX_IMAGE_WIDTH * 256];
    unsigned char srcYSliceImage[MAX_IMAGE_HEIGHT * 256];

    unsigned char madeXSliceImage[MAX_IMAGE_WIDTH * 256];
    unsigned char madeYSliceImage[MAX_IMAGE_HEIGHT * 256];

    memset(srcXSliceImage, 0, MAX_IMAGE_WIDTH * 256);
    memset(srcYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);

    memset(madeXSliceImage, 0, MAX_IMAGE_WIDTH * 256);
    memset(madeYSliceImage, 0, MAX_IMAGE_HEIGHT * 256);

    SugarCoatingTestImage->Picture->Bitmap->Width = MAX_IMAGE_WIDTH;
    SugarCoatingTestImage->Picture->Bitmap->Height = MAX_IMAGE_HEIGHT;
    SugarCoatingTestImage->Picture->Bitmap->PixelFormat = pf24bit;

    ySliceThreeDImage->Picture->Bitmap->Width = 256;
    ySliceThreeDImage->Picture->Bitmap->Height = MAX_IMAGE_HEIGHT;
    ySliceThreeDImage->Picture->Bitmap->PixelFormat = pf24bit;

    xSliceThreeDImage->Picture->Bitmap->Width = MAX_IMAGE_WIDTH;
    xSliceThreeDImage->Picture->Bitmap->Height = 256;
    xSliceThreeDImage->Picture->Bitmap->PixelFormat = pf24bit;

    int value;
    for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
    {
      value = AdjustThreeD_Data[MAX_IMAGE_WIDTH * y + X];

      if(value)
      {
        srcYSliceImage[256 * y + value] = 255;
      }
    }

    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      value = AdjustThreeD_Data[MAX_IMAGE_WIDTH * Y + x];

      if(value)
      {
        srcXSliceImage[MAX_IMAGE_WIDTH * (255 - value) + x] = 255;
      }
    }

    for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
    {
      value = TempImage[MAX_IMAGE_WIDTH * y + X];

      if(value)
      {
        madeYSliceImage[256 * y + value] = 255;
      }
    }

    for(x = 0; x < MAX_IMAGE_WIDTH; x++)
    {
      value = TempImage[MAX_IMAGE_WIDTH * Y + x];

      if(value)
      {
        madeXSliceImage[MAX_IMAGE_WIDTH * (255 - value) + x] = 255;
      }
    }

    Graphics::TBitmap *img = new Graphics::TBitmap;
    img->Width = 256;              
    img->Height = MAX_IMAGE_HEIGHT;
    img->PixelFormat = pf24bit;

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

      for(x = 0; x < 256; x++)
      {
        ptr[3 * x + 0] = 0;
        ptr[3 * x + 1] = 0;
        ptr[3 * x + 2] = 0;

        tempAddress = 256 * y + x;

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

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

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

    img->Width = MAX_IMAGE_WIDTH;              
    img->Height = 256;
    img->PixelFormat = pf24bit;

    for(y = 0; y < 256; y++)
    {
      Byte *ptr = (Byte *)img->ScanLine[y];

      for(x = 0; x < MAX_IMAGE_WIDTH; x++)
      {
        ptr[3 * x + 0] = 0;
        ptr[3 * x + 1] = 0;
        ptr[3 * x + 2] = 0;

        tempAddress = MAX_IMAGE_WIDTH * y + x;

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

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

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

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

void __fastcall TTabletSimulationForm::Button15Click(TObject *Sender)
{
  int printDataCount;
  int printNumber;
  int addStep;
  int i, j, r;
  int tempRotate = PrintMatchingResult.PrintRotationAngle;
  int matchingValue;
  int m;
  int tempX, tempY;
  int rotateX, rotateY;
  int tempAddress;
  int TabletDirection;

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

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

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

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

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

  // 초정밀매칭
  for (r = TabletMatchingResult.TabletRotationAngle + tempRotate + TabletDirection - 10; r <= TabletMatchingResult.TabletRotationAngle + tempRotate + TabletDirection + 10; r++)
  {
    for (i = PrintMatchingResult.PrintShiftY - 10; i <= PrintMatchingResult.PrintShiftY + 10; i++)
    {
      for (j = PrintMatchingResult.PrintShiftX - 10; j <= PrintMatchingResult.PrintShiftX + 10; j++)
      {
        memset(TempImage, 0, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT);
        for (m = 0; m < printDataCount; m += addStep)
        {
          tempX = tempPosition_printData[m][0];
          tempY = tempPosition_printData[m][1];

          if (r >= 0)
          {
            rotateX = ((tempX - MAX_IMAGE_WIDTH / 2)*CosData[(r) % 720] - (tempY - MAX_IMAGE_HEIGHT / 2)*SinData[(r) % 720]) / 1024 + TabletMatchingResult.AdjustCenterXInImage + j;
            rotateY = ((tempX - MAX_IMAGE_WIDTH / 2)*SinData[(r) % 720] + (tempY - MAX_IMAGE_HEIGHT / 2)*CosData[(r) % 720]) / 1024 + TabletMatchingResult.AdjustCenterYInImage + i;
          }
          else
          {
            rotateX = ((tempX - MAX_IMAGE_WIDTH / 2)*CosData[-r] + (tempY - MAX_IMAGE_HEIGHT / 2)*SinData[-r]) / 1024 + TabletMatchingResult.AdjustCenterXInImage + j;
            rotateY = (-(tempX - MAX_IMAGE_WIDTH / 2)*SinData[-r] + (tempY - MAX_IMAGE_HEIGHT / 2)*CosData[-r]) / 1024 + TabletMatchingResult.AdjustCenterYInImage + i;
          }

          tempAddress = MAX_IMAGE_WIDTH * rotateY + rotateX;

          TempImage[tempAddress] = 1;
        }

        for(int y = 10; y < ImageHeight-10; y++)
        {
          Byte *ptr = (byte*) img1->ScanLine[y];
          for(int x = 10; x < ImageWidth-10; x++)
          {
            tempAddress =  MAX_IMAGE_WIDTH*y + x;

            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(TempImage[tempAddress])
            {
              ptr[3*x + 2] = 255;
            }
          }
        }

        Image11->Picture->Bitmap->Assign(img1);
        Image11->Refresh();
      }
    }
  }

  delete img1;
}
//---------------------------------------------------------------------------


void __fastcall TTabletSimulationForm::TrackBar12Change(TObject *Sender)
{
  Graphics::TBitmap *img1;
  img1 = new Graphics::TBitmap();
  img1->Width =  MAX_IMAGE_WIDTH;
  img1->Height =  MAX_IMAGE_HEIGHT;
  img1->PixelFormat = pf24bit;

  unsigned char maskimg[640 * 480];
  memset(maskimg, 0, 640 * 480);

  int shx = StrToInt(Edit20->Text);
  int shy = StrToInt(Edit21->Text);

  for (int m = 0; m < SmallPrintCoreData1Count; m++)
  {
	  int tempAddress = detailedCorePrintRotationAddress1[TrackBar12->Position][m] + TabletMatchingResult.AdjustCenterYInImage * MAX_IMAGE_WIDTH + TabletMatchingResult.AdjustCenterXInImage + shy * MAX_IMAGE_WIDTH + shx;

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

    maskimg[tempAddress] = 1;
  }

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

      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(x > TabletMatchingResult.AdjustCenterXInImage - 2 && x < TabletMatchingResult.AdjustCenterXInImage + 2 &&
        y > TabletMatchingResult.AdjustCenterYInImage - 2 && y < TabletMatchingResult.AdjustCenterYInImage + 2)
      {
        ptr[3*x + 2] = 255;
      }

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

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

  delete img1;  
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::TrackBar13Change(TObject *Sender)
{
  int shiftX;
  int shiftY;
  int rotateAngle;

  rotateAngle = TrackBar13->Position;
  shiftX = UpDown11->Position;
  shiftY = UpDown16->Position;

  Edit9->Text = IntToStr(rotateAngle);
  Edit10->Text = IntToStr(shiftX);
  Edit11->Text = IntToStr(shiftY);
  
  int tempAddress;
  int matchingValue = 0;
  unsigned char *printArea;
  printArea = TempImage;
  memset(printArea, 0, 640 * 480);
  for (int m = 0; m < SmallPrintCoreData1CountFor3D; m++)
  {
	  tempAddress = detailedCorePrintRotationAddress1For3D[rotateAngle][m] + shiftX + shiftY * MAX_IMAGE_WIDTH;

    if (tempAddress < 100 || tempAddress > 296100)
      continue;
            
    matchingValue += realPrintMaskingArea[tempAddress];

    printArea[tempAddress] = 1;
  }

  Edit8->Text = IntToStr(matchingValue);

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;              
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  int x, y;

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    Byte *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(printArea[tempAddress] == 1)
      {
        ptr[3*x + 1] = 255;
      }
    }
  }

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

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

void __fastcall TTabletSimulationForm::UpDown16Click(TObject *Sender,
      TUDBtnType Button)
{
  int shiftX;
  int shiftY;
  int rotateAngle;

  rotateAngle = TrackBar13->Position;
  shiftX = UpDown11->Position;
  shiftY = UpDown16->Position;

  Edit9->Text = IntToStr(rotateAngle);
  Edit10->Text = IntToStr(shiftX);
  Edit11->Text = IntToStr(shiftY);
  
  int tempAddress;
  int matchingValue = 0;
  unsigned char *printArea;
  printArea = TempImage;
  memset(printArea, 0, 640 * 480);
  for (int m = 0; m < SmallPrintCoreData1CountFor3D; m++)
  {
	  tempAddress = detailedCorePrintRotationAddress1For3D[rotateAngle][m] + shiftX + shiftY * MAX_IMAGE_WIDTH;

    if (tempAddress < 100 || tempAddress > 296100)
      continue;
            
    matchingValue += realPrintMaskingArea[tempAddress];

    printArea[tempAddress] = 1;
  }

  Edit8->Text = IntToStr(matchingValue);

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;              
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  int x, y;

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    Byte *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(printArea[tempAddress] == 1)
      {
        ptr[3*x + 1] = 255;
      }
    }
  }

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

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

void __fastcall TTabletSimulationForm::UpDown11Click(TObject *Sender,
      TUDBtnType Button)
{
  int shiftX;
  int shiftY;
  int rotateAngle;

  rotateAngle = TrackBar13->Position;
  shiftX = UpDown11->Position;
  shiftY = UpDown16->Position;

  Edit9->Text = IntToStr(rotateAngle);
  Edit10->Text = IntToStr(shiftX);
  Edit11->Text = IntToStr(shiftY);
  
  int tempAddress;
  int matchingValue = 0;
  unsigned char *printArea;
  printArea = TempImage;
  memset(printArea, 0, 640 * 480);
  for (int m = 0; m < SmallPrintCoreData1CountFor3D; m++)
  {
	  tempAddress = detailedCorePrintRotationAddress1For3D[rotateAngle][m] + shiftX + shiftY * MAX_IMAGE_WIDTH;

    if (tempAddress < 100 || tempAddress > 296100)
      continue;
            
    matchingValue += realPrintMaskingArea[tempAddress];

    printArea[tempAddress] = 1;
  }

  Edit8->Text = IntToStr(matchingValue);

  Graphics::TBitmap *img = new Graphics::TBitmap;
  img->Width = MAX_IMAGE_WIDTH;              
  img->Height = MAX_IMAGE_HEIGHT;
  img->PixelFormat = pf24bit;

  int x, y;

  for(y = 0; y < MAX_IMAGE_HEIGHT; y++)
  {
    Byte *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(printArea[tempAddress] == 1)
      {
        ptr[3*x + 1] = 255;
      }
    }
  }

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

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

void __fastcall TTabletSimulationForm::TntButton1Click(TObject *Sender)
{
	TGradeSettingForm *gradeSettingForm = new TGradeSettingForm(this);
	gradeSettingForm->SetGradeData(&TabletGradeData_PC);
	gradeSettingForm->bUserMakingGradeData = false;
	if (gradeSettingForm->ShowModal() == mrOk)
	{
		gradeSettingForm->GetGradeData(&TabletGradeData_PC);
		AnsiString gradeFileName = ProgramPath.Product + "\\" + ProductData.ProductCode + "\\" + ProductData.ProductCode + ".grd";
		SaveGradeData(gradeFileName, TabletGradeData_PC);
	}
	delete gradeSettingForm;  
}
//---------------------------------------------------------------------------
void __fastcall TTabletSimulationForm::TntButton2Click(TObject *Sender)
{
	InspectionTimePanel->Visible = true;	
}
//---------------------------------------------------------------------------

void __fastcall TTabletSimulationForm::SpeedCheckPanelCloseButtonClick(
      TObject *Sender)
{
	InspectionTimePanel->Visible = false;	
}
//---------------------------------------------------------------------------
void _fastcall TTabletSimulationForm::SpeedCheckDisplay(int cameraIndex)
{
	double timeDouble;
	AnsiString tmpString;
	AnsiString SpeedCalStringMin;
    AnsiString SpeedCalStringMax;
    AnsiString SpeedCalStringAvg;
    
      TCheckBox *tempCheckBox = (TCheckBox*)(FindComponent("CameraMaskChkBox" + IntToStr(cameraIndex)));

      if(tempCheckBox)
      {
        if(tempCheckBox->Checked)
        {
	    	timeDouble = GetProcessingElapsedTime();
    		tmpString = "Cam ["+IntToStr(cameraIndex)+"] : " + "IMG ["+ FloatToStr(imgCntForAvg) + "] : " + FloatToStr(timeDouble);
    		InspectionTimeMemo->Lines->Add(tmpString);

            if(timeDoubleMin > timeDouble)
            {
            	timeDoubleMin = timeDouble;
            }
            if(timeDoubleMax < timeDouble)
            {
            	timeDoubleMax = timeDouble;
            }

            if(imgCntForAvg < 100)
            {
            	timeDoubleArray[imgCntForAvg] = timeDouble;
                imgCntForAvg++;

            	if(imgCntForAvg == 100)
            	{
                	timeDoubleAvg = 0;

            		for(int i = 0; i<100; i++)
                	{
                		timeDoubleAvg += timeDoubleArray[i];
                	}

                	timeDoubleAvg = timeDoubleAvg / 100;

				    SpeedCalStringMin = "Min : " +  FloatToStr(timeDoubleMin);
                    InspectionTimeMemo->Lines->Add(SpeedCalStringMin);
				    SpeedCalStringMax = "Max : " + FloatToStr(timeDoubleMax);
                    InspectionTimeMemo->Lines->Add(SpeedCalStringMax);
				    SpeedCalStringAvg = "Avg : " +FloatToStr(timeDoubleAvg);
                    InspectionTimeMemo->Lines->Add(SpeedCalStringAvg);


                    /*

				    SpeedCalStringMin = "Min : " + "Cam[ " + IntToStr(cameraIndex) + "], " + "Img[" + IntToStr(cameraIndex) + "] : " + FloatToStr(timeDoubleMin);
                    InspectionTimeMemo->Lines->Add(SpeedCalStringMin);
				    SpeedCalStringMax = "Max : " + "Cam[ " + IntToStr(cameraIndex) + "], " + "Img[" + IntToStr(cameraIndex) + "] : " + FloatToStr(timeDoubleMax[cameraIndex]);
                    InspectionTimeMemo->Lines->Add(SpeedCalStringMax);
				    SpeedCalStringAvg = "Avg : " +  "Cam[ " + IntToStr(cameraIndex) + "], " + "Img[" + IntToStr(cameraIndex) + "] : " +FloatToStr(timeDoubleAvg[cameraIndex]);
                    InspectionTimeMemo->Lines->Add(SpeedCalStringAvg);
                */
            	}
            }
	    }
      }
}
