회사일/STFAE2009.07.09 13:38
이녀석으로 인해 2일 꼬박 삽질을 했다.. (미네랄!)

일단 비트맵중에 256컬러는 indexed color라고도 부르며, 팔레트가 존재한다.
팔레트는 특이하게도(!) RGBQUAD로 32비트 구조체를 사용하며
현재 확인된 팔레트의 alpha값(정확하게는 reserved 값)은 0x00으로 설정되어 있다.
이는 Bitmap이 투명을 지원하지 않기 때문에 당연한것이긴한데..

문제는 STBlit 함수의 팔레트는 0x00 은 100% 투명을 의미한다는 것이다.

그런 이유로~!
비트맵을 팔레트와 이미지를 복사해서 STBlit을 이용하기 위해서는
팔레트의 Alpha 값을 0x80으로 설정을 해주어야 한다.
신고
Posted by 구차니

댓글을 달아 주세요

  1. 무슨말인지 도통 모르겠어요 저도 미네랄 ? ㅎ

    2009.07.09 15:13 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 일부로 적절한 단어를 조합/나열해서 어렵게 적어 놓은거에요 ㅋㅋ

      2009.07.09 15:35 신고 [ ADDR : EDIT/ DEL ]
  2. 오... 이런 삽질은 원인을 찾기 어려운데 무쟈게 고생하셨을 듯...

    2009.07.11 10:58 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 거의 2일을 잡아 먹었답니다 ㅠ.ㅠ
      디버깅도 printf밖에 없다보니 ㅠ.ㅠ

      2009.07.12 11:02 신고 [ ADDR : EDIT/ DEL ]
  3. 저도

    같은 삽질을 했었지요...

    2009.09.10 10:26 신고 [ ADDR : EDIT/ DEL : REPLY ]

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 ]

프로그램 사용/GIMP2009.01.07 16:13
GIMP는 Bitmap(*.bmp)로 저장시 기본설정 값이 32bit Bitmap으로 되어 있다.
일부 프로그램에서 반드시 24bit Bitmap을 사용할 경우에는 잊지 말고 bit를 설정해 주어야 한다.

1. 이미지 저장시 나오는 다이얼로그. 파일 유형 선택을 bmp로 고르거나,
   파일 이름에 .bmp을 붙여 주면 자동으로 bitmap으로 저장한다.


2. BMP로 저장시에는 고급 옵션을 눌러 보면 여러가지 옵션이 나오는데, 기본값은 32bit ARGB 이다.

신고
Posted by 구차니

댓글을 달아 주세요