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
[49972] Re:Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요
장성호 [nasilso] 1139 읽음    2007-07-19 15:53
[ 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 이미지 직사각형 자르기 좀 알려주세요 레이첼시 1518 2007/07/18
49937     Re:이미지 직사각형 자르기 좀 알려주세요 장성호 1453 2007/07/18
49938         Re:Re:이미지 직사각형 자르기 좀 알려주세요 레이첼시 1419 2007/07/18
49942             Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 장성호 1344 2007/07/18
49967                 Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 한충희 1053 2007/07/19
49972                     Re:Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 장성호 1139 2007/07/19
49996                         Re:Re:Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 한충희 1117 2007/07/20
50003                             Re:Re:Re:Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 장성호 1578 2007/07/20
50060                                 Re:Re:Re:Re:Re:Re:Re:Re:이미지 직사각형 자르기 좀 알려주세요 한충희 1172 2007/07/24
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.