관리 메뉴

ㄴrㅎnㅂrㄹrㄱi

[강좌 12] 그래픽3 본문

API 관련/API 강좌모음

[강좌 12] 그래픽3

님투 2007. 10. 26. 03:41
반응형

[API]강좌(12)<--그래픽3





이번 시간에는 DIB에 대해서 알아 보겠습니다.
이번 강좌는 조금 어려울 겁니다. 이번 강좌를 통해서 여러분들은 부수적으로 파일
입출력과 메모리 할당하는 방법도 같이 배우게 될 겁니다.
자 그러면 먼저 DIB가 무엇인지 알아 봅시다.
윈도우즈에서 사용하는 비트맵 그림은 크게 두가지로 나눌수 있습니다. 바로 장치
독립적인 비트맵 그림과 장치 의존적인 비트맵 그림입니다.
예를들어 그림을 그린후에 256컬러로 저장했다면 그 그림은 장치 독립적인 그림이
됩니다. 그런데 이 그림을 우리가 앞에서 배운 프로그램을 이용해서 화면에 출력
하게 되면 어떻게 될까요? 바로 장치 의존적인 비트맵 그림으로 됩니다.
우리는 비트맵 그림을 출력하기 위해서 리소스 파일을 이용했을 겁니다. 리소스
라는 것은 자원입니다. 즉 윈도우즈에서 관리하는 거죠.
이 리소스 파일을 이용해서 그림 파일을 출력하게 되면 장치 독립적인 비트맵 그림
이 장치 의존적인 비트맵 그림으로 바뀌는 거죠.
자 그러면 앞에서 배운 비트맵 그림 출력 결과를 생각해 봅시다. 그림은 256컬러인
데출력된 결과가 16컬러 아닙니까? 바로 장치 의존적으로 변해서 그런겁니다.
장치 의존적인 비트맵 그림은 윈도우즈의 컬러수에 의존하게 됩니다. 즉 윈도우즈의
색깔을 가져다가 출력하는 프로그램이 컬러를 이용하게 되면 이 이용한 컬러의 영
향때문에 제대로 출력이 되지 않는 것입니다. 윈도우즈 자체의 인터페이스가 그림
이기 때문에 더욱 그렇죠.
자 그러면 이제부터 장치 독립적인 비트맵 컬러를 그대로 출력해 봅시다. 그러면
아마 앞에서 만든 프로그램에서 출력했을때 깨졌던 그림이 제대로 나올겁니다.
먼저전체적으로 어떻게 돌아가는지 알아 봅시다. 우선 비트맵 파일의 구조를
알아 봅시다. 비트맵 파일은 다음과 같은 구조로 되어 있습니다.
1)파일헤더
2)그림정보헤더
3)팔레트 데이터
4)실제 데이터
비트맵 파일 하나가 위와같이 구성되어 있다고 이해하면 됩니다. 그리고 2번부터 4
번을 실제적인 비트맵 정보라고 합니다. 실제적인 비트맵 정보가 시작되는 곳에
그림정보 헤더가 위치해 옴을 알수 있습니다.
한번 하나씩 알아봅시다. 아마 다른 윈도우즈 프로그래밍 책에서 이 DIB 부분을
보고 쉽게 이해할수 있는 분은 없었을 겁니다. 그러나 이번에는 아마 이해할수 있
을 겁니다.
먼저 비트맵 그림파일을 열어야 겠죠? 드디어 파일 입출력 부분이 나오는 군요.
파일을 열기 위해서는 _lopen()이라는 함수를 사용합니다.
HFILE _lopen(
LPCSTR lpszFileName,
int fnOpenMode
);
첫번째 파라미터로 열 파일이름을 지정하고 두번째 파라미터에는 지정된 예약어를
지정하면 됩니다. 아래는 이 부분에 지정될수 있는 예약어입니다.
OF_READ 읽기 전용을 연다
OF_READWRITE 읽기, 쓰기용으로 연다
OF_WRITE쓰기 전용으로 연다
파일 여는데 실패하면 -1을 리턴합니다. 파일을 성공적으로 열었으면 읽어야 할겁
니다. 먼저 파일헤더 부분만큼 자료를 읽어야 하는데 파일헤더 크기를 어떻게 알수
있을까요? 비트맵 파일의 파일헤더의 크기는 어느 그림이나 같습니다. 그리고 더욱
중요한 것은 이 비트맵 파일의 파일 헤더의 크기와 구조가 같은 구조체가 이미 정의
되어 있다는 것입니다. 이 구조체 변수를 이용해서 그 구조체의 크기만큼 파일을
읽으면 파일헤더 부분을 뽑아 낼수 있죠. 파일에서 자료를 읽어 올때에는
_lread()라는 함수를 사용합니다.
UINT _lread(
HFILE hFile,
LPVOID lpBuffer,
UINT cbRead
);
_lopen()함수를 이용해서 얻은 파일 핸들을 첫번째 파라미터로 지정하면 됩니다.
두번째 파라미터는 읽은 데이터를 저장할 버퍼를 세번째 파라미터는 버퍼의 크
기를 지정하면 됩니다.
파일 헤더 부분을 뽑아 내기 위한 구조체의 원형은 다음과 같습니다.
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
여기서 다른 멤버는 알 필요없고 단지 첫번째 멤버인 bfType과 두번째 멤버인
bfSize만 알면 됩니다. bfType은 파일에는 파일의 타입이 저장되고 bfSize에는
파일의 전체 크기가 저장됩니다. 물론 이 구조체 변수를 이용해서 파일을 읽게
되면요.
이 구조체를 이용해서 이 크기만큼의 자료를 뽑아내면 이 구조체에 비트맵 파일에
대한 기본적인 정보가 기억되는데 이중에 파일 타입을 알아보는 bfType값이 0x4d42
이면 이 파일은 비트맵 파일임을 확인할수 있습니다. 이 멤버값을 가지고 비트맵
파일인지 확인한후에는 어떤 작업을 해야 할까요? 비트맵 정보를 읽어와야겠죠?
_lread()함수로 자료를 읽어오면 파일 포인터가 그 만큼 이동되어 있기 때문에 바로
읽어오면 됩니다. 여러분들 중에 도스에서 파일 입출력을 해보신 분은 이미 알고
있을 겁니다. 이렇게 합시다. 파일 헤더 부분을 제외한 나머지 부분 전체를 읽어
오면 결국은 비트맵 정보부분을 다 읽어 오는 셈이 되겠네요. 나머지 부분을 어떻게
읽어 올까요? 간단합니다. 파일헤더를 읽어 왔을때 우리는 bfType이라는 멤버를 이
용해서 이 파일이 비트맵 파일인지 알아 보았는데 다른 멤버인 bfSize변수에 이 파
일의 전체 크기가 저장되어 있습니다. 이 변수값에 비트맵 파일 헤더 부분의 크기를
빼면 바로 파일 헤더 다음부터의 전체 크기가 되겠죠? 그 크기만큼 _lread() 함수를
이용해서 읽어오면 되는 것입니다. 이 읽어온 자료의 주소시작이 바로 그림정보
부분이 시작되는 곳이됩니다. 이 주소를 두가지 변수에 기억시켜 놓아야합니다.
먼저 BITMAPINFO라는 구조체로 선언한 변수에 기억시켜 놓아야 하고
BITMAPINFOHEADER라는 구조체로 선언한 변수에 기억시켜 놓아야 합니다. 전자는 나
중에 실제로 그림파일을 출력할때 필요한 함수의 파라미터로 쓰기 위함이고 후자는
비트맵 그림의 색깔이 몇 컬러인지 알아내고 또 그림정보 헤더 부분 다음에 있는
팔레트 데이터 부분등을 읽기 위해서 사용합니다.
아래는 이 두 구조체의 원형입니다.
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;
두번째 맴버인 RGBQUAD란 자료형은 팔레트 데이처를 의미하는 것입니다. 아래는 이
구조체의 원형입니다.
typedef struct _RGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
멤버 이름만 봐도 어떤 의미를 가지는지 쉽게 짐작할수 있죠?
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;
무지하게 복잡하죠? 몇개의 의미만 알면 됩니다. 첫번째 멤버인 biSize는 그림정보
헤더의 크기를 의미합니다. 즉 바로 이 구조체의 전체크기를 의미하는 셈이죠. 두
번째와 세번째멤버는 이름에서 알수 있듯이 그림의 크기를 의미합니다. 다섯번째
멤버인 biBitCount는 비트수를 의미하는데 여러분들이 흔히 말하는 256컬러 16컬러
뭐 이런것들이 들어 갑니다. 단 비트수로 들어가기 때문에 256컬러인 경우에는 8
이란 값이 저장되죠. 2의 8승이 256이죠. 일곱번째 멤버인 biSizeImage는 그림전체
크기가 저장됩니다. 마지막 멤버쪽에 있는 biClrUsed는 사용된 컬러수가 저장됩니
다. 이 값은 비트로 표시되지 않고 그냥 사용된 색의 수로 저장됩니다.
자 다시 생각해 봅시다. 비트맵 정보부분 전체를 읽은후에 그 시작주소를
BITMAPINFOHEADER 구조체 변수에 저장한다고 위에서 설명드렸을 겁니다. 비트맵
정보부분은 다시 그림정보 헤더, 팔레트 데이터, 실제 데이터 부분으로 나뉘는데
팔레트 데이터가 시작되는 주소를 RGBQUAD 구조체 변수에 기억시키려면 어떻게 해야
할까요? 현재 비트맵 정보부분 시작 주소를 BITMAPINFOHEADER 크기만큼 이동시키
면 바로 그 주소가 팔레트 데이터의 첫 주소가 될겁니다. 한번 잘 생각해 보세요.
그렇죠? 그런후에 이 팔레트 데이터 부분의 색깔 정보를 가지고 가상 팔레트에 복사
한후에 조작하고 그 결과를 이용해서 팔레트를 생성하고 사용한후에 그림을 출력하
면 됩니다. 출력하고 나서는 그 팔레트를 원래 대로 돌려 주면 됩니다.
팔레트를 생성할때에는 아래 함수를 이용해서 할수 있습니다.
HPALETTE CreatePalette(
CONST LOGPALETTE *lplgpl
);
파라미터는 가상 팔레트 구조체를 의미합니다. 물론 조작이 다 끝난 가상 팔레트
죠.
위 함수를 이용해서 팔레트 핸들을 얻으면 이것을 실제로 디바이스 컨텍스트 핸들
로 선택해 주어야 하는데 아래 함수를 이용해서 하면 됩니다.
HPALETTE SelectPalette(
HDC hdc,
HPALETTE hpal,
BOOL bForceBackground
);
첫번째, 두번쩨 파라미터가 뭔지는 짐작이 가죠? 세번째 파라미터에는 보통 FALSE
를 지정합니다.
이제 진짜로 사용하겠다는 것을 알려주면 됩니다.
UINT RealizePalette(
HDC hdc
);
위 함수를 사용하면 됩니다.
int StretchDIBits(
HDC hdc,
int XDest,
int YDest,
int nDestWidth,
int nDestHeight,
int XSrc,
int YSrc,
int nSrcWidth,
int nSrcHeight,
CONST VOID *lpBits,
CONST BITMAPINFO * lpBitsInfo,
UINT iUsage,
DWORD dwRop
);
위 함수를 이용해서 화면에 복사할수있습니다. 두번째, 세번째 파라미터는 화면에
출력될 시작 좌표를 의미하고 네번째, 다섯번째 파라미터는 화면에 찍힐 크기를
의미합니다. 여섯번째, 일곱번째, 여덟번째, 아홉번째 파라미터의 의미는 그림의
시작점과 크기를 의미하고 열번째 파라미터인 lpBits는 비트맵 그림 파일의 실제
데이터 부분의 시작주소를 지정하면 되고 열한번째 파라미터인 lpBitsInfo는 비트맵
정보의 시작주소를 지정해 주면 됩니다. 열두번째 파라미터인 iUsage에는
DIB_RGB_COLORS라는 예약어 를 지정하면 되고 마지막 파라미터에는 앞에서 배운
BitBlt()함수의 마지막 파라미터와 같은 예약어를 지정해 주면 됩니다.
자 어떻습니까? 조금 복잡하죠.
그러면 이것을 구현한 실제 소스를보도록 합시다.
#include <windows.h>
#include <windowsx.h>
#include <string.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL PrintDIBFormat(HDC hDC, char *szBitmapFile);
int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
static char szAppName[] = "Graphic Example";
HWND hWnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW|CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = szAppName;
if(!RegisterClass(&WndClass))
return FALSE;
hWnd = CreateWindow(
szAppName,
szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
switch(message)
{
case WM_PAINT :
hDC = BeginPaint(hWnd, &ps);
PrintDIBFormat(hDC, "test.bmp");
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY :
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
BOOL PrintDIBFormat(HDC hDC, char *szBitmapFile)
{
HFILE hFile;
HPALETTE hPalette, hOldPalette;
BITMAPFILEHEADER BitmapFileHeader;
BITMAPINFO *BitmapInfo;
BITMAPINFOHEADER *BitmapInfoHeader;
RGBQUAD *RgbQuad;
char *szBits, *Dib;
int nColorNumber;
int nRealSize;
DWORD dwTableSize;
struct tagLOGICALPALETTE
{
WORD version;
WORD NumberOfEntries;
PALETTEENTRY PaletteEntry[256];
} LOGICALPALETTE;
static int n;
if(-1 != (hFile = _lopen(szBitmapFile, OF_READ)))
_lread(hFile, &BitmapFileHeader, sizeof(BITMAPFILEHEADER));
else
return FALSE;
if(BitmapFileHeader.bfType != 0x4d42)
return FALSE;
else
{
nRealSize = BitmapFileHeader.bfSize-sizeof(BITMAPFILEHEADER);
Dib = (char *)GlobalAllocPtr(GMEM_MOVEABLE, nRealSize);
_lread(hFile, Dib, nRealSize);
_lclose(hFile);
BitmapInfo = (BITMAPINFO *)Dib;
BitmapInfoHeader = (BITMAPINFOHEADER *)Dib;
RgbQuad = (RGBQUAD *)(Dib+BitmapInfoHeader->biSize);
if((BitmapInfoHeader->biClrUsed == 0) &&
(BitmapInfoHeader->biBitCount <= 8))
nColorNumber = (1 << BitmapInfoHeader->biBitCount);
else
nColorNumber = BitmapInfoHeader->biClrUsed;
if(BitmapInfoHeader->biSizeImage == 0)
{
BitmapInfoHeader->biSizeImage =
BitmapInfoHeader->biWidth*BitmapInfoHeader->biHeight;
}
dwTableSize = nColorNumber*sizeof(RGBQUAD);
szBits = Dib+BitmapInfoHeader->biSize+dwTableSize;
LOGICALPALETTE.version = 0x300;
LOGICALPALETTE.NumberOfEntries = 256;
for(n=0; n<nColorNumber; n++)
{
LOGICALPALETTE.PaletteEntry[n].peRed = RgbQuad[n].rgbRed;
LOGICALPALETTE.PaletteEntry[n].peGreen = RgbQuad[n].rgbGreen;
LOGICALPALETTE.PaletteEntry[n].peBlue = RgbQuad[n].rgbBlue;
LOGICALPALETTE.PaletteEntry[n].peFlags = 0;
}
hPalette = CreatePalette((LPLOGPALETTE)&LOGICALPALETTE);
hOldPalette = SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
StretchDIBits(hDC, 0, 0, BitmapInfoHeader->biWidth,
BitmapInfoHeader->biHeight, 0, 0, BitmapInfoHeader->biWidth,
BitmapInfoHeader->biHeight, szBits, BitmapInfo,
DIB_RGB_COLORS, SRCCOPY);
SelectPalette(hDC, hOldPalette, FALSE);
DeleteObject(hPalette);
GlobalFreePtr(Dib);
}
return TRUE;
}
위 소스를 분석해 보도록 하겠습니다.
이 프로그램은 리소스를 이용해서 비트맵 그림을 출력하는 것이 아니기 때문에 리
소스 파일에서 비트맵 그림을 정의 해줄 필요는 없습니다. 아마 봐서 알겠지만 그
러한 부분이 없었을 겁니다.
그러면 먼저 윈도우가 처음생성될 때 그리는 부분인 WM_PAINT 메시지 처리 부분을
보도록 합시다.
case WM_PAINT :
hDC = BeginPaint(hWnd, &ps);
PrintDIBFormat(hDC, "test.bmp");
EndPaint(hWnd, &ps);
return 0;
못보던 함수가 하나 있군요. 이것은 장치 독립적인 비트맵 그림을 출력하기 위해
서 필자가 만든 함수입니다. 이 함수안의 루틴만 이해하면 되겠죠?
BOOL PrintDIBFormat(HDC hDC, char *szBitmapFile)
{
HFILE hFile;
파일을 다루기 위해서 파일 핸들을 선언해준것입니다.
HPALETTE hPalette, hOldPalette;
파레트를 조작하고 다시 원래 팔레트로 돌아가기 위해서 위 변수를 선언했습니다.
BITMAPFILEHEADER BitmapFileHeader;
BITMAPINFO *BitmapInfo;
BITMAPINFOHEADER *BitmapInfoHeader;
RGBQUAD *RgbQuad;
위 4개의 구조체에 대한 것은 이미 앞에서 설명을 드렸습니다.
char *szBits, *Dib;
int nColorNumber;
int nRealSize;
DWORD dwTableSize;
struct tagLOGICALPALETTE
{
WORD version;
WORD NumberOfEntries;
PALETTEENTRY PaletteEntry[256];
} LOGICALPALETTE;
우리가 앞에서 알아본 CreatePalette()함수의 파라미터에 LOGPALETTE라는 구조체의
주소가 지정되어야 하는데 이 구조체와 같은 구조의 구조체를 직접 만든것입니다.
실제로 도움말을 이용해서 이 구조체의 원형과 위 구조체의 원형을 비교해 보시기
바랍니다.
static int n;
if(-1 != (hFile = _lopen(szBitmapFile, OF_READ)))
_lread(hFile, &BitmapFileHeader, sizeof(BITMAPFILEHEADER));
else
return FALSE;
비트맵 파일을 열어서 파일 헤더 부분을 읽는 구문입니다.
if(BitmapFileHeader.bfType != 0x4d42)
return FALSE;
이 파일이 비트맵 파일인지 조사하는 구문입니다.
else
{
이 안의 루틴은 이 파일이 비트맵 파일일 때 수행되는 부분이겠죠?
nRealSize = BitmapFileHeader.bfSize-sizeof(BITMAPFILEHEADER);
파일 전체 크기에서 파일헤더 부분을 빼서 파일 헤더 부분을 제외한 크기를 얻고
있는 구문입니다.
Dib = (char *)GlobalAllocPtr(GMEM_MOVEABLE, nRealSize);
위에서 얻은 크기만큼 메모리를 할당하는 구문입니다. 우리가 도스에서 메모리를
할당한 malloc()함수의 사용방법과 같죠? 단 첫 번째 파라미터에 들어간
GMEM_MOVEABLE은 동적으로 할당하겠다는 의미입니다.
_lread(hFile, Dib, nRealSize);
_lclose(hFile);
파일헤더 부분을 제외한 나머지 부분을 읽어 그 시작주소를 Dib에 저장하고 있습
니다. 그리고 연 파일을 닫는군요.
BitmapInfo = (BITMAPINFO *)Dib;
BitmapInfoHeader = (BITMAPINFOHEADER *)Dib;
앞에서 이 시작주소를 두가지 변수에 기억 시켜 놓아야 한다고 했을 겁니다.
RgbQuad = (RGBQUAD *)(Dib+BitmapInfoHeader->biSize);
나머지 부분 즉 비트맵 정보의 시작 주소가 Dib인데 이 부분에서 포인터를 그림정보
헤더 부분만큼 이동하면 그 시작 주소가 뭐가 됩니까? 바로 팔레트 데이터의 시작
주소가 되겠네요? 그렇죠? 그 주소를 팔레트 데이터 변수에 저장하고 있는 구문입
니다.
if((BitmapInfoHeader->biClrUsed == 0) &&
(BitmapInfoHeader->biBitCount <= 8))
nColorNumber = (1 << BitmapInfoHeader->biBitCount);
else
nColorNumber = BitmapInfoHeader->biClrUsed;
우리가 출력할 그림의 컬러수를 구하는 구문인데 쉬프트 연산이 있군요. 이것의 의
미는 만약에 BitmapInfoHeader->biBitCount값이 8이면 2의 8승을 구한다는 것입니
다. 왜 그런지 한번 생각해 보세요.
if(BitmapInfoHeader->biSizeImage == 0)
{
BitmapInfoHeader->biSizeImage =
BitmapInfoHeader->biWidth*BitmapInfoHeader->biHeight;
}
그림의 크기가 0으로 되어 있으면 그림의 가로 크기와 세로 크기를 곱해서 크기를
구하는 구문입니다.
dwTableSize = nColorNumber*sizeof(RGBQUAD);
하나의 컬러는 하나의 팔레트 정보를 갖고 있으므로 이 전체 크기를 알기 위해서
는 컬러수와 이 팔레트 데이터 변수의 크기를 곱해 주어야 그 실제 크기를 알수 있
습니다.
szBits = Dib+BitmapInfoHeader->biSize+dwTableSize;
자 위와 같은 포인터 연산의 결과로 szBis는 어떤 정보의 주소를 가지게 됩니까?
바로 팔레트 데이터의 다음에 위치한 실제 데이터의 시작주소를 갖게 됩니다.
LOGICALPALETTE.version = 0x300;
LOGICALPALETTE.NumberOfEntries = 256;
for(n=0; n<nColorNumber; n++)
{
LOGICALPALETTE.PaletteEntry[n].peRed = RgbQuad[n].rgbRed;
LOGICALPALETTE.PaletteEntry[n].peGreen = RgbQuad[n].rgbGreen;
LOGICALPALETTE.PaletteEntry[n].peBlue = RgbQuad[n].rgbBlue;
LOGICALPALETTE.PaletteEntry[n].peFlags = 0;
}
현재 팔레트 데이터의 정보를 가상 팔레트에 저장하는 구문입니다.
hPalette = CreatePalette((LPLOGPALETTE)&LOGICALPALETTE);
가상 팔레트를 이용해서 팔레트를 생성하고 있습니다.
hOldPalette= SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
팔레트를 선택하고 실제로 사용하겠다는 것을 알려 주고 있습니다.
SelectPalette()함수의 리턴값은 선택하기 이전의 팔레트입니다.
StretchDIBits(hDC, 0, 0, BitmapInfoHeader->biWidth,
BitmapInfoHeader->biHeight, 0, 0, BitmapInfoHeader->biWidth,
BitmapInfoHeader->biHeight, szBits, BitmapInfo,
DIB_RGB_COLORS, SRCCOPY);
화면에 출력하고 있습니다. 이 함수는 위에서 설명드렸을 겁니다.
SelectPalette(hDC, hOldPalette, FALSE);
출력이 끝난후에 원래 팔레트로 다시 맞춰주고 있습니다.
DeleteObject(hPalette);
GlobalFreePtr(Dib);
사용한 팔레트 핸들을 반환하고 할당한 메모리를 해제하는 구문입니다.
}
return TRUE;
}
어때요? 이제껏 알아본 것중에 그래도 가장 복잡한 구조를 띄죠? 잘 이해가 되지
않으면 다시 한번 천천히 생각하면서 읽어 보시기 바랍니다.
 
반응형

'API 관련 > API 강좌모음' 카테고리의 다른 글

[강좌 14] 멀티미디어2  (0) 2007.10.26
[강좌 13] 멀티미디어1  (0) 2007.10.26
[강좌 11] 그래픽2  (0) 2007.10.26
[강좌 10] 그래픽1  (0) 2007.10.26
[강좌 9] 메뉴2  (0) 2007.10.26
Comments