//---------------------------------------------------------------------------
// For SELMA200, 20180221, moon, 완료
// Camera Index 변경 관련 수정
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Capture_Frame.h"
#include "Bayer.h"
#include "MultiLanguage.h"
#include "Environment.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "TntButtons"
#pragma link "TntExtCtrls"
#pragma link "TntStdCtrls"
#pragma resource "*.dfm"

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

TCaptureFrame *CaptureFrame;
//---------------------------------------------------------------------------
__fastcall TCaptureFrame::TCaptureFrame(TComponent* Owner)
	: TFrame(Owner)
{
	if (DefaultLCID == 1028 || DefaultLCID == 2052 || DefaultLCID == 3076 || DefaultLCID == 4100)
		ComponentSetFontName(this, "SimSun");
  else if(DefaultLCID == 1041)
    ComponentSetFontName(this, "Meiryo UI");
  else if(DefaultLCID == 3082)
  {
    ComponentSetFontName(this, "Segoe UI");
    ComponentSetMultiLine(this);
  }

	CaptureWidth = 0;
	CaptureHeight = 0;
	GlobalCameraIndex = 0;
	DestImage = NULL;

	bOnCapture = false;
	bFrameCapture = false;
	CaptureData = NULL;

	ImageDirectoryListBox->Directory = ProgramPath.Image;
	FindFirstSubDir();
	IsSingleMode = true;
	IsFullCapture = false;

	BufferImage->Canvas->Brush->Color = clBlack;
	BufferImage->Canvas->FillRect(Rect(0, 0, BufferImage->Width, BufferImage->Height));

  threeDOption = 0;
}
//---------------------------------------------------------------------------
__fastcall TCaptureFrame::~TCaptureFrame()
{
	if (CaptureData != NULL)
	{
		delete[] CaptureData;
	}
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::SetCaptureProperty(int captureWidth, int captureHeight, TTntImage *destImage, TPixelFormat pixelFormat)
{
	CaptureWidth = captureWidth;
	CaptureHeight = captureHeight;
	DestImage = destImage;
	//DestImage->Width = CaptureWidth;
	//DestImage->Height = CaptureHeight;
	DestImage->Picture->Bitmap->Width = CaptureWidth;
	DestImage->Picture->Bitmap->Height = CaptureHeight;
	DestImage->Picture->Bitmap->PixelFormat = pixelFormat;
	if (pixelFormat == pf8bit)
	{
		SetGrayPalette(DestImage->Picture->Bitmap);
	}
	if (CaptureData != NULL)
	{
		delete[] CaptureData;
	}
	CaptureData = new char[(CaptureWidth + 1) * (CaptureHeight + 1)];     // bayer 보정을 위해 여분을 둔다.
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::SetCaptureProperty_Multi(int captureWidth, int captureHeight,
	TTntImage *destImage1, TTntImage *destImage2, TTntImage *destImage3, TTntImage *destImage4)
{
	CaptureWidth = captureWidth;
	CaptureHeight = captureHeight;
	MultiImage[0] = destImage1;
	MultiImage[1] = destImage2;
	MultiImage[2] = destImage3;
	MultiImage[3] = destImage4;
	if (CaptureData != NULL)
	{
		delete[] CaptureData;
	}
	CaptureData = new char[(CaptureWidth + 1) * (CaptureHeight + 1)];     // bayer 보정을 위해 여분을 둔다.
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::SetGlobalCameraIndex(int cameraIndex)
{
	GlobalCameraIndex = cameraIndex;
	if (CameraMapInfo[GlobalCameraIndex].CameraInspectPosition == CAMERA_POSITION_3D) // 3d camera
	{
		cb3DData->Checked = true;
	}
	else
	{
		cb3DData->Checked = false;
	}
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::SetMultiImageCameraIndex(int index1, int index2, int index3, int index4)
{
	MultiImageCameraIndex[0] = index1;
	MultiImageCameraIndex[1] = index2;
	MultiImageCameraIndex[2] = index3;
	MultiImageCameraIndex[3] = index4;
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::FindFirstSubDir(void)
{
	ImageSubDirIndex = 1;
	AnsiString dir = ImageDirectoryListBox->Directory;
	while (true)
	{
		if (!DirectoryExists(dir + "\\" + IntToStr(ImageSubDirIndex)))
		{
			break;
		}
		ImageSubDirIndex++;
	}
	CurrentImageIndex = 1;
	ImageSubDirIndex--;
	SubDirEdit->Text = IntToStr(ImageSubDirIndex);
	UpdateImageFileList();
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::UpdateImageFileList(void)
{
	AnsiString dir = ImageDirectoryListBox->Directory + "\\" + IntToStr(ImageSubDirIndex);
	if (DirectoryExists(dir))
	{
		ImageFileListBox->Directory = dir;
	}
	else
	{
		ImageFileListBox->Clear();
	}
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::StopTimerButtonClick(TObject *Sender)
{
	CaptureCheckTimer->Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::CaptureCheckTimerTimer(TObject *Sender)
{
	if (IsSingleMode)
	{
		ReadSingleModeImage();
	}
	else
	{
		ReadMultiModeImage();
	}
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::ReadSingleModeImage(void)
{
	bool bCaptureExist;
	// check capture exists
	char cameraIndex;
	unsigned int data[2];
	unsigned int receivedData[2];

	int spbIndex = CameraMapInfo[GlobalCameraIndex].SPBIndex;
	int camIndex = CameraMapInfo[GlobalCameraIndex].CamIndex;
	data[0] = camIndex;
	data[1] = CaptureWidth * CaptureHeight;

	if (!IsFullCapture)
	{
		try
		{
			if (!Comm_Request(COMM_SPB + spbIndex, CMD_CAPTURE_EXIST, data, sizeof(unsigned int),
				receivedData, sizeof(unsigned int) * 2))
			{
				//ShowMessageW(SPBConnection[spbIndex].GetLastErrorMessage());
				throw(0);
			}

			BufferImage->Canvas->Brush->Color = clBlack;
			BufferImage->Canvas->FillRect(Rect(0, 0, BufferImage->Width, BufferImage->Height));
			if (receivedData[0])
			{
				bCaptureExist = true;
				BufferImage->Canvas->Brush->Color = clLime;
				BufferImage->Canvas->FillRect(Rect(0, BufferImage->Height - BufferImage->Height * receivedData[0] / receivedData[1], BufferImage->Width, BufferImage->Height));
			}
			else
			{
				bCaptureExist = false;
			}
			if (bCaptureExist)
			{
				if (cb3DData->Checked)
				{
					data[1] = SYSTEM_CAMERA_WIDTH_3D * SYSTEM_CAMERA_HEIGHT_3D;
					if (!Comm_Request(COMM_SPB + spbIndex, CMD_CAPTURE_UPLOAD, data, 2 * sizeof(unsigned int),
						CaptureData, SYSTEM_CAMERA_WIDTH_3D * SYSTEM_CAMERA_HEIGHT_3D))
					{
						//ShowMessageW(SPBConnection[spbIndex].GetLastErrorMessage());
						throw(0);
					}
				}
				else
				{
					if (!Comm_Request(COMM_SPB + spbIndex, CMD_CAPTURE_UPLOAD, data, 2 * sizeof(unsigned int),
						CaptureData, (CaptureWidth) * CaptureHeight))
					{
						//ShowMessageW(SPBConnection[spbIndex].GetLastErrorMessage());
						throw(0);
					}
				}

        if (cbRAWData->Checked)
        {
          TFileStream *ImageFileStream;
          AnsiString dir = ImageDirectoryListBox->Directory + "\\" + IntToStr(ImageSubDirIndex);
          AnsiString ImagePath;
          if (!DirectoryExists(dir))
          {
            ForceDirectories(dir);
            UpdateImageFileList();
          }
          ImagePath +=dir+ "\\Image" + IntToStr(CurrentImageIndex) +".raw";
          ImageFileStream = new TFileStream(ImagePath,fmCreate);
          if(ImageFileStream)
          {
            ImageFileStream->Write(CaptureData,SYSTEM_CAMERA_WIDTH_3D* SYSTEM_CAMERA_HEIGHT_3D);
            delete ImageFileStream;
          }
        }

				if (cb3DData->Checked)
				{
          if (!cbRAWData->Checked)
          {
            Graphics::TBitmap *tempBitmap = new Graphics::TBitmap;
            tempBitmap->Width = IMAGE_WIDTH_3D;
            tempBitmap->Height = IMAGE_HEIGHT_3D;
            tempBitmap->PixelFormat = pf8bit;

            ImageConversion_3D(tempBitmap, IMAGE_WIDTH_3D, IMAGE_HEIGHT_3D, CaptureData, SYSTEM_CAMERA_WIDTH_3D, SYSTEM_CAMERA_HEIGHT_3D);

            for (int y = 1; y < IMAGE_HEIGHT_3D - 1; y++)
            {
              byte *pBitmap = (byte *)DestImage->Picture->Bitmap->ScanLine[y];

              byte *pSrc1 = (byte *)tempBitmap->ScanLine[y - 1];
              byte *pSrc2 = (byte *)tempBitmap->ScanLine[y];
              byte *pSrc3 = (byte *)tempBitmap->ScanLine[y + 1];

              for (int x = IMAGE_WIDTH_3D * 2 - 1; x >= 0; x--)
              {
                if (x & 2)
                {
                  pBitmap[x] = pSrc2[x / 2];
                }
                else
                {
                  pBitmap[x] = pSrc2[x / 2];
                }
              }
            }

            if(threeDOption)
            {
              ViewDentedArea();
            }
            delete tempBitmap;
          }
          else
          {
            for (int y = 1; y < IMAGE_HEIGHT_3D - 1; y++)
            {
              byte *pBitmap = (byte *)DestImage->Picture->Bitmap->ScanLine[y];

              for (int x = IMAGE_WIDTH_3D * 2 - 1; x >= 0; x--)
              {
                pBitmap[x] = CaptureData[IMAGE_WIDTH_3D * 2 * y + x];
              }
            }
          }
				}
				else if (!cbRAWData->Checked)
				{
          GetNFACamera2DColorImage(DestImage->Picture->Bitmap, CaptureData, CaptureWidth, CaptureHeight, GlobalCameraIndex, SystemImageOffsetSWCal[GlobalCameraIndex - 1], SystemOffsetImage[GlobalCameraIndex - 1],SubSamplingMode);
				}
				else
				{
					for (int y = 0; y < CaptureHeight; y++)
					{
						byte *pBitmap = (byte *)DestImage->Picture->Bitmap->ScanLine[y];
						for (int x = 0; x < CaptureWidth; x++)
						{
							pBitmap[0] = CaptureData[y * CaptureWidth + x];
							pBitmap[1] = CaptureData[y * CaptureWidth + x];
							pBitmap[2] = CaptureData[y * CaptureWidth + x];
							pBitmap += 3;
						}
					}
					DestImage->Repaint();
				}

				// For SELMA200, 영상 반전 수정 예정
        if (GlobalCameraIndex == SD2_2D_SIDE_FACE_P45_CAMERA_INDEX - 1 ||
            GlobalCameraIndex == SD2_2D_SIDE_FACE_M45_CAMERA_INDEX - 1)
        {
          byte *pTempLine = new byte[DestImage->Picture->Bitmap->Width * 3];
          for (int y = 0; y < (DestImage->Picture->Bitmap->Height); y++)
          {
            byte *pBitmap = (byte *)DestImage->Picture->Bitmap->ScanLine[y];

            for (int x = 0; x < DestImage->Picture->Bitmap->Width; x++)
            {
              pTempLine[x * 3 + 0] = pBitmap[(DestImage->Picture->Bitmap->Width - 1 - x) * 3 + 0];
              pTempLine[x * 3 + 1] = pBitmap[(DestImage->Picture->Bitmap->Width - 1 - x) * 3 + 1];
              pTempLine[x * 3 + 2] = pBitmap[(DestImage->Picture->Bitmap->Width - 1 - x) * 3 + 2];
            }
            memcpy(pBitmap, pTempLine, DestImage->Picture->Bitmap->Width * 3);
          }
          delete[] pTempLine;
        }
        else if (GlobalCameraIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX - 1 ||
                  GlobalCameraIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX - 1 ||
                  GlobalCameraIndex == SD1_2D_SIDE_FACE_00_CAMERA_INDEX - 1 ||
                  GlobalCameraIndex == SD1_2D_OTHER_SIDE_FACE_00_CAMERA_INDEX - 1 ||
                  GlobalCameraIndex == SD1_2D_SIDE_FACE_P45_CAMERA_INDEX - 1 ||
                  GlobalCameraIndex == SD1_2D_OTHER_SIDE_FACE_P45_CAMERA_INDEX - 1 ||
                  GlobalCameraIndex == SD1_2D_SIDE_FACE_M45_CAMERA_INDEX - 1 ||
                  GlobalCameraIndex == SD1_2D_OTHER_SIDE_FACE_M45_CAMERA_INDEX - 1)
        {
          byte *pTempLineT = new byte[DestImage->Picture->Bitmap->Width * 3];
          byte *pTempLineB = new byte[DestImage->Picture->Bitmap->Width * 3];
          for (int y = 0; y < (DestImage->Picture->Bitmap->Height + 1) / 2; y++)
          {
            byte *pBitmapT = (byte *)DestImage->Picture->Bitmap->ScanLine[y];
            byte *pBitmapB = (byte *)DestImage->Picture->Bitmap->ScanLine[DestImage->Picture->Bitmap->Height - 1 - y];

            memcpy(pTempLineT, pBitmapB, DestImage->Picture->Bitmap->Width * 3);
            memcpy(pTempLineB, pBitmapT, DestImage->Picture->Bitmap->Width * 3);
            memcpy(pBitmapT, pTempLineT, DestImage->Picture->Bitmap->Width * 3);
            memcpy(pBitmapB, pTempLineB, DestImage->Picture->Bitmap->Width * 3);
          }
          delete[] pTempLineT;
          delete[] pTempLineB;
        }


				if (SaveSpeedButton->Down)
				{
					AnsiString dir = ImageDirectoryListBox->Directory + "\\" + IntToStr(ImageSubDirIndex);
					if (!DirectoryExists(dir))
					{
						ForceDirectories(dir);
						UpdateImageFileList();
					}
					DestImage->Picture->Bitmap->SaveToFile(dir + "\\Image" + IntToStr(CurrentImageIndex) + ".bmp");
					CurrentImageIndex++;
					ImageFileListBox->Update();
				}

				unsigned int elapsedTime = GetTickCount() - CaptureStartTime;
				if (elapsedTime > 0)
				{
					lblFPS->Caption = FloatToStr(1000 * 1000 / elapsedTime / 1000.0) + "FPS";
				}
				CaptureStartTime = GetTickCount();
				CaptureCount++;
				elapsedTime = GetTickCount() - CaptureFirstStartTime;
				if (elapsedTime > 0)
				{
					lblAvgFPS->Caption = FloatToStr(1000 * 1000 / elapsedTime * CaptureCount / 1000.0) + "FPS";
				}
				DestImage->Repaint();
				if (shRefresh->Brush->Color == clWhite)
				{
					shRefresh->Brush->Color = clBlack;
				}
				else
				{
					shRefresh->Brush->Color = clWhite;
				}
				if (bFrameCapture)
				{
					CaptureCheckTimer->Enabled = false;
				}
			}
			else
			{
				if (!bFrameCapture && !bOnCapture)
				{
					CaptureCheckTimer->Enabled = false;
				}
			}
		}
		catch (...)
		{
			CaptureCheckTimer->Enabled = false;
		}
	}
	else
	{
		bool bCaptureAnyExist = false;
		for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
		{
			int spbIndex = CameraMapInfo[globalCameraIndex].SPBIndex;
			int camIndex = CameraMapInfo[globalCameraIndex].CamIndex;
			data[0] = camIndex;

			if (!Comm_IsConnected(spbIndex))
			{
				continue;
			}
			try
			{
				if (!Comm_Request(COMM_SPB + spbIndex, CMD_CAPTURE_EXIST, data, sizeof(unsigned int),
					receivedData, sizeof(unsigned int) * 2))
				{
					throw(0);
				}

				BufferImage->Canvas->Brush->Color = clBlack;
				BufferImage->Canvas->FillRect(Rect(0, 0, BufferImage->Width, BufferImage->Height));
				if (receivedData[0])
				{
					bCaptureExist = true;
					BufferImage->Canvas->Brush->Color = clLime;
					BufferImage->Canvas->FillRect(Rect(0, BufferImage->Height - BufferImage->Height * receivedData[0] / receivedData[1], BufferImage->Width, BufferImage->Height));
				}
				else
				{
					bCaptureExist = false;
				}
				if (bCaptureExist)
				{
					bCaptureAnyExist = true;
					if (!Comm_Request(COMM_SPB + spbIndex, CMD_CAPTURE_UPLOAD, data, 2 * sizeof(unsigned int),
						CaptureData, CaptureWidth * CaptureHeight))
					{
						throw(0);
					}

					if (!cbRAWData->Checked)
					{
            GetNFACamera2DColorImage(DestImage->Picture->Bitmap, CaptureData, CaptureWidth, CaptureHeight, globalCameraIndex, SystemImageOffsetSWCal[globalCameraIndex - 1], SystemOffsetImage[globalCameraIndex - 1],SubSamplingMode);
					}
					else
					{
						for (int y = 0; y < CaptureHeight; y++)
						{
							byte *pBitmap = (byte *)DestImage->Picture->Bitmap->ScanLine[y];
							for (int x = 0; x < CaptureWidth; x++)
							{
								pBitmap[0] = CaptureData[y * CaptureWidth + x];
								pBitmap[1] = CaptureData[y * CaptureWidth + x];
								pBitmap[2] = CaptureData[y * CaptureWidth + x];
								pBitmap += 3;
							}
						}
						DestImage->Repaint();
					}

					if (SaveSpeedButton->Down)
					{
						AnsiString dir = ImageDirectoryListBox->Directory + "\\" + IntToStr(ImageSubDirIndex);
						if (!DirectoryExists(dir))
						{
							ForceDirectories(dir);
							UpdateImageFileList();
						}
						DestImage->Picture->Bitmap->SaveToFile(dir + "\\Image" + IntToStr(CurrentCamImageIndex[globalCameraIndex]) + "_" + IntToStr(globalCameraIndex + 1) + ".bmp");
						CurrentCamImageIndex[globalCameraIndex]++;
						ImageFileListBox->Update();
					}

					unsigned int elapsedTime = GetTickCount() - CaptureStartTime;
					if (elapsedTime > 0)
					{
						lblFPS->Caption = FloatToStr(1000 * 1000 / elapsedTime / 1000.0) + "FPS";
					}
					CaptureStartTime = GetTickCount();
					CaptureCount++;
					elapsedTime = GetTickCount() - CaptureFirstStartTime;
					if (elapsedTime > 0)
					{
						lblAvgFPS->Caption = FloatToStr(1000 * 1000 / elapsedTime * CaptureCount / 1000.0) + "FPS";
					}
					DestImage->Repaint();
					if (shRefresh->Brush->Color == clWhite)
					{
						shRefresh->Brush->Color = clBlack;
					}
					else
					{
						shRefresh->Brush->Color = clWhite;
					}
				}
			}
			catch (...)
			{
				CaptureCheckTimer->Enabled = false;
			}
		}
		if (!bFrameCapture && !bOnCapture && !bCaptureAnyExist)
		{
			CaptureCheckTimer->Enabled = false;
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::ReadMultiModeImage(void)
{
	bool bCaptureExist[4];
	// check capture exists
	char cameraIndex;
	unsigned int data[2];
	unsigned int receivedData[2];

	for (int imageIndex = 0; imageIndex < 4; imageIndex++)
	{
		int globalCameraIndex = MultiImageCameraIndex[imageIndex];
		int spbIndex = CameraMapInfo[globalCameraIndex].SPBIndex;
		int camIndex = CameraMapInfo[globalCameraIndex].CamIndex;
		data[0] = camIndex;
		data[1] = CaptureWidth * CaptureHeight;

		if (!Comm_IsConnected(COMM_SPB + spbIndex))
		{
			if (bFrameCapture)
			{
				MultiImageFrameCaptured[imageIndex] = true;
			}
			else
			{
				bCaptureExist[imageIndex] = false;
			}
			continue;
		}

		try
		{
			if (!Comm_Request(COMM_SPB + spbIndex, CMD_CAPTURE_EXIST, data, sizeof(unsigned int),
				receivedData, sizeof(unsigned int) * 2))
			{
				throw(0);
			}

			BufferImage->Canvas->Brush->Color = clBlack;
			BufferImage->Canvas->FillRect(Rect(0, 0, BufferImage->Width, BufferImage->Height));
			if (receivedData[0])
			{
				bCaptureExist[imageIndex] = true;
				BufferImage->Canvas->Brush->Color = clLime;
				BufferImage->Canvas->FillRect(Rect(0, BufferImage->Height - BufferImage->Height * receivedData[0] / receivedData[1], BufferImage->Width, BufferImage->Height));
			}
			else
			{
				bCaptureExist[imageIndex] = false;
			}
			if (bCaptureExist[imageIndex])
			{
				if (!Comm_Request(COMM_SPB + spbIndex, CMD_CAPTURE_UPLOAD, data, 2 * sizeof(unsigned int),
					CaptureData, CaptureWidth * CaptureHeight))
				{
					throw(0);
				}

				Bayer_Conversion_Merge(MultiImage[imageIndex]->Picture->Bitmap, CaptureData + CaptureWidth, CaptureWidth, CaptureHeight, 2);
				MultiImage[imageIndex]->Repaint();

				if (SaveSpeedButton->Down)
				{
					AnsiString dir = ImageDirectoryListBox->Directory + "\\" + IntToStr(ImageSubDirIndex);
					if (!DirectoryExists(dir))
					{
						ForceDirectories(dir);
						UpdateImageFileList();
					}
					DestImage->Picture->Bitmap->SaveToFile(dir + "\\Image" + IntToStr(CurrentImageIndex) + "_" + IntToStr(globalCameraIndex + 1) + ".bmp");
					CurrentImageIndex++;
					ImageFileListBox->Update();
				}

				unsigned int elapsedTime = GetTickCount() - CaptureStartTime;
				if (elapsedTime > 0)
				{
					lblFPS->Caption = FloatToStr(1000 * 1000 / elapsedTime / 1000.0) + "FPS";
				}
				CaptureStartTime = GetTickCount();
				CaptureCount++;
				elapsedTime = GetTickCount() - CaptureFirstStartTime;
				if (elapsedTime > 0)
				{
					lblAvgFPS->Caption = FloatToStr(1000 * 1000 / elapsedTime * CaptureCount / 1000.0) + "FPS";
				}

				if (shRefresh->Brush->Color == clWhite)
				{
					shRefresh->Brush->Color = clBlack;
				}
				else
				{
					shRefresh->Brush->Color = clWhite;
				}
				if (bFrameCapture)
				{
					MultiImageFrameCaptured[imageIndex] = true;
				}
			}
		}
		catch (...)
		{
			CaptureCheckTimer->Enabled = false;
		}
	}
	if (bFrameCapture)
	{
		bool bCaptureEnd = true;
		for (int imageIndex = 0; imageIndex < 4; imageIndex++)
		{
			if (!MultiImageFrameCaptured[imageIndex])
			{
				bCaptureEnd = false;
			}
		}
		if (bCaptureEnd)
		{
			CaptureCheckTimer->Enabled = false;
		}
	}
	if (!bFrameCapture && !bOnCapture)
	{
		bool bCaptureEnd = true;
		for (int imageIndex = 0; imageIndex < 4; imageIndex++)
		{
			if (bCaptureExist[imageIndex])
			{
				bCaptureEnd = false;
			}
		}
		if (bCaptureEnd)
		{
			CaptureCheckTimer->Enabled = false;
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::CaptureStop(void)
{
	bOnCapture = false;
  CaptureCheckTimer->Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::CaptureStart(bool bFrame, bool bFullCapture,int subSamplingMode)
{
	CaptureStartTime = GetTickCount();
	bFrameCapture = bFrame;
	IsFullCapture = bFullCapture;
  SubSamplingMode = subSamplingMode;
	CaptureCheckTimer->Enabled = true;
	if (!bFrame)
	{
		CaptureFirstStartTime = GetTickCount();
		CaptureCount = 0;
		bOnCapture = true;

		if (SaveSpeedButton->Down)
		{
			ImageSubDirIndex++;
			CurrentImageIndex = 1;
			SubDirEdit->Text = IntToStr(ImageSubDirIndex);
		}
	}
	else
	{
		MultiImageFrameCaptured[0] = false;
		MultiImageFrameCaptured[1] = false;
		MultiImageFrameCaptured[2] = false;
		MultiImageFrameCaptured[3] = false;
	}

	if (IsFullCapture)
	{
		if (SaveSpeedButton->Down)
		{
			for (int globalCameraIndex = 0; globalCameraIndex < MAX_GLOBAL_CAM_COUNT; globalCameraIndex++)
			{
				CurrentCamImageIndex[globalCameraIndex] = 1;
			}
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::SaveImageButtonClick(TObject *Sender)
{
	AnsiString dir = ImageDirectoryListBox->Directory + "\\" + IntToStr(ImageSubDirIndex);
	if (!DirectoryExists(dir))
	{
		ForceDirectories(dir);
		UpdateImageFileList();
	}
	DestImage->Picture->Bitmap->SaveToFile(dir + "\\Image" + IntToStr(CurrentImageIndex) + ".bmp");
	CurrentImageIndex++;
	ImageFileListBox->Update();
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::SetViewMode(bool bSingleView)
{
	IsSingleMode = bSingleView;
}
//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::NewFolderButtonClick(TObject *Sender)
{
	AnsiString Dir = ImageDirectoryListBox->Directory;
	if (SelectDirectory(Dir, TSelectDirOpts() << sdAllowCreate << sdPerformCreate << sdPrompt, 0))
	{
		ImageDirectoryListBox->Directory = Dir;
	}
}
//---------------------------------------------------------------------------

void __fastcall TCaptureFrame::ImageDirectoryListBoxChange(TObject *Sender)
{
	FindFirstSubDir();
}
//---------------------------------------------------------------------------

void __fastcall TCaptureFrame::SubDirEditChange(TObject *Sender)
{
	try
	{
		ImageSubDirIndex = StrToInt(SubDirEdit->Text);
	}
	catch (...)
	{
		ImageSubDirIndex = 0;
	}
	UpdateImageFileList();
}
//---------------------------------------------------------------------------

void __fastcall TCaptureFrame::SetWhiteBalanceValue(int Value, int rgbIndex)
{
  whiteBalance[rgbIndex] = Value;
}

//---------------------------------------------------------------------------
void __fastcall TCaptureFrame::ViewDentedArea()
{
  memset(ThreeDImage, 0, SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT);
  memset(DentedThreeDImage, 0, SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT);

  int x, y;
  int tempAddress, tempAddress2;
  for (y = 1; y < SYSTEM_CAMERA_HEIGHT - 1; y++)
  {
    byte *pBitmap = (byte *)DestImage->Picture->Bitmap->ScanLine[y];

    for (x = 1; x < SYSTEM_CAMERA_WIDTH - 1; x++)
    {
      tempAddress = SYSTEM_CAMERA_WIDTH * y + x;
      ThreeDImage[tempAddress] = pBitmap[x];
    }
  }

  int l, n;
  int startL, endL;
  int lengthTable[10];
  int left;
	int right;
	int up;
	int down;
	int upleft;
	int upright;
	int downleft;
	int downright;
  int length;
  int tempNeighborHeight[4];
  int maxHeight;
  int upValue;
	int downValue;
	int leftValue;
	int rightValue;
	int upleftValue;
	int downrightValue;
	int uprightValue;
	int downleftValue;
  int tempDiff;
  
  lengthTable[0] = 8;
  lengthTable[1] = 13;
  lengthTable[2] = 20;
  lengthTable[3] = 30;
  lengthTable[4] = 45;
  lengthTable[5] = 45;
  lengthTable[6] = 60;

	startL = 1;
	endL = 4;

	for (l = startL; l < endL; l++)
	{
		length = lengthTable[l];
		up = -SYSTEM_CAMERA_WIDTH * length;
		down = SYSTEM_CAMERA_WIDTH * length;
		left = -1 * length;
		right = 1 * length;
		upleft = (-SYSTEM_CAMERA_WIDTH - 1)*length;
		upright = (-SYSTEM_CAMERA_WIDTH + 1)*length;
		downleft = (SYSTEM_CAMERA_WIDTH - 1)*length;
		downright = (SYSTEM_CAMERA_WIDTH + 1)*length;

		for (y = 1; y < SYSTEM_CAMERA_HEIGHT - 1; y++)
		{
			for (x = 1; x < SYSTEM_CAMERA_WIDTH - 1; x++)
			{
				tempAddress = SYSTEM_CAMERA_WIDTH * y + x;

				if (ThreeDImage[tempAddress])
				{
					maxHeight = 0;
					for (n = 0; n < 4; n++)
					{
						tempNeighborHeight[n] = 0;
					}

					tempAddress2 = tempAddress + up;
					if (tempAddress2 > SYSTEM_CAMERA_WIDTH * 4 + 4 && tempAddress2 < SYSTEM_CAMERA_WIDTH * (SYSTEM_CAMERA_HEIGHT - 4) + SYSTEM_CAMERA_WIDTH - 4)
						upValue = *(ThreeDImage + tempAddress + up);
					else
						upValue = 0;

					tempAddress2 = tempAddress + down;
					if (tempAddress2 > SYSTEM_CAMERA_WIDTH * 4 + 4 && tempAddress2 < SYSTEM_CAMERA_WIDTH * (SYSTEM_CAMERA_HEIGHT - 4) + SYSTEM_CAMERA_WIDTH - 4)
						downValue = *(ThreeDImage + tempAddress + down);
					else
						downValue = 0;

					tempAddress2 = tempAddress + left;
					if (tempAddress2 > SYSTEM_CAMERA_WIDTH * 4 + 4 && tempAddress2 < SYSTEM_CAMERA_WIDTH * (SYSTEM_CAMERA_HEIGHT - 4) + SYSTEM_CAMERA_WIDTH - 4)
						leftValue = *(ThreeDImage + tempAddress + left);
					else
						leftValue = 0;

					tempAddress2 = tempAddress + right;
					if (tempAddress2 > SYSTEM_CAMERA_WIDTH * 4 + 4 && tempAddress2 < SYSTEM_CAMERA_WIDTH * (SYSTEM_CAMERA_HEIGHT - 4) + SYSTEM_CAMERA_WIDTH - 4)
						rightValue = *(ThreeDImage + tempAddress + right);
					else
						rightValue = 0;

					tempAddress2 = tempAddress + upleft;
					if (tempAddress2 > SYSTEM_CAMERA_WIDTH * 4 + 4 && tempAddress2 < SYSTEM_CAMERA_WIDTH * (SYSTEM_CAMERA_HEIGHT - 4) + SYSTEM_CAMERA_WIDTH - 4)
						upleftValue = *(ThreeDImage + tempAddress + upleft);
					else
						upleftValue = 0;

					tempAddress2 = tempAddress + downright;
					if (tempAddress2 > SYSTEM_CAMERA_WIDTH * 4 + 4 && tempAddress2 < SYSTEM_CAMERA_WIDTH * (SYSTEM_CAMERA_HEIGHT - 4) + SYSTEM_CAMERA_WIDTH - 4)
						downrightValue = *(ThreeDImage + tempAddress + downright);
					else
						downrightValue = 0;

					tempAddress2 = tempAddress + upright;
					if (tempAddress2 > SYSTEM_CAMERA_WIDTH * 4 + 4 && tempAddress2 < SYSTEM_CAMERA_WIDTH * (SYSTEM_CAMERA_HEIGHT - 4) + SYSTEM_CAMERA_WIDTH - 4)
						uprightValue = *(ThreeDImage + tempAddress + upright);
					else
						uprightValue = 0;

					tempAddress2 = tempAddress + downleft;
					if (tempAddress2 > SYSTEM_CAMERA_WIDTH * 4 + 4 && tempAddress2 < SYSTEM_CAMERA_WIDTH * (SYSTEM_CAMERA_HEIGHT - 4) + SYSTEM_CAMERA_WIDTH - 4)
						downleftValue = *(ThreeDImage + tempAddress + downleft);
					else
						downleftValue = 0;

					if (upValue &&downValue)
					{
						tempNeighborHeight[0] = upValue + downValue;
					}
					if (leftValue && rightValue)
					{
						tempNeighborHeight[1] = leftValue + rightValue;
					}
					if (upleftValue && downrightValue)
					{
						tempNeighborHeight[2] = upleftValue + downrightValue;
					}
					if (uprightValue && downleftValue)
					{
						tempNeighborHeight[3] = uprightValue + downleftValue;
					}
					for (n = 0; n < 4; n++)
					{
						if (tempNeighborHeight[n] / 2 > maxHeight)
						{
							maxHeight = tempNeighborHeight[n] / 2;
						}
					}
          
					if (maxHeight)
					{
						tempDiff = maxHeight - *(ThreeDImage + tempAddress);
						if (tempDiff > 0)
						{
							if (tempDiff > *(DentedThreeDImage + tempAddress))
							{
								*(DentedThreeDImage + tempAddress) = tempDiff;
							}
						}
					}
				}
			}
		}
	}

  for (y = 1; y < SYSTEM_CAMERA_HEIGHT - 1; y++)
  {
    byte *pBitmap = (byte *)DestImage->Picture->Bitmap->ScanLine[y];

    for (x = 1; x < SYSTEM_CAMERA_WIDTH - 1; x++)
    {
      tempAddress = SYSTEM_CAMERA_WIDTH * y + x;

      if(DentedThreeDImage[tempAddress])
      {
        pBitmap[x] = pBitmap[x] / 3;
      }
    }
  }
}
