
#include <vcl.h>
#pragma hdrstop

#include "gui.h"

#include <jpeg.hpp>

#include "..\gui_part.h"

//[2021.03.26.금][추가]
#include "ide_library.h"


//[주의!!!]
//{
    //-------------------------------------------------------
    //Bitmap 처리 함수는 전부 24bit-Bitmap 을 대상으로 한다.
    //-------------------------------------------------------
//}


void __fastcall BMP_Dot(Graphics::TBitmap *pBITMAP,
                        int                pX,
                        int                pY,
                        int                pCOLOR)
{
  //[2006.10.26.목][생성!!!]{--------------------
  //bitmap 의 지정 위치에 지정 색의 점을 찍는다.
  //}--------------------------------------------

  //[VAR]
  //{
      RGBTRIPLE  *lineptr;
  //}

  //그림 영역안에서만 출력이 이루어 져야 한다.
  if(((0 <= pX) && ( pX < pBITMAP->Width)) &&
     ((0 <= pY) && ( pY < pBITMAP->Height)))
  {
    //{-------------------------------------------
    //[행] 의 pointer 를 얻는다.
    lineptr = (RGBTRIPLE *)pBITMAP->ScanLine[pY];
    //}-------------------------------------------

    //시정 색으로 칠한다.
    lineptr[pX].rgbtBlue   = (pCOLOR>>16)&0xff;
    lineptr[pX].rgbtGreen  = (pCOLOR>> 8)&0xff;
    lineptr[pX].rgbtRed    = (pCOLOR>> 0)&0xff;
  }
  
  return;

}

int __fastcall BMP_GetDot(Graphics::TBitmap *pBITMAP,
                          int                pX,
                          int                pY)
{
  //[2010.02.21.일][생성!!!]{-------------------------
  //bitmap 의 지정 위치의 지정색을 추출하여 반환한다.
  //}-------------------------------------------------

  //[VAR]
  //{
      RGBTRIPLE  *lineptr;

  //}

  //그림 영역안에서만 출력이 이루어 져야 한다.
  if(((0 <= pX) && ( pX < pBITMAP->Width)) &&
     ((0 <= pY) && ( pY < pBITMAP->Height)))
  {
    //{-------------------------------------------
    //[행] 의 pointer 를 얻는다.
    lineptr = (RGBTRIPLE *)pBITMAP->ScanLine[pY];
    //}-------------------------------------------

    return(((lineptr[pX].rgbtBlue  << 16) |
            (lineptr[pX].rgbtGreen << 8)  |
            (lineptr[pX].rgbtRed)) &
            0x00ffffff);

  }

  //영역을 벗어난 경우는 [흰색] 을 반환한다.
  return(clWhite);

}

void __fastcall BMP_Paint(Graphics::TBitmap *pBITMAP,
                          int                pCOLOR)
{
  //[2006.09.04.월][생성!!!]{------------------------
  //지정된 bitmap 영역 전체를 지정 [색] 으로 칠한다.
  //}------------------------------------------------

  //[참고]
  //{
      //Canvas->FillRect() 를 사용하는 것보다 속도가 느리다.
      //이는 일일히 점을 찍어서 처리 하기 때문인것 같다.
      //따라서 이 함수는 특별한 용도가 아니라면 사용하지 않는다.
  //}


  //[VAR]
  //{
      int         x, y;

      RGBTRIPLE  *lineptr;
  //}


  for(y = 0; y < pBITMAP->Height; y++)
  {
    //{------------------------------------------
    //[행] 의 pointer 를 얻는다.
    lineptr = (RGBTRIPLE *)pBITMAP->ScanLine[y];
    //}------------------------------------------

    for(x = 0 ; x < pBITMAP->Width; x++)
    {
      //시정 색으로 칠한다.
      lineptr[x].rgbtBlue   = (pCOLOR>>16)&0xff;
      lineptr[x].rgbtGreen  = (pCOLOR>> 8)&0xff;
      lineptr[x].rgbtRed    = (pCOLOR>> 0)&0xff;

    }
  }

  return;

}

void __fastcall BMP_Brightness(Graphics::TBitmap *pBITMAP,
                               int                pBRIGHT)
{
  //[2006.11.02.목][생성!!!]{------------------------------------------
  //전달된 bmp 의 밝기를 조정한다.
  //
  //[2018.08.07.화][수정!!!]-------------------------------------------
  //<pBRIGHT:음수> 인 경우는 [어둡게] 로 2종류로 구분 동작하도록 수정.
  //단, 값의 범위는 <-255:255> 까지.
  //값의 범위를 넘는 경우는 적용하지 않는다.
  //}------------------------------------------------------------------

  //[VAR]
  //{
      RGBTRIPLE  *line_ptr;

      int         x, y;
      
  //}

  //[값 범위 검사]
  //{
      //[2018.08.08.수][추가!!!]{-------------------------------------------
      //{ -255 <= 밝기 <= 255 } 에 해당하지 않는 경우는 적용하지 않고 종료.
      //}-------------------------------------------------------------------

      if(!((-255 <= pBRIGHT) && (pBRIGHT <= 255))) return;

  //}

  for(y = 0; y < pBITMAP->Height; y++)
  {
    //[line_ptr]{---------------------------------
    //[행] 의 pointer 를 얻는다.
    line_ptr = (RGBTRIPLE *)pBITMAP->ScanLine[y];
    //}-------------------------------------------

    for(x = 0; x < pBITMAP->Width; x++)
    {
      if(pBRIGHT >= 0)
      {
        //큰 값일수록 더 밝다.

        //[밝기조정]{------------------------------------------------------------------------------------
        line_ptr[x].rgbtBlue  = line_ptr[x].rgbtBlue  + ((255 - line_ptr[x].rgbtBlue)  * pBRIGHT) / 255;
        line_ptr[x].rgbtGreen = line_ptr[x].rgbtGreen + ((255 - line_ptr[x].rgbtGreen) * pBRIGHT) / 255;
        line_ptr[x].rgbtRed   = line_ptr[x].rgbtRed   + ((255 - line_ptr[x].rgbtRed)   * pBRIGHT) / 255;
        //}----------------------------------------------------------------------------------------------

      }
      else
      {
        //큰 값일수록 더 어둡다.

        //[어둡기조정]{-------------------------------------------------------------------------------
        line_ptr[x].rgbtBlue  = line_ptr[x].rgbtBlue  - ((line_ptr[x].rgbtBlue)  * (-pBRIGHT)) / 255;
        line_ptr[x].rgbtGreen = line_ptr[x].rgbtGreen - ((line_ptr[x].rgbtGreen) * (-pBRIGHT)) / 255;
        line_ptr[x].rgbtRed   = line_ptr[x].rgbtRed   - ((line_ptr[x].rgbtRed)   * (-pBRIGHT)) / 255;
        //}-------------------------------------------------------------------------------------------

      }

    }

  }

}

void __fastcall BMP_Get_Bright_Color(int   pCOLOR,
                                     int   pBRIGHT,
                                     int  *rBRIGHTcolor)
{
  //[2006.12.05.화][생성!!!]{-------------------------------------------------
  //전달된 색을 지정 밝기로 조정하여 다시 색을 반환한다.
  //
  //[2018.08.10.금][수정!!!]**************************************************
  //<BMP_Brightness()> 와 같이 [밝기] 를 [음수(어둡게)] 까지 지원하도록 수정.
  //<pBRIGHT:음수> 인 경우는 [어둡게] 로 2종류로 구분 동작하도록 수정.
  //단, 값의 범위는 <-255:255> 까지.
  //값의 범위를 넘는 경우는 적용하지 않는다.
  //}-------------------------------------------------------------------------

  //[VAR]
  //{
      RGBTRIPLE  pcolor,
                 mcolor;

      int        color;

  //}

  //[값 범위 검사]
  //{
      //[2018.08.08.수][추가!!!]{-------------------------------------------
      //{ -255 <= 밝기 <= 255 } 에 해당하지 않는 경우는 적용하지 않고 종료.
      //}-------------------------------------------------------------------

      if(!((-255 <= pBRIGHT) && (pBRIGHT <= 255))) return;

  //}

  //[색분해]
  //{
      pcolor.rgbtBlue   = (pCOLOR>>16)&0xff;
      pcolor.rgbtGreen  = (pCOLOR>> 8)&0xff;
      pcolor.rgbtRed    = (pCOLOR>> 0)&0xff;
      
  //}

  //[밝기 조정]
  //{
      if(pBRIGHT >= 0)
      {
        //큰 값일수록 더 밝다.

        mcolor.rgbtBlue  = pcolor.rgbtBlue  + ((255 - pcolor.rgbtBlue)  * pBRIGHT) / 255;
        mcolor.rgbtGreen = pcolor.rgbtGreen + ((255 - pcolor.rgbtGreen) * pBRIGHT) / 255;
        mcolor.rgbtRed   = pcolor.rgbtRed   + ((255 - pcolor.rgbtRed)   * pBRIGHT) / 255;

      }
      else
      {
        //큰 값일수록 더 어둡다.

        mcolor.rgbtBlue  = pcolor.rgbtBlue  - ((pcolor.rgbtBlue)  * (-pBRIGHT)) / 255;
        mcolor.rgbtGreen = pcolor.rgbtGreen - ((pcolor.rgbtGreen) * (-pBRIGHT)) / 255;
        mcolor.rgbtRed   = pcolor.rgbtRed   - ((pcolor.rgbtRed)   * (-pBRIGHT)) / 255;

      }

  //}

  //[색합성]
  //{
      color = ((int)(mcolor.rgbtBlue)  << 16) |
              ((int)(mcolor.rgbtGreen) <<  8) |
              ((int)(mcolor.rgbtRed)   <<  0);

  //}

  //[반환]
  //{
      (*rBRIGHTcolor) = color;

  //}

}

int __fastcall Bmp_Color_Enable(int   pColor,
                                bool  pEnable)
{
  //[2018.08.23.목][생성!!!]{---------------------------------------------
  //<pEnable> 에 따라 <pColor> 의 색을 [유/무효] 색으로 변경.
  //[그림부품] 의 [유/무효] 여부에 따라 다른 상태로 그려주기 위하여 필요.
  //
  //<pEnable:true>  : <pColor> 그대로 반환.
  //<pEnable:false> : <pColor> 을 [무효색] 으로 변경하여 반환.
  //}---------------------------------------------------------------------

  if(pEnable == true)
  {
    //[유효] 인 경우는 그대로 반환.
    return(pColor);

  }
  else
  {
    //[무효] 인 경우는 [무효색(밝은색)] 으로 변경해서 반환.
    BMP_Get_Bright_Color(pColor, d_Bright_Disable, &pColor);

    return(pColor);

  }
  
}

void __fastcall BMP_Load(Graphics::TBitmap *pBITMAP,
                         AnsiString         pBMPname,
                         //0인 경우는 무효.
                         int                pSETwidth,
                         //0인 경우는 무효.
                         int                pSETheight,
                         int                pOPTION)
{
  //[2006.11.04.토][생성!!!]{-----------------------------------
  //지정 [설정] 으로 bitmap 을 읽어들인뒤 후처리 까지 수행한다.
  //}-----------------------------------------------------------

  //[VAR]
  //{
      int  width;
      int  height;

      int  x, y;
  //}

  //[bmp load]
  //{
      //그림을 읽어 들인다.
      pBITMAP->LoadFromFile(pBMPname);

      //현 그림의 크기 정보를 얻는다.
      width  = pBITMAP->Width;
      height = pBITMAP->Height;
  //}

  //[지정 크기 적용]
  //{
      //크기가 지정된 경우는 다시 bmp 를 이 크기에 맞춘다.
      //단, 지정 크기가 0 이 경우는 적용하지 않는다.
      if(pSETwidth != 0)  { pBITMAP->Width  = pSETwidth;  }
      if(pSETheight != 0) { pBITMAP->Height = pSETheight; }
  //}

  //[option]
  //{
      //option 에 따른
      switch(pOPTION)
      {
        case  d_BMP_load_left_top :
        {
          //이미 LoadFromFile 로 읽어 들이면서 [왼쪽위] 로 정렬된 상태이다.
          //처리하지 않는다.

        } break;

        case  d_BMP_load_tile :
        {
          //바둑판식으로 배치한다.
          for(y = 0; y < pBITMAP->Height; y += height)
          {
            for(x = 0; x < pBITMAP->Width ; x += width)
            {
              //이미 Load 된 영역의 이미지를 copy 하여 다른 영역에 복사한다.
              BitBlt(//도착지 정보.
                     pBITMAP->Canvas->Handle, x, y, width, height,
                     //소스 정보.
                     pBITMAP->Canvas->Handle, 0, 0,
                     SRCCOPY);

            }

          }

        } break;

      }
  //}

  return;

}

void __fastcall BMP_LoadJpeg(//읽어 들인 Jpeg 그림을 올려 놓을 비트맵.
                             Graphics::TBitmap *pBITMAP,
                             AnsiString         pJpegFileName,
                             //0인 경우는 무효.
                             int                pSETwidth,
                             //0인 경우는 무효.
                             int                pSETheight,
                             int                pOPTION)
{
  //[2007.12.01.토][생성!!!]{-----------------------------------------------------
  //BMP_Load() 함수를 참고하여 bmp 가 아니라 jpeg 를 읽어 들여
  //지정 [비트맵] 공간에 올려 주는 함수로 개조 하였다.
  //이는 [비트맵] 의 경우는 포토샵등으로 편집하고 저장한 경우 BCB 에서 읽어들일때
  //오류가 발생하는 경우가 있기 때문이다.
  //}-----------------------------------------------------------------------------

  //[VAR]
  //{
      int  width;
      int  height;

      int  x, y;

      //[2007.12.01.토][추가!!!]
      //읽어 들일 jpeg 그림공간을 만든다.
      TJPEGImage *jpegFile = new TJPEGImage();

  //}

  //[Jpeg 그림 읽기]
  //{
      //지정한 jpeg 그림을 읽어 들인다.
      jpegFile->LoadFromFile(pJpegFileName);

      //jpeg 그림을 [비트맵] 으로 변환한다.
      pBITMAP->Assign(jpegFile);

      //생성된 jpeg 객체를 삭제한다.
      if(jpegFile != NULL) { delete jpegFile; jpegFile = NULL; }

      //현 그림의 크기 정보를 얻는다.
      width  = pBITMAP->Width;
      height = pBITMAP->Height;

  //}

  //[지정 크기 적용]
  //{
      //크기가 지정된 경우는 다시 bmp 를 이 크기에 맞춘다.
      //단, 지정 크기가 0 이 경우는 적용하지 않는다.
      if(pSETwidth != 0)  { pBITMAP->Width  = pSETwidth;  }
      if(pSETheight != 0) { pBITMAP->Height = pSETheight; }

  //}

  //[option]
  //{
      //option 에 따른
      switch(pOPTION)
      {
        case  d_BMP_load_left_top :
        {
          //이미 LoadFromFile 로 읽어 들이면서 [왼쪽위] 로 정렬된 상태이다.
          //처리하지 않는다.

        } break;

        case  d_BMP_load_tile :
        {
          //바둑판식으로 배치한다.
          for(y = 0; y < pBITMAP->Height; y += height)
          {
            for(x = 0; x < pBITMAP->Width ; x += width)
            {
              //이미 Load 된 영역의 이미지를 copy 하여 다른 영역에 복사한다.
              BitBlt(//도착지 정보.
                     pBITMAP->Canvas->Handle, x, y, width, height,
                     //소스 정보.
                     pBITMAP->Canvas->Handle, 0, 0,
                     SRCCOPY);

            }

          }

        } break;

      }

  //}

}

void __fastcall BMP_Copy_Transparent(//원본 정보.
                                     Graphics::TBitmap *pBMPsrc,
                                     int                pXsrc,
                                     int                pYsrc,
                                     int                pWIDTHsrc,
                                     int                pHEIGHTsrc,
                                     //도착지 정보.
                                     Graphics::TBitmap *pBMPdst,
                                     int                pXdst,
                                     int                pYdst,
                                     int                pWIDTHdst,
                                     int                pHEIGHTdst,
                                     //투명색을 적용할 색.
                                     int                pTRANSPARENTcolor)
{
  //[2006.11.16.목][생성!!!]{-------------------------
  //비트맵을 복사하되, 도착지의 영역 정보를 참고하고,
  //투명색으로 지정한 색은 복사하지 않는다.
  //}-------------------------------------------------

  //[VAR]
  //{
      DWORD    copy_option = SRCCOPY;
  //}

  //[VAR]
  //{
      int         x_src, y_src,
                  x_dst, y_dst;

      RGBTRIPLE  *lineptr_src,
                 *lineptr_dst;

      int         color;
  //}

  //[그림 복사]
  //{
      for(y_src = pYsrc, y_dst = pYdst;
          //영역을 넘어 에러가 발생하지 않게한다.
          ((pYsrc <= y_src) && (y_src < (pYsrc + pHEIGHTsrc))) &&
          ((pYdst <= y_dst) && (y_dst < (pYdst + pHEIGHTdst))) &&
          ((0 <= y_dst)     && (y_dst < pBMPdst->Height));
          y_src++, y_dst++)
      {
        //[행 핸들 얻기]{------------------------------------
        //[행] 의 pointer 를 얻는다.
        lineptr_src = (RGBTRIPLE *)pBMPsrc->ScanLine[y_src];
        lineptr_dst = (RGBTRIPLE *)pBMPdst->ScanLine[y_dst];
        //}--------------------------------------------------

        for(x_src = pXsrc, x_dst = pXdst;
            //영역을 넘어 에러가 발생하지 않게한다.
            ((pXsrc <= x_src) && (x_src < (pXsrc + pWIDTHsrc))) &&
            ((pXdst <= x_dst) && (x_dst < (pXdst + pWIDTHdst))) &&
            ((0 <= x_dst)     && (x_dst < pBMPdst->Width));
            x_src++, x_dst++)
        {
          //[color]
          //{
              color = ((int)(lineptr_src[x_src].rgbtBlue)  << 16) |
                      ((int)(lineptr_src[x_src].rgbtGreen) <<  8) |
                      ((int)(lineptr_src[x_src].rgbtRed)   <<  0);
          //}

          //[투명색 검사]
          //{
              //현재 색이 투명 지정색인지 검사한다.
              if(color == pTRANSPARENTcolor)
              {
                //투명색은 복사하지 않는다.

              }
              else
              {
                //투명색으로 지정하지 않는 색만 복사한다.
                lineptr_dst[x_dst].rgbtBlue  = (color >> 16) & 0xff;
                lineptr_dst[x_dst].rgbtGreen = (color >>  8) & 0xff;
                lineptr_dst[x_dst].rgbtRed   = (color >>  0) & 0xff;

              }
          //}

        }

      }
  //}

  return;

}

void __fastcall BMP_OneColor_CopyAndChange(//원본 정보.
                                           Graphics::TBitmap *pBMPsrc,
                                           int                pXsrc,
                                           int                pYsrc,
                                           int                pWIDTHsrc,
                                           int                pHEIGHTsrc,
                                           //도착지 정보.
                                           Graphics::TBitmap *pBMPdst,
                                           int                pXdst,
                                           int                pYdst,
                                           int                pWIDTHdst,
                                           int                pHEIGHTdst,
                                           //복사하고 바꿀 대상색.
                                           int                pThisColor,
                                           //바꿀 색.
                                           int                pChangeColor)
{
  //[2007.12.20.목][생성!!!]{----------------------------------------------
  //비트맵을 복사하되, 도착지의 영역 정보를 참고하고,
  //특정색만 복사하되 지정색으로 바꾸는 것도 동시에 수행한다.
  //
  //[2012.07.14.토][수정!!!]-----------------------------------------------
  //<pXdst>, <pXdst> 가 [음수] 인 경우 기존에는 아예 처리가 안되던것 수정.
  //}----------------------------------------------------------------------

  //[VAR]
  //{
      DWORD    copy_option = SRCCOPY;
  //}

  //[VAR]
  //{
      int         x_src, y_src,
                  x_dst, y_dst;

      RGBTRIPLE  *lineptr_src,
                 *lineptr_dst;

      int         color;
  //}

  //[그림 복사]
  //{
      //[도착지가 음수인 경우 처리]
      //{
          //[2012.07.14.토][추가!!!]{--------------------------------------------
          //[도착지] 가 [음수] 영역인 경우 기존 <for()> 문에서는
          //[유효영역] 이 아니라 아예 아무것도 처리하지 않게 된다.
          //따라서, [음수영역] 을 제외한 [유효영역] 만 남겨지도록 수정후 사용.
          //즉, [음수] 영역부분 만큼 [원본] 의 복사 영역을 지나치는 방법을 사용.
          //}--------------------------------------------------------------------

          if(pXdst < 0) { pXsrc -= pXdst; pWIDTHsrc  += pXdst; pXdst = 0; }
          if(pYdst < 0) { pYsrc -= pYdst; pHEIGHTdst += pYdst; pYdst = 0; }

      //}

      for(y_src = pYsrc, y_dst = pYdst;
          //영역을 넘어 에러가 발생하지 않게한다.
          ((pYsrc <= y_src) && (y_src < (pYsrc + pHEIGHTsrc))) &&
          ((pYdst <= y_dst) && (y_dst < (pYdst + pHEIGHTdst))) &&
          ((0 <= y_dst)     && (y_dst < pBMPdst->Height));
          y_src++, y_dst++)
      {
        //[행 핸들 얻기]{------------------------------------
        //[행] 의 pointer 를 얻는다.
        lineptr_src = (RGBTRIPLE *)pBMPsrc->ScanLine[y_src];
        lineptr_dst = (RGBTRIPLE *)pBMPdst->ScanLine[y_dst];
        //}--------------------------------------------------

        for(x_src = pXsrc, x_dst = pXdst;
            //영역을 넘어 에러가 발생하지 않게한다.
            ((pXsrc <= x_src) && (x_src < (pXsrc + pWIDTHsrc))) &&
            ((pXdst <= x_dst) && (x_dst < (pXdst + pWIDTHdst))) &&
            ((0 <= x_dst)     && (x_dst < pBMPdst->Width));
            x_src++, x_dst++)
        {
          //[color]
          //{
              color = ((int)(lineptr_src[x_src].rgbtBlue)  << 16) |
                      ((int)(lineptr_src[x_src].rgbtGreen) <<  8) |
                      ((int)(lineptr_src[x_src].rgbtRed)   <<  0);
          //}

          //[지정색 검사]
          //{
              //현재 색이 투명 지정색인지 검사한다.
              if(color == pThisColor)
              {
                //지정색인 경우는 바꿀색으로 바꾸어 복사한다.
                color = pChangeColor;

                lineptr_dst[x_dst].rgbtBlue  = (color >> 16) & 0xff;
                lineptr_dst[x_dst].rgbtGreen = (color >>  8) & 0xff;
                lineptr_dst[x_dst].rgbtRed   = (color >>  0) & 0xff;

              }
              else
              {
                //지정색이 아닌 경우는 복사하지 않는다.

              }

          //}

        }

      }

  //}

  return;

}

/*
void __fastcall BMP_OneColor_CopyAndChange(//원본 정보.
                                           Graphics::TBitmap *pBMPsrc,
                                           int                pXsrc,
                                           int                pYsrc,
                                           int                pWIDTHsrc,
                                           int                pHEIGHTsrc,
                                           //도착지 정보.
                                           Graphics::TBitmap *pBMPdst,
                                           int                pXdst,
                                           int                pYdst,
                                           int                pWIDTHdst,
                                           int                pHEIGHTdst,
                                           //복사하고 바꿀 대상색.
                                           int                pThisColor,
                                           //바꿀 색.
                                           int                pChangeColor)
{
  //[2007.12.20.목][생성!!!]{---------------------------------
  //비트맵을 복사하되, 도착지의 영역 정보를 참고하고,
  //특정색만 복사하되 지정색으로 바꾸는 것도 동시에 수행한다.
  //}---------------------------------------------------------

  //[VAR]
  //{
      DWORD    copy_option = SRCCOPY;
  //}

  //[VAR]
  //{
      int         x_src, y_src,
                  x_dst, y_dst;

      RGBTRIPLE  *lineptr_src,
                 *lineptr_dst;

      int         color;
  //}

  //[그림 복사]
  //{
      if(pYdst < 0) { pYdst = 0; pYsrc -= pYdst; pWIDTHsrc += pYdst; }

      for(y_src = pYsrc, y_dst = pYdst;
          //영역을 넘어 에러가 발생하지 않게한다.
          ((pYsrc <= y_src) && (y_src < (pYsrc + pHEIGHTsrc))) &&
          ((pYdst <= y_dst) && (y_dst < (pYdst + pHEIGHTdst))) &&
          ((0 <= y_dst)     && (y_dst < pBMPdst->Height));
          y_src++, y_dst++)
      {
        //[행 핸들 얻기]{------------------------------------
        //[행] 의 pointer 를 얻는다.
        lineptr_src = (RGBTRIPLE *)pBMPsrc->ScanLine[y_src];
        lineptr_dst = (RGBTRIPLE *)pBMPdst->ScanLine[y_dst];
        //}--------------------------------------------------

        for(x_src = pXsrc, x_dst = pXdst;
            //영역을 넘어 에러가 발생하지 않게한다.
            ((pXsrc <= x_src) && (x_src < (pXsrc + pWIDTHsrc))) &&
            ((pXdst <= x_dst) && (x_dst < (pXdst + pWIDTHdst))) &&
            ((0 <= x_dst)     && (x_dst < pBMPdst->Width));
            x_src++, x_dst++)
        {
          //[color]
          //{
              color = ((int)(lineptr_src[x_src].rgbtBlue)  << 16) |
                      ((int)(lineptr_src[x_src].rgbtGreen) <<  8) |
                      ((int)(lineptr_src[x_src].rgbtRed)   <<  0);
          //}

          //[지정색 검사]
          //{
              //현재 색이 투명 지정색인지 검사한다.
              if(color == pThisColor)
              {
                //지정색인 경우는 바꿀색으로 바꾸어 복사한다.
                color = pChangeColor;

                lineptr_dst[x_dst].rgbtBlue  = (color >> 16) & 0xff;
                lineptr_dst[x_dst].rgbtGreen = (color >>  8) & 0xff;
                lineptr_dst[x_dst].rgbtRed   = (color >>  0) & 0xff;

              }
              else
              {
                //지정색이 아닌 경우는 복사하지 않는다.

              }

          //}

        }

      }

  //}

  return;

}
*/

void __fastcall BMP_Copy_ChangeColor(//원본 정보.
                                     Graphics::TBitmap *pBMPsrc,
                                     int                pXsrc,
                                     int                pYsrc,
                                     int                pWIDTHsrc,
                                     int                pHEIGHTsrc,
                                     //도착지 정보.
                                     Graphics::TBitmap *pBMPdst,
                                     int                pXdst,
                                     int                pYdst,
                                     int                pWIDTHdst,
                                     int                pHEIGHTdst,
                                     //변환 대상이되는 색.
                                     int                pORGINcolor,
                                     //변환할 색.
                                     int                pCHANGEcolor)
{
  //[2006.11.09.목][생성!!!]{-------------------------
  //비트맵을 복사하되, 도착지의 영역 정보를 참고하고,
  //반전복사를 할수 있도록한다.
  //복사 하면서 특정색을 지정색으로 변환한다.
  //}-------------------------------------------------

  //[VAR]
  //{
      int         x_src, y_src,
                  x_dst, y_dst;

      RGBTRIPLE  *lineptr_src,
                 *lineptr_dst;

      int         color;
  //}

  //[그림 복사]
  //{
      for(y_src = pYsrc, y_dst = pYdst;
          //영역을 넘어 에러가 발생하지 않게한다.
          ((pYsrc <= y_src) && (y_src < (pYsrc + pHEIGHTsrc))) &&
          ((pYdst <= y_dst) && (y_dst < (pYdst + pHEIGHTdst))) &&
          ((0 <= y_dst)     && (y_dst < pBMPdst->Height));
          y_src++, y_dst++)
      {
        //[행 핸들 얻기]{------------------------------------
        //[행] 의 pointer 를 얻는다.
        lineptr_src = (RGBTRIPLE *)pBMPsrc->ScanLine[y_src];
        lineptr_dst = (RGBTRIPLE *)pBMPdst->ScanLine[y_dst];
        //}--------------------------------------------------

        for(x_src = pXsrc, x_dst = pXdst;
            //영역을 넘어 에러가 발생하지 않게한다.
            ((pXsrc <= x_src) && (x_src < (pXsrc + pWIDTHsrc))) &&
            ((pXdst <= x_dst) && (x_dst < (pXdst + pWIDTHdst))) &&
            ((0 <= x_dst)     && (x_dst < pBMPdst->Width));
            x_src++, x_dst++)
        {
          //[color]
          //{
              color = ((int)(lineptr_src[x_src].rgbtBlue)  << 16) |
                      ((int)(lineptr_src[x_src].rgbtGreen) <<  8) |
                      ((int)(lineptr_src[x_src].rgbtRed)   <<  0);
          //}

          //[변환색 검사]
          //{
              //현재 색이 변환 대상이 되는 색인지 검사한다.
              if(color == pORGINcolor)
              {
                //색을 변환할 색으로 바꾼다.
                color = pCHANGEcolor;

              }
          //}

          //[색 복사]
          //{
              lineptr_dst[x_dst].rgbtBlue  = (color >> 16) & 0xff;
              lineptr_dst[x_dst].rgbtGreen = (color >>  8) & 0xff;
              lineptr_dst[x_dst].rgbtRed   = (color >>  0) & 0xff;
          //}
        }
      }
  //}

  return;

}

void __fastcall BMP_Self_ChangeColor2(Graphics::TBitmap *pBITMAP,
                                     int                 pFcolor,
                                     int                 pFCcolor,
                                     int                 pBcolor,
                                     int                 pBCcolor)
{
  //[2006.11.12.일][생성!!!]{---------------------------------------
  //전달받은 bipmap 의 지정색 2 가지를 각각 변환 지정색으로 바꾼다.
  //}---------------------------------------------------------------

  //[VAR]
  //{
      int         x, y;

      RGBTRIPLE  *lineptr;

      int         color;
  //}

  //[그림 복사]
  //{
      for(y = 0;
          //영역을 넘어 에러가 발생하지 않게한다.
          (0 <= y) && (y < pBITMAP->Height);
          y++)
      {
        //[행 핸들 얻기]{----------------------------
        //[행] 의 pointer 를 얻는다.
        lineptr = (RGBTRIPLE *)pBITMAP->ScanLine[y];
        //}------------------------------------------

        for(x = 0;
            //영역을 넘어 에러가 발생하지 않게한다.
            (0 <= x) && (x < pBITMAP->Width);
            x++)
        {
          //[색 추출]
          //{
              color = ((int)(lineptr[x].rgbtBlue)  << 16) |
                      ((int)(lineptr[x].rgbtGreen) <<  8) |
                      ((int)(lineptr[x].rgbtRed)   <<  0);
          //}

          //[색 구분]
          //{
              if     (color == pFcolor)
              {
                //해당 지정색으로 바꾼다.
                color = pFCcolor;

              }
              else if(color == pBcolor)
              {
                //해당 지정색으로 바꾼다.
                color = pBCcolor;

              }
          //}

          //[다시 색 기록]
          //{
              lineptr[x].rgbtBlue  = (color >> 16) & 0xff;
              lineptr[x].rgbtGreen = (color >>  8) & 0xff;
              lineptr[x].rgbtRed   = (color >>  0) & 0xff;
          //}
        }
      }
  //}

  return;

}

void __fastcall Bmp_Area_ChangeColor_2(Graphics::TBitmap *pBmp,
                                       //[영역정보]----------------
                                       int                pX,
                                       int                pY,
                                       int                pWidth,
                                       int                pHeight,
                                       //[변환색지정]--------------
                                       int                pClrOrg1,
                                       int                pClrChg1,
                                       int                pClrOrg2,
                                       int                pClrChg2)
{
  //[2011.06.29.수][생성!!!]{-----------------------------------
  //지정된 BMP 의 지정 영역을 두가지 지정색각각으로 변경해준다.
  //}-----------------------------------------------------------

  //[VAR]
  //{
      int         x, y;

      RGBTRIPLE  *lineptr;

      int         color;
  //}

  //[그림 복사]
  //{
      for(y = pY;
          //영역을 넘어 에러가 발생하지 않게한다.
          (pY <= y) && (y < (pY + pHeight));
          y++)
      {
        //[행 핸들 얻기]{-------------------------
        //[행] 의 pointer 를 얻는다.
        lineptr = (RGBTRIPLE *)pBmp->ScanLine[y];
        //}---------------------------------------

        for(x = pX;
            //영역을 넘어 에러가 발생하지 않게한다.
            (pX <= x) && (x < (pX + pWidth));
            x++)
        {
          //[색 추출]
          //{
              color = ((int)(lineptr[x].rgbtBlue)  << 16) |
                      ((int)(lineptr[x].rgbtGreen) <<  8) |
                      ((int)(lineptr[x].rgbtRed)   <<  0);
          //}

          //[색 구분]
          //{
              if     (color == pClrOrg1)
              {
                //해당 지정색으로 바꾼다.
                color = pClrChg1;

              }
              else if(color == pClrOrg2)
              {
                //해당 지정색으로 바꾼다.
                color = pClrChg2;

              }
          //}

          //[다시 색 기록]
          //{
              lineptr[x].rgbtBlue  = (color >> 16) & 0xff;
              lineptr[x].rgbtGreen = (color >>  8) & 0xff;
              lineptr[x].rgbtRed   = (color >>  0) & 0xff;
          //}
        }
      }
  //}

  return;

}

void __fastcall _Bmp_Create_And_Load(Graphics::TBitmap **pBmp,
                                     AnsiString          pBmpFileName)
{
  //[2011.06.25.토][생성!!!]{------------------------------------------
  //<bmp> 를 생성하고 지정 경로의 그림을 읽어들인다.
  //여기서 <bmp> 를 생성하므로 **포인터로 전달 받아서 처리해야 한다.
  //
  //이 함수는 <editor_edit.cpp:_DbgView_Shape()> 함수를 위하여 만든다.
  //}------------------------------------------------------------------

  //실제 그림 영역을 생성한다.
  (*pBmp) = new Graphics::TBitmap;

  //그림 읽어 들이기.
  (*pBmp)->LoadFromFile(pBmpFileName);

  //24bit bitmap 으로 지정.
  (*pBmp)->PixelFormat = pf24bit;

}

bool __fastcall Bmp_Get_Size(char          *pPathNameExt,
                             unsigned int  *rWidth,
                             unsigned int  *rHeight)
{
  //[2021.03.26.금][생성]{---------------------
  //<bmp> 문서의 [폭/높이] 정보를 구해서 반환.
  //}------------------------------------------

  //[VAR]
  //{
      Graphics::TBitmap  *_bmp_;

      char  ext[1024];

  //}

  //[존재 확인]
  //{
      if(FileExists(pPathNameExt) != true) return(false);

  //}

  //[BMP 인가?]
  //{
      STR_GetFileExt(pPathNameExt, ext);

      //<bmp> 가 아니라면 더이상 처리하지 않고 종료.
      if(STR_Match_NoCase(ext, "bmp") != true) return(false);

  //}

  //[생성]
  //{
      _bmp_ = new Graphics::TBitmap;

      //24bit bitmap 으로 지정.
      _bmp_->PixelFormat = pf24bit;

  //}

  //[그림문서 열기]
  //{
      //[2021.05.23.일][수정]{---
      //<try ...catch> 추가.
      //}------------------------

      try
      {
        _bmp_->LoadFromFile(pPathNameExt);

      }
      catch(...)
      {
        //[!]{--------------------------------------------------------
        //확장자는 <bmp> 인데, 실제 그림은 <bmp> 가 아닌 경우에 해당.
        //이 경우는 위에서 열때 오류가 발생한다.
        //}-----------------------------------------------------------

        delete  _bmp_;

        return(false);

      }

  //}

  //[크기 정보 반환]
  //{
      if(rWidth  != NULL) { (*rWidth)  = _bmp_->Width;  }

      if(rHeight != NULL) { (*rHeight) = _bmp_->Height; }

  //}

  //[삭제]
  //{
      delete  _bmp_;

  //}

  return(true);

}

bool __fastcall Jpg_Get_Size(char          *pPathNameExt,
                             unsigned int  *rWidth,
                             unsigned int  *rHeight)
{
  //[2021.03.26.금][생성]{---------------------
  //<jpg> 문서의 [폭/높이] 정보를 구해서 반환.
  //}------------------------------------------
  
  //[VAR]
  //{
      TJPEGImage  *jpgFile; 

      char  ext[1024];

  //}

  //[존재 확인]
  //{
      if(FileExists(pPathNameExt) != true) return(false);

  //}

  //[JPG/JPEG 인가?]
  //{
      STR_GetFileExt(pPathNameExt, ext);

      //<jpg/jpeg> 가 아니라면 더이상 처리하지 않고 종료.
      if(!((STR_Match_NoCase(ext, "jpg") == true) || (STR_Match_NoCase(ext, "jpeg") == true))) return(false);

  //}

  //[생성]
  //{
      jpgFile = new TJPEGImage();

  //}

  //[그림문서 열기]
  //{
      //[2021.05.23.일][수정]{---
      //<try ...catch> 추가.
      //}------------------------

      try
      {
        jpgFile->LoadFromFile(pPathNameExt);

      }
      catch(...)
      {
        //[!]{--------------------------------------------------------
        //확장자는 <bmp> 인데, 실제 그림은 <bmp> 가 아닌 경우에 해당.
        //이 경우는 위에서 열때 오류가 발생한다.
        //}-----------------------------------------------------------

        delete  jpgFile;

        return(false);

      }

  //}
                                   
  //[크기 정보 반환]
  //{
      if(rWidth  != NULL) { (*rWidth)  = jpgFile->Width;  }

      if(rHeight != NULL) { (*rHeight) = jpgFile->Height; }

  //}

  //[삭제]
  //{
      delete  jpgFile;

  //}

  return(true);

}

bool __fastcall Image_Get_Size(char          *pPathNameExt,
                               unsigned int  *rWidth,
                               unsigned int  *rHeight)
{
  //[2021.03.29.월][생성]{------------------------------
  //<bmp/jpg/jpeg> 문서의 [폭/높이] 정보를 구해서 반환.
  //해당하지 않는 문서의 경우는 <false> 반환.
  //}---------------------------------------------------
  
  //[VAR]
  //{
      char  ext[1024];

  //}

  //[존재 확인]
  //{
      if(FileExists(pPathNameExt) != true) return(false);

  //}

  //[종류 구분 처리]
  //{
      //[확장자] 얻기.
      STR_GetFileExt(pPathNameExt, ext);

      if     (STR_Match_NoCase(ext, "bmp") == true)
      {
        return(Bmp_Get_Size(pPathNameExt, rWidth, rHeight));

      }
      else if((STR_Match_NoCase(ext, "jpg") == true) || (STR_Match_NoCase(ext, "jpeg") == true))
      {
        return(Jpg_Get_Size(pPathNameExt, rWidth, rHeight));

      }
      else
      {
        return(false);

      }

  //}

}

void __fastcall Bmp_Stretch(Graphics::TBitmap  *pBmp,
                            unsigned int        pWidth,
                            unsigned int        pHeight)
{
  //[2021.04.06.화][생성]{----------------------------------------------------------
  //<pBmp> 를 <pWidth, pHeight> 의 크기로 [축소/확장] 시킨다.
  //원본과 다른 [가로/세로비] 를 사용하여 [세로/가로] 로 잡아 늘릴수도 있다.
  //
  //[축소] 의 경우는 이미지 손상이 없으나, [확대] 의 경우는 [계단현상] 이 발생한다.
  //
  //<GImageBox> 를 제작하면서 필요해서 만든다.
  //}-------------------------------------------------------------------------------

  //[VAR]
  //{
      Graphics::TBitmap  *tempBmp;

      TRect               reSize;

  //}

  //[생성]
  //{
      tempBmp              = new Graphics::TBitmap;

      tempBmp->PixelFormat = pf24bit;

      tempBmp->Width       = pWidth;

      tempBmp->Height      = pHeight;

  //}

  //[크기 설정]
  //{
      reSize.Top    = 0;
      reSize.Left   = 0;
      reSize.Right  = pWidth;
      reSize.Bottom = pHeight;

  //}

  //[그림 변형]
  //{
      //<pBmp> 를 <크기:reSize> 로 늘리거나 줄여서 <tempBmp> 에 복사.
      tempBmp->Canvas->StretchDraw(reSize, pBmp);

  //}

  //[크기 변경]
  //{
      //늘거나 줄어든 그림을 모두 담기 위하여 해당 크기로 변경.
      pBmp->Width  = pWidth;
      pBmp->Height = pHeight;

  //}

  //[그림 복사]
  //{
      //<tempBmp> 에 있는 변경된 그림을 다시 <pBmp> 에 복사.
      pBmp->Canvas->CopyRect(reSize, tempBmp->Canvas, reSize);

  //}

  //[삭제]
  //{
      delete tempBmp;

  //}

}




