* DIB
1. DIB 파일 읽기 2. DIB를 DDB로 변환 3. 메모리 DC를 활용
==========================================================================================================
1. DIB 의 구조
다양한 장치에 사용할 수있도록 하기 위해서 비트맵 출력에 대한 상세 정보를 포함하고 있다.
[ DIB 구조 ] BITMAPFILEHEADER 구조체 BITMAPINFOHEADER 구조체 RGBQUAD 구조체 배열 비트 정보 => 실제 데이타의 비트 정보가 들어 있다.
1) BITMAPFILEHEADER 구조체
typedef struct tagBITMAPFILEHEADER {
WORD bfType; // 파일의 형태 : BM
DWORD bfSize; / 비트맵 파일의 크기를 바이트 단위로 WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits; // 실제 데이타의 위치 ( 헤더의 전체 크기)
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
|
2) BITMAPINFOHEADER 구조체
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // 구조체 크기
LONG biWidth; // 가로 픽셀수
LONG biHeight; // 세로 픽셀수
WORD biPlanes; // 플레인 갯수
WORD biBitCount; // 한 픽셀이 몇개의 비트로 이루어 지나 4= 16 / 8 = 256
DWORD biCompression; // 압축 방법 지정 BI_RGB : 비압축 BI_RLE8 : 8비트 압축 BI_RLE4 : 4비트 압축
DWORD biSizeImage; // 이미지의 크기를 바이트단위로 BI_RGB에서는 0
LONG biXPelsPerMeter; // 가로 해상도
LONG biYPelsPerMeter; // 세로 해상도
DWORD biClrUsed; // 색상테이블의 실제 사용 색상수 : 0이면 모두나 아니면 이크기가 RGB의 크기
DWORD biClrImportant; // 비트맵 출력의 필수적인 색상수 : 0이면 모두다
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
|
3) RGBQUAD 구조체 배열 => 일종의 팔레트
16색상의 비트맵이면 16개의 팔레트를 가진다. 256색이면 256 개의 팔레트 항목을 가진다.
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
|
[TIP ] BITMAPINFO 하나로 헤더와 팔레트를 관리 한다. typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO
4) 비트맵 파일을 열어서 16진수 파일을 살펴 보자
-------------------------------------------------------------------------------------------------
2 . DIB 출력
파일을 읽어서 BMP 파일을 출력
1) 출력 함수 => DDB 에 출력함수 내부적으로 포맽 변환을 하므로 속도가 느리다.
int SetDIBitsToDevice(
HDC hdc, // handle to DC
int XDest, // x-coord of destination upper-left corner
int YDest, // y-coord of destination upper-left corner DWORD dwWidth, // source rectangle width
DWORD dwHeight, // source rectangle height
int XSrc, // x-coord of source lower-left corner
int YSrc, // y-coord of source lower-left corner
UINT uStartScan, // first scan line in array
UINT cScanLines, // number of scan lines
CONST VOID *lpvBits, // array of DIB bits
CONST BITMAPINFO *lpbmi, // bitmap information
UINT fuColorUse // RGB or palette indexes
);
예)
SetDIBitsToDevice(hdc,0,0,bx,by, 0,0, 0,by ,pRaster,(BITMAPINFO *)ih,DIB_RGB_COLORS);
|
예) DIB 이미지 출력
BITMAPFILEHEADER *fh=NULL;
BITMAPINFOHEADER *ih;
int bx,by;
BYTE *pRaster;
void LoadDIB(char *Path)
{
HANDLE hFile;
DWORD FileSize, dwRead; hFile=CreateFile(Path,GENERIC_READ,0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile==INVALID_HANDLE_VALUE) {
return;
} FileSize=GetFileSize(hFile,NULL); if (fh)
free(fh);
// 헤더 정보 읽기
fh=(BITMAPFILEHEADER *)malloc(FileSize); // 메모리 할당
ReadFile(hFile,fh,FileSize,&dwRead,NULL);
CloseHandle(hFile);
// 데이타의 위치
pRaster=(PBYTE)fh+fh->bfOffBits;
// 비트맵 info
ih=(BITMAPINFOHEADER *)((PBYTE)fh+sizeof(BITMAPFILEHEADER));
// 이미지 폭과 넓이
bx=ih->biWidth;
by=ih->biHeight;
}
case WM_PAINT:
hdc=BeginPaint(hWnd, &ps);
if (fh) {
SetDIBitsToDevice(hdc,0,0,bx,by,0,0,0,by,pRaster,(BITMAPINFO *)ih,DIB_RGB_COLORS);
}
EndPaint(hWnd, &ps);
return 0;
|
2) 확대 함수 : dib 확대 함수 이다.
int StretchDIBits(
HDC hdc, // handle to DC
int XDest, // x-coord of destination upper-left corner
int YDest, // y-coord of destination upper-left corner
int nDestWidth, // width of destination rectangle
int nDestHeight, // height of destination rectangle
int XSrc, // x-coord of source upper-left corner
int YSrc, // y-coord of source upper-left corner
int nSrcWidth, // width of source rectangle
int nSrcHeight, // height of source rectangle
CONST VOID *lpBits, // bitmap bits
CONST BITMAPINFO *lpBitsInfo, // bitmap data
UINT iUsage, // usage options
DWORD dwRop // raster operation code
);
---------------------------------------------------------------------------------------------------------
3. DIB 속도 개선을 위한 변경
1) 접근법 화면과 호환되는 DDB 로 바꾸어 놓고 이 후 출력에는 BitBlt로 사용하는것이 훨씬더 유리하다.
2) 변환의 과정
DIB와 같은 크기를 가지는 호환 메모리 DC를 생성 => 이 DC에 호환 비트맵(DDB)를 선택해 놓고 => DIB를 출력
3) 변환 함수 (DIB->DDB)
HBITMAP CreateDIBitmap(
HDC hdc, // handle to DC
CONST BITMAPINFOHEADER *lpbmih, // bitmap data
DWORD fdwInit, // initialization option
CONST VOID *lpbInit, // initialization data
CONST BITMAPINFO *lpbmi, // color-format data
UINT fuUsage // color-data usage
);
예) BITMAP bit; hBit=CreateDIBitmap(hdc,(BITMAPINFOHEADER *)ih,CBM_INIT, (PBYTE)fh+fh->bfOffBits, (BITMAPINFO)ih,DIB_RGB_COLORS); DrawBitmap(hdc,0,0,hBit);
|
---------------------------------------------------------------------------------------------------------
4. 비트맵의 활용
1) 가상 화면 (offscreen BItmap) dc 와 호환 되는 메모리 DC를 만들고 메모리 DC에 비트맵을 선택하면 이 메모리 DC가 가상 화면이 된다. 가상화면에 모든 그래픽적인 출력이 가능하다. 이때 출력은 화면이 아니라 가상화면에 그려진다. => 더블 버퍼링을 이용 화면의 깜빡임이 줄어든다.
예)
// 전역 변수
HBITMAP MemBit; // 가상 메모리 비트맵
// 메모리 비트맵을 만들고 메모리 DC에 선택한다.
MemBit=CreateCompatibleBitmap(hdc, 600,400);
MemDC=CreateCompatibleDC(hdc);
hOldBmp=(HBITMAP)SelectObject(MemDC, MemBit); -------- 그리는 작업 -------------
// MemBit 비트맵을 화면으로 출력한다.
case WM_PAINT:
hdc=BeginPaint(hWnd, &ps);
MemDC=CreateCompatibleDC(hdc);
hOldBmp=(HBITMAP)SelectObject(MemDC, MemBit);
BitBlt(hdc, 0,0,600,400,MemDC,0,0,SRCCOPY);
SelectObject(MemDC, hOldBmp);
DeleteDC(MemDC);
EndPaint(hWnd, &ps);
return 0;
|
|