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

#include <vcl.h>
#pragma hdrstop

#include "TPBCameraSetting_Form.h"
#include "NFA2DCameraSetting_Form.h"
#include "Keyboard_Form.h"
#include "MultiLanguage.h"
#include "AdvMachineControl_Form.h"
#include "Bayer.h"
#include "Environment.h"
#include <inifiles.hpp>
#include <process.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "TntStdCtrls"
#pragma link "TntExtCtrls"
#pragma link "TntGrids"
#pragma link "TntComCtrls"
#pragma link "TntButtons"
#pragma resource "*.dfm"

#pragma data_seg("HookProc")

DWORD ThreadDword = 0;
HANDLE ImageControlHandle = NULL;
int last_TDG_cpbsendIndex = 0;
int view_monitor_cnt = 0;
TTPBCameraSettingForm *TPBCameraSettingForm;
//----------------------------------------------------------------------------

unsigned int WINAPI RTImageViewThread(PVOID pData)
{
  TTPBCameraSettingForm* srcForm = (TTPBCameraSettingForm*)pData;

	TFileStream *pFileStream = NULL;
	TTPBImageContainer tempTPBImageContainer;

	AnsiString filename;

	while (1)
	{
		try
		{
			int fileIndex = (srcForm->LastImageDisplayCount % MAX_SAVE_IMAGE_COUNT) + 1;

			filename = srcForm->foldername + "\\img" + IntToStr(fileIndex) + ".dat";
			pFileStream = new TFileStream(filename, fmOpenRead);
			pFileStream->Read(&tempTPBImageContainer.Header, sizeof(TTPBImageContainerHeader));
			pFileStream->Read(tempTPBImageContainer.CapturedImage, tempTPBImageContainer.Header.ImageWidth * tempTPBImageContainer.Header.ImageHeight);

			Bayer_Conversion_GBRG(srcForm->tempImage, tempTPBImageContainer.CapturedImage, tempTPBImageContainer.Header.ImageWidth, tempTPBImageContainer.Header.ImageHeight, 2);

			int x, y;
			int tempAddress;
			int tempBuff[3];
			int normalized[3];

			Byte *ptr1, *ptr2;

			int maxB = min((srcForm->TPBCameraParams.WhiteBalance[0] * 255) / 1000, 255);
			int maxG = min((srcForm->TPBCameraParams.WhiteBalance[1] * 255) / 1000, 255);
			int maxR = min((srcForm->TPBCameraParams.WhiteBalance[2] * 255) / 1000, 255);

			for (y = 0; y < tempTPBImageContainer.Header.ImageHeight; y++)
			{
				ptr1 = (Byte*) srcForm->tempImage->ScanLine[y];
				ptr2 = (Byte*) srcForm->lastImage->ScanLine[y];
				for (x = 0; x < tempTPBImageContainer.Header.ImageWidth; x++)
				{
					if (y >= srcForm->TPBCameraParams.bounaryStartY / srcForm->ImageScaleFactor && y <= srcForm->TPBCameraParams.bounaryEndY / srcForm->ImageScaleFactor)
					{
						tempBuff[0] = ptr1[3 * x + 0];
						tempBuff[1] = ptr1[3 * x + 1];
						tempBuff[2] = ptr1[3 * x + 2];

						tempBuff[0] = min((srcForm->TPBCameraParams.WhiteBalance[0] * tempBuff[0]) / 1000, 255);
						tempBuff[1] = min((srcForm->TPBCameraParams.WhiteBalance[1] * tempBuff[1]) / 1000, 255);
						tempBuff[2] = min((srcForm->TPBCameraParams.WhiteBalance[2] * tempBuff[2]) / 1000, 255);

						if (maxB)
							normalized[0] = min((tempBuff[0] * 255) / maxB, 255);
						else
							normalized[0] = 0;

						if (maxG)
							normalized[1] = min((tempBuff[1] * 255) / maxG, 255);
						else
							normalized[1] = 0;

						if (maxR)
							normalized[2] = min((tempBuff[2] * 255) / maxR, 255);
						else
							normalized[2] = 0;

						ptr2[3*x + 0] = normalized[0];
						ptr2[3*x + 1] = normalized[1];
						ptr2[3*x + 2] = normalized[2];
					}
					else
					{
						ptr2[3*x + 0] = 0;
						ptr2[3*x + 1] = 0;
						ptr2[3*x + 2] = 0;
					}
				}
			}

			delete pFileStream;
		}
		catch (...)
		{
			if (pFileStream)
				delete pFileStream;
		}

		srcForm->UploadFrameNumber = tempTPBImageContainer.Header.ImageIndex;
		srcForm->LastImageDisplayCount++;

		if (srcForm->LastImageDisplayCount >= srcForm->ReceivedImageCount - 1)
		{
			break;
		}
	}

	srcForm->uploading = false;
	_endthreadex(0);

	return true;
}
//---------------------------------------------------------------------------
unsigned int WINAPI VideoPlayThread(PVOID pData)
{
	TTPBCameraSettingForm* srcForm = (TTPBCameraSettingForm*)pData;

	Bayer_Conversion_GBRG(srcForm->tempImage, srcForm->VideoImage, srcForm->VideoWidth, srcForm->VideoHeight, 2);

	int x, y;
	int tempAddress;
	int tempBuff[3];
	int normalized[3];

	Byte *ptr1, *ptr2;

	int maxB = min((srcForm->TPBCameraParams.WhiteBalance[0] * 255) / 1000, 255);
	int maxG = min((srcForm->TPBCameraParams.WhiteBalance[1] * 255) / 1000, 255);
	int maxR = min((srcForm->TPBCameraParams.WhiteBalance[2] * 255) / 1000, 255);

	for (y = 0; y < srcForm->VideoHeight; y++)
	{
		ptr1 = (Byte*) srcForm->tempImage->ScanLine[y];
		ptr2 = (Byte*) srcForm->lastImage->ScanLine[y];
		for (x = 0; x < srcForm->VideoWidth; x++)
		{
			if (y >= srcForm->TPBCameraParams.bounaryStartY / srcForm->ImageScaleFactor && y <= srcForm->TPBCameraParams.bounaryEndY / srcForm->ImageScaleFactor)
			{
				tempBuff[0] = ptr1[3 * x + 0];
				tempBuff[1] = ptr1[3 * x + 1];
				tempBuff[2] = ptr1[3 * x + 2];

				tempBuff[0] = min((srcForm->TPBCameraParams.WhiteBalance[0] * tempBuff[0]) / 1000, 255);
				tempBuff[1] = min((srcForm->TPBCameraParams.WhiteBalance[1] * tempBuff[1]) / 1000, 255);
				tempBuff[2] = min((srcForm->TPBCameraParams.WhiteBalance[2] * tempBuff[2]) / 1000, 255);

				if (maxB)
					normalized[0] = min((tempBuff[0] * 255) / maxB, 255);
				else
					normalized[0] = 0;

				if (maxG)
					normalized[1] = min((tempBuff[1] * 255) / maxG, 255);
				else
					normalized[1] = 0;

				if (maxR)
					normalized[2] = min((tempBuff[2] * 255) / maxR, 255);
				else
					normalized[2] = 0;

				ptr2[3*x + 0] = normalized[0];
				ptr2[3*x + 1] = normalized[1];
				ptr2[3*x + 2] = normalized[2];
			}
			else
			{
				ptr2[3*x + 0] = 0;
				ptr2[3*x + 1] = 0;
				ptr2[3*x + 2] = 0;
			}
		}
	}

	srcForm->bExeVideoThread = false;
	_endthreadex(0);

	return true;
}
//---------------------------------------------------------------------------
unsigned int WINAPI ImageDownloadThread(PVOID pData)
{
	TTPBCameraSettingForm* srcForm = (TTPBCameraSettingForm*)pData;
	TFileStream *writeFileStream = NULL;

	bool bCaptureExist;
	int receivedData[2];
	int CaptureWidth, CaptureHeight;

	CaptureWidth = srcForm->ImageSettingWidth;
	CaptureHeight = srcForm->ImageSettingHeight;

	int camIndex;
	srcForm->data[1] = CaptureWidth * (srcForm->TPBCameraParams.bounaryEndY / srcForm->ImageScaleFactor);

  int tryCount = 10;

  for(int index = 0; index < tryCount; index++)
  {
    try
    {
      camIndex = 0;
      srcForm->data[0] = camIndex;

      Comm_Request(COMM_TPB, CMD_CAPTURE_EXIST, srcForm->data, sizeof(unsigned int), receivedData, sizeof(unsigned int) * 2);

      if (receivedData[0])
      {
        bCaptureExist = true;

        srcForm->BoardRemainingImageCount = receivedData[0] - 1;
        srcForm->BoardMaxBufferCount = receivedData[1];
      }
      else
      {
        bCaptureExist = false;
      }

      if (bCaptureExist)
      {
        srcForm->data[2] = CaptureWidth;
        srcForm->data[3] = srcForm->ImageScaleFactor;

        Comm_Request(COMM_TPB, CMD_CAPTURE_UPLOAD, srcForm->data, 4 * sizeof(unsigned int), srcForm->TPBImageContainer.CapturedImage, srcForm->data[1]);

        srcForm->TPBImageContainer.Header.ImageIndex = srcForm->ReceivedImageCount + 1;
        srcForm->TPBImageContainer.Header.time = Now().Val;
        srcForm->TPBImageContainer.Header.ImageWidth = CaptureWidth;
        srcForm->TPBImageContainer.Header.ImageHeight = CaptureHeight;

        int fileIndex = (srcForm->ReceivedImageCount % MAX_SAVE_IMAGE_COUNT) + 1;
        AnsiString filename = srcForm->foldername + "\\img" + IntToStr(fileIndex) + ".dat";

        writeFileStream = new TFileStream(filename, fmCreate);
        writeFileStream->Write(&srcForm->TPBImageContainer.Header, sizeof(TTPBImageContainerHeader));
        writeFileStream->Write(&srcForm->TPBImageContainer.CapturedImage, srcForm->TPBImageContainer.Header.ImageWidth * srcForm->TPBImageContainer.Header.ImageHeight);

        delete writeFileStream;
        writeFileStream = NULL;

        srcForm->ReceivedImageCount++;

        srcForm->LastFrameDownloadTime = Now().Val;

        srcForm->bExecUploadThread = false;
      }
    }
    catch (...)
    {
      if (writeFileStream)
        delete writeFileStream;
    }

    if(receivedData[0] - 1 <= 0)
    {
      break;
    }
  }

	srcForm->bExeDownloadThread = false;
	_endthreadex(0);

	return true;
}
//---------------------------------------------------------------------------
__fastcall TTPBCameraSettingForm::TTPBCameraSettingForm(TComponent* Owner)
		: TForm(Owner)
{
	bOnCapture = false;
	CaptureTrigger = false;

	tempImage = new Graphics::TBitmap;
	lastImage = new Graphics::TBitmap;

	//ImageScaleRadioButton2->Checked = true; // default

	BoardMaxBufferCount = 0;
	BoardRemainingImageCount = 0;
	LastImageDisplayCount = 0;
	ReceivedImageCount = 0;
	CaptureStartTime = 0;
	LastFrameDownloadTime = 0;
	instantCheckTime = 0;
	UploadFrameNumber = 0;
	fpsVariance = 0;
	fpsValInst = 0;

	VideoTrackBar->Enabled = false;
	VideoTrackBar->Min = 0;
	VideoTrackBar->Max = 0;
	VideoTrackBar->Position = 0;

	VideoPlayBtn->Enabled = false;
	VideoStopBtn->Enabled = false;
	RadioButton1->Enabled = false;
	RadioButton2->Enabled = false;
	RadioButton3->Enabled = false;
	RadioButton4->Enabled = false;
	RadioButton5->Enabled = false;
	RadioButton6->Enabled = false;
	RadioButton7->Enabled = false;
  RadioButton8->Enabled = false;
  FrameShiftBtn1->Enabled = false;
  FrameShiftBtn2->Enabled = false;

	FPSLabel->Caption = "Image Download : 0fps";

	bMouseDown = false;
	bVideoStop = false;
	bVideoPlay = false;
	bCaptureStop = false;

	Panel1->DoubleBuffered = true;
	GroupBox1->DoubleBuffered = true;

	foldername = ProgramPath.Root + "\\TPB Images"; //"C:\\Users\\mbc89\\Desktop\\tpb test";//

	if (!DirectoryExists(foldername))
	{
		ForceDirectories(foldername);
	}

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

void __fastcall TTPBCameraSettingForm::NumEditClick(TObject *Sender)
{
	TTntEdit *theEdit = (TTntEdit *) Sender;
	KeyboardForm->Text = theEdit->Text;
	if (KeyboardForm->ShowKeypad() == mrOk)
	{
		theEdit->Text = KeyboardForm->Text;
	}
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::WhiteBalanceRValueEditClick(
    TObject *Sender)
{
	TTntEdit *theEdit = (TTntEdit *) Sender;
	KeyboardForm->Text = theEdit->Text;
	if (KeyboardForm->ShowKeypad() == mrOk)
	{
		theEdit->Text = KeyboardForm->Text;

		if (theEdit->Tag == 0)
		{
			WhiteBalanceBValue->Position = StrToInt(theEdit->Text);
		}
		else if (theEdit->Tag == 1)
		{
			WhiteBalanceGValue->Position = StrToInt(theEdit->Text);
		}
		else if (theEdit->Tag == 2)
		{
			WhiteBalanceRValue->Position = StrToInt(theEdit->Text);
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::WhiteBalanceValueChange(TObject *Sender)
{
	TTrackBar *theTrackBar = (TTrackBar *) Sender;

	int WhiteBalanceValue;

	WhiteBalanceValue = theTrackBar->Position;

	if (theTrackBar->Tag == 0)
	{
		WhiteBalanceBValueEdit->Text = IntToStr(theTrackBar->Position);
	}
	else if (theTrackBar->Tag == 1)
	{
		WhiteBalanceGValueEdit->Text = IntToStr(theTrackBar->Position);
	}
	else if (theTrackBar->Tag == 2)
	{
		WhiteBalanceRValueEdit->Text = IntToStr(theTrackBar->Position);
	}
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::BoardIDEditKeyPress(TObject *Sender,
        char &Key)
{
	Key = NULL;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::ParamsInputTimerTimer(
    TObject *Sender)
{
	ParamsInputTimer->Enabled = false;

	TTntEdit *tempEdit;
	bool bRangeOver = false;
	try
	{
		tempEdit = BoardIDEdit;
		int boardID = StrToInt(BoardIDEdit->Text);
		tempEdit = CameraIDEdit;
		int CameraIndex = StrToInt(CameraIDEdit->Text);
		tempEdit = ShutterSpeedEdit;
		int ShutterSpeed = StrToInt(ShutterSpeedEdit->Text);
		tempEdit = CameraGainEdit;
		int CameraGain = StrToInt(CameraGainEdit->Text);
		int WhiteBalance[3];
		WhiteBalance[0] = WhiteBalanceBValue->Position;
		WhiteBalance[1] = WhiteBalanceGValue->Position;
		WhiteBalance[2] = WhiteBalanceRValue->Position;

		if (!(boardID >= 1 && boardID <= 8))
		{
			bRangeOver = true;

			if (boardID < 1)
			{
				BoardIDEdit->Text = "1";
			}
			else
			{
				BoardIDEdit->Text = "10";
			}

			throw Exception("Board ID");
		}

		if (!(CameraIndex >= 1 && CameraIndex <= 4))
		{
			bRangeOver = true;

			if (CameraIndex < 1)
			{
				CameraIDEdit->Text = "1";
			}
			else
			{
				CameraIDEdit->Text = "4";
			}

			throw Exception("Camera ID");
		}

		if (!(ShutterSpeed >= 1 && ShutterSpeed <= 500))
		{
			bRangeOver = true;

			if (ShutterSpeed < 1)
			{
				ShutterSpeedEdit->Text = "1";
			}
			else
			{
				ShutterSpeedEdit->Text = "500";
			}

			throw Exception("Shutter Speed");
		}

		if (!(CameraGain >= 1 && CameraGain <= 10))
		{
			bRangeOver = true;

			if (CameraGain < 1)
			{
				CameraGainEdit->Text = "1";
			}
			else
			{
				CameraGainEdit->Text = "10";
			}

			throw Exception("Digital Gain");
		}

		TPBCameraParams.ShutterSpeed = ShutterSpeed;
		TPBCameraParams.DigitalGain = CameraGain;

		TPBCameraParams.WhiteBalance[0] = WhiteBalance[0];
		TPBCameraParams.WhiteBalance[1] = WhiteBalance[1];
		TPBCameraParams.WhiteBalance[2] = WhiteBalance[2];
	}
	catch (Exception &exception)
	{
		if (bRangeOver)
		{
			ShowMessage("The input value is incorrect. [" + exception.Message + "]");
		}
		else
		{
			tempEdit->Text = "1";
			ShowMessage("The input value is incorrect. [0.0 / space / etc]");
		}
	}

	ParamsInputTimer->Enabled = true;
}
//---------------------------------------------------------------------------


void __fastcall TTPBCameraSettingForm::MachineControlButtonClick(
    TObject *Sender)
{
	if (ProductData.ProductCode.IsEmpty())
	{
		ShowMessageFA(ADVMACHINECONTROLFORM_MSG_01);
		return ;
	}

	AdvMachineControlForm->ShowModal();
}
//---------------------------------------------------------------------------

bool __fastcall TTPBCameraSettingForm::SendSPBCaptureSetup(void)
{
	bool returnValue = true;

	TCaptureSetupData captureSetupData;

	int camIndex = 0;

	int maxBufferingCount = 48;

	captureSetupData.CaptureType = CAPTURE_TYPE_SINGLE_CAPTURE;
	captureSetupData.CaptureMode = CAPTURE_MODE_DEFAULT;
	captureSetupData.FrameBufferCount = maxBufferingCount;
	captureSetupData.CameraMask = (0x0001 << camIndex);

	RefreshCameraInfo();

	captureSetupData.ShutterSpeed[camIndex] = TPBCameraParams.ShutterSpeed;
	captureSetupData.SubsamplingMode[camIndex] = RESOLUTION_NORMAL_QUALITY;

	captureSetupData.ShutterDelay[camIndex] = StrToFloat(FrameTimeEdit->Text) * 20 + 0.5;

	captureSetupData.TriggerFreq[camIndex] = 0;
	captureSetupData.ContainParams = 1;

	if (!ProductData.ProductName.IsEmpty())
	{
		captureSetupData.TabletType = ProductData.TabletType;
	}
	else
	{
		captureSetupData.TabletType = 2;
	}
	captureSetupData.SensorLength= 1000;
	if (!Comm_Request(COMM_TPB, CMD_CAPTURE_SETUP, &captureSetupData, sizeof(TCaptureSetupData), NULL, 0))
	{
		returnValue = false;
	}

	return returnValue;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::RefreshCameraInfo()
{
	TPBCameraParams.mask |= CAMERA_WRITE_MASK_2D_SH;
	TPBCameraParams.mask |= CAMERA_WRITE_MASK_2D_ROI;
	TPBCameraParams.mask |= CAMERA_WRITE_MASK_2D_SUBSAMPLING_MODE;
	TPBCameraParams.mask |= CAMERA_WRITE_MASK_2D_ANALOG_GAIN;
	TPBCameraParams.mask |= CAMERA_WRITE_MASK_2D_DIGITALGAIN;
	TPBCameraParams.AnalogGain = SYSTEM_DEFAULT_ANLOG_GAIN;

	Comm_Request(COMM_TPB, CMD_CAMERA_CONTROL_PROCESSING_MODE, &TPBCameraParams, sizeof(TPBCameraParams), NULL, 0);
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::HCBCaptureButtonClick(
    TObject *Sender)
{
	int camIndex = 0;
	bool returnValue = true;
	
	TCaptureSetupData captureSetupData;
	if (!bOnCapture)
	{
		int camIndex = 0;
		Comm_Request(COMM_TPB, CMD_CAPTURE_STOP, &camIndex, sizeof(int));

		if (DirectoryExists(foldername))
		{
			RemoveWholeDir(foldername);
		}
		captureSetupData.CameraMask = (0x0001 << camIndex);

		RefreshCameraInfo();

		captureSetupData.ShutterSpeed[camIndex] = TPBCameraParams.ShutterSpeed;
		captureSetupData.SubsamplingMode[camIndex] = RESOLUTION_NORMAL_QUALITY;

		captureSetupData.ShutterDelay[camIndex] = StrToFloat(FrameTimeEdit->Text) * 20 + 0.5;

		captureSetupData.TriggerFreq[camIndex] = 0;
		captureSetupData.ContainParams = 1;
		captureSetupData.SensorLength= 1000;
		if (!Comm_Request(COMM_TPB, CMD_CAPTURE_SETUP, &captureSetupData, sizeof(TCaptureSetupData), NULL, 0))
		{
			returnValue = false;
		}			
		TTPBInspectionData tbpInsData;
		  if(!ProductData.ProductName.IsEmpty())
		  {
				tbpInsData.TabletLength = ProductData.TabletLength;
				tbpInsData.TabletWidth = ProductData.TabletWidth;
				tbpInsData.WhiteBalance[0] = TPBCameraParams.WhiteBalance[0]; 
				tbpInsData.WhiteBalance[1] = TPBCameraParams.WhiteBalance[1];
				tbpInsData.WhiteBalance[2] = TPBCameraParams.WhiteBalance[2];
				tbpInsData.InsAreaLeft = TPBCameraParams.InsAreaLeft;
				tbpInsData.InsAreaRight = TPBCameraParams.InsAreaRight;
				tbpInsData.InsAreaTop = TPBCameraParams.InsAreaTop;
				tbpInsData.InsAreaBottom = TPBCameraParams.InsAreaBottom;
				tbpInsData.Threshold = TPBCameraParams.Threshold;
        
				tbpInsData.CaptureDelay_Min = StrToInt(eCaptureDelay_Min->Text);
        tbpInsData.CaptureDelay_Max = StrToInt(eCaptureDelay_Max->Text);
				if(ckbFreeUploadMode->Checked)
					tbpInsData.CaptureUploadOption = FREE_IMG_UPLOAD;
				else
					tbpInsData.CaptureUploadOption = DEFECT_IMG_UPLOAD_ONLY;
		  }
		  else
		  {
		  	tbpInsData.TabletLength= 10;
			  tbpInsData.TabletWidth= 4;
				tbpInsData.WhiteBalance[0] = TPBCameraParams.WhiteBalance[0]; 
				tbpInsData.WhiteBalance[1] = TPBCameraParams.WhiteBalance[1];
				tbpInsData.WhiteBalance[2] = TPBCameraParams.WhiteBalance[2];
				tbpInsData.InsAreaLeft = TPBCameraParams.InsAreaLeft;
				tbpInsData.InsAreaRight = TPBCameraParams.InsAreaRight;
				tbpInsData.InsAreaTop = TPBCameraParams.InsAreaTop;
				tbpInsData.InsAreaBottom = TPBCameraParams.InsAreaBottom;
				tbpInsData.Threshold = TPBCameraParams.Threshold;
        
				tbpInsData.CaptureDelay_Min = StrToInt(eCaptureDelay_Min->Text);
        tbpInsData.CaptureDelay_Max = StrToInt(eCaptureDelay_Max->Text);
				if(ckbFreeUploadMode->Checked)
					tbpInsData.CaptureUploadOption = FREE_IMG_UPLOAD;
				else
					tbpInsData.CaptureUploadOption = DEFECT_IMG_UPLOAD_ONLY;			  
		  }		
  	Comm_Request(COMM_TPB, CMD_TPB_INSPECTION, &tbpInsData, sizeof(TTPBInspectionData), NULL, 0);
		TCaptureCommandParam_HCB captureCommandParam_HCB;
		captureCommandParam_HCB.Action = 1;
		captureCommandParam_HCB.FrameTime = StrToFloat(FrameTimeEdit->Text) * 20 + 0.5;
		captureCommandParam_HCB.LEDMask[0] = 0x0020;
		captureCommandParam_HCB.LEDOnTime[0] = StrToFloat(LedOnTimeEdit->Text) * 20 + 0.5;
		captureCommandParam_HCB.ShutterDelay = 1;
		Comm_Request(COMM_HCB, CMD_TABLET_TPB_CAPTURE, &captureCommandParam_HCB, sizeof(TCaptureCommandParam_HCB), NULL, 0);

		GroupBox9->Visible = false;
		bExeDownloadThread = false;

		bOnCapture = true;
		CaptureTrigger = true;
		bCaptureStop = false;
		HCBCaptureButton->Caption = "HCB Capture Stop";
		TPBCaptureButton->Enabled = false;

		float interval = StrToFloat(FrameTimeEdit->Text);
		TntLabel14->Caption = "Capture Interval : " + FloatToStrF(1000 / interval, ffFixed, 10, 3) + "fps";
		TntLabel17->Caption = Now().TimeString();

		BoardMaxBufferCount = 0;
		BoardRemainingImageCount = 0;
		LastImageDisplayCount = 0;
		ReceivedImageCount = 0;
		UploadFrameNumber = 0;
		CaptureStartTime = Now().Val;
		LastFrameDownloadTime = Now().Val;
		instantCheckTime = Now().Val;
		fpsVariance = 0;
		fpsValInst = 0;

		VideoTrackBar->Enabled = false;
		VideoTrackBar->Min = 0;
		VideoTrackBar->Max = 0;
		VideoTrackBar->Position = 0;

		VideoPlayBtn->Enabled = false;
		VideoStopBtn->Enabled = false;
		RadioButton1->Enabled = false;
		RadioButton2->Enabled = false;
		RadioButton3->Enabled = false;
		RadioButton4->Enabled = false;
		RadioButton5->Enabled = false;
		RadioButton6->Enabled = false;
		RadioButton7->Enabled = false;
    RadioButton8->Enabled = false;
    FrameShiftBtn1->Enabled = false;
    FrameShiftBtn2->Enabled = false;

		ImageLoadTimer->Enabled = true;
	}
	else
	{
    if(Comm_IsConnected(COMM_TPB) && bOnCapture)
    {
      // Thread 실행중인경우 종료까지 waiting
      while(bExecUploadThread);
    }    

		TCaptureCommandParam_HCB captureCommandParam_HCB;
		captureCommandParam_HCB.Action = 0;
		Comm_Request(COMM_HCB, CMD_TABLET_TPB_CAPTURE, &captureCommandParam_HCB, sizeof(TCaptureCommandParam_HCB), NULL, 0);
		Comm_Request(COMM_TPB, CMD_CAPTURE_STOP, &camIndex, sizeof(int));
		HCBCaptureButton->Enabled = false;
		bCaptureStop = true;
		captureStopTime = Now().Val;
	}
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::CloseButtonClick(TObject *Sender)
{
	WriteTPBCameraInfo();
  TPBCameraSettingForm->Width = 1084;
  TPBCameraSettingForm->Height = 1550;

	this->Close();
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::ImageLoadTimerTimer(TObject *Sender)
{
	bool bTimerEnabled;
	bTimerEnabled = ImageLoadTimer->Enabled;
	ImageLoadTimer->Enabled = false;

	if (bExeDownloadThread == false)
	{
    if(ImageControlHandle)
    {
      WaitForSingleObject(ImageControlHandle, INFINITE);
      CloseHandle(ImageControlHandle);
      ImageControlHandle = NULL;
    }
    
		bExeDownloadThread = true;
		ImageControlHandle = (HANDLE)_beginthreadex(NULL, NULL, ImageDownloadThread, this, 0, (unsigned int*) & ThreadDword);
	}

	if (bOnCapture)
	{
		double elapedtime = (Now().Val - CaptureStartTime) * 24 * 3600;

		if (elapedtime)
		{
			double fpsVal = ReceivedImageCount / elapedtime;

			elapedtime = (Now().Val - instantCheckTime) * 24 * 3600;
			if (elapedtime > 1)
			{
				fpsValInst = ReceivedImageCount - fpsVariance;
				fpsVariance = ReceivedImageCount;
				instantCheckTime = Now().Val;
			}

			FPSLabel->Caption = "Image Download : " + FloatToStrF(fpsVal, ffFixed, 10, 3) + "fps(avg) / " + FloatToStrF(fpsValInst, ffFixed, 10, 1) + "fps(Inst)";
		}
		else
		{
			FPSLabel->Caption = "Image Download : 0fps";
		}
	}

	if (bCaptureStop)
	{
		if (((Now().Val - captureStopTime) * 24 * 3600 > MAX_BUFFERING_IMAGE_WAITING_TIME) ||
        BoardRemainingImageCount == 0 && ReceivedImageCount == LastImageDisplayCount)
		{
			bTimerEnabled = false;

      bCaptureStop = false;
		
      GroupBox9->Visible = true;

      if (ReceivedImageCount > MAX_SAVE_IMAGE_COUNT)
      {
        VideoTrackBar->Min = ReceivedImageCount - (MAX_SAVE_IMAGE_COUNT - 1);
      }
      else
      {
        VideoTrackBar->Min = 1;
      }

      VideoTrackBar->Max = ReceivedImageCount;
      VideoTrackBar->Position = ReceivedImageCount;
      TntLabel20->Caption = IntToStr(VideoTrackBar->Position);

      double ElapsedTime = LastFrameDownloadTime - CaptureStartTime;
      int elapsedTimeHour = ElapsedTime * 24;
      int elapsedTimeMin = ElapsedTime * 24 * 60 - elapsedTimeHour * 60;
      int elapsedTimeSec = ElapsedTime * 24 * 3600 - elapsedTimeHour * 3600 - elapsedTimeMin * 60;
      int elapsedTimeSubSec = ElapsedTime * 24 * 3600 * 100 - elapsedTimeHour * 3600 * 100 - elapsedTimeMin * 60 * 100 - elapsedTimeSec * 100;

      TntLabel22->Caption = Format("%.2d:%.2d.%.2d", ARRAYOFCONST((elapsedTimeMin, elapsedTimeSec, elapsedTimeSubSec)));

      bOnCapture = false;
      CaptureTrigger = false;
      HCBCaptureButton->Caption = "HCB Capture Start";
      TPBCaptureButton->Caption = "TPB Capture Start";

      HCBCaptureButton->Enabled = true;
      TPBCaptureButton->Enabled = true;
      ImageLoadTimer->Enabled = false;

      VideoTrackBar->Enabled = true;

      VideoPlayBtn->Enabled = true;
      VideoStopBtn->Enabled = false;
      RadioButton1->Enabled = true;
      RadioButton2->Enabled = true;
      RadioButton3->Enabled = true;
      RadioButton4->Enabled = true;
      RadioButton5->Enabled = true;
      RadioButton6->Enabled = true;
      RadioButton7->Enabled = true;
      RadioButton8->Enabled = true;
      FrameShiftBtn1->Enabled = true;
      FrameShiftBtn2->Enabled = true;
      InsAreaImageCheck = true;

		}
	}

	ImageLoadTimer->Enabled = bTimerEnabled;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::WriteTPBCameraInfo()
{
	TIniFile *iniFile = new TIniFile(ProgramPath.Env + "\\TPBCameraSetting.ini");

	if (iniFile)
	{
		iniFile->WriteInteger("Data", "Shutter Speed", TPBCameraParams.ShutterSpeed);
		iniFile->WriteInteger("Data", "Analog Gain", TPBCameraParams.AnalogGain);
		iniFile->WriteInteger("Data", "Digital Gain", TPBCameraParams.DigitalGain);
		iniFile->WriteInteger("Data", "White Balance B", TPBCameraParams.WhiteBalance[0]);
		iniFile->WriteInteger("Data", "White Balance G", TPBCameraParams.WhiteBalance[1]);
		iniFile->WriteInteger("Data", "White Balance R", TPBCameraParams.WhiteBalance[2]);
		iniFile->WriteInteger("Data", "Bounary Start Y", TPBCameraParams.bounaryStartY);
		iniFile->WriteInteger("Data", "Bounary End Y", TPBCameraParams.bounaryEndY);
		iniFile->WriteInteger("Data", "Mask", TPBCameraParams.mask);
    iniFile->WriteInteger("Data", "InsAreaLeft", TPBCameraParams.InsAreaLeft);
    iniFile->WriteInteger("Data", "InsAreaRight", TPBCameraParams.InsAreaRight);
    iniFile->WriteInteger("Data", "InsAreaTop", TPBCameraParams.InsAreaTop);
    iniFile->WriteInteger("Data", "InsAreaBottom", TPBCameraParams.InsAreaBottom);
    iniFile->WriteInteger("Data", "Threshold", TPBCameraParams.Threshold);

    iniFile->WriteInteger("Data", "ImageScale", TPBCameraParams.ImageScale);
    iniFile->WriteInteger("Data", "FrameTime", TPBCameraParams.FrameTime);
    iniFile->WriteInteger("Data", "LedOnTime", TPBCameraParams.LedOnTime);
    iniFile->WriteInteger("Data", "CaptureDelay_Min", TPBCameraParams.CaptureDelay_Min);
    iniFile->WriteInteger("Data", "CaptureDelay_Max", TPBCameraParams.CaptureDelay_Max);
    iniFile->WriteInteger("Data", "FreeCaptureUpload", TPBCameraParams.FreeCaptureUpload);

		delete iniFile;
	}
}

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

void __fastcall TTPBCameraSettingForm::ReadTPBCameraInfo()
{
	TIniFile *iniFile = new TIniFile(ProgramPath.Env + "\\TPBCameraSetting.ini");

	if (FileExists(ProgramPath.Env + "\\TPBCameraSetting.ini"))
	{
		if (iniFile)
		{
			TPBCameraParams.ShutterSpeed = iniFile->ReadInteger("Data", "Shutter Speed", 100);
			TPBCameraParams.AnalogGain = iniFile->ReadInteger("Data", "Analog Gain", 2);
			TPBCameraParams.DigitalGain = iniFile->ReadInteger("Data", "Digital Gain", 2);
			TPBCameraParams.WhiteBalance[0] = iniFile->ReadInteger("Data", "White Balance B", 1500);
			TPBCameraParams.WhiteBalance[1] = iniFile->ReadInteger("Data", "White Balance G", 1000);
			TPBCameraParams.WhiteBalance[2] = iniFile->ReadInteger("Data", "White Balance R", 1500);
			TPBCameraParams.bounaryStartY = iniFile->ReadInteger("Data", "Bounary Start Y", 30);
			TPBCameraParams.bounaryEndY = iniFile->ReadInteger("Data", "Bounary End Y", SYSTEM_CAMERA_HEIGHT - 30);
			TPBCameraParams.mask = iniFile->ReadInteger("Data", "Mask", 0);
      TPBCameraParams.InsAreaLeft = iniFile->ReadInteger("Data", "InsAreaLeft", 371);
      TPBCameraParams.InsAreaRight = iniFile->ReadInteger("Data", "InsAreaRight", 520);
      TPBCameraParams.InsAreaTop = iniFile->ReadInteger("Data", "InsAreaTop", 141);
      TPBCameraParams.InsAreaBottom = iniFile->ReadInteger("Data", "InsAreaBottom", 206);
      TPBCameraParams.Threshold = iniFile->ReadInteger("Data", "Threshold", 100);

      TPBCameraParams.ImageScale = iniFile->ReadInteger("Data", "ImageScale", 2);
      TPBCameraParams.FrameTime = iniFile->ReadInteger("Data", "FrameTime", 20);
      TPBCameraParams.LedOnTime = iniFile->ReadInteger("Data", "LedOnTime", 1);
      TPBCameraParams.CaptureDelay_Min = iniFile->ReadInteger("Data", "CaptureDelay_Min", 5);
      TPBCameraParams.CaptureDelay_Max = iniFile->ReadInteger("Data", "CaptureDelay_Max", 8);
      TPBCameraParams.FreeCaptureUpload = iniFile->ReadInteger("Data", "FreeCaptureUpload", 1);
      
			delete iniFile;
		}
	}
	else
	{

		TPBCameraParams.ShutterSpeed = 100;
		TPBCameraParams.AnalogGain = SYSTEM_DEFAULT_ANLOG_GAIN;
		TPBCameraParams.DigitalGain = 2;
		TPBCameraParams.WhiteBalance[0] = 1500;
		TPBCameraParams.WhiteBalance[1] = 1000;
		TPBCameraParams.WhiteBalance[2] = 1500;
		TPBCameraParams.bounaryStartY = 30;
		TPBCameraParams.bounaryEndY = SYSTEM_CAMERA_HEIGHT - 30;
		TPBCameraParams.mask = 0;
    TPBCameraParams.InsAreaLeft = 371;
    TPBCameraParams.InsAreaRight = 520;
    TPBCameraParams.InsAreaTop = 141;
    TPBCameraParams.InsAreaBottom = 206;

		TPBCameraParams.ImageScale = 2;
		TPBCameraParams.FrameTime = 20;
    TPBCameraParams.LedOnTime = 1;
    TPBCameraParams.CaptureDelay_Min = 5;
    TPBCameraParams.CaptureDelay_Max = 8;
    TPBCameraParams.FreeCaptureUpload = 1;

	}
}
//---------------------------------------------------------------------------
void __fastcall TTPBCameraSettingForm::FormCreate(TObject *Sender)
{
	ReadTPBCameraInfo();

	ShutterSpeedEdit->Text = IntToStr(TPBCameraParams.ShutterSpeed);
	CameraGainEdit->Text = IntToStr(TPBCameraParams.DigitalGain);
	WhiteBalanceBValue->Position = TPBCameraParams.WhiteBalance[0];
	WhiteBalanceGValue->Position = TPBCameraParams.WhiteBalance[1];
	WhiteBalanceRValue->Position = TPBCameraParams.WhiteBalance[2];

  if(TPBCameraParams.ImageScale == 1)
		ImageScaleRadioButton1->Checked = true;
	else if(TPBCameraParams.ImageScale == 2)
		ImageScaleRadioButton2->Checked = true;
	else if(TPBCameraParams.ImageScale == 3)
		ImageScaleRadioButton3->Checked = true;
	else
		ImageScaleRadioButton2->Checked = true;
		
	FrameTimeEdit->Text = IntToStr(TPBCameraParams.FrameTime);
	LedOnTimeEdit->Text = IntToStr(TPBCameraParams.LedOnTime);
	eCaptureDelay_Min->Text = IntToStr(TPBCameraParams.CaptureDelay_Min);
	eCaptureDelay_Max->Text = IntToStr(TPBCameraParams.CaptureDelay_Max);
  
  if(TPBCameraParams.FreeCaptureUpload == 1)
    ckbFreeUploadMode->Checked = true;
  else
    ckbFreeUploadMode->Checked = false;

  BoundaryArea.left = TPBCameraParams.InsAreaLeft;
  BoundaryArea.right = TPBCameraParams.InsAreaRight;
  BoundaryArea.top = TPBCameraParams.InsAreaTop;
  BoundaryArea.bottom = TPBCameraParams.InsAreaBottom;

  MinXValue->Caption = IntToStr(BoundaryArea.left);
  MinYValue->Caption = IntToStr(BoundaryArea.top);
  MaxXValue->Caption = IntToStr(BoundaryArea.right);
  MaxYValue->Caption = IntToStr(BoundaryArea.bottom);

  ThresholdLabel->Caption = IntToStr(TPBCameraParams.Threshold);
  ThresholdTrackBar->Position = TPBCameraParams.Threshold;

	BoundaryShape1->Top = Panel4->Top + TPBCameraParams.bounaryStartY - BoundaryShape1->Height / 2;
	BoundaryShape2->Top = Panel4->Top + TPBCameraParams.bounaryEndY - BoundaryShape2->Height / 2;

	RefreshBounaryResult();

	bExeDownloadThread = false;
	bExeVideoThread = false;
	uploading = false;
	bVideoPlay = false;
	bCaptureStop = false;
  InsAreaImageCheck = false;

	float interval = StrToFloat(FrameTimeEdit->Text);
	TntLabel14->Caption = "Capture Interval : " + FloatToStrF(1000 / interval, ffFixed, 10, 3) + "fps";
	TntLabel17->Caption = Now().TimeString();
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::BoundaryShape1MouseDown(TObject *Sender,
        TMouseButton Button, TShiftState Shift, int X, int Y)
{
	bMouseDown = true;
	GetCursorPos(&startMouse);
	boundaryStartPos = BoundaryShape1->Top;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::BoundaryShape1MouseUp(TObject *Sender,
        TMouseButton Button, TShiftState Shift, int X, int Y)
{
	bMouseDown = false;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::BoundaryShape2MouseDown(TObject *Sender,
        TMouseButton Button, TShiftState Shift, int X, int Y)
{
	bMouseDown = true;
	GetCursorPos(&startMouse);
	boundaryStartPos = BoundaryShape2->Top;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::BoundaryShape2MouseUp(TObject *Sender,
        TMouseButton Button, TShiftState Shift, int X, int Y)
{
	bMouseDown = false;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::BoundaryShape1MouseMove(TObject *Sender,
        TShiftState Shift, int X, int Y)
{
	if (bMouseDown)
	{
		GetCursorPos(&endMouse);

		int shiftPos = boundaryStartPos + (endMouse.y - startMouse.y);
		if (shiftPos > Panel4->Top && shiftPos < BoundaryShape2->Top - BoundaryShape1->Height)
		{
			BoundaryShape1->Top = shiftPos / ImageScaleFactor * ImageScaleFactor;

			RefreshBounaryResult();
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::BoundaryShape2MouseMove(TObject *Sender,
        TShiftState Shift, int X, int Y)
{
	if (bMouseDown)
	{
		GetCursorPos(&endMouse);

		int shiftPos = boundaryStartPos + (endMouse.y - startMouse.y);
		if (shiftPos > BoundaryShape1->Top + BoundaryShape1->Height && shiftPos < Panel4->Top + Image1->Height - BoundaryShape1->Height)
		{
			BoundaryShape2->Top = shiftPos / ImageScaleFactor * ImageScaleFactor;

			RefreshBounaryResult();
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::RefreshBounaryResult()
{
	TPBCameraParams.bounaryStartY = BoundaryShape1->Top - Panel4->Top + BoundaryShape1->Height / 2;
	TPBCameraParams.bounaryEndY = BoundaryShape2->Top - Panel4->Top + BoundaryShape2->Height / 2;

	Image1->Picture->Bitmap->Assign(lastImage);

  /*
	if (!bVideoPlay)
	{
		Image1->Canvas->MoveTo(0, TPBCameraParams.bounaryStartY / ImageScaleFactor);
		Image1->Canvas->LineTo(ImageSettingWidth, TPBCameraParams.bounaryStartY / ImageScaleFactor);

		Image1->Canvas->MoveTo(0, TPBCameraParams.bounaryEndY / ImageScaleFactor);
		Image1->Canvas->LineTo(ImageSettingWidth, TPBCameraParams.bounaryEndY / ImageScaleFactor);
	}
  */

	Image1->Refresh();
}
//---------------------------------------------------------------------------
void __fastcall TTPBCameraSettingForm::ImageViewTimerTimer(TObject *Sender)
{
	if ((LastImageDisplayCount < ReceivedImageCount) && uploading == false)
	{
    /*
    if(ImageControlHandle)
    {
      WaitForSingleObject(ImageControlHandle, INFINITE);
      CloseHandle(ImageControlHandle);
      ImageControlHandle = NULL;
    }

		uploading = true;
		ImageControlHandle = (HANDLE)_beginthreadex(NULL, NULL, RTImageViewThread, this, 0, (unsigned int*) & ThreadDword);
    */

    RTImageView();
	}

	TntLabel11->Caption = IntToStr(UploadFrameNumber);
	TntLabel12->Caption = IntToStr(ReceivedImageCount);
	TntLabel13->Caption = IntToStr(BoardRemainingImageCount) + " / " + IntToStr(BoardMaxBufferCount);

	if (VideoTrackBar->Enabled == false && bVideoPlay == false)
	{
		TntLabel20->Caption = IntToStr(UploadFrameNumber);
	}

	double ElapsedTime = LastFrameDownloadTime - CaptureStartTime;
	int elapsedTimeHour = ElapsedTime * 24;
	int elapsedTimeMin = ElapsedTime * 24 * 60 - elapsedTimeHour * 60;
	int elapsedTimeSec = ElapsedTime * 24 * 3600 - elapsedTimeHour * 3600 - elapsedTimeMin * 60;
	int elapsedTimeSubSec = ElapsedTime * 24 * 3600 * 100 - elapsedTimeHour * 3600 * 100 - elapsedTimeMin * 60 * 100 - elapsedTimeSec * 100;

	TntLabel18->Caption = Format("%.2d:%.2d.%.2d", ARRAYOFCONST((elapsedTimeMin, elapsedTimeSec, elapsedTimeSubSec)));
	if (VideoTrackBar->Enabled == false && bVideoPlay == false)
	{
		TntLabel22->Caption = Format("%.2d:%.2d.%.2d", ARRAYOFCONST((elapsedTimeMin, elapsedTimeSec, elapsedTimeSubSec)));
	}

	if (ReceivedImageCount > MAX_SAVE_IMAGE_COUNT)
	{
		VideoTrackBar->Min = ReceivedImageCount - (MAX_SAVE_IMAGE_COUNT - 1);
	}
	else
	{
		VideoTrackBar->Min = 1;
	}

	VideoTrackBar->Max = ReceivedImageCount;

	if (VideoTrackBar->Enabled == false && bVideoPlay == false)
	{
		VideoTrackBar->Position = LastImageDisplayCount;
	}

	RefreshBounaryResult();
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::RemoveWholeDir(AnsiString folderName)
{
	TSearchRec sr;
	int iAttributes = faAnyFile;
	if (FindFirst(folderName + "\\*.*", iAttributes, sr) == 0)
	{
		do
		{
			if (sr.Name == "." || sr.Name == "..")
				continue;
			if (sr.Attr & faDirectory)
			{
				RemoveWholeDir(folderName + "\\" + sr.Name);
			}
			else
			{
				DeleteFile(folderName + "\\" + sr.Name);
			}

		}
		while (FindNext(sr) == 0);
		FindClose(sr);
	}
}
//---------------------------------------------------------------------------
void __fastcall TTPBCameraSettingForm::VideoTrackBarChange(TObject *Sender)
{
	if (VideoTrackBar->Enabled == true && bVideoPlay == false)
	{
    if(VideoTrackBar->Max == 0) return;
    
		int ImageIndex = VideoTrackBar->Position - 1;

		TFileStream *pFileStream = NULL;
		TTPBImageContainer tempTPBImageContainer;

		try
		{
			int fileIndex = (ImageIndex % MAX_SAVE_IMAGE_COUNT) + 1;

			AnsiString filename = foldername + "\\img" + IntToStr(fileIndex) + ".dat";
			pFileStream = new TFileStream(filename, fmOpenRead);
			pFileStream->Read(&tempTPBImageContainer.Header, sizeof(TTPBImageContainerHeader));
			pFileStream->Read(tempTPBImageContainer.CapturedImage, tempTPBImageContainer.Header.ImageWidth * tempTPBImageContainer.Header.ImageHeight);

			Bayer_Conversion_GBRG(tempImage, tempTPBImageContainer.CapturedImage, tempTPBImageContainer.Header.ImageWidth, tempTPBImageContainer.Header.ImageHeight, 2);

			int x, y;
			int tempAddress;
			int tempBuff[3];
			int normalized[3];

			Byte *ptr1, *ptr2;

			int maxB = min((TPBCameraParams.WhiteBalance[0] * 255) / 1000, 255);
			int maxG = min((TPBCameraParams.WhiteBalance[1] * 255) / 1000, 255);
			int maxR = min((TPBCameraParams.WhiteBalance[2] * 255) / 1000, 255);

			for (y = 0; y < tempTPBImageContainer.Header.ImageHeight; y++)
			{
				ptr1 = (Byte*) tempImage->ScanLine[y];
				ptr2 = (Byte*) lastImage->ScanLine[y];
				for (x = 0; x < tempTPBImageContainer.Header.ImageWidth; x++)
				{
					if (y >= TPBCameraParams.bounaryStartY / ImageScaleFactor && y <= TPBCameraParams.bounaryEndY / ImageScaleFactor)
					{
						tempBuff[0] = ptr1[3 * x + 0];
						tempBuff[1] = ptr1[3 * x + 1];
						tempBuff[2] = ptr1[3 * x + 2];

						tempBuff[0] = min((TPBCameraParams.WhiteBalance[0] * tempBuff[0]) / 1000, 255);
						tempBuff[1] = min((TPBCameraParams.WhiteBalance[1] * tempBuff[1]) / 1000, 255);
						tempBuff[2] = min((TPBCameraParams.WhiteBalance[2] * tempBuff[2]) / 1000, 255);

						if (maxB)
							normalized[0] = min((tempBuff[0] * 255) / maxB, 255);
						else
							normalized[0] = 0;

						if (maxG)
							normalized[1] = min((tempBuff[1] * 255) / maxG, 255);
						else
							normalized[1] = 0;

						if (maxR)
							normalized[2] = min((tempBuff[2] * 255) / maxR, 255);
						else
							normalized[2] = 0;

						ptr2[3*x + 0] = normalized[0];
						ptr2[3*x + 1] = normalized[1];
						ptr2[3*x + 2] = normalized[2];
					}
					else
					{
						ptr2[3*x + 0] = 0;
						ptr2[3*x + 1] = 0;
						ptr2[3*x + 2] = 0;
					}
				}
			}

			delete pFileStream;
		}
		catch (...)
		{
			if (pFileStream)
				delete pFileStream;
		}

		TntLabel20->Caption = IntToStr(tempTPBImageContainer.Header.ImageIndex);

		double ElapsedTime = tempTPBImageContainer.Header.time - CaptureStartTime;
		int elapsedTimeHour = ElapsedTime * 24;
		int elapsedTimeMin = ElapsedTime * 24 * 60 - elapsedTimeHour * 60;
		int elapsedTimeSec = ElapsedTime * 24 * 3600 - elapsedTimeHour * 3600 - elapsedTimeMin * 60;
		int elapsedTimeSubSec = ElapsedTime * 24 * 3600 * 100 - elapsedTimeHour * 3600 * 100 - elapsedTimeMin * 60 * 100 - elapsedTimeSec * 100;

		TntLabel22->Caption = Format("%.2d:%.2d.%.2d", ARRAYOFCONST((elapsedTimeMin, elapsedTimeSec, elapsedTimeSubSec)));
	}
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::VideoPlayBtnClick(TObject *Sender)
{
	CloseButton->Visible = false;
	GroupBox4->Visible = false;
	VideoStopBtn->Enabled = true;
	VideoPlayBtn->Enabled = false;
	VideoTrackBar->Enabled = false;

	RadioButton1->Enabled = false;
	RadioButton2->Enabled = false;
	RadioButton3->Enabled = false;
	RadioButton4->Enabled = false;
	RadioButton5->Enabled = false;
	RadioButton6->Enabled = false;
	RadioButton7->Enabled = false;
  RadioButton8->Enabled = false;
  FrameShiftBtn1->Enabled = false;
  FrameShiftBtn2->Enabled = false;

	bVideoPlay = true;
	bExeVideoThread = false;

	memset(VideoImage, 0, SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT);

	if (VideoTrackBar->Max)
	{
		TFileStream *pFileStream = NULL;

		try
		{
			int start;
			if (VideoTrackBar->Position == VideoTrackBar->Max)
			{
				start = VideoTrackBar->Min;
			}
			else
			{
				start = VideoTrackBar->Position;
			}

			VideoTrackBar->Position = start;

			bool first = true;
			double lastExctime;
			double temptime;
			double prevExctime;
			lastExctime = Now().Val;

			double speed;
			int step;
			if (RadioButton3->Checked)
			{
				speed = 1;
				step = 1;
			}
			else if (RadioButton1->Checked)
			{
				speed = 0.5;
				step = 2;
			}
			else if (RadioButton2->Checked)
			{
				speed = 0.25;
				step = 4;
			}
			else if (RadioButton7->Checked)
			{
				speed = 0.125;
				step = 8;
			}
			else if (RadioButton4->Checked)
			{
				speed = 2;
				step = 1;
			}
			else if (RadioButton5->Checked)
			{
				speed = 4;
				step = 1;
			}
			else if (RadioButton6->Checked)
			{
				speed = 8;
				step = 1;
			}
      else if (RadioButton8->Checked)
			{
				speed = 16;
				step = 1;
			}

			int ImageIndex = VideoTrackBar->Max - 1;

			TTPBImageContainer tempTPBImageContainer;

			int fileIndex = (ImageIndex % MAX_SAVE_IMAGE_COUNT) + 1;

			AnsiString filename = foldername + "\\img" + IntToStr(fileIndex) + ".dat";
			pFileStream = new TFileStream(filename, fmOpenRead);
			pFileStream->Read(&tempTPBImageContainer.Header, sizeof(TTPBImageContainerHeader));
			pFileStream->Read(tempTPBImageContainer.CapturedImage, tempTPBImageContainer.Header.ImageWidth * tempTPBImageContainer.Header.ImageHeight);

			double lastElapsedTime = tempTPBImageContainer.Header.time - CaptureStartTime;

			delete pFileStream;

			bool finalSW = false;
			for (int pos = start; pos <= VideoTrackBar->Max; pos += step)
			{
				if (!finalSW)
				{
					if (pos + step > VideoTrackBar->Max)
					{
						step = VideoTrackBar->Max - pos;
						finalSW = true;

						if (step <= 0)
							step = 1;
					}
				}

				int ImageIndex = pos - 1;

				TTPBImageContainer tempTPBImageContainer;

				int fileIndex = (ImageIndex % MAX_SAVE_IMAGE_COUNT) + 1;

				AnsiString filename = foldername + "\\img" + IntToStr(fileIndex) + ".dat";
				pFileStream = new TFileStream(filename, fmOpenRead);
				pFileStream->Read(&tempTPBImageContainer.Header, sizeof(TTPBImageContainerHeader));
				pFileStream->Read(tempTPBImageContainer.CapturedImage, tempTPBImageContainer.Header.ImageWidth * tempTPBImageContainer.Header.ImageHeight);

				temptime = tempTPBImageContainer.Header.time;

				do
				{
					if (!first)
					{
						Application->ProcessMessages();
						if (bVideoStop)
						{
							break;
						}
					}

					double ElapsedTime = tempTPBImageContainer.Header.time - CaptureStartTime + (Now().Val - lastExctime) / speed;

					if (ElapsedTime > lastElapsedTime)
					{
						ElapsedTime = lastElapsedTime;
					}

					int elapsedTimeHour = ElapsedTime * 24;
					int elapsedTimeMin = ElapsedTime * 24 * 60 - elapsedTimeHour * 60;
					int elapsedTimeSec = ElapsedTime * 24 * 3600 - elapsedTimeHour * 3600 - elapsedTimeMin * 60;
					int elapsedTimeSubSec = ElapsedTime * 24 * 3600 * 100 - elapsedTimeHour * 3600 * 100 - elapsedTimeMin * 60 * 100 - elapsedTimeSec * 100;

					TntLabel22->Caption = Format("%.2d:%.2d.%.2d", ARRAYOFCONST((elapsedTimeMin, elapsedTimeSec, elapsedTimeSubSec)));

					if (first)
					{
						break;
					}
				}
				while ((Now().Val - lastExctime) * 24 * 36000000 < (temptime - prevExctime) * speed * 24 * 36000000); // waiting

				VideoWidth = tempTPBImageContainer.Header.ImageWidth;
				VideoHeight = tempTPBImageContainer.Header.ImageHeight;

				memcpy(VideoImage, tempTPBImageContainer.CapturedImage, VideoWidth * (TPBCameraParams.bounaryEndY / ImageScaleFactor));

				if (bExeVideoThread == false)
				{
          if(ImageControlHandle)
          {
            WaitForSingleObject(ImageControlHandle, INFINITE);
            CloseHandle(ImageControlHandle);
            ImageControlHandle = NULL;
          }

					bExeVideoThread = true;
					ImageControlHandle = (HANDLE)_beginthreadex(NULL, NULL, VideoPlayThread, this, 0, (unsigned int*) & ThreadDword);
				}

				TntLabel20->Caption = IntToStr(tempTPBImageContainer.Header.ImageIndex);

				delete pFileStream;

				first = false;
				VideoTrackBar->Position += step;

				lastExctime = Now().Val;
				prevExctime = tempTPBImageContainer.Header.time;

				Application->ProcessMessages();

				if (bVideoStop)
				{
					bVideoStop = false;
					break;
				}
			}
		}
		catch (...)
		{
			if (pFileStream)
				delete pFileStream;
		}
	}

	RadioButton1->Enabled = true;
	RadioButton2->Enabled = true;
	RadioButton3->Enabled = true;
	RadioButton4->Enabled = true;
	RadioButton5->Enabled = true;
	RadioButton6->Enabled = true;
	RadioButton7->Enabled = true;
  RadioButton8->Enabled = true;

	bVideoPlay = false;

	VideoTrackBar->Enabled = true;
	VideoStopBtn->Enabled = false;
	VideoPlayBtn->Enabled = true;
	CloseButton->Visible = true;
	GroupBox4->Visible = true;
  FrameShiftBtn1->Enabled = true;
  FrameShiftBtn2->Enabled = true;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::VideoStopBtnClick(TObject *Sender)
{
	bVideoStop = true;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::ImageScaleRadioButton1Click(
    TObject *Sender)
{
	if (ImageScaleRadioButton1->Checked)
	{
		ImageSettingWidth = SYSTEM_CAMERA_WIDTH;
		ImageSettingHeight = SYSTEM_CAMERA_HEIGHT;
		ImageScaleFactor = 1;
		Image1->Canvas->Pen->Width = 2;
    TPBCameraParams.ImageScale = 1;
	}
	else if (ImageScaleRadioButton2->Checked)
	{
		ImageSettingWidth = SYSTEM_CAMERA_WIDTH / 2;
		ImageSettingHeight = SYSTEM_CAMERA_HEIGHT / 2;
		ImageScaleFactor = 2;
		Image1->Canvas->Pen->Width = 1;
    TPBCameraParams.ImageScale = 2;
	}
	else if (ImageScaleRadioButton3->Checked)
	{
		ImageSettingWidth = SYSTEM_CAMERA_WIDTH / 4;
		ImageSettingHeight = SYSTEM_CAMERA_HEIGHT / 4;
		ImageScaleFactor = 4;
		Image1->Canvas->Pen->Width = 1;
    TPBCameraParams.ImageScale = 3;
	}

	Image1->Picture->Bitmap->Width = ImageSettingWidth;
	Image1->Picture->Bitmap->Height = ImageSettingHeight;
	Image1->Picture->Bitmap->PixelFormat = pf24bit;
	Image1->Canvas->Brush->Style = bsClear;

	Image1->Canvas->Pen->Color = clRed;

	tempImage->Width = ImageSettingWidth;
	tempImage->Height = ImageSettingHeight;
	tempImage->PixelFormat = pf24bit;

	lastImage->Width = ImageSettingWidth;
	lastImage->Height = ImageSettingHeight;
	lastImage->PixelFormat = pf24bit;
	lastImage->Canvas->Brush->Style = bsClear;
	lastImage->Canvas->Font->Name = "맑은 고딕";
	lastImage->Canvas->Font->Color = clWhite;
	lastImage->Canvas->Font->Size = 12;

	if (DirectoryExists(foldername))
	{
		RemoveWholeDir(foldername);
	}

	BoardMaxBufferCount = 0;
	BoardRemainingImageCount = 0;
	LastImageDisplayCount = 0;
	ReceivedImageCount = 0;
	UploadFrameNumber = 0;
	CaptureStartTime = Now().Val;
	LastFrameDownloadTime = Now().Val;
	instantCheckTime = Now().Val;
	fpsVariance = 0;
	fpsValInst = 0;

	VideoTrackBar->Enabled = false;
	VideoTrackBar->Min = 0;
	VideoTrackBar->Max = 0;
	VideoTrackBar->Position = 0;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::FormDestroy(TObject *Sender)
{
	delete tempImage;
	delete lastImage;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::GroupBox4DblClick(TObject *Sender)
{
	GroupBox6->Visible = !GroupBox6->Visible;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::CaptureTriggerTimerTimer(
    TObject *Sender)
{
	if (CaptureTrigger == true && bOnCapture == false)
	{
		HCBCaptureButtonClick(HCBCaptureButton);
	}
	else if (CaptureTrigger == false && bOnCapture == true)
	{
		HCBCaptureButtonClick(HCBCaptureButton);
	}
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::TPBCaptureButtonClick(
    TObject *Sender)
{
	if (!bOnCapture)
	{
		int camIndex = 0;
		Comm_Request(COMM_TPB, CMD_CAPTURE_STOP, &camIndex, sizeof(int));

		if (DirectoryExists(foldername))
		{
			RemoveWholeDir(foldername);
		}
		if (SendSPBCaptureSetup())
		{
			GroupBox9->Visible = false;
			bExeDownloadThread = false;
			bOnCapture = true;
			CaptureTrigger = true;
			bCaptureStop = false;
			TPBCaptureButton->Caption = "TPB Capture Stop";
			HCBCaptureButton->Enabled = false;
			float interval = StrToFloat(FrameTimeEdit->Text);
			TntLabel14->Caption = "Capture Interval : " + FloatToStrF(1000 / interval, ffFixed, 10, 3) + "fps";
			TntLabel17->Caption = Now().TimeString();

			BoardMaxBufferCount = 0;
			BoardRemainingImageCount = 0;
			LastImageDisplayCount = 0;
			ReceivedImageCount = 0;
			UploadFrameNumber = 0;
			CaptureStartTime = Now().Val;
			LastFrameDownloadTime = Now().Val;
			instantCheckTime = Now().Val;
			fpsVariance = 0;
			fpsValInst = 0;

			VideoTrackBar->Enabled = false;
			VideoTrackBar->Min = 0;
			VideoTrackBar->Max = 0;
			VideoTrackBar->Position = 0;

			VideoPlayBtn->Enabled = false;
			VideoStopBtn->Enabled = false;
			RadioButton1->Enabled = false;
			RadioButton2->Enabled = false;
			RadioButton3->Enabled = false;
			RadioButton4->Enabled = false;
			RadioButton5->Enabled = false;
			RadioButton6->Enabled = false;
			RadioButton7->Enabled = false;
      RadioButton8->Enabled = false;
      FrameShiftBtn1->Enabled = false;
      FrameShiftBtn2->Enabled = false;

			ImageLoadTimer->Enabled = true;
		}
	}
	else
	{
		int camIndex = 0;

    if(Comm_IsConnected(COMM_TPB) && bOnCapture)
    {
      // Thread 실행중인경우 종료까지 waiting
      while(bExecUploadThread);
    }

		Comm_Request(COMM_TPB, CMD_CAPTURE_STOP, &camIndex, sizeof(int));

		TPBCaptureButton->Enabled = false;
		bCaptureStop = true;
		captureStopTime = Now().Val;
	}
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::RTImageView()
{
	TFileStream *pFileStream = NULL;
	AnsiString filename;
  TTPBImageContainer tempTPBImageContainer;
  int tempReceivedImageCount = ReceivedImageCount;
  
  try
  {
    int fileIndex = ((tempReceivedImageCount - 1) % MAX_SAVE_IMAGE_COUNT) + 1;

    filename = foldername + "\\img" + IntToStr(fileIndex) + ".dat";
    pFileStream = new TFileStream(filename, fmOpenRead);
    pFileStream->Read(&tempTPBImageContainer.Header, sizeof(TTPBImageContainerHeader));
    pFileStream->Read(tempTPBImageContainer.CapturedImage, tempTPBImageContainer.Header.ImageWidth * tempTPBImageContainer.Header.ImageHeight);
    delete pFileStream;

    Bayer_Conversion_GBRG(tempImage, tempTPBImageContainer.CapturedImage, tempTPBImageContainer.Header.ImageWidth, tempTPBImageContainer.Header.ImageHeight, 2);

    int x, y;
    int tempAddress;
    int tempBuff[3];
    int normalized[3];

    Byte *ptr1, *ptr2;

    int maxB = min((TPBCameraParams.WhiteBalance[0] * 255) / 1000, 255);
    int maxG = min((TPBCameraParams.WhiteBalance[1] * 255) / 1000, 255);
    int maxR = min((TPBCameraParams.WhiteBalance[2] * 255) / 1000, 255);

    for (y = 0; y < tempTPBImageContainer.Header.ImageHeight; y++)
    {
      ptr1 = (Byte*) tempImage->ScanLine[y];
      ptr2 = (Byte*) lastImage->ScanLine[y];
      for (x = 0; x < tempTPBImageContainer.Header.ImageWidth; x++)
      {
        if (y >= TPBCameraParams.bounaryStartY / ImageScaleFactor && y <= TPBCameraParams.bounaryEndY / ImageScaleFactor)
        {
          tempBuff[0] = ptr1[3 * x + 0];
          tempBuff[1] = ptr1[3 * x + 1];
          tempBuff[2] = ptr1[3 * x + 2];

          tempBuff[0] = min((TPBCameraParams.WhiteBalance[0] * tempBuff[0]) / 1000, 255);
          tempBuff[1] = min((TPBCameraParams.WhiteBalance[1] * tempBuff[1]) / 1000, 255);
          tempBuff[2] = min((TPBCameraParams.WhiteBalance[2] * tempBuff[2]) / 1000, 255);

          if (maxB)
            normalized[0] = min((tempBuff[0] * 255) / maxB, 255);
          else
            normalized[0] = 0;

          if (maxG)
            normalized[1] = min((tempBuff[1] * 255) / maxG, 255);
          else
            normalized[1] = 0;

          if (maxR)
            normalized[2] = min((tempBuff[2] * 255) / maxR, 255);
          else
            normalized[2] = 0;

          ptr2[3*x + 0] = normalized[0];
          ptr2[3*x + 1] = normalized[1];
          ptr2[3*x + 2] = normalized[2];
        }
        else
        {
          ptr2[3*x + 0] = 0;
          ptr2[3*x + 1] = 0;
          ptr2[3*x + 2] = 0;
        }
      }
    }
  }
  catch (...)
  {
    if (pFileStream)
      delete pFileStream;
  }

  UploadFrameNumber = tempTPBImageContainer.Header.ImageIndex;
  LastImageDisplayCount = tempReceivedImageCount;

	uploading = false;
}
//---------------------------------------------------------------------------
void __fastcall TTPBCameraSettingForm::FrameShiftBtn1Click(TObject *Sender)
{
  VideoTrackBar->Position--;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::FrameShiftBtn2Click(TObject *Sender)
{
  VideoTrackBar->Position++;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::InsAreaSettingButtonClick(
      TObject *Sender)
{
  /*
  if(InsAreaImageCheck)
  {
    InsAreaSettingPanel->Visible = false;
    InsAreaSettingPanel->BringToFront();
    Panel1->SendToBack();
    InsAreaSettingButton->Enabled = false;

    AreaSettingImageShow();

  }
  else
  {
    ShowMessage("Not Exist Image.");
  }
  */

  InsAreaSettingPanel->Visible = true;
  InsAreaSettingPanel->BringToFront();
  Panel1->SendToBack();
  InsAreaSettingButton->Enabled = false;

  AreaSettingImageShow();
}
//---------------------------------------------------------------------------
void __fastcall TTPBCameraSettingForm::AreaSettingImageShow()
{


  AreaSetImage->Picture->Bitmap->Assign(Image1->Picture->Bitmap);
  AreaSetImage->Refresh();

  AreaSetImage->Canvas->Brush->Style = bsClear;
  AreaSetImage->Canvas->Pen->Color = clLime;

  AreaSetImage->Canvas->Rectangle(BoundaryArea.Left / 2, BoundaryArea.Top / 2, BoundaryArea.Right / 2, BoundaryArea.Bottom / 2);

  AreaSetImage->Refresh();



}
//---------------------------------------------------------------------------
void __fastcall TTPBCameraSettingForm::AreaKindSelect(TObject *Sender)
{
  TSpeedButton *theSpeedButton = (TSpeedButton *) Sender;
  AreaKind = theSpeedButton->Tag;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::AreaSetImageMouseDown(
      TObject *Sender, TMouseButton Button, TShiftState Shift, int X,
      int Y)
{
  //

  if(AreaKind == 0 || AreaKind == 2)
  {
    BoundaryArea.left = X /4 * 4;
  }
  else
  {
    BoundaryArea.right = X / 4 * 4;
  }

  if(AreaKind == 0 || AreaKind == 1)
  {
    BoundaryArea.top = Y / 4 * 4;
  }
  else
  {
    BoundaryArea.Bottom = Y / 4 * 4;
  }

  AreaSettingImageShow();
}
//---------------------------------------------------------------------------


void __fastcall TTPBCameraSettingForm::AreaSetOKButtonClick(
      TObject *Sender)
{
  TPBCameraParams.InsAreaLeft = BoundaryArea.left;
  TPBCameraParams.InsAreaRight = BoundaryArea.right;
  TPBCameraParams.InsAreaTop =  BoundaryArea.top;
  TPBCameraParams.InsAreaBottom = BoundaryArea.bottom;

  WriteTPBCameraInfo();

  MinXValue->Caption = IntToStr(TPBCameraParams.InsAreaLeft);
  MaxXValue->Caption = IntToStr(TPBCameraParams.InsAreaRight);
  MinYValue->Caption = IntToStr(TPBCameraParams.InsAreaTop);
  MaxYValue->Caption = IntToStr(TPBCameraParams.InsAreaBottom);


  InsAreaSettingButton->Enabled = true;
  InsAreaSettingPanel->Visible = false;
  InsAreaSettingPanel->SendToBack();
  Panel1->BringToFront();
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::tmrHCBReadTimer(TObject *Sender)
{
  short int ret_val_2;
  int cvt_val = 0;     
  int tmp_data_size = sizeof(short int);

  if(!Comm_Request(COMM_HCB, CMD_READ_THREEDSENSOR_MEM, NULL, 0, &ret_val_2, sizeof(short int)))
  {
    ret_val_2 = 0xABCD;
  }

  cvt_val = ((int)ret_val_2)&0xFFFF;

  eReadHCB->Text = IntToHex(cvt_val, 4);  
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::TntButton1Click(TObject *Sender)
{
tmrHCBRead->Enabled = true;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::TntButton2Click(TObject *Sender)
{
tmrHCBRead->Enabled = false;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::TntButton3Click(TObject *Sender)
{
  unsigned int test_val;
  unsigned int ret_val;

  test_val = StrToInt(eTest01->Text);

  if (!Comm_Request(COMM_TPB, CMD_MIS_EJECT_CONTROL, &test_val, sizeof(unsigned int), &ret_val, sizeof(unsigned int)))
  {
    test_val = 99;
  }

  eReturnTestVal->Text = IntToStr(ret_val);
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::TntButton4Click(TObject *Sender)
{
  if(pnTPBProcessInfo->Visible == true)
  {
    pnTPBProcessInfo->Visible = false;
    pnTPBProcessInfo->SendToBack();
  }
  else
  {
    pnTPBProcessInfo->Visible = true;
    pnTPBProcessInfo->BringToFront();
  }
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::tmrTPBInsDataTimer(TObject *Sender)
{
        int test_val = 0;
        int view_row_val = 0;
        TTPBMonitorInsData TmpDataGroup;

        if (!Comm_Request(COMM_TPB, CMD_MONITOR_TPB_INS_DATA, NULL, 0, &TmpDataGroup, sizeof(TTPBMonitorInsData)))
        {
          test_val = 99;
        }
        else
        {
            if(TmpDataGroup.cpbSendIndex > 0)
            {
              if(view_monitor_cnt > 98)
              {
                view_monitor_cnt = 0;
              }
              StringGrid1->Cells[0][view_monitor_cnt+1] = IntToStr(view_monitor_cnt+1);
              StringGrid1->Cells[1][view_monitor_cnt+1] = IntToStr(TmpDataGroup.cpbSendIndex);
              StringGrid1->Cells[2][view_monitor_cnt+1] = IntToStr(TmpDataGroup.workedCoreIndex);
              StringGrid1->Cells[3][view_monitor_cnt+1] = IntToStr(TmpDataGroup.inspection_result);
              StringGrid1->Cells[4][view_monitor_cnt+1] = IntToStr(TmpDataGroup.TPBMinX1);
              StringGrid1->Cells[5][view_monitor_cnt+1] = IntToStr(TmpDataGroup.TPBMaxX1);
              StringGrid1->Cells[6][view_monitor_cnt+1] = IntToStr(TmpDataGroup.TPBMinY1);
              StringGrid1->Cells[7][view_monitor_cnt+1] = IntToStr(TmpDataGroup.TPBMaxY1);
              StringGrid1->Cells[8][view_monitor_cnt+1] = IntToStr(TmpDataGroup.TPBMinX2);
              StringGrid1->Cells[9][view_monitor_cnt+1] = IntToStr(TmpDataGroup.TPBMinX3);
              StringGrid1->Cells[10][view_monitor_cnt+1] = IntToStr(TmpDataGroup.TPBMaxX3);
              StringGrid1->Cells[11][view_monitor_cnt+1] = IntToStr(TmpDataGroup.TPBMinY3);
              StringGrid1->Cells[12][view_monitor_cnt+1] = IntToStr(TmpDataGroup.TPBMaxY3);

              StringGrid1->Row = view_monitor_cnt+1;
              view_monitor_cnt++;

              //last_TDG_cpbsendIndex = TmpDataGroup.cpbSendIndex;
           }
        }  
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::TntButton5Click(TObject *Sender)
{
        for(int i=1; i<StringGrid1->RowCount; i++)
        {
                StringGrid1->Rows[i]->Clear();
        }

        StringGrid1->Cells[0][0] = "Num";
        StringGrid1->Cells[1][0] = "Count";
        StringGrid1->Cells[2][0] = "Core";
        StringGrid1->Cells[3][0] = "Res";
        StringGrid1->Cells[4][0] = "MinX1";
        StringGrid1->Cells[5][0] = "MaxX1";
        StringGrid1->Cells[6][0] = "MinY1";
        StringGrid1->Cells[7][0] = "MaxY1";
        StringGrid1->Cells[8][0] = "MinX2";
        StringGrid1->Cells[9][0] = "MinX3";
        StringGrid1->Cells[10][0] = "MaxX3";
        StringGrid1->Cells[11][0] = "MinY3";
        StringGrid1->Cells[12][0] = "MaxY3";
        
tmrTPBInsData->Interval = StrToInt(eTimerInterval->Text);
tmrTPBInsData->Enabled = true;
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::TntButton6Click(TObject *Sender)
{
tmrTPBInsData->Enabled = false;
}
//---------------------------------------------------------------------------



void __fastcall TTPBCameraSettingForm::btnCPBProcReadOnClick(
      TObject *Sender)
{
  int timer_interval = StrToInt(eTmrChkCPBProcess->Text);

        for(int i=1; i<sgCPBProcess->RowCount; i++)
        {
                sgCPBProcess->Rows[i]->Clear();
        }

        sgCPBProcess->Cells[0][0] = "Core";
        sgCPBProcess->Cells[1][0] = "Proc Step";
        sgCPBProcess->Cells[2][0] = "Proc Prd";
        sgCPBProcess->Cells[3][0] = "chk count";
        sgCPBProcess->Cells[4][0] = "CPB status";

        for(int core_index = 1; core_index < 8; core_index++)
        {
          sgCPBProcess->Cells[0][core_index] = IntToStr(core_index);
        }                                                            

  tmrChkCPBProcess->Interval = timer_interval;
  tmrChkCPBProcess->Enabled = true;  
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::btnCPBProcReadOffClick(
      TObject *Sender)
{
  tmrChkCPBProcess->Enabled = false;  
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::tmrChkCPBProcessTimer(
      TObject *Sender)
{
  TTBPProcessInfoCopy tmpDataGroup;
  int test_val = 0;
  int calPeriod = 0;
  
        if (!Comm_Request(COMM_TPB, CMD_CHK_CPB_PROCESS, NULL, 0, &tmpDataGroup, sizeof(TTBPProcessInfoCopy)))
        {
          test_val = 99;
        }
        else
        {
            for(int coreIndex = 1; coreIndex < 8; coreIndex++)
            {
              if((tmpDataGroup.ProcessingTime[coreIndex].checkcount > 0) && (tmpDataGroup.ProcessingTime[coreIndex].checkcount <= 255))
              {
                sgCPBProcess->Cells[1][coreIndex] = IntToStr(tmpDataGroup.ProcessStep[coreIndex]);
                sgCPBProcess->Cells[2][coreIndex] = IntToStr(tmpDataGroup.ProcessingTime[coreIndex].period[tmpDataGroup.ProcessingTime[coreIndex].checkcount-1]);
                sgCPBProcess->Cells[3][coreIndex] = IntToStr(tmpDataGroup.ProcessingTime[coreIndex].checkcount);
                sgCPBProcess->Cells[4][coreIndex] = IntToStr(tmpDataGroup.cpbStatus[coreIndex]);
              }
            }
        }
}
//---------------------------------------------------------------------------




void __fastcall TTPBCameraSettingForm::ThresholdTrackBarChange(
      TObject *Sender)
{
  TPBCameraParams.Threshold = ThresholdTrackBar->Position;
  ThresholdLabel->Caption = IntToStr(ThresholdTrackBar->Position);
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::Button1Click(TObject *Sender)
{
 int x,y;
  int ImageWidth;
  int protoThreshold;
  int maxLabelN;
  int tempAddress;
  int startX, startY, endX, endY;
  unsigned char BinaryImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  unsigned char OrgImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  short LabelImage[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
  Byte *ptr;

  startX = BoundaryArea.left;
  startY = BoundaryArea.top;
  endX = BoundaryArea.right;
  endY = BoundaryArea.Bottom;

  protoThreshold = TPBCameraParams.Threshold;


  memset(OrgImage,0,sizeof(OrgImage));
  memset(BinaryImage,0,sizeof(BinaryImage));
  memset(LabelImage,0,sizeof(LabelImage));

  for (y = startY; y < endY; y++)
  {
    ptr = (Byte*)AreaSetImage->Picture->Bitmap->ScanLine[y];
    for (x = startX; x < endX; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;
      OrgImage[tempAddress * 3 + 0] = ptr[3 * x + 0];
      OrgImage[tempAddress * 3 + 1] = ptr[3 * x + 1];
      OrgImage[tempAddress * 3 + 2] = ptr[3 * x + 2];
    }
  }

  for (y = startY; y < endY; y++)
  {
    for (x = startX; x < endX; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;
      if (*(OrgImage + (MAX_IMAGE_WIDTH*y + x) * 3 + 1) > protoThreshold && *(OrgImage + (MAX_IMAGE_WIDTH*y + x) * 3 + 2) > protoThreshold
            && *(OrgImage + (MAX_IMAGE_WIDTH*y + x) * 3 + 0) > protoThreshold)
      {
        BinaryImage[tempAddress] = 1;
      }
    }
  }

  maxLabelN = LabellingForTabletImage(LabelImage, BinaryImage, startX, endX, startY, endY, 640, 480);

  for(y = startY; y < endY; y++)
  {
    for(x = startX; x < endX; x++)
    {
      tempAddress = MAX_IMAGE_WIDTH * y + x;
      if(LabelImage[tempAddress] == 1)
      {
        AreaSetImage->Canvas->Pixels[x][y] = clRed;
      }
      if(LabelImage[tempAddress] == 2)
      {
        AreaSetImage->Canvas->Pixels[x][y] = clGreen;
      }
      if(LabelImage[tempAddress] == 3)
      {
        AreaSetImage->Canvas->Pixels[x][y] = clYellow;
      }
    }
  }
}
//---------------------------------------------------------------------------
int __fastcall TTPBCameraSettingForm::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;
	short CollisionArray[1000];
	int newLval;
	int temp;
	// int checkSW;
	//  int minValue;
	int tempAddress;
	// int smallSizeImagWidth;
	//  int smallSizeImagHeight;
	int maxLabelN;
  int maxLabelN2;
  int maxLabelN3;

	int maxLabelCount;
	int breakSW;
	unsigned short Pixel_N_Of_Label[10000]; //4k
	int StartX_Label[10000];
	int EndX_Label[10000];
	int StartY_Label[10000];
	int EndY_Label[10000];

	currentLabel = 0;
	for (i = 0; i < 1000; 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 >= 1000 - 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 > 1000)  newLval = 1000 - 1;
	new_count = newLval;

	for (y = 0; y < imageHeight; y++)
	{
		for (x = 0; x < imageWidth; 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 TTPBCameraSettingForm::BitBtn1Click(TObject *Sender)
{
     if(ckbTPB_Active->Checked)
    	MachineSetupData.EjectorInfo.TPB_MisejectActive = 1;
    else
    	MachineSetupData.EjectorInfo.TPB_MisejectActive = 0;
    	
    MachineSetupData.EjectorInfo.TPB_MisejectOpenDelay 		= StrToInt(eTPB_MisOpenDelayTime->Text);
    MachineSetupData.EjectorInfo.TPB_MisejectOpenRunTime 	= StrToInt(eTPB_MisOpenRunTime->Text);
    MachineSetupData.EjectorInfo.TPB_MisCmdValidCnt				= StrToInt(eTPB_MisCmdValidCnt->Text);

    if(ckbMultiMisejectAction->Checked)
    	MachineSetupData.EjectorInfo.IgnoreMultiMisejectAction = 1;
    else
    	MachineSetupData.EjectorInfo.IgnoreMultiMisejectAction = 0;

    if(ckbTPB_MisejectOperationMode->Checked)
    	MachineSetupData.EjectorInfo.TPB_MisejectOperationMode = TPB_MISEJECT_NO_INSPECTION_MODE;
    else
    	MachineSetupData.EjectorInfo.TPB_MisejectOperationMode = TPB_MISEJECT_NORMAL_MODE;

    WriteMachineSetupData(ProgramPath.Env + "\\SystemInfor.ini",MachineSetupData);

      if (!Comm_Request(COMM_HCB, CMD_MACHINE_PARAM_SETUP, &MachineSetupData, sizeof(TMachineSetupData)))
	    {
          //ShowMessageW(HCBConnection.GetLastErrorMessage());
      }
      else
      {
          ShowMessageFA(MACHINEPARAMSETTINGFORM_MSG_01);
      }
    //ModalResult = mrOk;  
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::btnTPBSetupClick(TObject *Sender)
{
	TPBCameraParams.FrameTime = StrToInt(FrameTimeEdit->Text);
  TPBCameraParams.LedOnTime = StrToInt(LedOnTimeEdit->Text);
  TPBCameraParams.CaptureDelay_Min   = StrToInt(eCaptureDelay_Min->Text);
  TPBCameraParams.CaptureDelay_Max   = StrToInt(eCaptureDelay_Max->Text);

  if(ckbFreeUploadMode->Checked)
    TPBCameraParams.FreeCaptureUpload = 1;
  else
    TPBCameraParams.FreeCaptureUpload = 0;

  WriteTPBCameraInfo();

  ShowMessageFA("Setup Completed");
}
//---------------------------------------------------------------------------

void __fastcall TTPBCameraSettingForm::HiddenPanelDblClick(TObject *Sender)
{
    if (ckbTPB_MisejectOperationMode->Visible)
    {
      ckbTPB_MisejectOperationMode->Visible = false;
    }
    else
    {
      ckbTPB_MisejectOperationMode->Visible = true;
    }    
}
//---------------------------------------------------------------------------


void __fastcall TTPBCameraSettingForm::pcTPBInfoChange(TObject *Sender)
{
    ReadMachineSetupData(ProgramPath.Env + "\\SystemInfor.ini",MachineSetupData);

    if(MachineSetupData.EjectorInfo.TPB_MisejectActive == 1)
      ckbTPB_Active->Checked = true;
    else
      ckbTPB_Active->Checked = false;

    eTPB_MisOpenDelayTime->Text = IntToStr(MachineSetupData.EjectorInfo.TPB_MisejectOpenDelay);
    eTPB_MisOpenRunTime->Text = IntToStr(MachineSetupData.EjectorInfo.TPB_MisejectOpenRunTime);
    eTPB_MisCmdValidCnt->Text = IntToStr(MachineSetupData.EjectorInfo.TPB_MisCmdValidCnt);

    if(MachineSetupData.EjectorInfo.IgnoreMultiMisejectAction == 1)
      ckbMultiMisejectAction->Checked = true;
    else
      ckbMultiMisejectAction->Checked = false;

    if(MachineSetupData.EjectorInfo.TPB_MisejectOperationMode == TPB_MISEJECT_NO_INSPECTION_MODE)
      ckbTPB_MisejectOperationMode->Checked = true;
    else
      ckbTPB_MisejectOperationMode->Checked = false;
}
//---------------------------------------------------------------------------

