C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[50003] Re:Re:Re:Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요
장성호 [nasilso] 1577 읽음    2007-07-20 17:31
혹시 서울이세요?
여기 2호선 디지탈 1단지인데..
와서 밥한끼 쏘면.. 자세히 설명해드리죠 ㅋㅋ
-농담-

님의 질문을 읽고서
사실 무얼 이해 못했는지 제가 이해 못하겠습니다.
그래서 정확하게 꼭 찝어서  설명하기가 참 어렵네요

그래도 설명하면 ...
전체 Pixcel의  Color를 알고있잖아요
색을 두가지로 구분합니다.
배경색과 같은것 , 그리고 그렇지 않는것

[사각형 영역 찾기]
처음부터 죽  scan하다가 어떤 pixcel이 배경색과 다르면?
그 pixcel부터 주변에 연결된 픽셀중에 배경색과 다른 pixcel을 계속 찾아가죠   --> 여기까지는 아시죠?

: :         //  현재 pixcel이 지금까지 찾은  Rect 경계와 비교
: :         if(px->w<rc.left)rc.left=px->w;
: :         else if(px->w>rc.right)rc.right=px->w;
: :         if(px->h<rc.top)rc.top=px->h;
: :         else if(px->h>rc.bottom)rc.bottom=px->h;

이부분이 사각형을 찾는것입니다.
어떤 픽셀부터 주변에 연결된 픽셀중에 배경색과 다른 픽샐이 있으면
그 픽셀이 현재까지의 영역중에서 가장 우측에 있으면 rc.right=px->w; 이렇게 해주죠
현재까지의 영역 (rc) 보다 왼쪽에 있으면 rc.left=px->w;
이런식으로 새로운 pixcel이 현재영역(rc)보다 바깥에 있으면
rc를 그것을 포함한  영역으로 변경하는것입니다.


[전체 검사하기]
원리는 간단합니다.
이미 찾은 영역을 clear해버리는것입니다.                        // 이것이 핵심
그러면 항상 첫번째 아이콘의 영역을 찾는것이죠
더이상 없으면 다 찾은것이구


: :     //bitmap에서 방금 찾은 영역 Rect를 Clear한다.
: :     //그래서 다시 호출할때는 찾아지지 않도록
: :     bmp->Canvas->Pen->Color=bkClr;
: :     bmp->Canvas->Brush->Color=bkClr;
: :     bmp->Canvas->Brush->Style=bsSolid;
: :     bmp->Canvas->Rectangle(rc);


이상입니다.


한충희 님이 쓰신 글 :
: 성호님 제가 능력이 부족해서 이해를 못하고 있습니다
: 제가 소스를 아무리 바도 사각형 위치를 찾는 방법을 도저히 모르겠습니다
: 제가 그림으로 올렷는데요 빨간줄이 읽는 거구 파란줄이 직사각형을 찾는 방법인거 같은데
: 이것이 맞는지요? 맞는 다면 어떻게 사각형 위치를 잡는거죠???
:
:
: 두번째 그림은 마우스로 일정영역을 잡아서 상하 좌우를 검사해서 하는건 성공했는데
: 전체를 검사하는 방법을 몰라서 이렇게 질문이 하게 되겁니다 ㅜ_ㅜ 이건 질문이 아니라 푸념 ㅜ_ㅜ
:
:
:
:
: 장성호 님이 쓰신 글 :
: : [ bmp 파일 포멧에 대해]
: :
: : BMP  파일을 Hex Editer로 열어보면 실제 데이타는
: : 이미지의 맨 끝에 라인부터 파일에 기록되어 있습니다.
: :
: : Graphics::TBitmap  에서  ScanLine을 이용해 Data의 Pointer를 가져오는데
: : 중요한것은
: : ScanLine(0) 에서  Width 만큼 Pointer를 증가하면  ScanLine(1)   이 아니구
: : 실제로는 그 반대로 되어있습니다.
: :
: : 첫번째 줄 ScanLine(0) 에서 다음줄로 가려면 포인터를 Width 만큼  더해주는것이 아니라 빼줘야합니다.
: : 그러니까 ScanLine(1) = ScanLine(0) - Width   이렇게 되죠
: :
: : 다시말하면  맨아랫줄  ScanLine(Height -1 ) 부터 한라인씩 파일에 기록되며
: : 맨끝에 첫번째 라인이 기록됩니다.
: :
: : 보통 bmp파일이 그렇게 되어있구요
: : TBitmap에서도 파일에 있는 순서대로 읽어옵니다.
: :
: :
: : [PixcelFormat 에 대해]
: : 프로그램에 보면 PixcelFormat =  pf32bit  로 했잖아
: :  32bit 는 4Byte 이므로 int * (int형 포인트)로  + , - 하면서 움직이면 한 Pixcel씩 움직이게 되죠
: :
: : 다시말해 ScanLine을 int * 로 받아왔기 때문에
: :  +1 ( 플러스 1 ) 또는 - 1 (마이너스 1 ) 하면 4Byte씩 주소가 움직이는겁니다.
: : Width 만큼 더하거나 빼면  포인터가  4*Width  만큼 움직이겠죠
: :
: :
: : 샘플 코드에 주석이 좀 부족했남?
: :
: : ==========================================================================================
: : //---------------------------------------------------------------------------
: : typedef struct _PIXCEL
: : {
: :     int *pxl;
: :     int w;
: :     int h;
: : }PIXCEL;
: : //---------------------------------------------------------------------------
: : bool __fastcall TForm1::FindIconRect(Graphics::TBitmap *bmp)
: : {
: :     int wid=bmp->Width;
: :     int hei=bmp->Height;
: :
: :     int * pt;
: :     ptLst->Clear();
: :     TRect rc;
: :     for(int h=0;h<hei;h++)
: :     {
: :         pt=(int *)bmp->ScanLine[h];
: :         for(int w=0;w<wid;w++)
: :         {
: :             if(*pt!=bkClr)
: :             {
: :                 AddPixcel(pt,w,h);
: :                 rc.left=w;
: :                 rc.right=w;
: :                 rc.top=h;
: :                 rc.bottom=h;
: :                 h=hei;
: :                 break;
: :             }
: :             pt++;
: :         }
: :     }
: :
: :     if(ptLst->Count<1)return false;
: :
: :     PIXCEL *px;
: :     while(ptLst->Count)  //특정 Pixcel로 부터 그와 연결된 모든 Pixcel을 찾아서 그pixcel들의 상/하/좌/우 가장자리를 찾는다.
: :     {
: :         px=(PIXCEL *)ptLst->Items[0];
: :
: :         //  현재 pixcel이 지금까지 찾은  Rect 경계와 비교
: :         if(px->w<rc.left)rc.left=px->w;
: :         else if(px->w>rc.right)rc.right=px->w;
: :         if(px->h<rc.top)rc.top=px->h;
: :         else if(px->h>rc.bottom)rc.bottom=px->h;
: :
: :
: :         // 현재 Pixcel의 상/하/좌/우/대각선 4 군데서 벼경색 bkClr 과 다른색이 있는지 찾는다.
: :         if(px->w<(wid-1)) //오른쪽
: :         {
: :             pt=px->pxl+1; // 현재 Pixcel의 오른쪽 Pixcel 확인
: :             if(*pt!=bkClr)
: :             {
: :                 AddPixcel(pt,px->w+1,px->h);
: :             }
: :
: :         }
: :         if(px->w > 0) //왼쪽
: :         {
: :             pt=px->pxl-1;  // 현재 Pixcel의 왼쪽 Pixcel 확인
: :             if(*pt!=bkClr)
: :             {
: :                 AddPixcel(pt,px->w-1,px->h);
: :             }
: :         }
: :         if(px->h<(hei-1)) //아랫쪽
: :         {
: :             pt=px->pxl-wid;  // 현재 Pixcel의 한 Line 아랫쪽 Pixcel확인
: :                             // wid 만큼 빼면 Iimage에서 아랫쪽 line이 된다.   ----------- 중요 :
: :             if(*pt!=bkClr)
: :             {
: :                 AddPixcel(pt,px->w,px->h+1);
: :             }
: :             //-----------------
: :             if(px->w<(wid-1)) //아랫쪽 -오른쪽 대각선
: :             {
: :
: :                 pt=px->pxl-wid+1; // 현재 Pixcel의 한 Line 아랫쪽 의 오른쪽   Pixcel확인
: :                 if(*pt!=bkClr)
: :                 {
: :                     AddPixcel(pt,px->w+1,px->h+1);
: :                 }
: :
: :             }
: :             if(px->w > 0) //아랫쪽 -왼쪽 대각선
: :             {
: :                 pt=px->pxl-wid-1; // 현재 Pixcel의 한 Line 아랫쪽 의 왼쪽   Pixcel확인
: :                 if(*pt!=bkClr)
: :                 {
: :                     AddPixcel(pt,px->w-1,px->h+1);
: :                 }
: :             }
: :         }
: :         if(px->h > 0)//윗쪽
: :         {
: :             pt=px->pxl+wid;   // 현재 Pixcel의 한 Line 윗쪽 Pixcel확인
: :             if(*pt!=bkClr)
: :             {
: :                 AddPixcel(pt,px->w,px->h-1);
: :             }
: :             //-----------------
: :             if(px->w<(wid-1)) //윗쪽 -오른쪽 대각선
: :             {
: :
: :                 pt=px->pxl+wid+1;   // 현재 Pixcel의 한 Line 윗쪽 의 오른쪽   Pixcel확인
: :                 if(*pt!=bkClr)
: :                 {
: :                     AddPixcel(pt,px->w+1,px->h-1);
: :                 }
: :
: :             }
: :             if(px->w > 0) //윗쪽 -왼쪽 대각선
: :             {
: :                 pt=px->pxl+wid-1;       // 현재 Pixcel의 한 Line 윗쪽 의 왼쪽   Pixcel확인
: :                 if(*pt!=bkClr)
: :                 {
: :                     AddPixcel(pt,px->w-1,px->h-1);
: :                 }
: :             }
: :         }
: :
: :         px->pxl[0] =bkClr;
: :         ptLst->Delete(0);
: :         delete px;
: :
: :     }
: :
: :     //bitmap에서 방금 찾은 영역 Rect를 Clear한다.
: :     //그래서 다시 호출할때는 찾아지지 않도록
: :     bmp->Canvas->Pen->Color=bkClr;
: :     bmp->Canvas->Brush->Color=bkClr;
: :     bmp->Canvas->Brush->Style=bsSolid;
: :     bmp->Canvas->Rectangle(rc);
: :
: :     String str;
: :     str.sprintf("%d , %d , %d , %d ",rc.left,rc.top,rc.right,rc.bottom); // 찾은 영역 Rect를 StringList에 기록해둔다.
: :     rcLst->Add(str);
: :
: :     return true;
: : }
: : //---------------------------------------------------------------------------
: : // 이미 같은 픽셀이 List에 등록되어잇는지 없는지 확인하구 없으면 추가한다.
: : void __fastcall TForm1::AddPixcel(int *pt,int w,int h)
: : {
: :     PIXCEL *pix;
: :     for(int i=0;i<ptLst->Count;i++)
: :     {
: :         pix=(PIXCEL *)ptLst->Items[i];
: :         if(pix->pxl==pt)return;
: :     }
: :     pix=new PIXCEL;
: :     pix->pxl=pt;
: :     pix->w=w;
: :     pix->h=h;
: :     ptLst->Add(pix);
: : }
: : //---------------------------------------------------------------------------
: : void __fastcall TForm1::Btn_FindIconsClick(TObject *Sender)
: : {
: :     bkClr = ColorBox->Selected ;
: :     rcLst=new TStringList;
: :     ptLst=new TList;
: :     Image1->Picture->Bitmap->PixelFormat=pf32bit;
: :     Graphics::TBitmap *bmp=new Graphics::TBitmap;
: :     bmp->Assign(Image1->Picture->Bitmap);
: : //    int itic=GetTickCount();
: :
: :     while(FindIconRect(bmp));   // 이미지의 Icon영역을 찾는다.
: :
: : //    itic=GetTickCount()-itic;
: : //    ShowMessage(itic);
: :
: :     TStringList *lst=new TStringList;
: :     TRect rc;
: :
: :     Image1->Picture->Bitmap->Canvas->Pen->Color=clRed;
: :     Image1->Picture->Bitmap->Canvas->Brush->Style=bsClear;
: :
: :     for(int i=0;i<rcLst->Count;i++) // 찾응 Icon영역을 TImage에 그려준다.
: :     {
: :         lst->Clear();
: :         lst->CommaText=rcLst->Strings[i];
: :         rc.left=StrToInt(lst->Strings[0]);
: :         rc.top=StrToInt(lst->Strings[1]);
: :         rc.right=StrToInt(lst->Strings[2])+1;
: :         rc.bottom=StrToInt(lst->Strings[3])+1;
: :         Image1->Picture->Bitmap->Canvas->Rectangle(rc);
: :
: :     }
: :     delete lst;
: :     delete bmp;
: :     delete ptLst;
: :     delete rcLst;
: : }
: : //---------------------------------------------------------------------------
: :
: : 그럼..
: :
: :
: : 한충희 님이 쓰신 글 :
: : : 성호님 정말 죄송합니다 하루 왼종일 바도 모르겠어요
: : : 그냥 가져다 쓰는 것도 말도 안되는거 같구
: : : 정말 죄송하지만 픽셀 나가는 방향을 그림으로 아니면 순서라도
: : : 알려주시면 안될까요???
: : : 귀찮게 해서 죄송합니다

+ -

관련 글 리스트
49930 이미지 직사각형 자르기 좀 알려주세요 레이첼시 1517 2007/07/18
49937     Re:이미지 직사각형 자르기 좀 알려주세요 장성호 1452 2007/07/18
49938         Re:Re:이미지 직사각형 자르기 좀 알려주세요 레이첼시 1418 2007/07/18
49942             Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 장성호 1343 2007/07/18
49967                 Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 한충희 1052 2007/07/19
49972                     Re:Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 장성호 1139 2007/07/19
49996                         Re:Re:Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 한충희 1116 2007/07/20
50003                             Re:Re:Re:Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 장성호 1577 2007/07/20
50060                                 Re:Re:Re:Re:Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 한충희 1171 2007/07/24
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.