|
혹시 서울이세요?
여기 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;
: : }
: : //---------------------------------------------------------------------------
: :
: : 그럼..
: :
: :
: : 한충희 님이 쓰신 글 :
: : : 성호님 정말 죄송합니다 하루 왼종일 바도 모르겠어요
: : : 그냥 가져다 쓰는 것도 말도 안되는거 같구
: : : 정말 죄송하지만 픽셀 나가는 방향을 그림으로 아니면 순서라도
: : : 알려주시면 안될까요???
: : : 귀찮게 해서 죄송합니다
|