300번째 글 기념(응?)
완전 날로먹는 Bitmap 구조 분석하기 입니다 ^^;
Visual Studio C++ 6.0 프로젝트이며, 헤더만 있다면 다른 플랫폼도 이식 가능할 듯 합니다.


알림 : 네이버 블로그 / 구차니의 잡동사니 모음에서 같은 거 있는데! 라고 하시면..
        동일 인물입니다라고 밖에 답변을 해드릴게 없습니다 -ㅁ-!

typedef struct tagBITMAPFILEHEADER
{
  WORD  bfType;
  DWORD bfSize;
  WORD  bfReserved1;
  WORD  bfReserved2;
  DWORD bfOffBits;
} BITMAPFILEHEADER,  *PBITMAPFILEHEADER;
WORD bfType;          // 위의 첫 바이트 BM 으로 Bitmap 이라는 의미를 지닌 헤더
DWORD bfSize;         // 0x00075736 = 481078 bytes, 파일 전체 크기(헤더 포함한 전체 파일)
WORD bfReserved1;  // 0x0000 으로 사용하지 않는 부분
WORD bfReserved2;  // 0x0000 으로 사용하지 않는 부분
DWORD bfOffBits;      // 현재 위치로부터 실제 데이터가 존재하는 곳 까지의 거리

bfOffBits는 약간의 설명이 필요하다. 일단 256색상 이하의 비트맵은 indexed color 방식으로
팔레트를 이용하게 된다. 팔레트 이후에는 1pixel = 1byte로 연결된 인덱스들이 나열되어 있다.
그런 이유로, 팔레트에 저장된 색상의 갯수가 다르거나, 팔레트를 사용하지 않는다면 이 값은 상당히 다른 값을 보이게 된다.
자세한 내용은 아래의 팔레트를 참고하면 된다.

typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[1]; } BITMAPINFO, *PBITMAPINFO;
256 색 이하의 이미지라면, RGBQUAD는 팔레트로 사용되고,
16bit 이상의 이미지라면 이 내용에 바로 pixel별 색상이 들어간다.

typedef struct tagBITMAPINFOHEADER
{
  DWORD biSize;
  LONG  biWidth;
  LONG  biHeight;
  WORD  biPlanes;
  WORD  biBitCount;
  DWORD biCompression;
  DWORD biSizeImage;
  LONG  biXPelsPerMeter;
  LONG  biYPelsPerMeter;
  DWORD biClrUsed;
  DWORD biClrImportant;
} BITMAPINFOHEADER,  *PBITMAPINFOHEADER;
DWORD biSize;                      // BITMAPINFO 헤더의 크기
LONG  biWidth;                      // 이미지의 넓이(화면상에 보이는 크기)
LONG  biHeight;                     // 이미지의 높이(화면상에 보이는 크기)
WORD  biPlanes;                    // 이미지의 장수(bitmap은 layer가 존재하지 않으므로 항상 1)
WORD  biBitCount;                  // 한 픽셀의 컬러 비트수(256컬러는 2^8 이므로 8이 표기됨)
DWORD biCompression;          // 비트맵이 압축이 되었는지 어떠한 방식으로 압축이 되었는지 표시
DWORD biSizeImage;
LONG  biXPelsPerMeter;
LONG  biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;

typedef struct tagRGBQUAD
{
  BYTE rgbBlue;
  BYTE rgbGreen;
  BYTE rgbRed;
  BYTE rgbReserved;
} RGBQUAD;

BYTE rgbBlue;            // RGB 중 파랑(Blue)에 대한 값
BYTE rgbGreen;          // RGB 중 녹색(Green)에 대한 값
BYTE rgbRed;             // RGB 중 빨강(Red)에 대한 값
BYTE rgbReserved;     // 사용하지 않음

---------------------------------------------------------------------------------------------------
1.
bitmap은 단순하게, 하나의 pixel에 대한 RGB 정보나 index 정보를 이용하여 이미지를 표시한다.
pixelPicture Element의 약자이며, 우리가 말하는 점 하나를 의미한다.

2.
비트맵은 4사분면을 기준 좌표로 사용하며,
좌상단이 (0.0)이다. 하지만 pc에서는 1사분면을 기준 좌표로 사용하므로 우하단이 (0,0)이다.
그런 이유로, 좌표대로 출력을 하면 비트맵은 상하가 뒤집힌 채로 나오게 된다.
(다르게 말하면, 저장시에 데이터는 상하가 뒤집힌 채로 저장되어 있다)

3.
비트맵은 특정 크기의 데이터를 한번에 전송하기 위해 DMA(Direct Memory Access)나 BLIT(Bit-Block Transfer)를
사용한다. 그런 이유로 특정 블럭을 맞추어 주어야 하고, 그렇기 때문에 이미지는 byte align이나 DWORD align
사용하게 된다(DWORD = 4bytes = 64bit) 이 방법은 몇 비트 이미지냐에 따라 달라지게 되는데,
기본적으로는 4byte align을 맞춰준다.

지루한 계산


4.
256색 미만의 비트맵은 팔레트라는 것을 사용한다. (팔레트는 RGBQUAD 구조체 사용)
이러한 팔레트는 8bit로 표현이 가능하므로, 256가지의 색상을 팔레트로 주로 사용가능하다.
예를 들어

이러한 팔레트를 만들고, 번호만으로 각 픽셀별로 색상을 지정해준다. 그렇다면 상당한 저장 공간을 아낄 수 있다.
그런 이유로, 팔레트를 사용하는 경우에는 팔레트를 Lookup(참조) 하여 변환을 해야하는 작업이 추가되게 된다.

지루한 계산

grayscale의 경우에는 256color RGBQUAD 구조체
팔레트가 없을 경우(jpeg 변환등) for(i=0;i<256;i++) ; 을 이용하여 생성하면 된다.

5.
이유는 모르겠지만, 24bit 비트맵의 경우는 RGBQUAD가 아닌 RGBTRIPLE이라는 구조를 사용한다.

6. 정리를 하자면
1bit - RGBQUAD 팔레트 2개 / 1byte = 8 pixel / 1byte align 4byte align(2009.10.12 windows 그림판 확인)
2bit -
RGBQUAD 팔레트 4개 / 1byte = 4 pixel / 1byte align
4bit - RGBQUAD 팔레트 16개 / 1byte = 2 pixel / 1byte align
8bit - RGBQUAD 팔레트 256개 / 1byte = 1 pixel / 4byte align
16bit - RGBTRIPLE / 2byte = 1 pixel / 4byte align
24bit - RGBTRIPLE / 3byte = 1 pixel / 4byte align (width * 3)을 한뒤 align
32bit - RGBQUAD  / 4byte = 1 pixel / 4byte align 픽셀이 이미 4의 배수이므로 align 안해도 상관없음

 BITMAPFILEINFO
 http://msdn.microsoft.com/en-us/library/dd183374(VS.85).aspx
 BITMAPINFO  http://msdn.microsoft.com/ko-kr/library/dd183375(en-us,VS.85).aspx
 BITMAPINFOHEADER  http://msdn.microsoft.com/ko-kr/library/dd183376(en-us,VS.85).aspx
 RGBQUAD  http://msdn.microsoft.com/ko-kr/library/dd162938(en-us,VS.85).aspx

 BITMAPCOREINFO  http://msdn.microsoft.com/en-us/library/dd183373(VS.85).aspx
 BITMAPCOREHEADER  http://msdn.microsoft.com/en-us/library/dd183372(VS.85).aspx
 RGBTRIPLE  http://msdn.microsoft.com/en-us/library/dd162939(VS.85).aspx

신고
Posted by 구차니

댓글을 달아 주세요

  1. 오~ 비트맵이다. 매트랩으로 짠거 C로도 짜볼까...

    2010.02.06 13:08 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 독한시키 ㄱ- c언어는 능동으로 배열 하기 힘들어서 힘들텐데? matlab이 배열이 강해서 쓰는데, 머.. matlab c api 쓰면 가능할지도 ㅋ

      2010.02.06 13:09 신고 [ ADDR : EDIT/ DEL ]
  2. 모르는사람

    저기 bfsize가 왜8바이트인가요? 다른데 보면 4바이트로 되어 있어서 질문 드립니다.

    2013.10.24 19:14 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 음? 0x00000000 면 4바이트 표기 아닌가요? 8바이트는 어디에 있나요?
      소스에 실수했나요? ㅠㅠ

      2013.10.25 09:00 신고 [ ADDR : EDIT/ DEL ]
  3. 모르는사람

    이런 제가 잘못확인한거였군요. 죄송합니다. bfReserved를 확인안하고 거기까지 읽어버렸습니다.

    2013.10.28 11:15 신고 [ ADDR : EDIT/ DEL : REPLY ]

프로그램 사용/GIMP2008.12.10 15:32

GIMP를 쓰다보니 불편한 점이 포토샾에서는 현재 찍은 위치의 RGB 값과 현재 pixel의 위치가 나왔는데
GIMP에는 나오지가 않는다는 점이었는데, 생각을 해보니 어딘가에 숨어 있을 것 같더군요!

docking 가능한 윈도우 형태로 포토샾에서도 있었으니 GIMP 에서도 한번 찾아 봅시다!

Step.1 창 - 도킹가능한 대화상자에 각종 창들이 있습니다.
                우리가 원하는 녀석은 포인터 라는 녀석 입니다.


Step.2 포인터를 누른후 이미지를 띄운 화면입니다.
          하단의 포인터 도킹 윈도우에 현재 좌표와 RGB 값이 출력되고 있습니다.

신고
Posted by 구차니

댓글을 달아 주세요

  1. 김프의 레이아웃은 언제봐도 어질어질해요. 왜케 적응이 안되는지.. -_-;

    2008.12.10 20:48 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 공짜와 친해지려면 그정도는 감수 해야죠 ㅎㅎ
      많이 쓰지는 않지만 그래도 나름 친해져 가고 있다고 생각하는 중이랍니다 ㅋ

      2008.12.10 21:55 신고 [ ADDR : EDIT/ DEL ]
  2. 공개 진영의 프로그램 사용을 막는 벽중하나는 인터페이스의 일관성인 것 같습니다. 저도 김프의 레이아웃 때문에 꼭꺼려지더군요.

    2008.12.11 12:22 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 좋게 말하면 자유도가 좋은것이고 나쁘게 말하면 일관성이 없는것이죠. 막상 써보니 상당히 유사해서 약간의 찾아 보는 수고를 하면 별반 차이 없이 쓸 수 있는데, 그 약간의 수고를 하냐 안하냐의 차이인 것 같습니다.
      GIMP에 익숙해지면 아마 Photoshop이 적응이 안되겠죠 ㅎ

      2008.12.11 13:19 신고 [ ADDR : EDIT/ DEL ]

프로그램 사용/GIMP2008.12.09 13:01
공짜를 사랑하는 나로서는 Adobe PhotoShop은 너무나 먼 당신이고
그렇다고 Paint.net은 닷넷 알레르기로 인해서 너무나 먼 당신이다.

아무튼 공짜 만세를 외치면서 GIMP의 간단한 사용법을 알아 보자.


원하는 색상으로 변경하기
UI 작업을 하다 보니 받아온 시안의 색상이 마음에 안들때가 있다. 다시 디자이너에게 요청하기는 뭣하고
그래서 GIMP로 간단하게 변경을 하고 싶다. 이 경우에는 아래와 같이 따라 하면된다.

step 1. 색상 메뉴의 색상-채도를 선택한다.

step 2.  원하는 색상으로 변경하기 위해서 색상 슬라이드 바를 움직여 준다.
            그리고 원하는 밝기/채도로 선택한다. 원본 이미지는 파란색이었는데, 색상을 변경하여 붉은색으로 바꾸어 주었다.

step 3. 색상 메뉴의 무채화를 선택하면 흑백으로 변경된다.

step 4. 흑백 이미지에 색상을 주고 싶다면, 색상 메뉴의 컬러화를 선택하여 원하는 색상으로 준다.

위의 예는 단색에 아까운 이미지라서 차이가 안나지만,
여러가지 색이 들어간 이미지에 적용해보면 상당한 차이가 있다.

신고
Posted by 구차니

댓글을 달아 주세요