API

CreateDibSection 이용 비트맵 생성하기

디버그정 2012. 10. 29. 04:01

CreateCompatibleBitmap의 경우 실패할 경우가 종종 생긴다.

위 api로 생성한 비트맵 자원들의 총합이 16메가인 초과한 경우 실패하다라나

색표현이 제대로 안된다던가 깨진다더거나 그런 경우도 생긴다고 한다.

이 경우에 CreateDibSection api를 사용하면 된다.

이 함수를 통해 비트맵 생성시는 프로그램이 제공하는 메모리 허용량까지 가능하다.

 

인터넷에 돌아다니는 소스는 색상(bpp)부분과

팔레트 설정부분이  누락된 코드가 많았다.


// 색상(bpp)이 8비트 이하인 경우 팔레트 설정이 필요하다.
HBITMAP __stdcall CreateBitmapByCreateDIBSection(HDC hdc, int cx, int cy, int bpp = 0)
{
 int i;
 unsigned int cbPalette;
 RGBQUAD *pPalette;
 HPALETTE hPal;
 PALETTEENTRY pe[256];

 void *pBits;
 
 // 비트맵 정보를 위한 헤더와 팔레트 공간. 팔레트 최대 사이즈(8비트인 경우)를 고려한다.
 byte pbi[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256] = {0};

 // 참고로 malloc 사용시
 //BITMAPINFO *pbi = (BITMAPINFO *)malloc(sizeof(BITMAPINFOHEADER) + cbPalette);
 //if(!pbi) return 0;
 //memset(pbi, 0, sizeof(BITMAPINFOHEADER)+cbPalette);

 // bpp가 0인 경우 hdc의 bpp로 설정한다.
 if (bpp == 0) {
  bpp = GetDeviceCaps(hdc, BITSPIXEL);
 }

 // 팔레트 사이즈 구하기
 cbPalette = (bpp > 8 ? 0 : 1 << bpp) * sizeof(RGBQUAD); // 8비트보다 크면 필요없다.

 // 이미지 사이즈
 //unsigned int cbImageSize=((((cx * bpp) + 31) & ~31) >> 3) * cy;

 // 헤더파일 입력
 ((BITMAPINFOHEADER *)pbi)->biSize = sizeof(BITMAPINFOHEADER);
 ((BITMAPINFOHEADER *)pbi)->biWidth = cx;
 ((BITMAPINFOHEADER *)pbi)->biHeight = cy;
 ((BITMAPINFOHEADER *)pbi)->biPlanes = 1;
 ((BITMAPINFOHEADER *)pbi)->biBitCount = bpp;
 ((BITMAPINFOHEADER *)pbi)->biCompression = BI_RGB;
 //((BITMAPINFOHEADER *)pbi)->biSizeImage = iImageSize;

 // 팔레트 설정
 pPalette = (RGBQUAD *)((byte *)pbi + sizeof(BITMAPINFOHEADER));
 switch (bpp)
 {
 case 1:
  // 흑백 팔레트
  memset(pPalette, 0, sizeof(RGBQUAD) * 2);
  pPalette[1].rgbBlue = 255;
  pPalette[1].rgbGreen = 255;
  pPalette[1].rgbRed = 255;
  break;

 case 4:
  // 16색(4비트) 팔레트
  hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  GetPaletteEntries(hPal, 0, 16, pe);
  for (i = 0; i < 16; i++) {
   pPalette[i].rgbRed = pe[i].peRed;
   pPalette[i].rgbGreen = pe[i].peGreen;
   pPalette[i].rgbBlue = pe[i].peBlue;
   pPalette[i].rgbReserved = 0;
  }
  break;
 
 case 8:
  // 256색(8비트) 팔레트
  hPal = CreateHalftonePalette(hdc);
  GetPaletteEntries(hPal, 0, 256, pe);
  DeleteObject(hPal);
  for (i = 0; i < 256; i++) {
   pPalette[i].rgbRed = pe[i].peRed;
   pPalette[i].rgbGreen = pe[i].peGreen;
   pPalette[i].rgbBlue = pe[i].peBlue;
   pPalette[i].rgbReserved = 0;
  }
  break;
 }

 return CreateDIBSection(hdc, (BITMAPINFO *)pbi, DIB_RGB_COLORS, &pBits, NULL, 0);
}