�������� Linux Tags

16. ��ɫ�̹�����

���Ӳ�����������¾�û�д��ڵı�Ҫ�����������ִ�����ʾ���ṩ24λԪ��ɫ��Ҳ�ơ�true color����������ɫ������16λԪ��ɫ������ǿɫ������������ɫ������һЩ��ʾ������������Я���͵����ϻ�߽�����ģʽ�У�ÿ��ͼ��ֻ����8λԪ������ζ������256����ɫ��

������256����ɫ����ʲô�أ������ԣ�Ҫ��ʾ��ʵ�����ͼ�񣬽�16����ɫ�Dz����ģ�����Ҫʹ����ǧ������������ɫ��256����ɫλ��м�״̬���ǵģ���256����ɫ����ʾ��ʵ�����ͼ���㹻�ˣ�����Ҫ�����ض���ͼ����ָ����Щ��ɫ������ζ����ҵϵͳ���ܼ򵥵�ѡ�񡸱�׼��ϵ�е�256����ɫ����ϣ�����Ƕ�ÿ��Ӧ�ó�ʽ�����������ɫ��

�����Windows��ɫ�̹�������Ҫ�漰��ȫ�����ݡ������ָ����ʽ��8λԪ��ʾģʽ��ִ��ʱ����Ҫ����ɫ�����֪����ʽ�϶�������8λԪ��ʾģʽ��ִ�У���ô��Ҳ����Ҫʹ�õ�ɫ�̹���������������춲����˵���ͼ��һЩϸ�ڣ����Ա��»��ǰ�����Ҫ��Ѷ�ġ�

ʹ�õ�ɫ��
��

��ͳ�Ͻ�����ɫ���ǻ������������ɫ�İ��ӡ������Ҳ����ָ�����ڻ滭������ʹ�õ�������ɫ���ڵ���ͼ���У���ɫ������ͼ������豸��������Ѷ��ʾ�����Ͽ��õ���ɫ��Χ���������Ҳ����ָ֧Ԯ256ɫģʽ����ʾ���ϵĶ��ձ���

��ƵӲ��
��

��ʾ���ϵĵ�ɫ�̶��ձ�������������ͼ��ʾ��


��

��8λԪ��ʾģʽ�У�ÿ��ͼ��ռ8λԪ��ͼ��ֵ��ѯ����256RGBֵ�Ķ��ձ���λַ����ЩRGBֵ��������24λԪ��������Сһ�㣬ͨ����18λԪ��������Ҫ�ĺ졢�̺�����6λԪ����ÿ����ɫ��ֵ�����뵽��λ���ת�������Եõ����͸��������ĺ졢�̺�����������źš�

ͨ�����������������ֵ�������ɫ�̶��ձ��������װ���޹ص��Ӵ����棬����Microsoft Windows������һЩ���š����ȣ�Windows�����ṩ������棬�Ա��ڲ�ֱ�Ӹ���Ӳ�������£�Ӧ�ó�ʽ�Ϳ��Դ�ȡ��ɫ�̹��������ڶ�����������أ���Ϊ���е�Ӧ�ó�ʽ������ͬһ����Ѷ��ʾ��������ͬʱִ�У�����һ��Ӧ�ó�ʽʹ���˵�ɫ�̶��ձ����ܻ�Ӱ��������ʽ��ʹ�á�

��ʱ����Ҫʹ��Windows��ɫ�̹���������Windows 3.0��������ˡ�Windows������256����ɫ�е�20�֣�������Ӧ�ó�ʽ�޸������236�֡�����ijЩ����£�Ӧ�ó�ʽ�����Ըı�256����ɫ�е�254�֣�ֻ�к�ɫ�Ͱ�ɫ���⣭������һ���鷳����WindowsΪϵͳ������20����ɫ����ʱ��Ϊ20�֡���̬����ɫ�����16-1��ʾ��

��16-1 256����ɫ��ʾģʽ�е�20�ֱ�������ɫ
ͼ��λԪ RGBֵ ��ɫ���� ͼ��λԪ RGBֵ ��ɫ����
00000000 00 00 00 �� 11111111 FF FF FF ��
00000001 80 00 00 ���� 11111110 00 FF FF ��
00000010 00 80 00 ���� 11111101 FF 00 FF ���
00000011 80 80 00 ���� 11111100 00 00 FF ��
00000100 00 00 80 ���� 11111011 FF FF 00 ��
00000101 80 00 80 ����� 11111010 00 FF 00 ��
00000110 00 80 80 ���� 11111001 FF 00 00 ��
00000111 C0 C0 C0 ���� 11111000 80 80 80 ����
00001000 C0 DC C0 ��Ԫ�� 11110111 A0 A0 A4 ���Ի�
00001001 A6 CA F0 ���� 11110110 FF FB F0 ���ɫ

��256����ɫ��ʾģʽ��ִ��ʱ����Windowsά��ϵͳ��ɫ�̣��˵�ɫ������ʾ���ϵ�Ӳ���ɫ�̶��ձ���ͬ���ڶ���ϵͳ��ɫ�����16-1��ʾ��Ӧ�ó�ʽ����ͨ��ָ�����߼���ɫ�̣�logical palettes�������޸�����236����ɫ������ж��Ӧ�ó�ʽʹ���߼���ɫ�̣���ôWindows�͸���Ӵ��������Ȩ������֪������Ӵ��и�����ʾ�����У�������ʾ�����������Ӵ���ǰ�棩�����ǽ���һЩ�򵥵ķ�����ʽ�����������ι����ġ�

Ҫִ�б����������ֵij�ʽ����������Ҫ����ʾ���л���256ɫģʽ���������ϵ��滬���Ҽ����ӹ��ܱ���ѡ�����ԡ���Ȼ��ѡ���趨��ҳ���ǩ��

��ʾ�ҽ�
��

��ʽ16-1��ʾ��GRAYS1��ʽû��ʹ��Windows��ɫ�̹���������������������ʾ��65���ֽ���Ϊ�Ӻڵ��׵Ķ��ֲ�ɫ�ġ���Դ����

 ï¿½ï¿½Ê½16-1  GRAYS1
GRAYS1.C
/*---------------------------------------------------------------------------
   	GRAYS1.C -- 	Gray Shades
               						(c) Charles Petzold, 1998
-----------------------------------------------------------------------------*/

#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    		PSTR szCmdLine, int iCmdShow)
{
     	static TCHAR 	szAppName[] = TEXT ("Grays1") ;
     	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 		= 	(HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= 	NULL ;
     	wndclass.lpszClassName 		= 	szAppName ;

     	if (!RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"), 
                      			szAppName, MB_ICONERROR) ;
          			return 0 ;
     	}
     
     	hwnd = CreateWindow (	szAppName, TEXT ("Shades of Gray #1"),
                               WS_OVERLAPPEDWINDOW,
                          	   CW_USEDEFAULT, CW_USEDEFAULT,
                          	   CW_USEDEFAULT, CW_USEDEFAULT,             
                          	   NULL, NULL, hInstance, NULL) ;
     
     	ShowWindow (hwnd, iCmdShow) ;
     	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)
{
     	static int  		cxClient, cyClient ;
     	HBRUSH      		hBrush ;
     	HDC         		hdc ;
     	int         		i ;
     	PAINTSTRUCT 		ps ;
     	RECT        		rect ;
     
     	switch (message)
     	{
     	case 	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
          			return 0 ;
          
     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

               					// Draw the fountain of grays

          			for (i = 0 ; i < 65 ; i++)
          			{
               					rect.left   		= i * cxClient / 65 ;
               					rect.top    		= 0 ;
               					rect.right  		= (i + 1) * cxClient / 65 ;
               					rect.bottom 		= cyClient ;

               			hBrush = CreateSolidBrush (RGB(min (255, 4 * i),	
								min (255, 4 * i), 
								min (255, 4 * i))) ;
               					FillRect (hdc, &rect, hBrush) ;
               					DeleteObject (hBrush) ;
          			}
          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_DESTROY:
          			PostQuitMessage (0) ;
          			return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

��WM_PAINTѶϢ�����ڼ䣬��ʽ������65��FillRect��ʽ��ÿ�ζ�ʹ�ò�ͬ�ҽ׽����Ļ�ˢ���ҽ�ֵ��RGBֵ��0,0,0������4,4,4������8,8,8���ȵȣ�ֱ������һ��ֵ��255,255,255��������һ��ֵ����CreateSolidBrush��ʽ�е�min�޼���

�����256ɫ��ʾģʽ��ִ�иó�ʽ�����������Ӻڵ��׵�65�ֻҽף��������Ǽ������û�ɫ��ɫ������ɫֻ�к�ɫ������ɫ��128,128,128��������ɫ��192,192,192���Ͱ�ɫ��������ɫ�ǻ������Щ����ɫ�Ķ�λԪģʽ�������������ʾ�л����֣�����������65�ֻҽ��������Windows����ʹ�û�ɫ��ֻʹ�������ִ�ɫ���������������ʾ����ͼ����ͼ����20�ֱ�׼Windows��ɫ���ơ���ʱ����ͬ����ִ������һ���еij�ʽ��ͬʱ�������˲�ɫ��ҽ�DIB��������һ����ͨ����Windows�ڵ���ͼ�в�ʹ�û�ɫ��

��ʽ16-2��ʾ��GRAYS2��ʽ�ý��ٵ��ⲿ��ʽ����֤�˵�ɫ�̹�����������Ҫ�ĺ�ʽ��ѶϢ��

 ï¿½ï¿½Ê½16-2  GRAYS2
GRAYS2.C
/*---------------------------------------------------------------------------
   	GRAYS2.C -- 	Gray Shades Using Palette Manager
               						(c) Charles Petzold, 1998
-----------------------------------------------------------------------------*/

#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    							PSTR szCmdLine, int iCmdShow)
{
     	static TCHAR 	szAppName[] = TEXT ("Grays2") ;
     	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= NULL ;
     	wndclass.lpszClassName 		= szAppName ;

     	if	(!	RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"), 
                      			szAppName, MB_ICONERROR) ;
			return 0 ;
     	}
     
     	hwnd = CreateWindow (	szAppName, TEXT ("Shades of Gray #2"),
                          		WS_OVERLAPPEDWINDOW,
                          		CW_USEDEFAULT, CW_USEDEFAULT,
                          		CW_USEDEFAULT, CW_USEDEFAULT,             
                          		NULL, NULL, hInstance, NULL) ;
     
     	ShowWindow (hwnd, iCmdShow) ;
     	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)
{
     	static HPALETTE 		hPalette ;
     	static int      		cxClient, cyClient ;
     	HBRUSH          		hBrush ;
     	HDC             		hdc ;
     	int             		i ;
     	LOGPALETTE    			* 	plp ;
     	PAINTSTRUCT     		ps ;
     	RECT            		rect ;
     
     	switch (message)
     	{
     	case 	WM_CREATE:
               				// Set up a LOGPALETTE structure and create a palette

          			plp = malloc (sizeof (LOGPALETTE) + 64 * sizeof (PALETTEENTRY)) ;

          			plp->palVersion  	= 0x0300 ;
          			plp->palNumEntries	= 65 ;

          			for (i = 0 ; i < 65 ; i++)
          {
               		plp->palPalEntry[i].peRed   	= (BYTE) min (255, 4 * i) ;
               		plp->palPalEntry[i].peGreen 	= (BYTE) min (255, 4 * i) ;
               		plp->palPalEntry[i].peBlue 	= (BYTE) min (255, 4 * i) ;
               		plp->palPalEntry[i].peFlags 	= 0 ;
          			}
          			hPalette = CreatePalette (plp) ;
          			free (plp) ;
          			return 0 ;

     	case	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
          			return 0 ;
     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

               				// Select and realize the palette in the device context

          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;

               				// Draw the fountain of grays

          			for (i = 0 ; i < 65 ; i++)
          			{
               				rect.left   		= i * cxClient / 64 ;
               				rect.top    		= 0 ;
               				rect.right  		= (i + 1) * cxClient / 64 ;
               				rect.bottom 		= cyClient ;

              			 hBrush = CreateSolidBrush (PALETTERGB(	min	(255, 4 * i), 
                                                           min	(255, 4 * i), 
                                                           min	(255, 4 * i))) ;
               				FillRect (hdc, &rect, hBrush) ;
               				DeleteObject (hBrush) ;
          			}
          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_QUERYNEWPALETTE:
          			if (!hPalette)
               					return FALSE ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			InvalidateRect (hwnd, NULL, TRUE) ;

          			ReleaseDC (hwnd, hdc) ;
          			return TRUE ;

     	case 	WM_PALETTECHANGED:
          			if (!hPalette || (HWND) wParam == hwnd)
               					break ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			UpdateColors (hdc) ;
  
          			ReleaseDC (hwnd, hdc) ;
          			break ;

     	case 	WM_DESTROY:
          			DeleteObject (hPalette) ;
          			PostQuitMessage (0) ;
          			return 0 ;
	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

ͨ����ʹ�õ�ɫ�̹������ĵ�һ�����Ǻ���CreatePalette��ʽ�������߼���ɫ�̡��߼���ɫ�̰�����ʽ����Ҫ��ȫ����ɫ����236����ɫ��GRAYS1��ʽ��WM_CREATEѶϢ�����ڼ䴦������ҵ������ʼ��LOGPALETTE����logical palette���߼���ɫ�̡����ṹ����λ����������ṹ��ָ�괫�ݸ�CreatePalette��ʽ��CreatePalette�����߼���ɫ�̵Ĵ��ţ������˴��Ŵ����ھ�̬����hPalette�С�

LOGPALETTE�ṹ�������£�

typedef struct
{
     	WORD         	palVersion ;
     	WORD         	palNumEntries ;
     	PALETTEENTRY 	palPalEntry[1] ;
}
LOGPALETTE, * PLOGPALETTE ;

��һ����λͨ����Ϊ0x0300����ʾ����Windows 3.0���ڶ�����λ�趨Ϊ��ɫ�̱��е���Ŀ����LOGPALETTE�ṹ�еĵ�������λ��һ��PALETTEENTRY�ṹ�����У��˽ṹҲ��һ����ɫ����Ŀ��PALETTEENTRY�ṹ�������£�

typedef struct
{
     	BYTE peRed ;
     	BYTE peGreen ;
     	BYTE peBlue ;
     	BYTE peFlags ;
}
PALETTEENTRY, * PPALETTEENTRY ;

ÿ��PALETTEENTRY�ṹ��������һ������Ҫ�ڵ�ɫ����ʹ�õ�RGB��ɫֵ��

ע�⣬LOGPALETTE��ֻ�ܶ���һ��PALETTEENTRY�ṹ�����С�����ҪΪLOGPALETTE�ṹ�͸��ӵ�PALETTEENTRY�ṹ�����㹻��ļ�����ռ䡣GRAYS2��Ҫ65�ֻҽף������ΪLOGPALETTE�ṹ��64�����ӵ�PALETTEENTRY�ṹ�������㹻��ļ�����ռ䡣GRAYS2��palNumEntries��λ�趨Ϊ65��Ȼ���0��64��Ȧ������ҽ׵ȼ���һ���ǻ�Ȧ������4������������255�������ṹ�е�peRed��peGreen��peBlue��λ�趨Ϊ�˻ҽ׵ȼ���peFlags��λ��Ϊ0����ʽ��ָ�������������ָ�괫�ݸ�CreatePalette����һ����̬�����д���õ�ɫ�̴��ţ�Ȼ���ͷż����塣

�߼���ɫ����GDI�������ʽӦ��ɾ�����ǽ����������߼���ɫ�̡�WndProc͸����WM_DESTROYѶϢ�����ڼ����DeleteObject����ϸ��ɾ�����߼���ɫ�̡�

ע���߼���ɫ���Ƕ�����װ�����ݡ�������ʹ��֮ǰ������ȷ������ѡ��װ�����ݡ���WM_PAINTѶϢ�����ڼ䣬SelectPalette���߼���ɫ��ѡ��װ�����ݡ����˺��е������������⣬�˺�ʽ��SelectObject��ʽ���ơ�ͨ����������������ΪFALSE�����SelectPalette�ĵ�����������ΪTRUE����ô��ɫ�̽�ʼ���ǡ�������ɫ�̡�������ζ�����������г�ʽ�������˸��Եĵ�ɫ��֮�ᣬ�õ�ɫ�̲ſ��Ի����λ�ϵͳ��ɫ���е�һ��δʹ����Ŀ��

���κ�ʱ��ֻ��һ���߼���ɫ����ѡ��װ�����ݡ���ʽ������ǰһ��ѡ��װ�����ݵ��߼���ɫ�̴��š������ϣ�������߼���ɫ������ѡ��װ�����ݣ�����Դ���˴��š�

ͨ������ɫӳ�䵽ϵͳ��ɫ�̣�RealizePalette��ʽʹWindows��װ�������С����֡��߼���ɫ�̣���ϵͳ��ɫ��������ʾ��ʵ�ʵ�ʵ�ʵ�ɫ�����Ӧ��ʵ�ʹ����ڴ˺�ʽ�����ڼ���С�Windows����������к�ʽ���Ӵ��ǻ�Ļ��Ƿǻ�ģ��������ܽ�ϵͳ��ɫ���Ѹı�֪ͨ�������Ӵ������ǽ���Ҫ˵��һ��֪ͨ�ij��򣩡�

����һ��GRAYS1������RGB�޼���ָ����ɫ��ˢ����ɫ��RGB�޼�����һ��32λԪ������������COLORREFֵ�������и�λԪ����0��3����λԪ���Ǻ졢�̺��������ȡ�

ʹ��Windows��ɫ�̹������ij�ʽ���Լ���ʹ��RGB��ɫֵ��ָ����ɫ����������ЩRGB��ɫֵ�����ܴ�ȡ�߼���ɫ���еĸ�����ɫ�����ǵ�������û��ʹ�õ�ɫ�̹�������ͬ��Ҫ���߼���ɫ����ʹ�ø��ӵ���ɫ����Ҫ�õ�PALETTERGB�޼�������COLORREFֵ�ĸ�λԪ����Ϊ2������0���⣬����ɫ��RGB����ɫ��RGB��ɫ�����ơ�

��������Ҫ�Ĺ���

  • Ϊ��ʹ���߼���ɫ���е���ɫ�����õ�ɫ��RGBֵ���ɫ��������ָ�����ҽ���Ҫ���۵�ɫ������������Ҫʹ�ó����RGBֵ�����ʹ���˳����RGBֵ�������õ�һ�ֱ�׼��ɫ���������߼���ɫ���е���ɫ��
    ��
  • û�н���ɫ��ѡ��װ������ʱ����Ҫʹ�õ�ɫ��RGBֵ���ɫ��������
    ��
  • ���ܿ���ʹ�õ�ɫ��RGBֵ��ָ���߼���ɫ����û�е���ɫ����������Ҫ���߼���ɫ�̻����ɫ��
    ��

���磬��GRAYS2�д���WM_PAINT�ڼ䣬����ѡ���������߼���ɫ��֮�ᣬ�����ͼ��ʾ��ɫ������ʾ�ҽס���������RGB��ɫֵ��ѡ�����߼���ɫ���е���ɫ��

ע�⣬GRAYS2�Ӳ������Ѷ��ʾ������ʽ�Ƿ�֧Ԯ��ɫ�̹�����ʽ���ڲ�֧Ԯ��ɫ�̹�����ʽ����ʾģʽ�������з�256����ɫ����ʾģʽ����ִ��GRAYS2ʱ��GRAYS2�Ĺ�����GRASY1��ͬ��

��ɫ����Ѷ
��

�����ʽ���߼���ɫ����ָ��һ����ɫ������ɫ����20�ֱ�����ɫ֮һ����ôWindows�����߼���ɫ����Ŀӳ�������ɫ�����⣬�����������Ӧ�ó�ʽ�������ǵ��߼���ɫ����ָ����ͬһ����ɫ����ô��ЩӦ�ó�ʽ������ϵͳ��ɫ����Ŀ����ʽ����ͨ����PALETTEENTRY�ṹ��peFlags��λָ��Ϊ����PC_NOCOLLAPSE�����Ը��ڶ�״̬�������������ܵı����PC_EXPLICIT�������ʾϵͳ��ɫ�̣���PC_RESERVED����춵�ɫ�̶��������ҽ��ڱ��µ�����չʾ��������ǣ���

Ҫ������֯ϵͳ��ɫ�̣�Windows��ɫ�̹����������������͸����Ӵ���ѶϢ��

��һ����QM_QUERYNEWPALETTE�������Ӵ��ʱ����ѶϢ���͸����Ӵ��������ʽ�������Ӵ��ϻ滭ʱʹ���˵�ɫ�̹��������������봦����ѶϢ��GRAYS2չʾ�������������ʽ���װ�����ݴ��ţ���ѡ����ɫ�̣�����RealizePalette��Ȼ��ʹ�Ӵ�ʧЧ�Բ���WM_PAINTѶϢ������������߼���ɫ�̣����Ӵ�ѶϢ������ʽ�Ӹ�ѶϢ����TRUE�����򴫻�FALSE��

��ϵͳ��ɫ�̸ij���WM_QUERYNEWPALETTEѶϢ�Ľ����ͬʱ��Windows��WM_PALETTECHANGEDѶϢ���͸���Ŀǰ����Ӵ�����������ֹ�����Ӵ������������Ӵ���������ǰ̨�Ӵ�������Ȩ�����ݸ��Ӵ�ѶϢ������ʽ��wParamֵ�ǻ�Ӵ��Ĵ��š�ֻ�е�wParam����춳�ʽ���Ӵ�����ʱ��ʹ�õ�ɫ�̹������ij�ʽ�Żᴦ����ѶϢ��

ͨ�����ڴ���WM_PALETTECHANGEDʱ��ʹ���Զ���ɫ�̵��κγ�ʽ������SelectPalette��RealizePalette���������Ӵ���ѶϢ�����ڼ����RealizePaletteʱ��Windows���ȼ���߼���ɫ���е�RGB��ɫ�Ƿ��������뵽ϵͳ��ɫ���е�RGB��ɫ��ƥ�䡣���������ʽ��Ҫ��ͬ����ɫ����ô��������ʽ�͹�ͬʹ��һ��ϵͳ��ɫ����Ŀ����������Windows���δʹ�õ�ϵͳ��ɫ����Ŀ���������ʹ�ã����߼���ɫ���е���ɫ��20�ֱ�����Ŀӳ�䵽�������ɫ��

��������ij�ʽ�ǻʱ��ʾ�������ۣ���ô�����ش���WM_PALETTECHANGEDѶϢ��������������ѡ��GRAYS2��ʾ����֮һ���ڴ���WM_QUERYNEWPALETTEѶϢʱ�������װ�����ݣ�ѡ����ɫ�̣�Ȼ�����RealizePalette����ʱ�Ϳ����ڴ���WM_QUERYNEWPALETTEʱ����InvalidateRect�ˡ��෴�أ�GRAYS2����UpdateColors�������ʽͨ�������»����Ӵ�����Ч��ͬʱ���ı��Ӵ���ͼ�ص�ֵ������������ǰ����ɫ��

ʹ�õ�ɫ�̹������������ʽ������WM_QUERYNEWPALETTE��WM_PALETTECHANGEDѶϢ��GRAYS2����ʾ�ķ�����������

��ɫ����������
��

��ʽ16-3��ʾ��GRAYS3��ʽ��GRAYS2�dz����ƣ�ֻ���ڴ���WM_PAINT�ڼ�ʹ���˺���PALETTEINDEX�ľ޼���������PALETTERGB��

 ï¿½ï¿½Ê½16-3  GRAYS3
GRAYS3.C
/*---------------------------------------------------------------------------
   	GRAYS3.C -- 	Gray Shades Using Palette Manager
               						(c) Charles Petzold, 1998
-----------------------------------------------------------------------------*/

#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    							PSTR szCmdLine, int iCmdShow)
{
     	static TCHAR szAppName[] = TEXT ("Grays3") ;
	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= NULL ;
     	wndclass.lpszClassName 		= szAppName ;

     	if (!RegisterClass (&wndclass))
     {
         	 		MessageBox (	NULL, TEXT ("This program requires Windows NT!"), 
                      					szAppName, MB_ICONERROR) ;
      			return 0 ;
     	}
     
     	hwnd = CreateWindow (	szAppName, TEXT ("Shades of Gray #3"),
                          		WS_OVERLAPPEDWINDOW,
                          		CW_USEDEFAULT, CW_USEDEFAULT,
                          		CW_USEDEFAULT, CW_USEDEFAULT,             
                          		NULL, NULL, hInstance, NULL) ;
     
     	ShowWindow (hwnd, iCmdShow) ;
     	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)
{
     	static HPALETTE 		hPalette ;
     	static int      		cxClient, cyClient ;
     	HBRUSH          		hBrush ;
    	HDC             		hdc ;
     	int             		i ;
     	LOGPALETTE    			* 	plp ;
     	PAINTSTRUCT     		ps ;
     	RECT            		rect ;
     	switch (message)
     {
     	case 	WM_CREATE:
               			// 	Set up a LOGPALETTE structure and create a palette

          			plp = malloc (sizeof (LOGPALETTE) + 64 * sizeof (PALETTEENTRY)) ;

          			plp->palVersion 		= 0x0300 ;
          			plp->palNumEntries	= 65 ;

          			for (i = 0 ; i < 65 ; i++)
          			{
               		plp->palPalEntry[i].peRed   	= (BYTE) min (255, 4 * i) ;
               		plp->palPalEntry[i].peGreen 	= (BYTE) min (255, 4 * i) ;
               		plp->palPalEntry[i].peBlue  	= (BYTE) min (255, 4 * i) ;
               		plp->palPalEntry[i].peFlags 	= 0 ;
          			}
 			hPalette = CreatePalette (plp) ;
         			free (plp) ;
          			return 0 ;

     	case 	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
          			return 0 ;
          
     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

   				// Select and realize the palette in the device context

    				SelectPalette (hdc, hPalette, FALSE) ;
 				RealizePalette (hdc) ;

               				// Draw the fountain of grays

			for (i = 0 ; i < 65 ; i++)
			{
               				rect.left   	= i * cxClient / 64 ;
               				rect.top    	= 0 ;
               				rect.right  	= (i + 1) * cxClient / 64 ;
               				rect.bottom 	= cyClient ;

               				hBrush = CreateSolidBrush (PALETTEINDEX (i)) ;

               				FillRect (hdc, &rect, hBrush) ;
               				DeleteObject (hBrush) ;
          			}

          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_QUERYNEWPALETTE:
          			if (!hPalette)
               					return FALSE ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			InvalidateRect (hwnd, NULL, FALSE) ;
     
          			ReleaseDC (hwnd, hdc) ;
          			return TRUE ;

     	case 	WM_PALETTECHANGED:
          			if (!hPalette || (HWND) wParam == hwnd)
               					break ;

          			hdc 	= GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			UpdateColors (hdc) ;

          			ReleaseDC (hwnd, hdc) ;
          			break ;

     	case 	WM_DESTROY:
          			PostQuitMessage (0) ;
          			return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

����ɫ�̡���������ɫ��ͬ춵�ɫ��RGB��ɫ�����λԪ����1������λԪ���ֵ��Ŀǰ��װ��������ѡ��ġ��߼���ɫ���е���������GRAYS3�У��߼���ɫ����65����Ŀ�������Щ��Ŀ��������0��64��ֵ

PALETTEINDEX (0)

ָ��ɫ��

PALETTEINDEX (32)

ָ��ɫ����

PALETTEINDEX (64)

ָ��ɫ��

��ΪWindows����Ҫִ�������ɫ������������ʹ�õ�ɫ��������ʹ��RGBֵ����Ч��

��ѯ��ɫ��֧Ԯ
��

���������׵���֤����Windows��16λԪ��24λԪ��ʾģʽ��ִ��ʱ��GRAYS2��GRAYS3��ʽִ�����á�������ijЩ����£�Ҫʹ�õ�ɫ�̹�������WindowsӦ�ó�ʽ����Ҫ��ȷ��װ��������ʽ�Ƿ�֧Ԯ������ʱ�������Ժ���GetDeviceCaps��������Ѷ��ʾ��װ�����ݴ��ź�PASTERCAPS��Ϊ��������ʽ��������һϵ�������ɵ�������ͨ���ڴ���ֵ�ͳ���RC_PALETTE֮��ִ��λԪ����������֧Ԯ�ĵ�ɫ�̣�

RC_PALETTE & GetDeviceCaps (hdc, RASTERCAPS)

�����ֵ���㣬����Ѷ��ʾ��װ��������ʽ��֧Ԯ��ɫ�̲��������������֮�£�����GetDeviceCaps������������Ҫ��ĿҲ�ǿ��õġ���ʽ����

GetDeviceCaps (hdc, SIZEPALETTE)

����������ʾ���ϵ�ɫ�̱����ܳߴ硣����ͬʱ��ʾ����ɫ������ͬ����Ϊ��ɫ�̹�����ֻ���ÿͼ��8λԪ����Ѷ��ʾģʽ�����Դ�ֵ����256��

��ʽ����

GetDeviceCaps (hdc, NUMRESERVED)

�����ڵ�ɫ�̱��е���ɫ�����ñ���װ��������ʽΪϵͳ�����ģ���ֵ��20�������е�ɫ�̹���������Щֻ��WindowsӦ�ó�ʽ��256ɫ��ʾģʽ��ʹ�õĴ�ɫ��Ҫʹ�������236����ɫ����ʽ����ʹ�õ�ɫ�̹�������ʽ��

һ��������ĿҲ���ã�

GetDeviceCaps (hdc, COLORRES)

��ֵ���������뵽Ӳ���ɫ�̱���RGB��ɫֵ�����ȣ���λԪ�ƣ�����Щ�ǽ�����λ���ת������λԪ��ijЩ��Ѷ��ʾ��ֻʹ��6λԪADC�����Ը�ֵ��18������ʹ��8λԪ��ADC������ֵ��24��

Windows��ʽע����ɫ�����Ȳ���˲�ȡһЩ�����Ǻ����õġ����磬�������ɫ��������18����ô��ʽ��������Ҫ��128�ֻҽף���Ϊֻ��64����ɢ�Ļҽ׿��á�Ҫ��128�ֻҽ׾Ͳ����ö������Ŀ�����Ӳ���ɫ�̱���

ϵͳ��ɫ��
��

����ǰ�������Windowsϵͳ��ɫ��ֱ������ʾ���ϵ�Ӳ���ɫ�̲�ѯ�������Ȼ����Ӳ���ɫ�̲�ѯ�����ܱ�ϵͳ��ɫ�̵���ɫ�����ȵͣ�����ʽ����ͨ����������ĺ�ʽ�����ϵͳ��ɫ���е�ijЩ��ȫ����RGB��Ŀ��

GetSystemPaletteEntries (hdc, uStart, uNum, &pe) ;

ֻ����ʾ��ģʽ֧Ԯ��ɫ�̲���ʱ���ú�ʽ����ִ�С��ڶ����͵���������������������������ʾ��һ����ɫ����Ŀ�������͵�ɫ����Ŀ��������һ��������ָ��PALETTEENTRY��̬��ָ�ꡣ

�������ڼ��������ʹ�øú�ʽ����ʽ���Զ���PALETTEENTRY�ṹ���£�

PALETTEENTRY pe ;

Ȼ��ɰ�����ķ�����κ���GetSystemPaletteEntries��

GetSystemPaletteEntries (hdc, i, 1, &pe) ;

���е�i��0��ij��ֵ����ֵС춴�GetDeviceCaps������SIZEPALETTE����255�����ص�ֵ�����ߣ���ʽҪ������е�ϵͳ��ɫ����Ŀ������ͨ������ָ��PALETTEENTRY�ṹ��ָ�꣬Ȼ�����������㹻�ļ�����飬�Դ������ɫ�̴�Сָ��ͬ�����PALETTEENTRY�ṹ��

GetSystemPaletteEntries��ʽȷʵ����������Ӳ���ɫ�̱���ϵͳ��ɫ���е���Ŀ��ͼ��ֵ���ӵ�˳�����У���Щֵ��춱�ʾ��Ѷ��ʾ�������е���ɫ���ҽ��򵥵�����һ�¾���������

������ɫ�̺�ʽ
��

������ǰ�濴����Windows��ʽ�ܹ��ı�ϵͳ��ɫ�̣���ֻ�Ǽ�Ӹı䣺��һ�������߼���ɫ�̣����������dz�ʽҪʹ�õ�RGB��ɫֵ���С�CreatePalette��ʽ���ᵼ��ϵͳ��ɫ�̻�����ʾ����ɫ�̱����κα仯���߼���ɫ�̱������κ����鷢��֮ǰ��ѡ��װ�����ݲ����֡�

��ʽ����ͨ������

GetPaletteEntries (hPalette, uStart, uNum, &pe) ;

����ѯ�߼���ɫ���е�RGB��ɫֵ�������԰�ʹ��GetSystemPaletteEntries�ķ�����ʹ�ô˺�ʽ������Ҫע�⣬��һ���������߼���ɫ�̵Ĵ��ţ�������װ�����ݵĴ��š�

�����߼���ɫ�����ᣬ�����ı����е�ֵ����Ӧ��ʽ�ǣ�

SetPaletteEntries (hPalette, uStart, uNum, &pe) ;

���⣬��ס���д˺�ʽ������ϵͳ��ɫ�̵��κα仯����ʹĿǰ��ɫ��ѡ����װ�����ݡ��˺�ʽҲ���ı��߼���ɫ�̵ijߴ硣Ҫ�ı��߼���ɫ�̵ijߴ磬��ʹ��ResizePalette��

����ĺ�ʽ����RGB��ɫ����ֵ��Ϊ����IJ����������������ظ��߼���ɫ�̣����߼���ɫ���������ӽ���RGB��ɫֵ���Ӧ��

iIndex = GetNearestPaletteIndex (hPalette, cr) ;

�ڶ���������COLORREFֵ�����ϣ���Ļ�������GetPaletteEntries�Ϳ��Ի���߼���ɫ����ʵ�ʵ�RGB��ɫֵ��

�����ʽ��8λԪ��ʾģʽ����Ҫ���236���Զ���ɫ������Ժ���GetSystemPaletteUse����������ʽ�趨254���Զ���ɫ��ϵͳ��������ɫ�Ͱ�ɫ����������ʽ������󻯳���ȫөĻʱ����������������������һЩϵͳ��ɫ��Ϊ��ɫ�Ͱ�ɫ���Ա�����к͹��ܱ�����Ȼ�ɼ���

λԪӳ���������
��

�ӵ����¿����˽⵽��GDI����ʹ�ò�ͬ�ġ��滭ģʽ����λԪӳ������������߲����������SetROP2�趨�滭ģʽ�����еġ�2����ʾ�������֮��Ķ�Ԫ��binary��λԪӳ���������ԪλԪӳ�������춴���BitBlt�����ƹ��ܡ���ЩλԪӳ��������������ڻ������ͼ�������ͼ�صĽ�Ϸ�ʽ�����磬�����Ի�һ��ֱ�ߣ��Ա����ϵ�ͼ������ʾ��ͼ�ذ�λԪ���ķ�ʽ���ϡ�

λԪӳ�����������ͼ��λԪ����������λԪ��˳����в������ı��ɫ�̻�Ӱ�쵽��ЩλԪӳ�������λԪӳ������IJ��������ͼ��λԪ������Щͼ��λԪ������ʵ����ɫû�й�����

͸��ִ��GRAYS2��GRAYS3��ʽ�����Լ��Ϳ��Եó�������ۡ������ߴ�ʱ���϶�������ײ��ı߽紩���Ӵ���Windows���÷�ת����ͼ��λԪ��λԪӳ���������ʾ�϶��ߴ�ı߽磬��Ŀ����ʹ�϶��ߴ�߽����ǿɼ��ġ�����GRAYS2��GRAYS3��ʽ�У�����������������任����ɫ����Щ��ɫǡ�����Ӧ춵�ɫ�̱���δʹ�õ���Ŀ�����Ƿ�ת��ʾͼ��λԪ�Ľ����������ɫû�з�ת��ֻ��ͼ��λԪ��ת�ˡ�

�������ڱ�16-1����������һ����20�ֱ�׼������ɫλ�ϵͳ��ɫ�̵Ķ����͵ײ����Ա�λԪӳ������Ľ����Ȼ������Ȼ����һ������ʼ�޸ĵ�ɫ�̣��������滻�˱�����ɫ����ô��ɫ�����λԪӳ������ͱ��û�������ˡ�

Ψһ��֤����λԪӳ��������ú�ɫ�Ͱ�ɫ��������ɫ��ϵͳ��ɫ���еĵ�һ����Ŀ�����е�ͼ��λԪ����Ϊ0��������ɫ���������Ŀ�����е�ͼ��λԪ����Ϊ1������������Ŀ���ܸı䡣�����ҪԤ֪����ɫ����Ͻ���λԪӳ������Ľ����������Ȼ��ϵͳ��ɫ�̱���Ȼ��鿴��ͬͼ��λԪֵ��RGB��ɫֵ��

�鿴ϵͳ��ɫ��
��

��Windows��ִ�еij�ʽ�������߼���ɫ�̣�Ϊʹ�߼���ɫ�̸��õط��������ʹ���߼���ɫ�̵ij�ʽ��Windows����ϵͳ��ɫ�����趨��ɫ����ϵͳ��ɫ�̸�������ʾ����Ӳ����ձ����ݡ��������鿴ϵͳ��ɫ������춵��ʵ�ɫ��Ӧ�ó�ʽ��

��Ϊ���������������ֽ�Ȼ��ͬ�Ĵ�����ʽ�������ҽ�����չʾ������ʽ������ʾϵͳ��ɫ�̵����ݡ�

SYSPAL1��ʽ�����ʽ16-4��ʾ��ʹ����ǰ��������GetSystemPaletteEntries��ʽ��

 ï¿½ï¿½Ê½16-4  SYSPAL1
SYSPAL1.C
/*---------------------------------------------------------------------------
   SYSPAL1.C --	Displays system palette
         						(c) Charles Petzold, 1998
-----------------------------------------------------------------------------*/

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

TCHAR szAppName [] = TEXT ("SysPal1") ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    							PSTR szCmdLine, int iCmdShow)
{
     	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 		    = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  			= NULL ;
     	wndclass.lpszClassName 			= szAppName ;
     
     	if (!RegisterClass (&wndclass))
     	{
			MessageBox (	NULL, TEXT ("This program requires Windows NT!"),
                      				szAppName, MB_ICONERROR) ;
          			return 0 ;
     	}
     
     	hwnd = CreateWindow (	szAppName, TEXT ("System Palette #1"), 
                          	WS_OVERLAPPEDWINDOW, 
                          	CW_USEDEFAULT, CW_USEDEFAULT,
                          	CW_USEDEFAULT, CW_USEDEFAULT,
                          	NULL, NULL, hInstance, NULL) ;

     	if (!hwnd)
          			return 0 ;
     	ShowWindow (hwnd, iCmdShow) ;
     	UpdateWindow (hwnd) ;

     	while (GetMessage (&msg, NULL, 0, 0))
     	{
          		TranslateMessage (&msg) ;
          		DispatchMessage (&msg) ;
     	}
     	return msg.wParam ;
}

BOOL CheckDisplay (HWND hwnd)
{
     	HDC	hdc ;
     	int 	iPalSize ;

     	hdc = GetDC (hwnd) ;
     	iPalSize = GetDeviceCaps (hdc, SIZEPALETTE) ;
     	ReleaseDC (hwnd, hdc) ;

     	if (iPalSize != 256)
  	{
		MessageBox (hwnd,TEXT ("This program requires that the video ")
                         TEXT ("display mode have a 256-color palette."),
                      	    	szAppName, MB_ICONERROR) ;
          		return FALSE ;
     	}
     	return TRUE ;
}

LRESULT CALLBACK WndProc (	HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
     	static int   		cxClient, cyClient ;
     	static SIZE  		sizeChar ;
     	HDC          		hdc ;
     	HPALETTE     		hPalette ;
     	int             	i, x, y ;
     	PAINTSTRUCT  		ps ;
     	PALETTEENTRY 		pe [256] ;
     	TCHAR        					szBuffer [16] ;

     	switch (message)
     	{
     	case WM_CREATE:
          			if (!CheckDisplay (hwnd))
               					return -1 ;
          			hdc = GetDC (hwnd) ;
          			SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
          			GetTextExtentPoint32 (hdc, TEXT ("FF-FF-FF"), 10, &sizeChar) ;
          			ReleaseDC (hwnd, hdc) ;
          			return 0 ;
     
     	case 	WM_DISPLAYCHANGE:
          			if (!CheckDisplay (hwnd))
               					DestroyWindow (hwnd) ;

          			return 0 ;

     	case 	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
          			return 0 ;

     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;
          			SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;

          			GetSystemPaletteEntries (hdc, 0, 256, pe) ;

          			for (i = 0, x = 0, y = 0 ; i < 256 ; i++)
          			{
               		wsprintf (	szBuffer, TEXT ("%02X-%02X-%02X"),
                    pe[i].peRed, pe[i].peGreen, pe[i].peBlue) ;

               		TextOut (hdc, x, y, szBuffer, lstrlen (szBuffer)) ;

               		if ((	x += sizeChar.cx) + sizeChar.cx > cxClient)
               					{
                    					x = 0 ;
          
                    					if ((	y += sizeChar.cy) > cyClient)
                         						break ;
               					}
          			}
          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_PALETTECHANGED:
          			InvalidateRect (hwnd, NULL, FALSE) ;
          			return 0 ;

     	case 	WM_DESTROY:
          			PostQuitMessage (0) ;
          			return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

��SYSPALϵ���е�������ʽһ�������Ǵ���SIZEPALETTE������GetDeviceCaps����ֵΪ256������SYSPAL1����ִ�С�

ע������SYSPAL1����ʾ����ʲôʱ���յ�WM_PALETTECHANGEDѶϢ����������Ч�ġ��ںϲ�WM_PAINTѶϢ�����ڼ䣬SYSPAL1����GetSystemPaletteEntries������һ����256��PALETTEENTRY�ṹ��������Ϊ������RGBֵ��Ϊ�����ִ���ʾ����ʾ���򡣳�ʽִ��ʱ��ע��20�ֱ�����ɫ��RGBֵ�б��е�ǰ10������10���������16-1��ʾ��ͬ��

��SYSPAL1��ʾ���õ���Ѷʱ������ʵ�ʿ�����256����ɫ��ͬ���Ǿ���SYSPAL2����ҵ�����ʽ16-5��ʾ��

 ï¿½ï¿½Ê½16-5  SYSPAL2
SYSPAL2.C
/*---------------------------------------------------------------------------
   SYSPAL2.C --	Displays system palette
          						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

TCHAR szAppName [] = TEXT ("SysPal2") ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    		PSTR szCmdLine, int iCmdShow)
{
     	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= NULL ;
     	wndclass.lpszClassName 		= szAppName ;
     
     	if (!RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"),
                      								szAppName, MB_ICONERROR) ;
          			return 0 ;
     }
     
     	hwnd = CreateWindow (	szAppName, TEXT ("System Palette #2"), 
                          		WS_OVERLAPPEDWINDOW, 
                          		CW_USEDEFAULT, CW_USEDEFAULT,
                          		CW_USEDEFAULT, CW_USEDEFAULT,
                          		NULL, NULL, hInstance, NULL) ;
     	if (!hwnd)
          			return 0 ;
     	ShowWindow (hwnd, iCmdShow) ;
     	UpdateWindow (hwnd) ;

     	while (GetMessage (&msg, NULL, 0, 0))
     	{
          			TranslateMessage (&msg) ;
          			DispatchMessage (&msg) ;
     	}
     	return msg.wParam ;
}

BOOL CheckDisplay (HWND hwnd)
{
     	HDC hdc ;
     	int iPalSize ;

     	hdc = GetDC (hwnd) ;
     	iPalSize = GetDeviceCaps (hdc, SIZEPALETTE) ;
     	ReleaseDC (hwnd, hdc) ;

	if (iPalSize != 256)
     	{
 	MessageBox (hwnd, TEXT	("This program requires that the video ")
                      TEXT	("display mode have a 256-color palette."),
                      		szAppName, MB_ICONERROR) ;
          		return FALSE ;
     	}
     	return TRUE ;
}

LRESULT CALLBACK WndProc (	HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
     	static HPALETTE 		hPalette ;
     	static int      		cxClient, cyClient ;
     	HBRUSH          		hBrush ;
     	HDC             		hdc ;
     	int             		i, x, y ;
     	LOGPALETTE    			* 	plp ;
     	PAINTSTRUCT     		ps ;
     	RECT            		rect ;

     	switch (message)
     {
     	case 	WM_CREATE:
          			if (!CheckDisplay (hwnd))
               					return -1 ;

			plp = malloc (sizeof (LOGPALETTE) + 255 * sizeof (PALETTEENTRY)) ;

			plp->palVersion 			= 0x0300 ;
			plp->palNumEntries 		= 256 ;

 			for (i = 0 ; i < 256 ; i++)
			{
					plp->palPalEntry[i].peRed   		= i ;
					plp->palPalEntry[i].peGreen 		= 0 ;
               					plp->palPalEntry[i].peBlue  	= 0 ;
               					plp->palPalEntry[i].peFlags 	= PC_EXPLICIT ;
         	 		}
          
			hPalette = CreatePalette (plp) ;
			free (plp) ;          
			return 0 ;
     
	case 	WM_DISPLAYCHANGE:
          			if (!CheckDisplay (hwnd))
               					DestroyWindow (hwnd) ;

          			return 0 ;

     	case 	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
          			return 0 ;

     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;

          			for (y = 0 ; y < 16 ; y++)
          			for (x = 0 ; x < 16 ; x++)
          			{
               				hBrush = CreateSolidBrush (PALETTEINDEX (16 * y + x)) ;
               				SetRect (&rect, x 	* cxClient /16, y	* cyClient / 16,
                             (x + 1)`	* 	cxClient	/	16,(y+1)	* cyClient / 16);
               				FillRect (hdc, &rect, hBrush) ;
               				DeleteObject (hBrush) ;
          			}
          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_PALETTECHANGED:
          			if ((HWND) wParam != hwnd)
               					InvalidateRect (hwnd, NULL, FALSE) ;

          			return 0 ;

     	case 	WM_DESTROY:
          			DeleteObject (hPalette) ;
          			PostQuitMessage (0) ;
          			return 0 ;
     }
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

SYSPAL2��WM_CREATEѶϢ�����ڼ佨�����߼���ɫ�̡�������ע�⣺�߼���ɫ�������е�256��ֵ���Ǵ�0��255�ĵ�ɫ������������peFlags��λ��PC_EXPLICIT�����������������ģ����߼���ɫ����Ŀ�Ľϵ�����ָ����һ��Ӳ���ɫ�����������������Ӧ�ó�ʽ��ʾӲ���ɫ�̵����ݡ�����������רΪ����Ҫ��������������Ƶġ�

��WM_PAINTѶϢ�����ڼ䣬SYSPAL2���õ�ɫ��ѡ��װ�����ݲ����������ⲻ������ϵͳ��ɫ�̵��κ����飬����������ʽʹ��PALETTEINDEX�޼���ָ��ϵͳ��ɫ���е���ɫ�����˷�����SYSPAL2��ʾ��256�����Ρ����⣬����ִ�иó�ʽʱ��ע�ⶥ�к͵��е�ǰ10�ֺ���10����ɫ��20�ֱ�����ɫ�����16-1��ʾ������ִ��ʹ���Լ��߼���ɫ�̵ij�ʽʱ����ʾ�͸ı��ˡ�

�������ϲ����SYSPAL2�е���ɫ����ϲ��RGB��ֵ����ô����ڰ��µ�WHATCLR��ʽͬʱִ�С�

SYSPALϵ���еĵ�����ʹ�õļ���������˵������ų��ֵģ����ҿ�ʼ�о�Windows��ɫ�̹�����������ᣬ�ų�������Щ������

��ʵ�ϣ����е�GDI��ʽ��ֱ�ӻ��ӵ�ָ����ɫ��ΪRGBֵ����GDI�ڲ����⽫ת�������Ǹ���ɫ��ص�ͼ��λԪ����ijЩ��ʾģʽ�У����磬16λԪ��24λԪ��ɫģʽ������Щת�����൱ֱ�ӵġ���������ʾģʽ�У�4λԪ��8λԪ��ɫ����������漰��ӽ���ɫ��������

Ȼ����������GDI��ʽ����ֱ��ָ��ͼ��λԪ�е���ɫ����Ȼ�����ַ�ʽ��ʹ�õ���������ʽ�����豸�߶���ء�����̫�����豸�ˣ���������ǿ���ֱ����ʾ��Ѷ��ʾ����ʵ�ʵĵ�ɫ�̶��ձ�����������ʽ��BitBlt��StretchBlt��

��ʽ16-6��ʾ��SYSPAL3��ʽ��ʾ��ʹ��StretchBlt��ʾϵͳ��ɫ������ɫ�ķ�����

 ï¿½ï¿½Ê½16-6  SYSPAL3
SYSPAL3.C
/*---------------------------------------------------------------------------
   	SYSPAL3.C -- 	Displays system palette
                						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName [] = TEXT ("SysPal3") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    							PSTR szCmdLine, int iCmdShow)
{
     	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= NULL ;
     	wndclass.lpszClassName 		= szAppName ;
     	if (!RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"),
                      								szAppName, MB_ICONERROR) ;
          		return 0 ;
     	}

	hwnd = CreateWindow (	szAppName, TEXT ("System Palette #3"), 
                          	WS_OVERLAPPEDWINDOW, 
                          	CW_USEDEFAULT, CW_USEDEFAULT,
                          	CW_USEDEFAULT, CW_USEDEFAULT,
                          	NULL, NULL, hInstance, NULL) ;

	if (!hwnd)
          			return 0 ;
	ShowWindow (hwnd, iCmdShow) ;
     	UpdateWindow (hwnd) ;

     	while (GetMessage (&msg, NULL, 0, 0))
     	{
          			TranslateMessage (&msg) ;
          			DispatchMessage (&msg) ;
     	}
     	return msg.wParam ;
}

BOOL CheckDisplay (HWND hwnd)
{
     	HDC hdc ;
     	int iPalSize ;

     	hdc = GetDC (hwnd) ;
     	iPalSize = GetDeviceCaps (hdc, SIZEPALETTE) ;
     	ReleaseDC (hwnd, hdc) ;

     	if (iPalSize != 256)
     	{
       MessageBox (hwnd,TEXT("This program requires that the video ")
                        TEXT("display mode have a 256-color palette."),
                      		 szAppName, MB_ICONERROR) ;
          			return FALSE ;
     	}
	return TRUE ;
}

LRESULT CALLBACK WndProc (	HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
     	static HBITMAP hBitmap ;
     	static int     			cxClient, cyClient ;
     	BYTE           			bits [256] ;
     	HDC            			hdc, hdcMem ;
     	int            			i ;
     	PAINTSTRUCT    			ps ;

     	switch (message)
     	{
     	case 	WM_CREATE:
          			if (!	CheckDisplay (hwnd))
               						return -1 ;

          			for (	i = 0 ; i < 256 ; i++)
               				 		bits [i] = i ;
          
          			hBitmap = CreateBitmap (16, 16, 1, 8, &bits) ;
          			return 0 ;
                                                        
     	case 	WM_DISPLAYCHANGE:
          			if (!CheckDisplay (hwnd))
               					DestroyWindow (hwnd) ;

          			return 0 ;

     	case 	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
          			return 0 ;

     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

          			hdcMem = CreateCompatibleDC (hdc) ;
          			SelectObject (hdcMem, hBitmap) ;

          			StretchBlt (hdc,    0, 0, cxClient, cyClient,
          					    hdcMem, 0, 0, 16, 16, SRCCOPY) ;

          			DeleteDC (hdcMem) ;
          			EndPaint (hwnd, &ps) ;
          			return 0 ;
     	case 	WM_DESTROY:
          			DeleteObject (hBitmap) ;
          			PostQuitMessage (0) ;
          			return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

��WM_CREATEѶϢ�����ڼ䣬SYSPAL3ʹ��CreateBitmap������16��16��ÿͼ��8λԪ�ĵ���ͼ���ú�ʽ������һ�������ǰ�����ֵ0��255��256λԪ�����С���Щ��256�ֿ��ܵ�ͼ��λԪֵ���ڴ���WM_PAINTѶϢ�ij����У���ʽ���������ͼѡ��������װ�����ݣ���StretchBlt����ʾ��������ʾ����Windows��������ͼ�е�ͼ��λԪ���䵽��Ѷ��ʾ��Ӳ�壬�Ӷ�������Щͼ��λԪ��ȡ��ɫ�̶��ձ��е�256����Ŀ����ʽ����ʾ������������ʹ����WM_PALETTECHANGEDѶϢ��Ч����춶��ձ����κ��޸Ķ�������Ӱ�쵽SYSPAL3����ʾ��

��ɫ�̶���
��

�ڱ��ڵı����п�����������һ�ʣ�����ʼ����өĻ��Χִ�еġ����Գ��ʱ��������ǰ���ܻ�Ϊ֮һ�����ǵģ�������ʹ��Windows��ɫ�̹�������һЩ��������������һ��רҵˮƽ�Ķ�����

ͨ����Windows�µĶ������ǿ�����������ʾһϵ�е���ͼ����ɫ�̶��������ַ����кܴ��������͸����өĻ�ϻ���������Ҫ��ÿ��������ʼ��Ȼ����������ɫ�����ı���Щ�������ɫ�������ǻ�һЩ����өĻ������˵�Dz��ɼ���ͼ���������ַ����Ϳ��Ի�ö���Ч�����������ػ��κζ�������ɫ�̶������ٶ����൱��ġ�

��춵�ɫ�̶���������Ľ�������������ǰ�濴������Щ��ͬ����춶����ڼ�Ҫ�޸ĵ�ÿ��RGB��ɫֵ��PALETTEENTRY�ṹ��peFlags��λ�����趨ΪPC_RESERVED��

ͨ��������������������һ�����ڽ����߼���ɫ��ʱ������peFlags�����Ϊ0��������GDI������߼���ɫ����ͬ������ɫӳ�䵽��ͬ��ϵͳ��ɫ����Ŀ�����磬��������Windows��ʽ�������˰���RGB��Ŀ10-10-10���߼���ɫ�̣���ô��ϵͳ��ɫ�̱��У�Windowsֻ��Ҫһ��10-10-10��Ŀ���������������ʽ�е�һ��ʹ�õ�ɫ�̶����������Ͳ�Ҫ����GDIʹ�õ�ɫ���ˡ���ɫ�̶�����ζ���ٶȷdz��죭����������ػ�����Ҳֻ��������ٶȡ���ʹ�õ�ɫ�̶����ij�ʽ�޸ĵ�ɫ��ʱ��������Ӱ��������ʽ��������ʹGDI����ϵͳ��ɫ�̱���PC_RESERVED��peFlagsֵΪ�����߼���ɫ�̴���ϵͳ��ɫ����Ŀ��

ʹ�õ�ɫ�̶���ʱ��ͨ����������WM_PAINTѶϢ�����ڼ����SelectPalette��RealizePalette��ʹ��PALETTEINDEX�޼���ָ����ɫ���þ޼���һ�����������߼���ɫ�̱���

��춶�����������Ҫͨ���ı��ɫ������ӦWM_TIMERѶϢ��Ҫ�ı��߼���ɫ���е�RGB��ɫֵ����ʹ��һ��PALETTEENTRY�ṹ�����������к�ʽAnimatePalette���˺�ʽ�ٶȺܿ죬��Ϊ��ֻ��Ҫ�ı�ϵͳ��ɫ���Լ���ʾ��Ӳ���ɫ�̱��е���Ŀ��

��������
��

��ʽ16-7��ʾ��BOUNCE��ʽ��Ԫ����������һ����ʽ����ʾ��������Ϊ�˼������������ʾ����Ĵ�С���򻭳�����Բ�Ρ���Ϊ�����м�����ɫ�̶�����ʽ������PALANIM.C������ɫ�̶���������������һЩͨ�����ݡ�

 ï¿½ï¿½Ê½16-7  BOUNCE
PALANIM.C
/*--------------------------------------------------------------------------
   	PALANIM.C -- 	Palette Animation Shell Program
                						s(c) Charles Petzold, 1998
---------------------------------------------------------------------------*/

#include <windows.h>
extern HPALETTE 	CreateRoutine  		(HWND) ;
extern void     		PaintRoutine   	(HDC, int, int) ;
extern void     		TimerRoutine   	(HDC, HPALETTE) ;
extern void     		DestroyRoutine 	(HWND, HPALETTE) ;

LRESULT 	CALLBA CK 	WndProc  (HWND, UINT, WPARAM, LPARAM) ;

extern TCHAR szAppName [] ;
extern TCHAR szTitle [] ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    							PSTR szCmdLine, int iCmdShow)
{
     	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= NULL ;
     	wndclass.lpszClassName 		= szAppName ;
     
     	if (!RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"),
                      								szAppName, MB_ICONERROR) ;
          			return 0 ;
     }
     
     	hwnd = CreateWindow (	szAppName, szTitle, 
                          WS_OVERLAPPEDWINDOW, 
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;

     	if (!hwnd)
          			return 0 ;
     	ShowWindow (hwnd, iCmdShow) ;
     	UpdateWindow (hwnd) ;

     	while (GetMessage (&msg, NULL, 0, 0))
     {
          			TranslateMessage (&msg) ;
          			DispatchMessage (&msg) ;
     	}
     	return msg.wParam ;
}

BOOL CheckDisplay (HWND hwnd)
{
     	HDC hdc ;
     	int iPalSize ;

     	hdc = GetDC (hwnd) ;
     	iPalSize = GetDeviceCaps (hdc, SIZEPALETTE) ;
     	ReleaseDC (hwnd, hdc) ;

	if (iPalSize != 256)
     	{
      MessageBox (hwnd,	TEXT ("This program requires that the video ")
                        TEXT ("display mode have a 256-color palette."),
                      		szAppName, MB_ICONERROR) ;
          		return FALSE ;
     	}
     	return TRUE ;
}

LRESULT CALLBACK WndProc (	HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
     	static HPALETTE 	hPalette ;
     	static int      			cxClient, cyClient ;
     	HDC             					hdc ;
     	PAINTSTRUCT     			ps ;

     	switch (message)
     	{
     	case 	WM_CREATE:
     			if (!CheckDisplay (hwnd))
        					return -1 ;

     			hPalette = CreateRoutine (hwnd) ;
      			return 0 ;
     
  	case 	WM_DISPLAYCHANGE:
      			if (!CheckDisplay (hwnd))
         					DestroyWindow (hwnd) ;

     			return 0 ;

  	case 	WM_SIZE:
     			cxClient = LOWORD (lParam) ;
     			cyClient = HIWORD (lParam) ;
     			return 0 ;

 	case 	WM_PAINT:
      			hdc = BeginPaint (hwnd, &ps) ;

     			SelectPalette (hdc, hPalette, FALSE) ;
     			RealizePalette (hdc) ;

     			PaintRoutine (hdc, cxClient, cyClient) ;

     			EndPaint (hwnd, &ps) ;
     			return 0 ;
 	case 	WM_TIMER:
     			hdc = GetDC (hwnd) ;

     			SelectPalette (hdc, hPalette, FALSE) ;

      			TimerRoutine (hdc, hPalette) ;

          			ReleaseDC (hwnd, hdc) ;
          			return 0 ;

   	case 	WM_QUERYNEWPALETTE:
			if (!hPalette)
					return FALSE ;

			hdc = GetDC (hwnd) ;
			SelectPalette (hdc, hPalette, FALSE) ;
			RealizePalette (hdc) ;
			InvalidateRect (hwnd, NULL, TRUE) ;

			ReleaseDC (hwnd, hdc) ;
			return TRUE ;

     	case 	WM_PALETTECHANGED:
          			if (!hPalette || (HWND) wParam == hwnd)
               					break ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			UpdateColors (hdc) ;

          			ReleaseDC (hwnd, hdc) ;
          			break ;

     	case 	WM_DESTROY:
          			DestroyRoutine (hwnd, hPalette) ;
          			PostQuitMessage (0) ;
          			return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}
 BOUNCE.C
/*--------------------------------------------------------------------------
   	BOUNCE.C -- 	Palette Animation Demo
               						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>
#define ID_TIMER 1
TCHAR szAppName 	[] = TEXT ("Bounce") ;
TCHAR szTitle   	[] = TEXT ("Bounce: Palette Animation Demo") ;

static LOGPALETTE * plp ;
HPALETTE CreateRoutine (HWND hwnd)
{
     	HPALETTE 		hPalette ;
     	int 			i ;

     	plp = malloc (sizeof (LOGPALETTE) + 33 * sizeof (PALETTEENTRY)) ;
     	plp->palVersion 		= 0x0300 ;
     	plp->palNumEntries	= 34 ;

     	for (i = 0 ; i < 34 ; i++)
     	{
          			plp->palPalEntry[i].peRed   	= 255 ;
          			plp->palPalEntry[i].peGreen 	= (i == 0 ? 0 : 255) ;
          			plp->palPalEntry[i].peBlue  	= (i == 0 ? 0 : 255) ;
          			plp->palPalEntry[i].peFlags 	= (i == 33 ? 0 : PC_RESERVED) ;
     }
	hPalette = CreatePalette (plp) ;
	SetTimer (hwnd, ID_TIMER, 50, NULL) ;
	return hPalette ;
}

void PaintRoutine (HDC hdc, int cxClient, int cyClient)
{
     	HBRUSH 	hBrush ;
     	int  		i, x1, x2, y1, y2 ;
     	RECT 		rect ;
          				// Draw window background using palette index 33

     	SetRect (&rect, 0, 0, cxClient, cyClient) ;
     	hBrush = CreateSolidBrush (PALETTEINDEX (33)) ;
	FillRect (hdc, &rect, hBrush) ;
	DeleteObject (hBrush) ;

          			// Draw the 33 balls
     	SelectObject (hdc, GetStockObject (NULL_PEN)) ;
     	for (i = 0 ; i < 33 ; i++)
     	{
          			x1 =  i * cxClient / 33 ;
          			x2 = (i + 1)* cxClient / 33 ;

          			if (i < 9)
          			{
               				y1  = i * cyClient / 9 ;
               				y2 = (i + 1) * cyClient / 9 ;
      				}
          		else if (i < 17)
          				{
               				y1 = (16 - i) * cyClient / 9 ;
               				y2 = (17 - i) * cyClient / 9 ;
          				}
          		else if (i < 25)
          		{
               				y1 = (i - 16) * cyClient / 9 ;
               				y2 = (i - 15) * cyClient / 9 ;
          		}
          		else 
          		{
               				y1 = (32 - i) * cyClient / 9 ;
               				y2 = (33 - i) * cyClient / 9 ;
          		}

          		hBrush = CreateSolidBrush (PALETTEINDEX (i)) ;
          		SelectObject (hdc, hBrush) ;
          		Ellipse (hdc, x1, y1, x2, y2) ;
          		DeleteObject (SelectObject (hdc, GetStockObject (WHITE_BRUSH))) ;
     	}
     	return ;
}

void TimerRoutine (HDC hdc, HPALETTE hPalette)
{
  	static BOOL bLeftToRight = TRUE ;
     	static int  iBall ;

          		// Set old ball to white
     	plp->palPalEntry[iBall].peGreen = 255 ;
     	plp->palPalEntry[iBall].peBlue  = 255 ;

     	iBall += (bLeftToRight ? 1 : -1) ;
     	if (	iBall == (bLeftToRight ? 33 : -1))
     	{
          			iBall = (bLeftToRight ? 31 : 1) ;
          			bLeftToRight ^= TRUE ;
     	}

          		// Set new ball to red

     	plp->palPalEntry[iBall].peGreen = 0 ;
     	plp->palPalEntry[iBall].peBlue  = 0 ;

          		// Animate the palette

     	AnimatePalette (hPalette, 0, 33, plp->palPalEntry) ;
     	return ;
}

void DestroyRoutine (HWND hwnd, HPALETTE hPalette)
{
     	KillTimer (hwnd, ID_TIMER) ;
     	DeleteObject (hPalette) ;
     	free (plp) ;
     	return ;
}

����Windows���֧Ԯ��ɫ�̵���ʾģʽ�£������ɫ�̶��������ܹ�������ˣ�PALANIM.Cͨ������CheckDisplay��ʽ����SYSPAL��ʽ�еĺ�ʽ��ͬ������ʼ����WM_CREATE��

PALANIM.C����BOUNCE.C�е��ĸ���ʽ����WM_CREATEѶϢ�����ڼ����CreateRoutine����BOUNCE����춽����߼���ɫ�̣�����WM_PAINTѶϢ�����ڼ����PaintRoutine����WM_TIMERѶϢ�����ڼ����TimerRoutine����WM_DESTROYѶϢ�����ڼ����DestroyRoutine����BOUNCE�������������ں���PaintRoutine��TimerRoutine֮ǰ��PALANIM.C���װ�����ݣ�������ѡ���߼���ɫ�̡��ں���PaintRoutine֮ǰ����Ҳ���ֵ�ɫ�̡�PALANIM.C����TimerRoutine����AnimatePalette������AnimatePalette��Ҫ��װ��������ѡ���ɫ�̣���������Ҫ����RealizePalette��

BOUNCE�е��򰴡�W��·������ʾ������������������ʾ���򱳾��ǰ�ɫ�����Ǻ�ɫ���κ�ʱ�򣬶�������33�����ص���λ��֮һ����������Ҫ34����ɫ����Ŀ��һ����춱���������33����춲�ͬλ�õ�����CreateRoutine�У�BOUNCE��ʼ��PALETTEENTRY�ṹ��һ�����У�����һ����ɫ����Ŀ�����������Ͻǵ�λ�ö�Ӧ���趨Ϊ��ɫ���������趨Ϊ��ɫ��ע�⣬��춳����������������Ŀ��peFlags��λ���趨ΪPC_RESERVED�������������һ����ɫ����Ŀ����BOUNCEͨ����Windows��ʱ���ļ���趨Ϊ50��������ֹCreateRoutine��

BOUNCE��PaintRoutine������еĻ滭�������Ӵ�������һ��ʵ�Ļ�ˢ�͵�ɫ������33��ָ������ɫ�����ơ�33�������ɫ�����ݴ�0��32�ĵ�ɫ����������ɫ����BOUNCE��һ������ʾ�����ڻ滭ʱ��0�ĵ�ɫ������ӳ��ɺ�ɫ��������ɫ������ӳ�䵽��ɫ���⵼������������Ͻǡ�

��WndProc����WM_TIMERѶϢ������TimerRoutineʱ�������ͷ����ˡ�TimerRoutineͨ������AnimatePalette���������﷨���£�

AnimatePalette (hPalette, uStart, uNum, &pe) ;

���У���һ�������ǵ�ɫ�̴��ţ�����һ��������ָ�����е�ָ�꣬��������һ������PALETTEENTRY�ṹ��ɡ��ú�ʽ�ı��߼���ɫ���д�uStart��Ŀ��uNum��Ŀ֮���������Ŀ���߼���ɫ�����µ�uStart��Ŀ��PALETTEENTRY�ṹ�еĵ�һ����Ա�����ģ�uStart�����ǽ���ԭʼ�߼���ɫ�̱��������������ǽ���PALETTEENTRY���е�������

Ϊ�˷��������BOUNCEʹ��PALETTEENTRY�ṹ�����У��ýṹ�ǽ����߼���ɫ��ʱʹ�õ�LOGPALETTE�ṹ��һ���֡����Ŀǰλ�ã���0��32�������ھ�̬����iBall�С���TimerRoutine�ڼ䣬BOUNCE��PALETTEENTRY��Ա��Ϊ��ɫ��Ȼ����������һ��λ�ã�������Ԫ����Ϊ��ɫ��������ĺ������ı��ɫ�̣�

AnimatePalette (hPalette, 0, 33, plp->palPalEntry) ;

GDI�ı�33�߼���ɫ����Ŀ�еĵ�һ��������ʵ����ֻ�ı�����������ʹ����ϵͳ��ɫ�̱��еı仯���Ӧ��Ȼ���޸���ʾ���ϵ�Ӳ���ɫ�̱��������������ػ���Ϳ�ʼ�ƶ��ˡ�

BOUNCEִ��ʱ�����ᷢ��ͬʱִ��SYSPAL2��SYSPAL3Ч������á�

����AnimatePaletteִ�е÷dz��죬���ǵ�ֻ��һ������Ŀ�ı�ʱ������Ӧ�þ�������ı����е��߼���ɫ����Ŀ������BOUNCE���е㸴�ӣ���Ϊ��Ҫ���ص�����iBallҪ�����ӣ�Ȼ���ټ��١�һ�ַ�����ʹ�������������ֱ��ΪiBallOld���趨���Ŀǰλ�ã���iBallMin��iBall��iBallOld�н�С�ģ���Ȼ�����Ϳ�����������������AnimatePalette���ı�������Ŀ�ˣ�

iBallMin = min (iBall, iBallOld) ;
AnimatePalette (hPal, iBallMin, 2, plp->palPalEntry + iBallMin) ;

������һ�ַ����������ȼٶ���������һ��PALETTEENTRY�ṹ��

PALETTEENTRY pe ;

��TimerRoutine�ڼ䣬����PALETTEENTRY��λ��Ϊ��ɫ��������AnimatePalette���ı��߼���ɫ����iBallλ�õ�һ����Ŀ��

pe.peRed   		= 255 ;
     	pe.peGreen 		= 255 ;
     	pe.peBlue  		= 255 ;
     	pe.peFlags 		= PC_RESERVED ;
     	AnimatePalette (hPalette, iBall, 1, &pe) ;

Ȼ�������ʾ��BOUNCE�е�iBall����ֵ����PALETTEENTRY�ṹ����λ����Ϊ��ɫ��Ȼ���ٴκ���AnimatePalette��

pe.peRed   		= 255 ;
     	pe.peGreen 		= 0 ;
     	pe.peBlue  		= 0 ;
     	pe.peFlags 		= PC_RESERVED ;
     	AnimatePalette (hPalette, iBall, 1, &pe) ;

�������������ǶԶ�����һ����ͳ�ļ�˵��������ʵ���ϲ����ʺϵ�ɫ�̶�������Ϊ�����Ȼ���������п���λ�á���ɫ�̶������ʺ����ʾ�˶����ظ�ͼ����

һ����Ŀ�ĵ�ɫ�̶���
��

��ɫ�̶�����һ������Ȥ�ķ�����ǣ�����ֻʹ��һ����ɫ����Ŀ�����һЩ��Ȥ�ļ����������ʽ16-8��ʾ��FADER��ʽ�������ʽҲ��Ҫǰ���PALANIM.C������

 ï¿½ï¿½Ê½16-8  FADER
FADER.C
/*--------------------------------------------------------------------------
   	FADER.C -- 	Palette Animation Demo
              					(c) Charles Petzold, 1998
--------------------------------------------------------------------------*/

#include <windows.h>
#define ID_TIMER 1
TCHAR szAppName	[] 	= TEXT ("Fader") ;
TCHAR szTitle 	[]	= TEXT ("Fader: Palette Animation Demo") ;

static LOGPALETTE lp ;
HPALETTE CreateRoutine (HWND hwnd)
{
     	HPALETTE hPalette ;
     	lp.palVersion             		= 0x0300 ;
     	lp.palNumEntries          		= 1 ;
     	lp.palPalEntry[0].peRed   		= 255 ;
     	lp.palPalEntry[0].peGreen 		= 255 ;
     	lp.palPalEntry[0].peBlue  		= 255 ;
     	lp.palPalEntry[0].peFlags 		= PC_RESERVED ;
   
     	hPalette = CreatePalette (&lp) ;
     	SetTimer (hwnd, ID_TIMER, 50, NULL) ;
     	return hPalette ;
}

void 	PaintRoutine (HDC hdc, int cxClient, int cyClient)
{
    	static TCHAR 		szText [] = TEXT (" Fade In and Out ") ;
    	int          					x, y ;
     	SIZE         					sizeText ;

     	SetTextColor (hdc, PALETTEINDEX (0)) ;
     	GetTextExtentPoint32 (hdc, szText, lstrlen (szText), &sizeText) ;

     	for (x = 0 ; x < cxClient ; x += sizeText.cx)
     	for (y = 0 ; y < cyClient ; y += sizeText.cy)
     	{
          		TextOut (hdc, x, y, szText, lstrlen (szText)) ;
     	}

     	return ;
}

void TimerRoutine (HDC hdc, HPALETTE hPalette)
{
     	static BOOL bFadeIn = TRUE ;
     	if (bFadeIn)
     	{
          			lp.palPalEntry[0].peRed   -= 4 ;
          			lp.palPalEntry[0].peGreen -= 4 ;

          			if (	lp.palPalEntry[0].peRed == 3)
               					bFadeIn = FALSE ;
     	}
     	else
     	{
          			lp.palPalEntry[0].peRed   += 4 ;
          			lp.palPalEntry[0].peGreen += 4 ;

          			if 	 (lp.palPalEntry[0].peRed == 255)
               					bFadeIn = TRUE ;
     	}

     	AnimatePalette (hPalette, 0, 1, lp.palPalEntry) ;
     	return ;
}

void DestroyRoutine (HWND hwnd, HPALETTE hPalette)
{
     	KillTimer (hwnd, ID_TIMER) ;
     	DeleteObject (hPalette) ;
     	return ;
}

FADER����ʾ��������ʾ���������ִ���Fade In And Out��������������ʾΪ��ɫ�����춰�ɫ�������Ӵ���˵�ǿ��������ġ�ͨ��ʹ�õ�ɫ�̶�����FADER�����ؽ����ֵ���ɫ��Ϊ��ɫ��Ȼ���ٸĻذ�ɫ������һ��һ����ظ������־��н��ֽ�������ʾЧ���ˡ�

FADER��CreateRoutine��ʽ�������߼���ɫ�̣���ֻ��Ҫһ����ɫ����Ŀ��������ɫ��ʼ��Ϊ��ɫ����ɫ����ɫ����ɫֵ����Ϊ255����PaintRoutine�У����������𣬵��߼���ɫ��ѡ��װ�����ݲ��������ᣬPALANIM���й��˺�ʽ����FADER����SetTextColor��������ɫ�趨ΪPALETTEINDEX(0)������ζ��������ɫ�趨Ϊ��ɫ�̱����еĵ�һ����Ŀ������Ŀ��ʼΪ��ɫ��Ȼ��FADER�á�Fade In And Out�������ִ������ʾ������ʱ���Ӵ������ǰ�ɫ������Ҳ�ǰ�ɫ���������ֲ��ɼ���

��TimerRoutine��ʽ�У�FADERͨ���ı�PALETTEENTRY�ṹ�����䴫�ݸ�AnimatePalette����ɵ�ɫ�̶������������ÿһ��WM_TIMERѶϢ����ʽ������ɫ����ɫֵ��4��ֱ�����3��Ȼ�Ὣ��Щֵ��4��ֱ�����255���⽫ʹ������ɫ�𽥴Ӱ�ɫ�䵽��ɫ��Ȼ���ֻص���ɫ��

��ʽ16-9��ʾ��ALLCOLOR��ʽֻ�����߼���ɫ�̵�һ����Ŀ����ʾ��ʾ��������ɫ��������ɫ����Ȼ����ʽ����ͬʱ��ʾ��Щ��ɫ������������ʾ�������ʾ����18λԪ�Ľ����ȣ���ʱ����262144�ֲ�ͬ����ɫ������ô��������ɫ���55������ٶ��£�ֻ��Ҫ4Сʱ�Ϳ�����өĻ�Ͽ������е���ɫ��

 ï¿½ï¿½Ê½16-9  ALLCOLOR
ALLCOLOR.C
/*---------------------------------------------------------------------------
   	ALLCOLOR.C -- 		Palette Animation Demo
                 							(c) Charles Petzold, 1998
-----------------------------------------------------------------------------*/

#include <windows.h>
#define ID_TIMER    1

TCHAR szAppName 	[] = TEXT ("AllColor") ;
TCHAR szTitle   	[] = TEXT ("AllColor: Palette Animation Demo") ;

static 	int          				iIncr ;
static 	PALETTEENTRY 	pe ;

HPALETTE CreateRoutine (HWND hwnd)
{
     	HDC        		hdc ;
	HPALETTE   			hPalette ;
     	LOGPALETTE 		lp ;

          			// Determine the color resolution and set iIncr
     	hdc = GetDC (hwnd) ;
     	iIncr = 1 << (8 - GetDeviceCaps (hdc, COLORRES) / 3) ;
     	ReleaseDC (hwnd, hdc) ;

          			// Create the logical palette
     	lp.palVersion             	    = 0x0300 ;
     	lp.palNumEntries         	 	= 1 ;
     	lp.palPalEntry[0].peRed   		= 0 ;
     	lp.palPalEntry[0].peGreen 		= 0 ;
     	lp.palPalEntry[0].peBlue  		= 0 ;
     	lp.palPalEntry[0].peFlags 		= PC_RESERVED ;
   
     	hPalette = CreatePalette (&lp) ;
          			// Save global for less typing
     	pe = lp.palPalEntry[0] ;
     	SetTimer (hwnd, ID_TIMER, 10, NULL) ;
     	return hPalette ;
}

void DisplayRGB (HDC hdc, PALETTEENTRY * ppe)
{
     	TCHAR szBuffer [16] ;
     	wsprintf (szBuffer, TEXT (" %02X-%02X-%02X "),
               					ppe->peRed, ppe->peGreen, ppe->peBlue) ;
     	TextOut (hdc, 0, 0, szBuffer, lstrlen (szBuffer)) ;
}

void PaintRoutine (HDC hdc, int cxClient, int cyClient)
{
     	HBRUSH   		hBrush ;
     	RECT     			rect ;

          			// Draw Palette Index 0 on entire window

	hBrush = CreateSolidBrush (PALETTEINDEX (0)) ;
     	SetRect (&rect, 0, 0, cxClient, cyClient) ;
     	FillRect (hdc, &rect, hBrush) ;
     	DeleteObject (SelectObject (hdc, GetStockObject (WHITE_BRUSH))) ;
          			// Display the RGB value
     	DisplayRGB (hdc, &pe) ;
     	return ;
}

void TimerRoutine (HDC hdc, HPALETTE hPalette)
{
     	static BOOL  bRedUp = TRUE, bGreenUp = TRUE, bBlueUp = TRUE ;
          					// Define new color value
     	pe.peBlue += (bBlueUp ? iIncr : -iIncr) ;
     	if (	pe.peBlue == (BYTE) (bBlueUp ? 0 : 256 - iIncr))
     	{
      			pe.peBlue = (bBlueUp ? 256 - iIncr : 0) ;
          			bBlueUp ^= TRUE ;
          			pe.peGreen += (bGreenUp ? iIncr : -iIncr) ;

          		if (	pe.peGreen == (BYTE) (bGreenUp ? 0 : 256 - iIncr))
          	{
					pe.peGreen = (bGreenUp ? 256 - iIncr : 0) ;
               					bGreenUp ^= TRUE ;
					pe.peRed += (bRedUp ? iIncr : -iIncr) ;

               					if (	pe.peRed == (BYTE) (bRedUp ? 0 : 256 - iIncr))
               					{
                    					pe.peRed = (bRedUp ? 256 - iIncr : 0) ;
                    					bRedUp ^= TRUE ;
               					}
          			}
	 }

          					// Animate the palette
     	AnimatePalette (hPalette, 0, 1, &pe) ;
     	DisplayRGB (hdc, &pe) ;
     	return ;
}

void DestroyRoutine (HWND hwnd, HPALETTE hPalette)
{
     	KillTimer (hwnd, ID_TIMER) ;
     	DeleteObject (hPalette) ;
     	return ;
}

�ڽṹ�ϣ�ALLCOLOR��FADER�dz����ơ���CreateRoutine�У�ALLCOLORֻ��һ����Ϊ��ɫ�ĵ�ɫ����Ŀ��PALETTEENTRY�ṹ��red��green��blue��λ��Ϊ0����������ɫ�̡���PaintRoutine�У�ALLCOLOR��PALETTEINDEX(0)����ʵ�Ļ�ˢ��������FillRect���ô˻�ˢΪ������ʾ������ɫ��

��TimerRoutine�У�ALLCOLORͨ���ı�PALETTEENTRY��ɫ������AnimatePalette��������ɫ�̡��ұ�дALLCOLOR��ʽ���Ա���ɫ�仯˳�������ȣ���ɫֵ�������ӡ��ﵽ���ʱ����ɫֵ���ӣ�����ɫֵ�������١���ɫ����ɫ����ɫֵ�����Ӻͼ���ȡ���iIncr��������CreateRoutine�ڼ䣬�⽫������COLORRES������GetDeviceCaps���ص�ֵ�����㡣���磬���GetDeviceCaps����18����ôiIncr��Ϊ4�����������ɫ����Ҫ����Сֵ��

ALLCOLOR������ʾ��������Ͻ���ʾĿǰ��RGB��ɫֵ����������������ʽ���dz�춲���Ŀ�ģ���������֤���������õģ������ұ���������

����Ӧ�ó�ʽ
��

�ڹ���Ӧ�ó�ʽ�У����������ʾ��е�������ù��̺����á��ڵ���өĻ����ʾ��ȼ������Ȼ�򵥣����Ƕ�������ʹ����ø����������Ҹ��������ʾ�乤������

ʹ�õ�ɫ�̶�����һ���÷���������ʾ����ͨ�����ӵĹ��̡�����һ�����ӣ�ͼ�񲻱�ʮ�־�ȷ��ʵ���ϣ����ͼ��ܾ�ȷ������͸���Ĺ��ӣ��������˵�������������������˶��ġ���ʱ�÷��Ż����һЩ����ʽ16-10��ʾ��PIPES��ʽ�Ǵ˼����ļ�ʾ��������ʾ����������ˮƽ�Ĺ��ӣ�����������Ĺ��������������������������Ĺ�������������ƶ���

��ʽ16-10 PIPES

 PIPES.C
/*-------------------------------------------------------------------------
   	PIPES.C -- 		Palette Animation Demo
              						(c) Charles Petzold, 1998
---------------------------------------------------------------------------*/

#include <windows.h>
#define ID_TIMER 1
TCHAR szAppName [] = TEXT ("Pipes") ;
TCHAR szTitle   [] = TEXT ("Pipes: Palette Animation Demo") ;

static LOGPALETTE * plp ;

HPALETTE CreateRoutine (HWND hwnd)
{
     	HPALETTE 		hPalette ;
     	int  			i ;

     	plp = malloc (sizeof (LOGPALETTE) + 32 * sizeof (PALETTEENTRY)) ;
          				// Initialize the fields of the LOGPALETTE structure
     	plp->palVersion    	= 0x300 ;
     	plp->palNumEntries 	= 16 ;

     	for (i = 0 ; i <= 8 ; i++)
	{
          			plp->palPalEntry[i].peRed   	= (BYTE) min (255, 0x20 * i) ;
          			plp->palPalEntry[i].peGreen 	= 0 ;
          			plp->palPalEntry[i].peBlue  	= (BYTE) min (255, 0x20 * i) ;
          			plp->palPalEntry[i].peFlags 	= PC_RESERVED ;

          			plp->palPalEntry[16 - i] 	= plp->palPalEntry[i] ;
          			plp->palPalEntry[16 + i] 	= plp->palPalEntry[i] ;
          			plp->palPalEntry[32 - i] 	= plp->palPalEntry[i] ;
     	}

     	hPalette = CreatePalette (plp) ;
     	SetTimer (hwnd, ID_TIMER, 100, NULL) ;
     	return hPalette ;
}

void PaintRoutine (HDC hdc, int cxClient, int cyClient)
{
     	HBRUSH 	hBrush ;
     	int    		i ;
     	RECT   		rect ;

          					// Draw window background

     	SetRect (&rect, 0, 0, cxClient, cyClient) ;
     	hBrush = SelectObject (hdc, GetStockObject (WHITE_BRUSH)) ;
     	FillRect (hdc, &rect, hBrush) ;

          					// Draw the interiors of the pipes
     	for (i = 0 ; i < 128 ; i++)
     	{
          			hBrush = CreateSolidBrush (PALETTEINDEX (i % 16)) ;
          			SelectObject (hdc, hBrush) ;

          			rect.left   		= (127 - i) * cxClient / 128 ;
          			zrect.right  		= (128 - i) * cxClient / 128 ;
          			rect.top    		= 4 * cyClient / 14 ;
          			rect.bottom 		= 5 * cyClient / 14 ;

          			FillRect (hdc, &rect, hBrush) ;

          			rect.left   		=  	i * cxClient / 128 ;
          			rect.right  		= (	i + 1) 	* cxClient / 128 ;
          			rect.top    		=  	9 	* cyClient / 14 ;
          			rect.bottom 		= 	10 	* cyClient / 14 ;

          			FillRect (hdc, &rect, hBrush) ;

          		DeleteObject (SelectObject (hdc, GetStockObject (WHITE_BRUSH))) ;
     }

          					// Draw the edges of the pipes
     	MoveToEx 		(hdc, 0,  4 * cyClient / 14, NULL) ;
     	LineTo   		(hdc, cxClient,  4 	* cyClient / 14) ;

     	MoveToEx 		(hdc, 0,  5 * cyClient / 14, NULL) ;
     	LineTo   		(hdc, cxClient,	5 	* cyClient / 14) ;

     	MoveToEx 		(hdc, 0,  9	* cyClient / 14, NULL) ;
     	LineTo   		(hdc, cxClient, 9 * cyClient / 14) ;

     	MoveToEx 		(hdc, 0,  10 * cyClient / 14, NULL) ;
     	LineTo   (hdc, cxClient, 		10 * cyClient / 14) ;
     	return ;
}

void TimerRoutine (HDC hdc, HPALETTE hPalette)
{
     	static int iIndex ;
     	AnimatePalette (hPalette, 0, 16, plp->palPalEntry + iIndex) ;
     	iIndex = (iIndex + 1) % 16 ;

     	return ;
}

void DestroyRoutine (HWND hwnd, HPALETTE hPalette)
{
     	KillTimer (hwnd, ID_TIMER) ;
     	DeleteObject (hPalette) ;
     	free (plp) ;
     	return ;
}

PIPESΪ����ʹ����16����ɫ����Ŀ���������ܻ�ʹ�ø��ٵ���Ŀ����С��ʱ��������Ҫ�������㹻����Ŀ����ʾ�����ķ�����������ɫ����ĿҪ����һ����̬��ͷ�á�

��ʽ16-11��ʾ��TUNNEL��ʽ�������ʽ����̰�ĵij�ʽ����Ϊ����ʹ����128����ɫ����Ŀ�����Ǵ�Ч��������ֵ����������

 ï¿½ï¿½Ê½16-11  TUNNEL
TUNNEL.C
/*---------------------------------------------------------------------------
   	TUNNEL.C -- 	Palette Animation Demo
               						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>
#define ID_TIMER 1
TCHAR szAppName 	[] = TEXT ("Tunnel") ;
TCHAR szTitle   	[] = TEXT ("Tunnel: Palette Animation Demo") ;

static LOGPALETTE * plp ;
HPALETTE CreateRoutine (HWND hwnd)
{
     	BYTE     		byGrayLevel ;
     	HPALETTE 		hPalette ;
     	int      		i ;

     	plp = malloc (sizeof (LOGPALETTE) + 255 * sizeof (PALETTEENTRY)) ;
          			// Initialize the fields of the LOGPALETTE structure
     	plp->palVersion    	= 0x0300 ;
     	plp->palNumEntries 	= 128 ;
     
     	for (i = 0 ; i < 128 ; i++)
     	{
          			if (i < 64)
               					byGrayLevel = (BYTE) (4 * i) ;
          			else
               					byGrayLevel = (BYTE) min (255, 4 * (128 - i)) ;
          			plp->palPalEntry[i].peRed 	= byGrayLevel ;
          			plp->palPalEntry[i].peGreen	= byGrayLevel ;
          			plp->palPalEntry[i].peBlue	= byGrayLevel ;
          			plp->palPalEntry[i].peFlags	= PC_RESERVED ;
          
          			plp->palPalEntry[i + 128].peRed 	 = byGrayLevel ;
          			plp->palPalEntry[i + 128].peGreen = byGrayLevel ;
          			plp->palPalEntry[i + 128].peBlue  = byGrayLevel ;
          			plp->palPalEntry[i + 128].peFlags = PC_RESERVED ;
     	}
   
     	hPalette = CreatePalette (plp) ;
     	SetTimer (hwnd, ID_TIMER, 50, NULL) ;
     	return hPalette ;
}

void PaintRoutine (HDC hdc, int cxClient, int cyClient)
{
     	HBRUSH 	hBrush ;
     	int    		i ;
     	RECT   		rect ;
     
     	for (i = 0 ; i < 127 ; i++)
     {
               				// Use a RECT structure for each of 128 rectangles
      			rect.left   =   i * cxClient / 255 ;
       			rect.top    =   i * cyClient / 255 ;
          			rect.right  = cxClient - i * cxClient / 255 ;
          			rect.bottom = cyClient - i * cyClient / 255 ;
          
          			hBrush = CreateSolidBrush (PALETTEINDEX (i)) ;
               				// Fill the rectangle and delete the brush
          
          			FillRect (hdc, &rect, hBrush) ;
          			DeleteObject (hBrush) ;
     	}
     	return ;
}

void TimerRoutine (HDC hdc, HPALETTE hPalette)
{
     	static int iLevel ;
     	iLevel = (iLevel + 1) % 128 ;
     	AnimatePalette (hPalette, 0, 128, plp->palPalEntry + iLevel) ;
     	return ;
}

void DestroyRoutine (HWND hwnd, HPALETTE hPalette)
{
     	KillTimer (hwnd, ID_TIMER) ;
     	DeleteObject (hPalette) ;
     	free (plp) ;
     	return ;
}

TUNNEL��128����ɫ����Ŀ��ʹ��64���ƶ��Ļҽף��Ӻڵ��ף��ٴӰ׵��ڣ��������������е�Ч����

��ɫ�̺���ʵ����ͼ��
��

��Ȼ�����������Ѿ������������Ȥ���£�������ʾɫ�ʵ����ס����˵�ɫ�̶���������ɫ�̹�����������Ŀ����������8λԪ��ʾģʽ����ʾ��ʵ�����е�ͼ�񡣶�춱��µ����ಿ�֣����������о�һ�¡��������������ģ���ʹ��packed DIB��GDI����ͼ�����DIB����ʱ�����밴�ղ�ͬ�ķ�����ʹ�õ�ɫ�̡������������ʽ�������õ�ɫ������������ͼ�ĸ��ּ�����

��ɫ�̺�packed DIB
��

����������ʽ����������ǽ�������packed DIB��������һϵ�к�ʽ����Щ��ʽ���ڳ�ʽ16-12��ʾ��PACKEDIB�����С�

 ï¿½ï¿½Ê½16-12  PACKEDIB����
PACKEDIB.H
/*-------------------------------------------------------------------------
   PACKEDIB.H -- 	Header file for PACKEDIB.C
          							(c) Charles Petzold, 1998
--------------------------------------------------------------------------*/

#include <windows.h>

BITMAPINFO * PackedDibLoad (PTSTR szFileName) ;
int PackedDibGetWidth (BITMAPINFO * pPackedDib) ;
int PackedDibGetHeight (BITMAPINFO * pPackedDib) ;
int PackedDibGetBitCount (BITMAPINFO * pPackedDib) ;
int PackedDibGetRowLength (BITMAPINFO * pPackedDib) ;
int PackedDibGetInfoHeaderSize (BITMAPINFO * pPackedDib) ;
int PackedDibGetColorsUsed (BITMAPINFO * pPackedDib) ;
int PackedDibGetNumColors (BITMAPINFO * pPackedDib) ;
int PackedDibGetColorTableSize (BITMAPINFO * pPackedDib) ;
RGBQUAD * PackedDibGetColorTablePtr (BITMAPINFO * pPackedDib) ;
RGBQUAD * PackedDibGetColorTableEntry (BITMAPINFO * pPackedDib, int i) ;
BYTE * PackedDibGetBitsPtr (BITMAPINFO * pPackedDib) ;
int PackedDibGetBitsSize (BITMAPINFO * pPackedDib) ;
HPALETTE PackedDibCreatePalette (BITMAPINFO * pPackedDib) ;
PACKEDIB.C
/*-------------------------------------------------------------------------
   	PACKEDIB.C -- 		Routines for using packed DIBs
                 							(c) Charles Petzold, 1998
---------------------------------------------------------------------------*/

#include <windows.h>

/*---------------------------------------------------------------------------
   	PackedDibLoad: Load DIB File as Packed-Dib Memory Block
----------------------------------------------------------------------------*/

BITMAPINFO * PackedDibLoad (PTSTR szFileName)
{
     	BITMAPFILEHEADER 		bmfh ;
     	BITMAPINFO     			*	pbmi ;
     	BOOL             		bSuccess ;
     	DWORD            		dwPackedDibSize, dwBytesRead ;
     	HANDLE           		hFile ;
          		// Open the file: read access, prohibit write access

     	hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
        OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL) ;
     	if (hFile == INVALID_HANDLE_VALUE)
          			return NULL ;
  			// Read in the BITMAPFILEHEADER
     	bSuccess = ReadFile (	hFile, &bmfh, sizeof (BITMAPFILEHEADER), 
                          	&dwBytesRead, NULL) ;

     	if (!bSuccess 	|| (dwBytesRead != sizeof (BITMAPFILEHEADER))         
                   		|| (bmfh.bfType != * (WORD *) "BM"))
     	{
          			CloseHandle (hFile) ;
          			return NULL ;
     	}

          			// Allocate memory for the packed DIB & read it in
     	dwPackedDibSize = bmfh.bfSize - sizeof (BITMAPFILEHEADER) ;
     	pbmi = malloc (dwPackedDibSize) ;
  	bSuccess = ReadFile (hFile, pbmi, dwPackedDibSize, &dwBytesRead, NULL) ;
     	CloseHandle (hFile) ;

     	if (!bSuccess || (dwBytesRead != dwPackedDibSize))
     	{
          			free (pbmi) ;
          			return NULL ;
     	}

     	return pbmi ;
}

/*--------------------------------------------------------------------------
   Functions to get information from packed DIB
----------------------------------------------------------------------------*/

int PackedDibGetWidth (BITMAPINFO * pPackedDib)
{
     	if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
          			return ((PBITMAPCOREINFO)pPackedDib)->bmciHeader.bcWidth ;
     	else
          			return pPackedDib->bmiHeader.biWidth ;
}

int PackedDibGetHeight (BITMAPINFO * pPackedDib)
{
    	if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
          			return ((PBITMAPCOREINFO)pPackedDib)->bmciHeader.bcHeight ;
     	else
          			return abs (pPackedDib->bmiHeader.biHeight) ;
}

int PackedDibGetBitCount (BITMAPINFO * pPackedDib)
{
     	if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
          			return ((PBITMAPCOREINFO)pPackedDib)->bmciHeader.bcBitCount ;
     	else
          			return pPackedDib->bmiHeader.biBitCount ;
}

int PackedDibGetRowLength (BITMAPINFO * pPackedDib)
{
     	return ((	PackedDibGetWidth (pPackedDib) * 
              					PackedDibGetBitCount (pPackedDib) + 31) & ~31) >> 3 ;
}

/*---------------------------------------------------------------------------
   	PackedDibGetInfoHeaderSize includes possible color masks!
----------------------------------------------------------------------------*/

int PackedDibGetInfoHeaderSize (BITMAPINFO * pPackedDib)
{
     	if (	pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
         		 	return ((PBITMAPCOREINFO)pPackedDib)->bmciHeader.bcSize ;

     	else 	if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPINFOHEADER))
          			return pPackedDib->bmiHeader.biSize + 
                    (pPackedDib->bmiHeader.biCompression == 
                     BI_BITFIELDS ? 12 : 0) ;
     	else return pPackedDib->bmiHeader.biSize ;
}

/*--------------------------------------------------------------------------
   	PackedDibGetColorsUsed returns value in information header;
          			could be 0 to indicate non-truncated color table!
----------------------------------------------------------------------------*/

int PackedDibGetColorsUsed (BITMAPINFO * pPackedDib)
{
     	if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
          			return 0 ;
     	else
          			return pPackedDib->bmiHeader.biClrUsed ;
}

/*----------------------------------------------------------------------------
   	PackedDibGetNumColors is actual number of entries in color table
-----------------------------------------------------------------------------*/

int PackedDibGetNumColors (BITMAPINFO * pPackedDib)
{
     	int iNumColors ;
     	iNumColors = PackedDibGetColorsUsed (pPackedDib) ;
     	if (	iNumColors == 	0 && PackedDibGetBitCount (pPackedDib) < 16)
          			 iNumColors =1 << PackedDibGetBitCount (pPackedDib) ;

     	return iNumColors ;
}

int PackedDibGetColorTableSize (BITMAPINFO * pPackedDib)
{
     	if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
          			return PackedDibGetNumColors (pPackedDib) * sizeof (RGBTRIPLE) ;
     	else
          			return PackedDibGetNumColors (pPackedDib) * sizeof (RGBQUAD) ;
}

RGBQUAD * PackedDibGetColorTablePtr (BITMAPINFO * pPackedDib)
{
	if (PackedDibGetNumColors (pPackedDib) == 0)
          			return 0 ;
     	return (RGBQUAD *) (((BYTE *)	pPackedDib) + 
                            PackedDibGetInfoHeaderSize (pPackedDib)) ;
}

RGBQUAD * PackedDibGetColorTableEntry (BITMAPINFO * pPackedDib, int i)
{
     	if 	(	PackedDibGetNumColors (pPackedDib) == 0)
          			return 0 ;

     	if 	(	pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
          			return (RGBQUAD *) 
               				(((RGBTRIPLE *) PackedDibGetColorTablePtr (pPackedDib)) + i) ;
     	else
          		return PackedDibGetColorTablePtr (pPackedDib) + i ;
}

/*--------------------------------------------------------------------------
   PackedDibGetBitsPtr finally!
----------------------------------------------------------------------------*/

BYTE * PackedDibGetBitsPtr (BITMAPINFO * pPackedDib)
{
     	return ((BYTE *) pPackedDib)+	PackedDibGetInfoHeaderSize (pPackedDib) +
                                        PackedDibGetColorTableSize (pPackedDib) ;
}

/*----------------------------------------------------------------------------- 
   	PackedDibGetBitsSize can be calculated from the height and row length
          		if it's not explicitly in the biSizeImage field
-----------------------------------------------------------------------------*/

int PackedDibGetBitsSize (BITMAPINFO * pPackedDib)
{
     		if ((pPackedDib->bmiHeader.biSize != sizeof (BITMAPCOREHEADER)) &&
         				(pPackedDib->bmiHeader.biSizeImage != 0))
         				return pPackedDib->bmiHeader.biSizeImage ;

     		return 	PackedDibGetHeight (pPackedDib) * 
            					PackedDibGetRowLength (pPackedDib) ;
}

/*---------------------------------------------------------------------------
   PackedDibCreatePalette creates logical palette from PackedDib
-----------------------------------------------------------------------------*/
HPALETTE PackedDibCreatePalette (BITMAPINFO * pPackedDib)
{
     	HPALETTE   hPalette ;
     	int        i, iNumColors ;
     	LOGPALETTE 	* 	plp ;
     	RGBQUAD    * 	prgb ;

     	if (0 == ( iNumColors = PackedDibGetNumColors (pPackedDib)))
  			return NULL ;
     	plp = malloc (sizeof 	(LOGPALETTE) * 
        (iNumColors - 1) * sizeof (PALETTEENTRY)) ;

     	plp->palVersion    = 0x0300 ;
     	plp->palNumEntries = iNumColors ;
     	for (i = 0 ; i < iNumColors ; i++)
     	{
          			prgb = PackedDibGetColorTableEntry (pPackedDib, i) ;
          			plp->palPalEntry[i].peRed   	= prgb->rgbRed ;
          			plp->palPalEntry[i].peGreen 	= prgb->rgbGreen ;
          			plp->palPalEntry[i].peBlue  	= prgb->rgbBlue ;
          			plp->palPalEntry[i].peFlags 	= 0 ;
     	}

     	hPalette = CreatePalette (plp) ;
     	free (plp) ;

     	return hPalette ;
}

��һ����ʽ��PackedDibLoad������Ψһ�IJ�����Ϊ��������������ָ���������packed DIB��ָ�ꡣ�������к�ʽ�������packed DIBָ����Ϊ���ǵĵ�һ�������������й�DIB����Ѷ����Щ��ʽ�������¶��ϡ�˳�����е������С�ÿ����ʽ��ʹ�ô�ǰ�溯ʽ��õ���Ѷ��

�Ҳ������˵�����ڴ���packed DIBʱ���õġ���������ʽ�������ң���Ҳ������һ����������չ������Ϊ�Ҳ���Ϊ���Ǵ���packed DIB��һ���÷�������д��������ĺ�ʽʱ����������Եط�����һ�㣺

dwPixel = PackedDibGetPixel (pPackedDib, x, y) ;

���ֺ�ʽ����̫��ij�״��ʽ���У������Ч�ʷdz��Ͷ��Һ��������µ����潫����һ������Ϊ���õķ�����

���⣬����ע�⵽���������ຯʽ����Ҫ��OS/2���ݵ�DIB��ȡ��ͬ�Ĵ���������������ʽ��Ƶ���ؼ��BITMAPINFO�ṹ�ĵ�һ����λ�Ƿ���BITMAPCOREHEADER�ṹ�Ĵ�С��ͬ��

�ر�ע������һ����ʽPackedDibCreatePalette�������ʽ��DIB�е���ɫ����������ɫ�̡����DIB��û����ɫ��������ζ��DIB��ÿͼ����16��24��32λԪ������ô�Ͳ�������ɫ�̡�������ʱ�Ὣ��DIB��ɫ�������ĵ�ɫ�̳�ΪDIB ï¿½Ô¼ï¿½ï¿½ï¿½ ï¿½ï¿½É«ï¿½Ì¡ï¿½

PACKEDIB����������SHOWDIB3�����ʽ16-13��ʾ��

 ï¿½ï¿½Ê½16-13  SHOWDIB3
SHOWDIB3.C
/*--------------------------------------------------------------------------
   	SHOWDIB3.C -- 		Displays DIB with native palette
                 							(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>
#include "PackeDib.h"
#include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("ShowDib3") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    	PSTR szCmdLine, int iCmdShow)
{
     	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= szAppName ;
     	wndclass.lpszClassName 		= szAppName ;
     	if (!RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"), 
                      				szAppName, MB_ICONERROR) ;
         	 		return 0 ;
     }

     	hwnd = CreateWindow (	szAppName, TEXT ("Show DIB #3: Native Palette"),
                          	WS_OVERLAPPEDWINDOW,
                          	CW_USEDEFAULT, CW_USEDEFAULT,
                          	CW_USEDEFAULT, CW_USEDEFAULT, 
                          	NULL, NULL, hInstance, NULL) ;
	
     	ShowWindow (hwnd, iCmdShow) ;
     	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)
{
     	static BITMAPINFO *	pPackedDib ;
     	static HPALETTE     			hPalette ;
     	static int          			cxClient, cyClient ;
     	static OPENFILENAME 	ofn ;
     	static TCHAR        	szFileName [MAX_PATH], szTitleName [MAX_PATH] ;
     	static TCHAR        	szFilter[] = 	TEXT ("Bitmap Files (*.BMP)\0*.bmp\0")
        TEXT ("All Files (*.*)\0*.*\0\0") ;
     	HDC                 					hdc ;
     	PAINTSTRUCT         					ps ;

     	switch (message)
     	{
     	case 	WM_CREATE:
          			ofn.lStructSize       		= sizeof (OPENFILENAME) ;
          			ofn.hwndOwner         		= hwnd ;
          			ofn.hInstance         		= NULL ;
          			ofn.lpstrFilter      		= szFilter ;
          			ofn.lpstrCustomFilter 		= NULL ;
          			ofn.nMaxCustFilter    		= 0 ;
          			ofn.nFilterIndex      		= 0 ;
          			ofn.lpstrFile         		= szFileName ;
          			ofn.nMaxFile          		= MAX_PATH ;
          			ofn.lpstrFileTitle    		= szTitleName ;
          			ofn.nMaxFileTitle     		= MAX_PATH ;
          			ofn.lpstrInitialDir   		= NULL ;
          			ofn.lpstrTitle        		= NULL ;
          			ofn.Flags             		= 0 ;
          			ofn.nFileOffset       		= 0 ;
          			ofn.nFileExtension    		= 0 ;
          			ofn.lpstrDefExt       		= TEXT ("bmp") ;
          			ofn.lCustData         		= 0 ;
          			ofn.lpfnHook          		= NULL ;
          			ofn.lpTemplateName    		= NULL ;

          			return 0 ;

     	case 	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
          			return 0 ;

	case 	WM_COMMAND:
          			switch (LOWORD (wParam))
          			{
          			case IDM_FILE_OPEN:

                    		// Show the File Open dialog box

               					if (!GetOpenFileName (&ofn))
                    							return 0 ;
               
                    		// If there's an existing packed DIB, free the memory

               					if (pPackedDib)
               					{
                    						free (pPackedDib) ;
                    						pPackedDib = NULL ;
               				}
               
                    		// If there's an existing logical palette, delete it

               					if (hPalette)
               					{
                    							DeleteObject (hPalette) ;
                    							hPalette = NULL ;
               				}
                    							// Load the packed DIB into memory

               						SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
               						ShowCursor (TRUE) ;

               						pPackedDib = PackedDibLoad (szFileName) ;

               						ShowCursor (FALSE) ;
               						SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               						if (pPackedDib)
               						{
                         		// Create the palette from the DIB color table

                    			hPalette = PackedDibCreatePalette (pPackedDib) ;
               						}
               						else
               						{
                    MessageBox (	hwnd, TEXT ("Cannot load DIB file"), 
                                    szAppName, 0) ;
               						}
               						InvalidateRect (hwnd, NULL, TRUE) ;
               						return 0 ;
          			}
          			break ;

     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

          			if (hPalette)
          			{
               					SelectPalette (hdc, hPalette, FALSE) ;
               					RealizePalette (hdc) ;
          			}
          
          			if (pPackedDib)
               		SetDIBitsToDevice (hdc, 0,0,PackedDibGetWidth (pPackedDib), 
                                  				PackedDibGetHeight (pPackedDib),
                                		0,0,0,PackedDibGetHeight (pPackedDib),  
                                  		      PackedDibGetBitsPtr (pPackedDib), 
                                  			  pPackedDib, 
                    DIB_RGB_COLORS) ;
          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_QUERYNEWPALETTE:
          			if (!hPalette)
               					return FALSE ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			InvalidateRect (hwnd, NULL, TRUE) ;

          			ReleaseDC (hwnd, hdc) ;
          			return TRUE ;

	case 	WM_PALETTECHANGED:
          			if (!hPalette || (HWND) wParam == hwnd)
               					break ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			UpdateColors (hdc) ;

          			ReleaseDC (hwnd, hdc) ;
          			break ;

          
     	case 	WM_DESTROY:
          			if (pPackedDib)
               					free (pPackedDib) ;

          			if (hPalette)
               					DeleteObject (hPalette) ;

          			PostQuitMessage (0) ;
          			return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}
 SHOWDIB3.RC ��ժ¼��
//Microsoft Developer Studio generated resource script.
#include "resource.h"
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
// Menu
SHOWDIB3 MENU DISCARDABLE 
BEGIN
    	POPUP "&File"
    	BEGIN
        MENUITEM "&Open",  			IDM_FILE_OPEN
    	END
END
 RESOURCE.H ��ժ¼��
// Microsoft Developer Studio generated include file.
// Used by ShowDib3.rc

#define IDM_FILE_OPEN         40001

SHOWDIB3�е��Ӵ�ѶϢ������ʽ��packed DIBָ����Ϊ��̬������ά�����Ӵ�ѶϢ������ʽ�ڡ�File Open�������ڼ����PACKEDIB.C�е�PackedDibLoad��ʽʱ����˴�ָ�ꡣ�ڴ���������Ĺ����У�SHOWDIB3Ҳ����PackedDibCreatePalette����ÿ������DIB�ĵ�ɫ�̡�ע�⣬����SHOWDIB3ʲôʱ��׼�������µ�DIB����Ӧ���ͷ�ǰһ��DIB�ļ����壬��ɾ��ǰһ��DIB�ĵ�ɫ�̡��ڴ���WM_DESTROYѶϢ�ij����У������DIB�����ͷţ�����ĵ�ɫ������ɾ����

����WM_PAINTѶϢ�ܼ򵥣�������ڵ�ɫ�̣���SHOWDIB3����ѡ��װ�����ݲ���������Ȼ��������SetDIBitsToDevice���������й�DIB�ĺ�ʽ��Ѷ����������ߺ�ָ��DIBͼ��λԪ��ָ�� )����Щ��Ѷ��PACKEDIB�еĺ�ʽ��á�

���⣬���סSHOWDIB3����DIB�е���ɫ�������˵�ɫ�̡������DIB��û����ɫ����ͨ����16λԪ��24λԪ��32λԪDIB��������Ͳ�������ɫ�̡���8λԪ��ʾģʽ����ʾDIBʱ����ֻ���ñ�׼������20����ɫ��ʾ��

��������������ֽ����������һ���Ǽ򵥵�ʹ�á�ͨ�á���ɫ�̣����ֵ�ɫ�����������ͼ�Ρ���Ҳ�����Լ�������ɫ�̡��ڶ��ֽ�������Ƿ���DIB��ͼ��λԪ��������Ҫ��ʾͼ��������ɫ�������ԣ��ڶ��ַ������漰����Ĺ�������춳�ʽд���ߺʹ�����������ˣ��������ҽ��ڱ��½���֮ǰ���������ʹ�õڶ��ַ�����

��ͨ�á���ɫ��
��

��ʽ16-14��ʾ��SHOWDIB4��ʽ������һ��ͨ�õĵ�ɫ�̣��������ʾ���뵽��ʽ�е�����DIB�����⣬SHOWDIB4��SHOWDIB3�dz����ơ�

 ï¿½ï¿½Ê½16-14  SHOWDIB4
SHOWDIB4.C
/*---------------------------------------------------------------------------
   	SHOWDIB4.C -- 	Displays DIB with "all-purpose" palette
                 						(c) Charles Petzold, 1998
-----------------------------------------------------------------------------*/

#include <windows.h>
#include "..\\ShowDib3\\PackeDib.h"
#include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("ShowDib4") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    			PSTR szCmdLine, int iCmdShow)
{
     	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= szAppName ;
     	wndclass.lpszClassName 		= szAppName ;
     	if (!RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"), 
                      								szAppName, MB_ICONERROR) ;
        			return 0 ;
     	}
	
     	hwnd = CreateWindow (	szAppName, TEXT ("Show DIB #4: All-Purpose Palette"),
                          	WS_OVERLAPPEDWINDOW,
                          	CW_USEDEFAULT, CW_USEDEFAULT,
                          	CW_USEDEFAULT, CW_USEDEFAULT, 
                          	NULL, NULL, hInstance, NULL) ;

     	ShowWindow (hwnd, iCmdShow) ;
     	UpdateWindow (hwnd) ;

     	while (GetMessage (&msg, NULL, 0, 0))
     	{
         			TranslateMessage (&msg) ;
          			DispatchMessage (&msg) ;
     	}
     	return msg.wParam ;
}

/*-----------------------------------------------------------------------------
   	CreateAllPurposePalette: Creates a palette suitable for a wide variety
       		of images; the palette has 247 entries, but 15 of them are 
   		duplicates or match the standard 20 colors.
-----------------------------------------------------------------------------*/

HPALETTE CreateAllPurposePalette (void)
{
     	HPALETTE hPalette ;
     	int          				i, incr, R, G, B ;
     	LOGPALETTE * 	plp ;

     	plp = malloc (sizeof (LOGPALETTE) + 246 * sizeof (PALETTEENTRY)) ;
     	plp->palVersion  	= 0x0300 ;
     	plp->palNumEntries 	= 247 ;

       		// The following loop calculates 31 gray shades, but 3 of them
          		//     will match the standard 20 colors

     	for (i = 0, G = 0, incr = 8 ; G <= 0xFF ; i++, G += incr)
     	{
          			plp->palPalEntry[i].peRed 	= (BYTE) G ;
          			plp->palPalEntry[i].peGreen 	= (BYTE) G ;
          			plp->palPalEntry[i].peBlue  	= (BYTE) G ;
          			plp->palPalEntry[i].peFlags 	= 0 ;

          			incr = (incr == 9 ? 8 : 9) ;
     	}

          		// The following loop is responsible for 216 entries, but 8 of 
          		// them will match the standard 20 colors, and another
          		// 4 of them will match the gray shades above.

     	for (R = 0 ; R <= 0xFF ; R += 0x33)
     	for (G = 0 ; G <= 0xFF ; G += 0x33)
     	for (B = 0 ; B <= 0xFF ; B += 0x33)
     {
          			plp->palPalEntry	[i].peRed   	= (BYTE) R ;
          			plp->palPalEntry	[i].peGreen 	= (BYTE) G ;
          			plp->palPalEntry	[i].peBlue  	= (BYTE) B ;
          			plp->palPalEntry	[i].peFlags 	= 0 ;
			
          			i++ ;
     	}
     	hPalette = CreatePalette (plp) ;
     	free (plp) ;
     	return hPalette ;
}

LRESULT CALLBACK WndProc (	HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
     	static 	BITMAPINFO * 	pPackedDib ;
     	static 	HPALETTE     			hPalette ;
     	static 	int          				cxClient, cyClient ;
     	static 	OPENFILENAME 	ofn ;
     	static 	TCHAR        szFileName [MAX_PATH], szTitleName [MAX_PATH] ;
     	static 	TCHAR        szFilter[] =	TEXT ("Bitmap Files (*.BMP)\0*.bmp\0")
        TEXT ("All Files (*.*)\0*.*\0\0") ;
     	HDC                 							hdc ;
     	PAINTSTRUCT         					ps ;
     	switch (message)
     {
     	case 	WM_CREATE:
          			ofn.lStructSize       		= sizeof (OPENFILENAME) ;
          			ofn.hwndOwner         		= hwnd ;
          			ofn.hInstance         		= NULL ;
          			ofn.lpstrFilter       		= szFilter ;
          			ofn.lpstrCustomFilter 		= NULL ;
          			ofn.nMaxCustFilter    		= 0 ;
          			ofn.nFilterIndex      		= 0 ;
          			ofn.lpstrFile         		= szFileName ;
          			ofn.nMaxFile          		= MAX_PATH ;
          			ofn.lpstrFileTitle    		= szTitleName ;
          			ofn.nMaxFileTitle     		= MAX_PATH ;
          			ofn.lpstrInitialDir   		= NULL ;
          			ofn.lpstrTitle        		= NULL ;
          			ofn.Flags             		= 0 ;
          			ofn.nFileOffset       		= 0 ;
          			ofn.nFileExtension    		= 0 ;
          			ofn.lpstrDefExt       		= TEXT ("bmp") ;
          			ofn.lCustData         		= 0 ;
          			ofn.lpfnHook          		= NULL ;
          			ofn.lpTemplateName    		= NULL ;

               					// Create the All-Purpose Palette

          			hPalette = CreateAllPurposePalette () ;
          			return 0 ;

     	case 	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
     			return 0 ;

     	case 	WM_COMMAND:
       	   		switch (LOWORD (wParam))
          			{
          			case 	IDM_FILE_OPEN:

                    						// Show the File Open dialog box

               					if (!GetOpenFileName (&ofn))
                    							return 0 ;
               
                    	// If there's an existing packed DIB, free the memory
        					if (pPackedDib)
               					{
                    						free (pPackedDib) ;
                    						pPackedDib = NULL ;
               					}
               
                    						// Load the packed DIB into memory
	
               					SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
               					ShowCursor (TRUE) ;

               					pPackedDib = PackedDibLoad (szFileName) ;

               					ShowCursor (FALSE) ;
               					SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               					if (!pPackedDib)
               					{
                    MessageBox (	hwnd, TEXT ("Cannot load DIB file"), 
                    				szAppName, 0) ;
               					}
               					InvalidateRect (hwnd, NULL, TRUE) ;
               					return 0 ;
          			}
          			break ;

     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

          			if (pPackedDib)
          			{
               					SelectPalette (hdc, hPalette, FALSE) ;
               					RealizePalette (hdc) ;
          
       				SetDIBitsToDevice (hdc,0,0,PackedDibGetWidth (pPackedDib), 
  										  PackedDibGetHeight (pPackedDib),
                                  		0,0,0,PackedDibGetHeight (pPackedDib),  
                                  			  PackedDibGetBitsPtr (pPackedDib), 
                                  			  pPackedDib, 
                    DIB_RGB_COLORS) ;
          			}
          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_QUERYNEWPALETTE:
          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			InvalidateRect (hwnd, NULL, TRUE) ;

          			ReleaseDC (hwnd, hdc) ;
          			return TRUE ;

     	case 	WM_PALETTECHANGED:
          			if ((HWND) wParam != hwnd)

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			UpdateColors (hdc) ;

          			ReleaseDC (hwnd, hdc) ;
          			break ;
          
     	case 	WM_DESTROY:
          			if (pPackedDib)
               					free (pPackedDib) ;

          			DeleteObject (hPalette) ;

          			PostQuitMessage (0) ;
          			return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}
 SHOWDIB4.RC ��ժ¼��
//Microsoft Developer Studio generated resource script.
#include "resource.h"
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
// Menu
SHOWDIB4 MENU DISCARDABLE 
BEGIN
    	POPUP "&Open"
    	BEGIN
        			MENUITEM "&File",  			IDM_FILE_OPEN
    	END
END
 RESOURCE.H ��ժ¼��
// Microsoft Developer Studio generated include file.
// Used by ShowDib4.rc

#define IDM_FILE_OPEN            40001

�ڴ���WM_CREATEѶϢʱ��SHOWDIB4������CreateAllPurposePalette�����ڳ�ʽ�б����õ�ɫ�̣�����WM_DESTROYѶϢ�����ڼ�ɾ��������Ϊ��ʽ֪����ɫ��һ�����ڣ������ڴ���WM_PAINT��WM_QUERYNEWPALETTE��WM_PALETTECHANGEDѶϢʱ�����ؼ���ɫ�̵Ĵ��ڡ�

CreateAllPurposePalette��ʽ�ƺ�����247����Ŀ�������߼���ɫ�̣���������ϵͳ��ɫ����������ʽ������ȡ��236����Ŀ����ȷ��ˣ������������ܷ��㡣��Щ��Ŀ����15�������ƻ���ӳ�䵽20�ֱ�׼�ı�����ɫ�С�

CreateAllPurposePalette�ӽ���31�ֻҽ׿�ʼ����0x00��0x09��0x11��0x1A��0x22��0x2B��0x33��0x3C��0x44��0x4D��0x55��0x5E��0x66��0x6F��0x77��0x80��0x88��0x91��0x99��0xA2��0xAA��0xB3��0xBB��0xC4��0xCC��0xD5��0xDD��0xE6��0xEE��0xF9��0xFF�ĺ�ɫ����ɫ����ɫֵ��ע�⣬��һ��������һ�����м����Ŀ���ڱ�׼��20�ֱ�����ɫ�С���һ����ʽ�ú�ɫ����ɫ����ɫֵ��������Ͻ�������ɫ0x00��0x33��0x66��0x99��0xCC��0xFF�������͹���216����ɫ����������8����ɫ�����˱�׼��20�ֱ�����ɫ��������4��������ǰ�����Ļҽס������PALETTEENTRY�ṹ��peFlags��λ��Ϊ0����Windows�����Ѹ��Ƶ���Ŀ�Ž�ϵͳ��ɫ�̡�

��Ȼ�أ�ʵ�ʵij�ʽ��ϣ������16λԪ��24λԪ����32λԪDIB����ѵ�ɫ�̣���ʽ������ʹ��DIB��ɫ������ʾ8λԪDIB��SHOWDIB4��������������ֻ��ÿ���¶�ʹ��ͨ�õ�ɫ�̡���ΪSHOWDIB4��һ��չʾ��ʽ��������������SHOWDIB3��ʾ��8λԪDIB���бȽϡ������һЩ����IJ�ɫDIB����ô�����ܻ�ó������Ľ��ۣ�SHOWDIB4û���㹻����ɫ����ȷ�ر�ʾ���޵�ɫ����

�����SHOWDIB4�е�CreateAllPurposePalette��ʽ�����飨������ͨ�����߼���ɫ�̵Ĵ�С���ٵ�ֻ�м�����Ŀ�ķ��������������ֵ���ɫ��ѡ��װ������ʱ��Windows��ֻʹ�õ�ɫ���е���ɫ������ʹ�ñ�׼��20����ɫ��ɫ�̵���ɫ��

�м�ɫ��ɫ��
��

Windows API����һ��ͨ�õ�ɫ�̣���ʽ����ͨ������CreateHalftonePalette����øõ�ɫ�̡�ʹ�ô˵�ɫ�̵ķ�����ʹ�ô�SHOWDIB4�е�CreateAllPurposePalette��õ�ɫ�̵ķ�����ͬ��������Ҳ���������ͼ����ģʽ�е�HALFTONE�趨����SetStretchBltMode�趨��һ��ʹ�á���ʽ16-15��ʾ��SHOWDIB5��ʽչʾ��ʹ���м�ɫ��ɫ�̵ķ�����

 ï¿½ï¿½Ê½16-15  SHOWDIB5
SHOWDIB5.C
/*--------------------------------------------------------------------------
   	SHOWDIB5.C -- 	Displays DIB with halftone palette
                 						(c) Charles Petzold, 1998
--------------------------------------------------------------------------*/

#include <windows.h>
#include "..\\ShowDib3\\PackeDib.h"
#include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("ShowDib5") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    							PSTR szCmdLine, int iCmdShow)
{
     	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= szAppName ;
     	wndclass.lpszClassName 		= szAppName ;

     	if (!RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"), 
                      								szAppName, MB_ICONERROR) ;
          			return 0 ;
     }

     	hwnd = CreateWindow (	szAppName, TEXT ("Show DIB #5: Halftone Palette"),
                          		WS_OVERLAPPEDWINDOW,
                          		CW_USEDEFAULT, CW_USEDEFAULT,
                          		CW_USEDEFAULT, CW_USEDEFAULT, 
                          		NULL, NULL, hInstance, NULL) ;

     	ShowWindow (hwnd, iCmdShow) ;
     	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)
{
     	static 	BITMAPINFO * 	pPackedDib ;
     	static 	HPALETTE     	hPalette ;
     	static 	int          	cxClient, cyClient ;
     	static 	OPENFILENAME 	ofn ;
     	static 	TCHAR        	szFileName [MAX_PATH], szTitleName [MAX_PATH] ;
     	static 	TCHAR        	szFilter[] =	TEXT ("Bitmap Files (*.BMP)\0*.bmp\0")
        TEXT ("All Files (*.*)\0*.*\0\0") ;
     	HDC                 				hdc ;
     	PAINTSTRUCT        					ps ;

     	switch (message)
     {
     	case 	WM_CREATE:
          			ofn.lStructSize       		= sizeof (OPENFILENAME) ;
          			ofn.hwndOwner         		= hwnd ;
          			ofn.hInstance         		= NULL ;
          			ofn.lpstrFilter       		= szFilter ;
          			ofn.lpstrCustomFilter 		= NULL ;
          			ofn.nMaxCustFilter    		= 0 ;
          			ofn.nFilterIndex      		= 0 ;
          			ofn.lpstrFile         		= szFileName ;
          			ofn.nMaxFile          		= MAX_PATH ;
          			ofn.lpstrFileTitle    		= szTitleName ;
          			ofn.nMaxFileTitle     		= MAX_PATH ;
          			ofn.lpstrInitialDir   		= NULL ;
          			ofn.lpstrTitle        		= NULL ;
          			ofn.Flags             		= 0 ;
          			ofn.nFileOffset       		= 0 ;
          			ofn.nFileExtension    		= 0 ;
          			ofn.lpstrDefExt       		= TEXT ("bmp") ;
          			ofn.lCustData         		= 0 ;
          			ofn.lpfnHook          		= NULL ;
          			ofn.lpTemplateName    		= NULL ;

               				// Create the All-Purpose Palette

          			hdc = GetDC (hwnd) ;
          			hPalette = CreateHalftonePalette (hdc) ;
          			ReleaseDC (hwnd, hdc) ;
          			return 0 ;

     	case 	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
          			return 0 ;

     	case 	WM_COMMAND:
          			switch (LOWORD (wParam))
          			{
          			case 	IDM_FILE_OPEN:

                    						// Show the File Open dialog box

               					if (!GetOpenFileName (&ofn))
                    							return 0 ;
               
                   	// If there's an existing packed DIB, free the memory

               					if (pPackedDib)
               					{
                    						free (pPackedDib) ;
                    						pPackedDib = NULL ;
               					}
               
                    						// Load the packed DIB into memory

               					SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
               					ShowCursor (TRUE) ;

               					pPackedDib = PackedDibLoad (szFileName) ;

               					ShowCursor (FALSE) ;
               					SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               					if (!pPackedDib)
               					{
                   MessageBox (	hwnd, TEXT ("Cannot load DIB file"), 
                                szAppName, 0) ;
               					}
               					InvalidateRect (hwnd, NULL, TRUE) ;
               					return 0 ;
          			}
          			break ;

     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

          			if (pPackedDib)
          			{
                   					// Set halftone stretch mode

               				SetStretchBltMode (hdc, HALFTONE) ;
               				SetBrushOrgEx (hdc, 0, 0, NULL) ;

                    					// Select and realize halftone palette

               				SelectPalette (hdc, hPalette, FALSE) ;
               				RealizePalette (hdc) ;

                    	// StretchDIBits rather than SetDIBitsToDevice
               			StretchDIBits (	hdc,0,0,PackedDibGetWidth (pPackedDib), 
                       					PackedDibGetHeight (pPackedDib),
                              				0,0,PackedDibGetWidth (pPackedDib),
                              				PackedDibGetHeight (pPackedDib),  
                              				PackedDibGetBitsPtr (pPackedDib), 
                              				pPackedDib, 
                    DIB_RGB_COLORS, 
                    SRCCOPY) ;
          			}
          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_QUERYNEWPALETTE:
          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			InvalidateRect (hwnd, NULL, TRUE) ;

          			ReleaseDC (hwnd, hdc) ;
          			return TRUE ;

     	case 	WM_PALETTECHANGED:
          			if ((HWND) wParam != hwnd)

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			UpdateColors (hdc) ;

          			ReleaseDC (hwnd, hdc) ;
          			break ;
          
     	case 	WM_DESTROY:
          			if (pPackedDib)
               					free (pPackedDib) ;

          			DeleteObject (hPalette) ;

          			PostQuitMessage (0) ;
          			return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}
 SHOWDIB5.RC ��ժ¼��
//Microsoft Developer Studio generated resource script.
#include "resource.h"
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
// Menu
SHOWDIB5 MENU DISCARDABLE 
BEGIN
    	POPUP "&Open"
    	BEGIN
        			MENUITEM "&File",  		IDM_FILE_OPEN
    	END
END
 RESOURCE.H ��ժ¼��
// Microsoft Developer Studio generated include file.
// Used by ShowDib5.rc

#define IDM_FILE_OPEN            40001

SHOWDIB5��ʽ�����SHOWDIB4��SHOWDIB4�в�ʹ��DIB�е���ɫ������ʹ�������ͼ��Χ����ĵ�ɫ�̡�Ϊ�ˣ�SHOWDIB5ʹ������Windows֧Ԯ���߼���ɫ�̣�����ſ��Դ�CreateHalftonePalette��ʽ��á�

�м�ɫ��ɫ�̲�����SHOWDIB4�е�CreateAllPurposePalette��ʽ�������ĵ�ɫ�̸����ӡ���ȷ�����ֻ���������ã���������Ƶġ�Ȼ�����������������������ʽ��

SetStretchBltMode (hdc, HALFTONE) ;
               			SetBrushOrgEx (hdc, x, y, NULL) ;

���У�x��y��DIB���Ͻǵ�װ�����꣬�����������StretchDIBits������SetDIBitsToDevice����ʾDIB����ô����������Ծ�����ɫɫ��Ҫ�Ȳ��趨����ͼ����ģʽ��ʹ��CreateAllPurposePalette����CreateHalftonePalette����ȷ��Windowsʹ��һ�ֻ�ɫͼ���������м�ɫ��ɫ���ϵ���ɫ����ʹ����ӽ�8λԪ��ʾ����ԭʼͼ�����ɫ�������������һ������������ȱ������Ҫ����Ĵ���ʱ�䡣

������ɫ����ɫ
��

���ڿ�ʼ����SetDIBitsToDevice��StretchDIBits��CreateDIBitmap��SetDIBits��GetDIBits��CreateDIBSection��fClrUse������ͨ����������������趨ΪDIB_RGB_COLORS�����0������������Ҳ�ܽ����趨ΪDIB_PAL_COLORS������������£��ٶ�BITMAPINFO�ṹ�е���ɫ��������RGB��ɫֵ�����ǰ����߼���ɫ������ɫ��Ŀ��16λԪ�������߼���ɫ������Ϊ��һ���������ݸ���ʽ��װ��������Ŀǰѡ����Ǹ���ʵ���ϣ���CreateDIBSection�У�֮������Ҫָ��һ����NULL��װ�����ݴ�����Ϊ��һ��������ֻ����Ϊʹ����DIB_PAL_COLORS��

DIB_PAL_COLORS��Ϊ����Щʲô�أ����������һЩ���ܡ�����һ����8λԪ��ʾģʽ�º���SetDIBitsToDevice��ʾ��8λԪDIB��Windows���ȱ�����DIB��ɫ����������ɫ���������豸������ɫ��ӽ�����ɫ��Ȼ���趨һ��С�����Ա㽫DIBͼ��ֵӳ�䵽�豸ͼ�ء�Ҳ����˵�������Ҫ����256����ӽ�����ɫ���������DIB��ɫ���к��д�װ��������ѡ����ɫ���߼���ɫ����Ŀ��������ô�Ϳ�������������

����ʹ�õ�ɫ���������⣬��ʽ16-16��ʾ��SHOWDIB6��ʽ��SHOWDIB3���ơ�

 ï¿½ï¿½Ê½16-16  SHOWDIB6
SHOWDIB6.C
/*---------------------------------------------------------------------------
   	SHOWDIB6.C -- 	Display DIB with palette indices
                 						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>
#include "..\\ShowDib3\\PackeDib.h"
#include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("ShowDib6") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    							PSTR szCmdLine, int iCmdShow)
{
     	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= szAppName ;
     	wndclass.lpszClassName 		= szAppName ;

     	if (!RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"), 
                      								szAppName, MB_ICONERROR) ;
          			return 0 ;
     }

     	hwnd = CreateWindow (	szAppName, TEXT ("Show DIB #6: Palette Indices"),
                          	WS_OVERLAPPEDWINDOW,
                          	CW_USEDEFAULT, CW_USEDEFAULT,
                          	CW_USEDEFAULT, CW_USEDEFAULT, 
                          	NULL, NULL, hInstance, NULL) ;

     	ShowWindow (hwnd, iCmdShow) ;
     	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)
{
     	static 	BITMAPINFO *	pPackedDib ;
     	static 	HPALETTE     	hPalette ;
     	static 	int          	cxClient, cyClient ;
     	static 	OPENFILENAME 	ofn ;
     	static 	TCHAR        	szFileName [MAX_PATH], szTitleName [MAX_PATH] ;
     	static 	TCHAR        	szFilter[] = 	TEXT ("Bitmap Files (*.BMP)\0*.bmp\0")
        TEXT ("All Files (*.*)\0*.*\0\0") ;
     	HDC                 	hdc ;
     	int                 	i, iNumColors ;
     	PAINTSTRUCT        		ps ;
     	WORD              		* 		pwIndex ;

     	switch (message)
     	{
     	case 	WM_CREATE:
          			ofn.lStructSize       		= sizeof (OPENFILENAME) ;
          			ofn.hwndOwner         		= hwnd ;
          			ofn.hInstance         		= NULL ;
          			ofn.lpstrFilter      		= szFilter ;
          			ofn.lpstrCustomFilter 		= NULL ;
          			ofn.nMaxCustFilter    		= 0 ;
          			ofn.nFilterIndex      		= 0 ;
          			ofn.lpstrFile         		= szFileName ;
          			ofn.nMaxFile          		= MAX_PATH ;
          			ofn.lpstrFileTitle    		= szTitleName ;
          			ofn.nMaxFileTitle     		= MAX_PATH ;
          			ofn.lpstrInitialDir   		= NULL ;
          			ofn.lpstrTitle        		= NULL ;
          			ofn.Flags             		= 0 ;
          			ofn.nFileOffset       		= 0 ;
          			ofn.nFileExtension    		= 0 ;
          			ofn.lpstrDefExt       		= TEXT ("bmp") ;
          			ofn.lCustData         		= 0 ;
          			ofn.lpfnHook          		= NULL ;
          			ofn.lpTemplateName    		= NULL ;

          			return 0 ;

     	case 	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
          			return 0 ;

     	case 	WM_COMMAND:
          			switch (LOWORD (wParam))
          			{
          			case 	IDM_FILE_OPEN:

                    						// Show the File Open dialog box
               					if (!GetOpenFileName (&ofn))
                    							return 0 ;
               
                    		// If there's an existing packed DIB, free the memory

               			if (pPackedDib)
               			{
                    					free (pPackedDib) ;
                    					pPackedDib = NULL ;
          			}
               
                    	// If there's an existing logical palette, delete it

               			if (hPalette)
               			{
                    					DeleteObject (hPalette) ;
                   	 				hPalette = NULL ;
               			}
               
                    				// Load the packed DIB into memory

               			SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
               			ShowCursor (TRUE) ;

               			pPackedDib = PackedDibLoad (szFileName) ;

               			ShowCursor (FALSE) ;
               			SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               			if (pPackedDib)
               			{
                         	// Create the palette from the DIB color table

                    	hPalette = PackedDibCreatePalette (pPackedDib) ;

                         	// Replace DIB color table with indices

                    				if (hPalette)
                    				{
                         	iNumColors = PackedDibGetNumColors (pPackedDib) ;
                         						pwIndex = (WORD *) 
                                        		PackedDibGetColorTablePtr (pPackedDib) ;

                         		for (i = 0 ; i < iNumColors ; i++)
                              							pwIndex[i] = (WORD) i ;
                   	 				}
               				}
               				else
               				{
           MessageBox (	hwnd, TEXT ("Cannot load DIB file"), 
               			szAppName, 0) ;
               				}
               				InvalidateRect (hwnd, NULL, TRUE) ;
               				return 0 ;
          			}
          			break ;

     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

          			if (hPalette)
          			{
               					SelectPalette (hdc, hPalette, FALSE) ;
               					RealizePalette (hdc) ;
          			}
          
          			if (pPackedDib)
   					SetDIBitsToDevice (hdc,0,0,PackedDibGetWidth  (pPackedDib), 
                                  		       PackedDibGetHeight (pPackedDib),
                                  		 0,0,0,PackedDibGetHeight (pPackedDib),  
                                  		       PackedDibGetBitsPtr (pPackedDib), 
                                  			   pPackedDib, 
                    DIB_PAL_COLORS) ;
          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_QUERYNEWPALETTE:
          			if (!hPalette)
               					return FALSE ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			InvalidateRect (hwnd, NULL, TRUE) ;

          			ReleaseDC (hwnd, hdc) ;
          			return TRUE ;

     	case 	WM_PALETTECHANGED:
          			if (!hPalette || (HWND) wParam == hwnd)
               					break ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			UpdateColors (hdc) ;

          			ReleaseDC (hwnd, hdc) ;
          			break ;

          
     	case 	WM_DESTROY:
          			if (pPackedDib)
               					free (pPackedDib) ;

          			if (hPalette)
               					DeleteObject (hPalette) ;

          			PostQuitMessage (0) ;
          			return 0 ;
     }
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}
 SHOWDIB6.RC ��ժ¼��
//Microsoft Developer Studio generated resource script.
#include "resource.h"
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
// Menu
SHOWDIB6 MENU DISCARDABLE 
BEGIN
    	POPUP "&File"
    	BEGIN
        			MENUITEM "&Open", 				IDM_FILE_OPEN
    	END
END
 RESOURCE.H ��ժ¼��
// Microsoft Developer Studio generated include file.
// Used by ShowDib6.rc
//
#define IDM_FILE_OPEN           40001

SHOWDIB6��DIB���뵽�����岢�ɴ˽����˵�ɫ�����ᣬSHOWDIB6�򵥵�����0��ʼ��WORD�����滻��DIB��ɫ���е���ɫ��PackedDibGetNumColors��ʽ����ʾ�ж�������ɫ����PackedDibGetColorTablePtr��ʽ����ָ��DIB��ɫ����ʼλ�õ�ָ�ꡣ

ע�⣬ֻ��ֱ�Ӵ�DIB��ɫ����������ɫ��ʱ���˼����ſ��С����ʹ��ͨ�õ�ɫ�̣������������ӽ�����ɫ���Ի�÷���DIB��������

���Ҫʹ�õ�ɫ����������ô���ڽ�DIB���浽��Ƭ֮ǰ��ȷʵ�滻��DIB�е���ɫ�������⣬��Ҫ��������ɫ��������DIB�����������ʵ���ϣ�����ʾ֮ǰ������ɫ����������DIB��Ȼ�ὫRGB��ɫֵ�Żأ������ȫһЩ��

��ɫ�̺͵���ͼ���
��

��ʽ16-17�е�SHOWDIB7��ʽ��ʾ�����ʹ����DIB������ĵ�ɫ�̣���ЩDIB��ʹ��CreateDIBitmap��ʽת����GDI����ͼ����ġ�

 ï¿½ï¿½Ê½16-17  SHOWDIB7
SHOWDIB7.C
/*--------------------------------------------------------------------------
   	SHOWDIB7.C --	 	Shows DIB converted to DDB 
                 							(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>
#include "..\\ShowDib3\\PackeDib.h"
#include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("ShowDib7") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    							PSTR szCmdLine, int iCmdShow)
{
    	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= szAppName ;
     	wndclass.lpszClassName 		= szAppName ;

     	if (!RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"), 
                      								szAppName, MB_ICONERROR) ;
          			return 0 ;
     }

     	hwnd = CreateWindow (	szAppName, TEXT ("Show DIB #7: Converted to DDB"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT, 
                          NULL, NULL, hInstance, NULL) ;

     	ShowWindow (hwnd, iCmdShow) ;
     	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)
{
     	static HBITMAP     			hBitmap ;
     	static HPALETTE     		hPalette ;
     	static int          		cxClient, cyClient ;
     	static OPENFILENAME 	    ofn ;
     	static TCHAR        		szFileName [MAX_PATH], szTitleName [MAX_PATH] ;
     	static TCHAR        		szFilter[] = 	TEXT ("Bitmap Files (*.BMP)\0*.bmp\0")
        TEXT ("All Files (*.*)\0*.*\0\0") ;
     	BITMAP              		bitmap ;
     	BITMAPINFO        		   *	pPackedDib ;
     	HDC                 		hdc, hdcMem ;
     	PAINTSTRUCT         		ps ;

	switch (message)
     {
     	case	WM_CREATE:
          			ofn.lStructSize       = sizeof (OPENFILENAME) ;
          			ofn.hwndOwner         = hwnd ;
          			ofn.hInstance         = NULL ;
          			ofn.lpstrFilter       = szFilter ;
          			ofn.lpstrCustomFilter = NULL ;
          			ofn.nMaxCustFilter    = 0 ;
          			ofn.nFilterIndex      = 0 ;
          			ofn.lpstrFile         = szFileName ;
          			ofn.nMaxFile          = MAX_PATH ;
          			ofn.lpstrFileTitle    = szTitleName ;
          			ofn.nMaxFileTitle     = MAX_PATH ;
          			ofn.lpstrInitialDir   = NULL ;
          			ofn.lpstrTitle        = NULL ;
          			ofn.Flags             = 0 ;
          			ofn.nFileOffset       = 0 ;
          			ofn.nFileExtension    = 0 ;
          			ofn.lpstrDefExt       = TEXT ("bmp") ;
          			ofn.lCustData         = 0 ;
          			ofn.lpfnHook          = NULL ;
          			ofn.lpTemplateName    = NULL ;

          			return 0 ;

     	case 	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
          			return 0 ;

     	case 	WM_COMMAND:
          			switch (LOWORD (wParam))
          			{
          			case IDM_FILE_OPEN:

                    				// Show the File Open dialog box

               				if (!GetOpenFileName (&ofn))
					return 0 ;
               	
                    // If there's an existing packed DIB, free the memory

			if (hBitmap)
               			{
                    					DeleteObject (hBitmap) ;
                    					hBitmap = NULL ;
          			}
               
                    // If there's an existing logical palette, delete it

			if (hPalette)
               			{
                    					DeleteObject (hPalette) ;
                    					hPalette = NULL ;
               			}
               
                    				// Load the packed DIB into memory

			SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
			ShowCursor (TRUE) ;

               			pPackedDib = PackedDibLoad (szFileName) ;

               			ShowCursor (FALSE) ;
               			SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               			if (pPackedDib)
              	 		{
                        // Create palette from the DIB and select it into DC

                    hPalette = PackedDibCreatePalette (pPackedDib) ;

                    				hdc = GetDC (hwnd) ;
                    
                    				if (hPalette)
                    				{
                         	SelectPalette (hdc, hPalette, FALSE) ;
                         						RealizePalette (hdc) ;
                    					}
                         						// Create the DDB from the DIB
                    hBitmap = CreateDIBitmap(hdc,(PBITMAPINFOHEADER) pPackedDib,
                              CBM_INIT,PackedDibGetBitsPtr (pPackedDib), 
pPackedDib, DIB_RGB_COLORS) ;
                    					ReleaseDC (hwnd, hdc) ;

                         	// Free the packed-DIB memory

                    					free (pPackedDib) ;
               				}
               				else
               				{
                  MessageBox (	hwnd, TEXT ("Cannot load DIB file"), 
                  				szAppName, 0) ;
               }
               					InvalidateRect (hwnd, NULL, TRUE) ;
               					return 0 ;
          			}
          			break ;
     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

          			if (hPalette)
          			{
               					SelectPalette (hdc, hPalette, FALSE) ;
               					RealizePalette (hdc) ;
          			}
          			if (hBitmap)
          			{
               					GetObject (hBitmap, sizeof (BITMAP), &bitmap) ;

               					hdcMem = CreateCompatibleDC (hdc) ;
               					SelectObject (hdcMem, hBitmap) ;

               					BitBlt (hdc,0,0,bitmap.bmWidth, bitmap.bmHeight, 
                       					hdcMem,	0,	0,	SRCCOPY) ;

               				DeleteDC (hdcMem) ;
          			}
         			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_QUERYNEWPALETTE:
          			if (!hPalette)
               					return FALSE ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			InvalidateRect (hwnd, NULL, TRUE) ;

          			ReleaseDC (hwnd, hdc) ;
          			return TRUE ;

     	case 	WM_PALETTECHANGED:
          			if (!hPalette || (HWND) wParam == hwnd)
               					break ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			UpdateColors (hdc) ;

          			ReleaseDC (hwnd, hdc) ;
          			break ;

          
     	case 	WM_DESTROY:
          			if (hBitmap)
               					DeleteObject (hBitmap) ;

          			if (hPalette)
               					DeleteObject (hPalette) ;

          					PostQuitMessage (0) ;
          					return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}
 SHOWDIB7.RC ��ժ¼��
//Microsoft Developer Studio generated resource script.
#include "resource.h"
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
// Menu
SHOWDIB7 MENU DISCARDABLE 
BEGIN
   	POPUP "&File"
    	BEGIN
        			MENUITEM "&Open",  			IDM_FILE_OPEN
    	END
END
 RESOURCE.H ��ժ¼��
// Microsoft Developer Studio generated include file.
// Used by ShowDib7.rc

#define IDM_FILE_OPEN      40001

��ǰ��ij�ʽһ����SHOWDIB7�����һ��ָ��packed DIB��ָ�꣬��DIB��Ӧ���ܱ��ġ�File������Open�������ʽ��packed DIB�����˵�ɫ�̣�Ȼ�ᣭ������WM_COMMANDѶϢ�Ĵ��������У�����������Ѷ��ʾ��װ�����ݣ���ѡ����ɫ�̣����ֵ�ɫ�̡�Ȼ��SHOWDIB7����CreateDIBitmap�Ա��DIB����DDB�������ɫ��û��ѡ��װ�����ݲ����֣���ôCreateDIBitmap������DDB����ʹ���߼���ɫ���еĸ�����ɫ��

����CreateDIBitmap���ᣬ�ó�ʽ���ͷ�packed DIBռ�õļ�����ռ䡣pPackedDib�������Ǿ�̬�������෴�ģ�SHOWDIB7����̬���������˵���ͼ���ţ�hBitmap�����߼���ɫ�̴��ţ�hPalette����

��WM_PAINTѶϢ�����ڼ䣬��ɫ���ٴ�ѡ��װ�����ݲ����֡�GetObject��ʽ�ɻ�õ���ͼ�Ŀ��Ⱥ͸߶ȡ�Ȼ�ᣬ��ʽͨ���������ݵļ�����װ����������ʾ������ʾ����ͼ��ѡ������ͼ����ִ��BitBlt����ʾDDBʱ���õĵ�ɫ�̣��������CreateDIBitmap���н���ʱ���õ�һ����

���������ͼ���Ƶ��������������ʹ��packed DIB��ʽ��Ȼ��Windows���Խ�����ͼ����ṩ��ϣ��ʹ����Щ����ͼ�ij�ʽ��Ȼ���������Ҫ������ͼ������Ƶ���������������Ҫ�����Ѷװ�����ݲ����ֵ�ɫ�̡�������Windows����Ŀǰ��ϵͳ��ɫ�̽�DDBת��ΪDIB��

��ɫ�̺�DIB����
��

���ᣬ��ʽ16-18��ʾ��SHOWDIB8˵�������ʹ�ô���DIB����ĵ�ɫ�̡�

 ï¿½ï¿½Ê½16-18  SHOWDIB8
SHOWDIB8.C
/*--------------------------------------------------------------------------
   	SHOWDIB8.C -- 		Shows DIB converted to DIB section
                 							(c) Charles Petzold, 1998
---------------------------------------------------------------------------*/

#include <windows.h>
#include "..\\ShowDib3\\PackeDib.h"
#include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("ShowDib8") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    							PSTR szCmdLine, int iCmdShow)
{
     	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= szAppName ;
     	wndclass.lpszClassName 		= szAppName ;

     	if (!RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"), 
                      								szAppName, MB_ICONERROR) ;
          			return 0 ;
     	}

     	hwnd = CreateWindow (	szAppName, TEXT ("Show DIB #8: DIB Section"),
                          	WS_OVERLAPPEDWINDOW,
                          	CW_USEDEFAULT, CW_USEDEFAULT,
                          	CW_USEDEFAULT, CW_USEDEFAULT, 
                          	NULL, NULL, hInstance, NULL) ;

     	ShowWindow (hwnd, iCmdShow) ;
     	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)
{
     	static HBITMAP      			hBitmap ;
     	static HPALETTE     			hPalette ;
     	static int          			cxClient, cyClient ;
     	static OPENFILENAME 	        ofn ;
     	static PBYTE        			pBits ;
     	static TCHAR        			szFileName [MAX_PATH], szTitleName [MAX_PATH] ;
     	static TCHAR        			szFilter[] = 	TEXT ("Bitmap Files (*.BMP)\0*.bmp\0")
        TEXT ("All Files (*.*)\0*.*\0\0") ;
     	BITMAP              		bitmap ;
     	BITMAPINFO        			* 	pPackedDib ;
  	    HDC                 		hdc, hdcMem ;
     	PAINTSTRUCT         		ps ;

     	switch (message)
     	{
     	case 	WM_CREATE:
          			ofn.lStructSize       	= sizeof (OPENFILENAME) ;
          			ofn.hwndOwner         	= hwnd ;
          			ofn.hInstance         	= NULL ;
          			ofn.lpstrFilter       	= szFilter ;
          			ofn.lpstrCustomFilter 	= NULL ;
          			ofn.nMaxCustFilter    	= 0 ;
          			ofn.nFilterIndex      	= 0 ;
          			ofn.lpstrFile         	= szFileName ;
          			ofn.nMaxFile          	= MAX_PATH ;
          			ofn.lpstrFileTitle    	= szTitleName ;
          			ofn.nMaxFileTitle     	= MAX_PATH ;
          			ofn.lpstrInitialDir   	= NULL ;
          			ofn.lpstrTitle        	= NULL ;
          			ofn.Flags             	= 0 ;
          			ofn.nFileOffset       	= 0 ;
          			ofn.nFileExtension    	= 0 ;
          			ofn.lpstrDefExt       	= TEXT ("bmp") ;
          			ofn.lCustData         	= 0 ;
          			ofn.lpfnHook          	= NULL ;
          			ofn.lpTemplateName    	= NULL ;

          			return 0 ;

     	case 	WM_SIZE:
          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;
          			return 0 ;

     	case 	WM_COMMAND:
          			switch (LOWORD (wParam))
          			{
          			case 	IDM_FILE_OPEN:

                    					// Show the File Open dialog box

               					if (!GetOpenFileName (&ofn))
                    							return 0 ;
               
                    // If there's an existing packed DIB, free the memory

               					if (hBitmap)
               					{
                    								DeleteObject (hBitmap) ;
                    								hBitmap = NULL ;
               					}

                    // If there's an existing logical palette, delete it

					if (hPalette)
               					{
                    								DeleteObject (hPalette) ;
                    								hPalette = NULL ;
               					}
                    // Load the packed DIB into memory

               					SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
               					ShowCursor (TRUE) ;

               					pPackedDib = PackedDibLoad (szFileName) ;

               					ShowCursor (FALSE) ;
               					SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               					if (pPackedDib)
               					{
                         	// Create the DIB section from the DIB

hBitmap = CreateDIBSection (NULL,pPackedDib,DIB_RGB_COLORS,&pBits,NULL, 0) ;

                   // Copy the bits

                   CopyMemory (pBits,	PackedDibGetBitsPtr  (pPackedDib),
                                        PackedDibGetBitsSize (pPackedDib)) ;

                     // Create palette from the DIB

                    hPalette = PackedDibCreatePalette (pPackedDib) ;

                       // Free the packed-DIB memory

                    						free (pPackedDib) ;
               					}
               					else
               					{
                MessageBox (	hwnd, TEXT ("Cannot load DIB file"), 
                            	szAppName, 0) ;
              					 	}
               					InvalidateRect (hwnd, NULL, TRUE) ;
               					return 0 ;
          			}
          			break ;
     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

          			if (hPalette)
          			{
               				SelectPalette (hdc, hPalette, FALSE) ;
               				RealizePalette (hdc) ;
          			}
          			if (hBitmap)
          			{
               				GetObject (hBitmap, sizeof (BITMAP), &bitmap) ;

               				hdcMem = CreateCompatibleDC (hdc) ;
               				SelectObject (hdcMem, hBitmap) ;

               	BitBlt (	hdc,    0, 0, bitmap.bmWidth, bitmap.bmHeight, 
                       		hdcMem, 0, 0, SRCCOPY) ;

               				DeleteDC (hdcMem) ;
          			}
          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_QUERYNEWPALETTE:
          			if (!hPalette)
               					return FALSE ;

          			hdc = GetDC 		(hwnd) ;
          			SelectPalette 		(hdc, hPalette, FALSE) ;
          			RealizePalette 		(hdc) ;
          			InvalidateRect 		(hwnd, NULL, TRUE) ;

          			ReleaseDC (hwnd, hdc) ;
          			return TRUE ;

     	case 	WM_PALETTECHANGED:
          			if (!hPalette || (HWND) wParam == hwnd)
               					break ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			UpdateColors (hdc) ;

          			ReleaseDC (hwnd, hdc) ;
          			break ;

          
     	case 	WM_DESTROY:
          			if (hBitmap)
               					DeleteObject (hBitmap) ;

          			if (hPalette)
               					DeleteObject (hPalette) ;

          			PostQuitMessage (0) ;
          			return 0 ;
     }
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}
 SHOWDIB8.RC ��ժ¼��
//Microsoft Developer Studio generated resource script.
#include "resource.h"
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
// Menu
SHOWDIB8 MENU DISCARDABLE 
BEGIN
    	POPUP "&File"
    	BEGIN	
        			MENUITEM "&Open", 			IDM_FILE_OPEN
    	END
END
 RESOURCE.H ��ժ¼��
// Microsoft Developer Studio generated include file.
// Used by ShowDib8.rc

#define IDM_FILE_OPEN             40001

��SHOWDIB7��SHOWDIB8�е�WM_PAINT������һ���ģ�������ʽ��������ͼ���ţ�hBitmap�����߼���ɫ�̴��ţ�hPalette����Ϊ��̬��������ɫ�̱�ѡ��װ�����ݲ����֣�����ͼ�Ŀ��Ⱥ͸߶ȴ�GetObject��ʽ��ã���ʽ����������װ�����ݲ�ѡ������ͼ��Ȼ��ͨ������BitBlt������ͼ��ʾ����ʾ����

������ʽ֮�����IJ����춴�����File������Open�����ܱ�����ij����ڻ��ָ��packed DIB��ָ�겢�����˵�ɫ�����ᣬSHOWDIB7���뽫��ɫ��ѡ����Ѷװ�����ݣ����ں���CreateDIBitmap֮ǰ���֡�SHOWDIB8�ڻ��packed DIBָ���������CreateDIBSection�����ؽ���ɫ��ѡ��װ�����ݣ�������ΪCreateDIBSection����DIBת�����豸��صĸ�ʽ����ȷ��CreateDIBSection�ĵ�һ����������װ�����ݴ��ţ���Ψһ��;������Ƿ�ʹ��DIB_PAL_COLORS��ꡣ

����CreateDIBSection���ᣬSHOWDIB8��ͼ��λԪ��packed DIB���Ƶ���CreateDIBSection��ʽ���صļ�����λ�ã�Ȼ�����PackedDibCreatePalette�����ܴ˺�ʽ��춳�ʽʹ�ã�����SHOWDIB8�����ݴ�GetDIBColorTable��ʽ���ص���Ѷ������ɫ�̡�

DIB������ʽ��
��

�������ڣ��������dz�ʱ���ѧϰGDI����ͼ�����װ���޹ص���ͼ��DIB�����Windows��ɫ�̹�����֮�ᣭ���Dz������˿���һ������춴�������ͼ�ĺ�ʽ��׼����

ǰ���PACKEDIB����չʾ��һ�ֿ��ܵķ������������е�packed DIBֻ��ָ������ָ���ʾ����ʽ�����й�DIB��ȫ����Ѷ�����ԴӴ�ȡ��ͷ��Ѷ�ṹ�ĺ�ʽ��á�Ȼ����ʵ���ϵ���get pixel���͡�set pixel����ʽʱ�����ַ����ͻ�������ص�ִ�����⡣ͼ��������Ȼ��Ҫ��ȡ����ͼλԪ��������Щ��ʽҲӦ�þ����ܵؿ졣

���ܵ�C++�Ľ����ʽ�а�������DIB�����ʱָ��packed DIB��ָ��������һ����Ա������������Ա�����ͳ�Ա��ʽ����춸����ִ�л�ú��趨DIB�е�ͼ�صij�ʽ����������Ϊ���ڵ�һ���Ѿ�ָ������춱�����ֻ��Ҫ�˽�C��ʹ��C++����������ķ�Χ��

��Ȼ����C++������������CҲ������һ���õ����Ӿ�������Windows��ʽ��ʹ�ô��š����˽����ŵ�����ֵ���⣬Ӧ�ó�ʽ�������˽�ʲô�أ���ʽ֪��������������ĺ�ʽ�������֪����ʽ��춴����ִ���������Ȼ����ҵϵͳ��ij�ַ�ʽ�ô���������������ڲ���Ѷ�����ſ�����ṹָ��һ���򵥡�

���磬������һ����ʽ������Щ��ʽ��ʹ��һ����ΪHDIB�Ĵ��š�HDIB��ʲô�أ���������ij����ͷ�����ж������£�

typedef void * HDIB ;

�˶����á����������¡��ش��ˡ�HDIB��ʲô��������⡣

Ȼ����ʵ����HDIB�����ǽṹָ�꣬�ýṹ��������ָ��packed DIB��ָ�꣬������������Ѷ��

typedef struct
{
     	BITMAPINFO 	* 	pPackedDib ;
     	int          				cx, cy, cBitsPerPixel, cBytesPerRow ;
     	BYTE       			* pBits ;
{
DIBSTRUCTURE, * PDIBSTRUCTURE ;

�˽ṹ�����������λ������packed DIB����������Ѷ����Ȼ���ṹ����Щֵ���������ٵش�ȡ���ǡ���ͬ��DIB��ʽ�⺯ʽ�����Դ�������ṹ��������pPackedDibָ�ꡣ���԰�����ķ�����ִ��DibGetPixelPointer��ʽ��

BYTE * DibGetPixelPointer (HDIB hdib, int x, int y)
{
     	PDIBSTRUCTURE pdib = hdib ;
     	return pdib->pBits + 	y * pdib->cBytesPerRow + 
                          			x * pdib->cBitsPerPixel / 8 ;
}

��Ȼ�����ַ�������Ҫ��PACKEDIB.C��ִ�С�get pixel����ʽ�졣

������ַ����dz������������Ҿ�������packed DIB�������ô���DIB�����DIB��ʽ�⡣��ʵ����ʹ���Ƕ�packed DIB�Ĵ����и���ĵ��ԣ�Ҳ����˵���ܹ���װ���޹صķ�ʽ�²���DIBͼ��λԪ����������Windows NT��ִ��ʱ������Ч��

DIBSTRUCT�ṹ
��

DIBHELP.C�����������������Ϊ�Դ���DIB�ṩ����������ǧ�У����ڼ���С��������ʾ���������������ǿ�һ��DIBHELP��ʽ�������Ľṹ���ýṹ��DIBHELP.C�ж������£�

typedef struct
{
     	PBYTE    	* ppRow ;       // array of row pointers
     	int        	iSignature ;  	// = "Dib "
     	HBITMAP    	hBitmap ;     	// handle returned from CreateDIBSection
     	BYTE     	* 	pBits ;     // pointer to bitmap bits
     	DIBSECTION 	ds ;          	// DIBSECTION structure
     	int        	iRShift[3] ;  	// right-shift values for color masks
     	int        	iLShift[3] ;  	// left-shift values for color masks
}
DIBSTRUCT, * PDIBSTRUCT ;

����������һ����λ����֮����Ϊ��һ����λ����Ϊ��ʹijЩ�޼������ʹ�ã���������������λ�������������һ����λ�͸������ˡ�

��DIBHELP.C�У���DIB�����ĺ�ʽ�����趨�˴˽ṹʱ���ڶ�����λ���趨Ϊ�����ִ���Dib���Ķ���λֵ��ͨ��һЩDIBHELP��ʽ���ڶ�����λ����춽ṹ��Чָ���һ����ǡ�

��������λ����hBitmap���Ǵ�CreateDIBSection��ʽ���صĵ���ͼ���š���������ô��ſ��ж���ʹ�÷�ʽ�����������ڵ�ʮ����������GDI����ͼ����Ĵ����÷�һ������������CreateDIBSection���صĴ��Ž��漰��װ���޹ظ�ʽ����ĵ���ͼ���õ���ͼ��ʽһֱ���浽ͨ������BitBlt��StretchBlt����λԪͼ��������豸��

DIBSTRUCT�ĵ��ĸ���λ��ָ�����ͼλԪ��ָ�ꡣ��ֵҲ����CreateDIBSection��ʽ�趨������������ҵϵͳ���������������飬��Ӧ�ó�ʽ�д�ȡ��������Ȩ����ɾ������ͼ����ʱ��������齫�Զ��ͷš�

DIBSTRUCT�ĵ������λ��DIBSECTION�ṹ��������д�CreateDIBSection���صĵ���ͼ���ţ���ô�����Խ����Ŵ��ݸ�GetObject��ʽ�Ի���й�DIBSECTION�ṹ�еĵ���ͼ��Ѷ��

GetObject (hBitmap, sizeof (DIBSECTION), &ds) ;

��Ϊ��ʾ��DIBSECTION�ṹ��WINGDI.H�ж������£�

typedef struct tagDIBSECTION {
    	BITMAP     				dsBm ;
   	BITMAPINFOHEADER 	dsBmih ;
   	DWORD            	dsBitfields[3] ;    // Color masks
    	HANDLE          dshSection ;
    	DWORD           dsOffset ;
}
DIBSECTION, * PDIBSECTION ;

��һ����λ��BITMAP�ṹ������CreateBitmapIndirectһ��������ͼ�������GetObjectһ�𴫻ع��DDB����Ѷ���ڶ�����λ��BITMAPINFOHEADER�ṹ�����ܵ���ͼ��Ѷ�ṹ�Ƿ񴫵ݸ�CreateDIBSection��ʽ��DIBSECTION�ṹ����BITMAPINFOHEADER�ṹ�����������ṹ������BITMAPCOREHEADER�ṹ������ζ���ڴ�ȡ�˽ṹʱ��DIBHELP.C�е����ຯʽ�����ؼ����OS/2���ݵ�DIB��

���16λԪ��32λԪ��DIB�����BITMAPINFOHEADER�ṹ��biCompression��λ��BI_BITFIELDS����ô����Ѷ��ͷ�ṹ����ͨ������������ֵ����Щ����ֵ������ν�16λԪ��32λͼ��ֵת����RGB��ɫ�����ִ�����DIBSECTION�ṹ�ĵ�������λ�С�

DIBSECTION�ṹ������������λָ����DIB���飬�������ɵ���ӳ�佨����DIBHELP��ʹ��CreateDIBSection��������ԣ���˿��Ժ�����Щ��λ��

DIBSTRUCT������������λ����������λֵ����Щֵ��춴���16λԪ��32λԪDIB����ɫ���֡����ǽ��ڵ�ʮ����������Щ��λֵ��

�������ٻ�����һ��DIBSTRUCT�ĵ�һ����λ������������������һ�����ڿ�ʼ����DIBʱ������λ�趨Ϊָ��һ��ָ�����е�ָ�꣬�������е�ÿ��ָ�궼ָ��DIB�е�һ��ͼ�ء���Щָ�������Ը���ķ�ʽ�����DIBͼ��λԪ��ͬʱҲ�����壬�Ա㶥�п�����������DIBͼ��λԪ�������е�����һ��Ԫ�أ�����DIBͼ�������У�ͨ�����DIBSTRUCT��pBits��λ��

��Ѷ��ʽ
��

DIBHELP.C�Զ���DIBSTRUCT�ṹ��ʼ��Ȼ���ṩһ����ʽ�����˺�ʽ������Ӧ�ó�ʽ����й�DIB�������Ѷ����ʽ16-19��ʾ��DIBHELP.C�ĵ�һ���֡�

 ï¿½ï¿½Ê½16-19  DIBHELP.C�����ĵ�һ����
DIBHELP.C ����һ���֣� 
/*--------------------------------------------------------------------------
   	DIBHELP.C -- 	DIB Section Helper Routines 
                						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>
#include "dibhelp.h"

#define HDIB_SIGNATURE (* (int *) "Dib ")
typedef struct
{
     	PBYTE    			* 	ppRow ;    // must be first field for macros!
     	int        			iSignature ;
     	HBITMAP    			hBitmap ;
     	BYTE     			* 	pBits ;
     	DIBSECTION 		ds ;
     	int        				iRShift[3] ;
     	int        				iLShift[3] ;
}
DIBSTRUCT, * PDIBSTRUCT ;

/*----------------------------------------------------------------------------
	DibIsValid:  Returns TRUE if hdib points to a valid DIBSTRUCT
-----------------------------------------------------------------------------*/

BOOL DibIsValid (HDIB hdib)
{
     	PDIBSTRUCT pdib = hdib ;
     	if (pdib == NULL)
          			return FALSE ;
     	if (IsBadReadPtr (pdib, sizeof (DIBSTRUCT)))
          			return FALSE ;
     	if (pdib->iSignature != HDIB_SIGNATURE)
          			return FALSE ;
     	return TRUE ;
}

/*----------------------------------------------------------------------------
   	DibBitmapHandle:	Returns the handle to the DIB section bitmap object
-----------------------------------------------------------------------------*/

HBITMAP DibBitmapHandle (HDIB hdib)
{
     	if (!DibIsValid (hdib))
          			return NULL ;
     	return ((PDIBSTRUCT) hdib)->hBitmap ;
}

/*---------------------------------------------------------------------------
   	DibWidth:  Returns the bitmap pixel width
-----------------------------------------------------------------------------*/

int DibWidth (HDIB hdib)
{
     	if (!DibIsValid (hdib))
          			return 0 ;
     	return ((PDIBSTRUCT) hdib)->ds.dsBm.bmWidth ;
}

/*---------------------------------------------------------------------------
   	DibHeight:  Returns the bitmap pixel height
----------------------------------------------------------------------------*/

int DibHeight (HDIB hdib)
{
 	if (!DibIsValid (hdib))
          			return 0 ; 
     	return ((PDIBSTRUCT) hdib)->ds.dsBm.bmHeight ;
}

/*---------------------------------------------------------------------------
   DibBitCount:  	Returns the number of bits per pixel
----------------------------------------------------------------------------*/

int DibBitCount (HDIB hdib)
{
     	if (!DibIsValid (hdib))
          			return 0 ;
     
     	return ((PDIBSTRUCT) hdib)->ds.dsBm.bmBitsPixel ;
}

/*----------------------------------------------------------------------------
   	DibRowLength:  	Returns the number of bytes per row of pixels
-----------------------------------------------------------------------------*/

int DibRowLength (HDIB hdib)
{
   	if (!DibIsValid (hdib))
          			return 0 ;
     	return 4 * ((DibWidth (hdib) * DibBitCount (hdib) + 31) / 32) ;
}

/*---------------------------------------------------------------------------
   DibNumColors:  	Returns the number of colors in the color table
----------------------------------------------------------------------------*/

int DibNumColors (HDIB hdib)
{
     	PDIBSTRUCT pdib = hdib ;

     	if (!DibIsValid (hdib))
          			return 0 ;

     	if (pdib->ds.dsBmih.biClrUsed != 0)
     {
          			return pdib->ds.dsBmih.biClrUsed ;
     }
     	else if (DibBitCount (hdib) <= 8)
     {
          		return 1 << DibBitCount (hdib) ;
     }
     	return 0 ;
}
/*---------------------------------------------------------------------------
   	DibMask:  Returns one of the color masks
---------------------------------------------------------------------------*/

DWORD 	DibMask (HDIB hdib, int i)
{
     	PDIBSTRUCT pdib = hdib ;

     	if (!DibIsValid (hdib) || i < 0 || i > 2)
          			return 0 ;
     
     	return pdib->ds.dsBitfields[i] ;
}

/*----------------------------------------------------------------------------
   	DibRShift:  Returns one of the right-shift values
-----------------------------------------------------------------------------*/

int 	DibRShift (HDIB hdib, int i)
{	
     	PDIBSTRUCT pdib = hdib ;

     	if (!DibIsValid (hdib) || i < 0 || i > 2)
          			return 0 ;
     
     	return pdib->iRShift[i] ;
}

/*----------------------------------------------------------------------------
   	DibLShift:  Returns one of the left-shift values
----------------------------------------------------------------------------*/

int DibLShift (HDIB hdib, int i)
{
     	PDIBSTRUCT pdib = hdib ;

     	if (!DibIsValid (hdib) || i < 0 || i > 2)
          			return 0 ;
     
     	return pdib->iLShift[i] ;
}

/*---------------------------------------------------------------------------
   	DibCompression:  Returns the value of the biCompression field
----------------------------------------------------------------------------*/
int DibCompression (HDIB hdib)
{
     	if (!DibIsValid (hdib))
          			return 0 ;

     	return ((PDIBSTRUCT) hdib)->ds.dsBmih.biCompression ;
}

/*---------------------------------------------------------------------------
   	DibIsAddressable:  Returns TRUE if the DIB is not compressed
----------------------------------------------------------------------------*/

BOOL 	DibIsAddressable (HDIB hdib)
{
     	int iCompression ;

     	if (!DibIsValid (hdib))
          			return FALSE ;

     	iCompression = DibCompression (hdib) ;

     	if (	iCompression == BI_RGB || iCompression == BI_BITFIELDS)
         			return TRUE ;

     	return FALSE ;
}

/*---------------------------------------------------------------------------
   	These functions return the sizes of various components of the DIB section
     	AS THEY WOULD APPEAR in a packed DIB. These functions aid in converting
	the DIB section to a packed DIB and in saving DIB files.
-----------------------------------------------------------------------------*/

DWORD DibInfoHeaderSize (HDIB hdib)
{
     	if (!DibIsValid (hdib))
          			return 0 ;
     	return ((PDIBSTRUCT) hdib)->ds.dsBmih.biSize ;
}

DWORD 	DibMaskSize (HDIB hdib)
{
     	PDIBSTRUCT pdib = hdib ;
     	if (!DibIsValid (hdib))
          			return 0 ;

	if (pdib->ds.dsBmih.biCompression == BI_BITFIELDS)
          			return 3 * sizeof (DWORD) ;

     	return 0 ;
}

DWORD DibColorSize (HDIB hdib)
{
	return DibNumColors (hdib) * sizeof (RGBQUAD) ;
} 

DWORD DibInfoSize (HDIB hdib)
{
     	return DibInfoHeaderSize(hdib) + DibMaskSize(hdib) + DibColorSize(hdib) ;
}

DWORD DibBitsSize (HDIB hdib)
{
     	PDIBSTRUCT pdib = hdib ;

     	if (!DibIsValid (hdib))
          			return 0 ;

     	if (pdib->ds.dsBmih.biSizeImage != 0)
     {
          			return pdib->ds.dsBmih.biSizeImage ;
     }
     	return DibHeight (hdib) * DibRowLength (hdib) ;
}

DWORD DibTotalSize (HDIB hdib)
{
     	return DibInfoSize (hdib) + DibBitsSize (hdib) ;
}

/*---------------------------------------------------------------------------
   	These functions return pointers to the various components of the DIB 
     	section.
-----------------------------------------------------------------------------*/
BITMAPINFOHEADER * DibInfoHeaderPtr (HDIB hdib)
{
     	if (!DibIsValid (hdib))
          			return NULL ;
     	return & (((PDIBSTRUCT) hdib)->ds.dsBmih) ;
}

DWORD * DibMaskPtr (HDIB hdib)
{
     	PDIBSTRUCT pdib = hdib ;
     	if (!DibIsValid (hdib))
         			return 0 ;
     	return pdib->ds.dsBitfields ;
}

void * DibBitsPtr (HDIB hdib)
{
     	if (!DibIsValid (hdib))
          			return NULL ;
     	return ((PDIBSTRUCT) hdib)->pBits ;
}

/*---------------------------------------------------------------------------
   	DibSetColor:  Obtains entry from the DIB color table
-----------------------------------------------------------------------------*/

BOOL DibGetColor (HDIB hdib, int index, RGBQUAD * prgb)
{
     	PDIBSTRUCT pdib = hdib ;
     	HDC        				hdcMem ;
     	int        				iReturn ;

     	if (!DibIsValid (hdib))
          			return 0 ;
     	hdcMem = CreateCompatibleDC (NULL) ;
     	SelectObject (hdcMem, pdib->hBitmap) ;
     	iReturn = GetDIBColorTable (hdcMem, index, 1, prgb) ;
     	DeleteDC (hdcMem) ;
     	return iReturn ? TRUE : FALSE ;
}

/*----------------------------------------------------------------------------
   	DibGetColor:  Sets an entry in the DIB color table
----------------------------------------------------------------------------*/
 
BOOL DibSetColor (HDIB hdib, int index, RGBQUAD * prgb)
{
     	PDIBSTRUCT 	pdib = hdib ;
     	HDC        			hdcMem ;
     	int        			iReturn ;

     	if (!DibIsValid (hdib))
          			return 0 ;
     	hdcMem = CreateCompatibleDC (NULL) ;
     	SelectObject (hdcMem, pdib->hBitmap) ;
     	iReturn = SetDIBColorTable (hdcMem, index, 1, prgb) ;
     	DeleteDC (hdcMem) ;

     	return iReturn ? TRUE : FALSE ;
}

DIBHELP.C�еĴ󲿷ֺ�ʽ�Dz��ý��͵ġ�DibIsValid��ʽ������춱�������ϵͳ������ͼ����DIBSTRUCT�е���Ѷ֮ǰ��������ʽ������DibIsValid��������Щ��ʽ���У�����ͨ����ֻ�У�HDIB��̬�ĵ�һ��������( ���ǽ������������ò�����DIBHELP.H�ж���Ϊ��ָ�ꡣ��Щ��ʽ���Խ��˲������浽PDIBSTRUCT��Ȼ���ٴ�ȡ�ṹ�е���λ��

ע�⴫��BOOLֵ��DibIsAddressable��ʽ��DibIsNotCompressed��ʽҲ���Ժ��д˺�ʽ������ֵ��ʾ������DIBͼ���ܷ�ַ��

��DibInfoHeaderSize��ʼ�ĺ�ʽ����ȡ��DIB�����в�ͬԪ��������packed DIB�еĴ�С����������������һ������Щ��ʽ����춽�DIB����ת����packed DIB��������DIB��������Щ��ʽ�������ǻ��ָ��ͬDIBԪ����ָ��ĺ�ʽ����

����DIBHELP.C��������ΪDibInfoHeaderPtr�ĺ�ʽ�����Ҹú�ʽ�����ָ��BITMAPINFOHEADER�ṹ��ָ�꣬������û�к�ʽ���Ի��BITMAPINFO�ṹָ�꣭������DIB��ɫ���������Ѷ�ṹ��������Ϊ�ڴ���DIB����ʱ��Ӧ�ó�ʽ����ֱ�Ӵ�ȡ������̬�Ľṹ��BITMAPINFOHEADER�ṹ����ɫ���ֶ���DIBSECTION�ṹ����Ч�����Ҵ�CreateDIBSection��ʽ����ָ��ͼ��λԪ��ָ�꣬��ʱͨ������GetDIBColorTable��SetDIBColorTable����ֻ�ܼ�Ӵ�ȡDIB��ɫ������Щ���ܶ���װ��DIBHELP��DibGetColor��DibSetColor��ʽ��ͷ�ˡ�

��DIBHELP.C�����棬����DibCopyToInfo����һ��ָ��BITMAPINFO�ṹ��ָ�꣬�������Ѷ������������ָ����������ִ�ṹ��ָ�겻��ȫ��ͬ��

����дͼ��
��

Ӧ�ó�ʽά��packed DIB��DIB�����һ������עĿ���ŵ����ܹ�ֱ�Ӳ���DIBͼ��λԪ����ʽ16-20��ʾ��DIBHELP.C�ڶ������г����ṩ�˹��ܵĺ�ʽ��

 ï¿½ï¿½Ê½16-20  DIBHELP.C�����ĵڶ�����
DIBHELP.C ���ڶ����֣� 
/*----------------------------------------------------------------------------
   	DibPixelPtr:  	Returns a pointer to the pixel at position (x, y)
-----------------------------------------------------------------------------*/

BYTE * DibPixelPtr (HDIB hdib, int x, int y)
{
     	if (!DibIsAddressable (hdib))
          			return NULL ;
     	if (x < 0 || x >= DibWidth (hdib) || y < 0 || y >= DibHeight (hdib))
          			return NULL ;
     	return (((PDIBSTRUCT) hdib)->ppRow)[y] + (x * DibBitCount (hdib) >> 3) ;
}

/*---------------------------------------------------------------------------
   	DibGetPixel:  Obtains a pixel value at (x, y)
-----------------------------------------------------------------------------*/

DWORD DibGetPixel (HDIB hdib, int x, int y)
{
     	PBYTE pPixel ;
     	if (!(pPixel = DibPixelPtr (hdib, x, y)))
     			return 0 ;
     	switch (DibBitCount (hdib))
     	{
     	case 		1:  return 0x01 & (* pPixel >> (7 - (x & 7))) ;
     	case		4:  return 0x0F & (* pPixel >> (x & 1 ? 0 : 4)) ;
     	case  		8:  return * pPixel ;
     	case 		16: return * (WORD *) pPixel ;
     	case 		24: return 0x00FFFFFF & * (DWORD *) pPixel ; 
     	case 		32: return * (DWORD *) pPixel ;
     	}
  	return 0 ;
}

/*-------------------------------------------------------------------------
   	DibSetPixel:  Sets a pixel value at (x, y)
---------------------------------------------------------------------------*/

BOOL DibSetPixel (HDIB hdib, int x, int y, DWORD dwPixel)
{
     	PBYTE pPixel ;
     	if (!(pPixel = DibPixelPtr (hdib, x, y)))
          			return FALSE ;
     	switch (DibBitCount (hdib))
     {
     	case  1:  	* 	pPixel &= ~(1     << (7 - (x & 7))) ;
               		* 	pPixel |= dwPixel 	  << (7 - (x & 7)) ;
               					break ;
     	case  	4:  * 	pPixel &= 0x0F    << (x & 1 ? 4 : 0) ;
               		* 	pPixel |= dwPixel 	  << (x & 1 ? 0 : 4) ;
               					break ;
     	case 8:  	* 	pPixel = (BYTE) dwPixel ;
               					break ;

     	case 16:  	* 	(WORD *) pPixel = (WORD) dwPixel ;
               					break ;

     	case 24:  	* 	(RGBTRIPLE *) pPixel = * (RGBTRIPLE *) &dwPixel ; 
               					break ;

     	case 32:  	* 	(DWORD *) pPixel = dwPixel ;
               					break ;
     	default:
          			return FALSE ;
     	}
     	return TRUE ;
}

/*---------------------------------------------------------------------------
   	DibGetPixelColor:  Obtains the pixel color at (x, y)
----------------------------------------------------------------------------*/

BOOL DibGetPixelColor (HDIB hdib, int x, int y, RGBQUAD * prgb)
{
     	DWORD      			dwPixel ;
     	int        			iBitCount ;
     	PDIBSTRUCT 	pdib = hdib ;

          			// Get bit count; also use this as a validity check

     	if (0 == (iBitCount = DibBitCount (hdib)))
          			return FALSE ;
          			// Get the pixel value
     	dwPixel = DibGetPixel (hdib, x, y) ;
          			// If the bit-count is 8 or less, index the color table
     	if (iBitCount <= 8)
          			return DibGetColor (hdib, (int) dwPixel, prgb) ;
          			// If the bit-count is 24, just use the pixel
     	else 	if (iBitCount == 24)
     {
          		* 	(RGBTRIPLE *) prgb = * (RGBTRIPLE *) & dwPixel ;
          			prgb->rgbReserved = 0 ;
 	}

          		// If the bit-count is 32 and the biCompression field is BI_RGB,
          		//   just use the pixel

     	else 	if (iBitCount == 32 && 
               					pdib->ds.dsBmih.biCompression == BI_RGB)
     	{
          		* 	prgb = * (RGBQUAD *) & dwPixel ;
     	}

          		// Otherwise, use the mask and shift values
          		//   (for best performance, don't use DibMask and DibShift functions)
     	else
     	{
          	prgb->rgbRed = (BYTE)(((pdib->ds.dsBitfields[0] & dwPixel) 
                     >> pdib->iRShift[0]) << pdib->iLShift[0]) ;

          	prgb->rgbGreen=(BYTE((pdib->ds.dsBitfields[1] & dwPixel) 
                     >> pdib->iRShift[1]) << pdib->iLShift[1]) ;

          	prgb->rgbBlue=(BYTE)(((pdib->ds.dsBitfields[2] & dwPixel) 
                     >> pdib->iRShift[2]) << pdib->iLShift[2]) ;
     	}
    	return TRUE ;
}

/*-----------------------------------------------------------------------------
   	DibSetPixelColor:  Sets the pixel color at (x, y) 
-----------------------------------------------------------------------------*/

BOOL DibSetPixelColor (HDIB hdib, int x, int y, RGBQUAD * prgb)
{
     	DWORD      			dwPixel ;
     	int        			iBitCount ;
     	PDIBSTRUCT 	pdib = hdib ;

          		// Don't do this function for DIBs with color tables

     	iBitCount = DibBitCount (hdib) ;
     	if (iBitCount <= 8)
          			return FALSE ;
          		// The rest is just the opposite of DibGetPixelColor
     	else if (iBitCount == 24)
     	{
          			* (RGBTRIPLE *) & dwPixel = * (RGBTRIPLE *) prgb ;
       			dwPixel &= 0x00FFFFFF ;
     	}
     	else if (iBitCount == 32 &&
               					pdib->ds.dsBmih.biCompression == BI_RGB)
     {
          			* (RGBQUAD *) & dwPixel = * prgb ;
     }

     	else
     {
        dwPixel  = 	(((DWORD)	prgb->rgbRed >> pdib->iLShift[0]) 
        << pdib->iRShift[0]) ; 

        dwPixel |= 	(((DWORD) 	prgb->rgbGreen >> pdib->iLShift[1])
        << pdib->iRShift[1]) ; 

        dwPixel |= 	(((DWORD) 	prgb->rgbBlue >> pdib->iLShift[2])
        << pdib->iRShift[2]) ; 
     	}

     	DibSetPixel (hdib, x, y, dwPixel) ;
     	return TRUE ;
}

�ⲿ��DIBHELP.C��DibPixelPtr��ʽ��ʼ���ú�ʽ���ָ�򴢴棨�򲿷ִ��棩������ͼ�ص�λԪ���ָ�ꡣ����һ��DIBSTRUCT�ṹ��ppRow��λ�����Ǹ�ָ��DIB���ɶ��п�ʼ���е�ͼ����λַ��ָ�ꡣ������

((PDIBSTRUCT) hdib)->pprow)[0]

����ָ��DIB���������ͼ�ص�ָ�꣬��

(((PDIBSTRUCT) hdib)->ppRow)[y] + (x * DibBitCount (hdib) >> 3)

��ָ��λ�(x,y)��ͼ�ص�ָ�ꡣע�⣬���DIB�е�ͼ�ز��ɱ���ַ���������ѹ���������������ʽ��x��y�����Ǹ��������λ�DIB�����������ʽ������NULL���˼�齵���˺�ʽ�������������DibPixelPtr�ĺ�ʽ����ִ���ٶȣ������ҽ�����һЩ����ij�ʽ��

���������DibGetPixel��DibSetPixel��ʽ������DibPixelPtr�����8λԪ��16λԪ��32λԪDIB����Щ��ʽֻ��¼ָ��������ϳߴ��ָ�꣬����ȡͼ��ֵ�����1λԪ��4λԪ��DIB������Ҫ���ֺ���λ�Ƕȡ�

DibGetColor��ʽ��RGBQUAD�ṹ���ͼ����ɫ�����1λԪ��4λԪ��8λԪDIB�������ʹ��ͼ��ֵ����DIB��ɫ�������ɫ�����16λԪ��24λԪ��32λԪDIB��ͨ�����뽫ͼ��ֵ���ֺ���λ�Եõ�RGB��ɫ��DibSetPixel��ʽ���෴����������RGBQUAD�ṹ�趨ͼ��ֵ���ú�ʽֻΪ16λԪ��24λԪ��32λԪDIB���塣

������ת��
��

��ʽ16-21��ʾ��DIBHELP�������ֺ����Ჿ��չʾ����ν���DIB���飬�Լ���ν�DIB������packed DIB�໥ת����

 ï¿½ï¿½Ê½16-21  DIBHELP.C�����ĵ������ֺ����Ჿ��
DIBHELP.C ���������֣� 
/*--------------------------------------------------------------------------
	Calculating shift values from color masks is required by the 
	DibCreateFromInfo function.
----------------------------------------------------------------------------*/

static int MaskToRShift (DWORD dwMask)
{
     	int iShift ;
     	if (dwMask == 0)
          			return 0 ;
     	for (iShift = 0 ; !(dwMask & 1) ; iShift++)
          			dwMask >>= 1 ;
     	return iShift ;
}

static int MaskToLShift (DWORD dwMask)
{
     	int iShift ;
     	if (dwMask == 0)
          			return 0 ;
     	while (!(dwMask & 1))
          			dwMask >>= 1 ;
     	for (iShift = 0 ; dwMask & 1 ; iShift++)
          			dwMask >>= 1 ;
     	return 8 - iShift ;
}
/*----------------------------------------------------------------------------
	DibCreateFromInfo: All DIB creation functions ultimately call this one.
	This function is responsible for calling CreateDIBSection, allocating
	memory for DIBSTRUCT, and setting up the row pointer.
-----------------------------------------------------------------------------*/

HDIB DibCreateFromInfo (BITMAPINFO * pbmi)
{
     	BYTE      			* 	pBits ;
     	DIBSTRUCT 	* 	pdib ;
     	HBITMAP     			hBitmap ;
     	int         				i, iRowLength, cy, y ;
     
     	hBitmap = CreateDIBSection (NULL, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0) ;
     	if (hBitmap == NULL)
          			return NULL ;
     	if (NULL == (pdib = malloc (sizeof (DIBSTRUCT))))
     	{
          			DeleteObject (hBitmap) ;
          			return NULL ;
 	}

     	pdib->iSignature 	= HDIB_SIGNATURE ;
     	pdib->hBitmap 		= hBitmap ;
     	pdib->pBits      	= pBits ;

     	GetObject (hBitmap, sizeof (DIBSECTION), &pdib->ds) ;
          		// Notice that we can now use the DIB information functions 
          		//   defined above.

          		// If the compression is BI_BITFIELDS, calculate shifts from masks

     	if (DibCompression (pdib) == BI_BITFIELDS)
     	{
          		for (i = 0 ; i < 3 ; i++)
          		{
               			pdib->iLShift[i] = MaskToLShift (pdib->ds.dsBitfields[i]) ;
               			pdib->iRShift[i] = MaskToRShift (pdib->ds.dsBitfields[i]) ;
          		}
     	}

          		// If the compression is BI_RGB, but bit-count is 16 or 32,
          		//   set the bitfields and the masks
     	else if (DibCompression (pdib) == BI_RGB)
     	{
          		if (DibBitCount (pdib) == 16)
          		{
               			pdib->ds.dsBitfields[0] = 0x00007C00 ;
               			pdib->ds.dsBitfields[1] = 0x000003E0 ;
               			pdib->ds.dsBitfields[2] = 0x0000001F ;

               			pdib->iRShift	[0]	= 		10 	;
               			pdib->iRShift	[1]	=  		5 	;
               			pdib->iRShift	[2]	=  		0 	; 

               			pdib->iLShift	[0]	=  		3 	;
               			pdib->iLShift	[1]	=  		3 	;
               			pdib->iLShift	[2]	=  		3 	;
          		}
          		else if (DibBitCount (pdib) == 24 || DibBitCount (pdib) == 32)
          		{
               			pdib->ds.dsBitfields[0] = 0x00FF0000 ;
               			pdib->ds.dsBitfields[1] = 0x0000FF00 ;
               			pdib->ds.dsBitfields[2] = 0x000000FF ;

               			pdib->iRShift	[0] 	= 		16 	;
               			pdib->iRShift	[1] 	=  		8 	;
               			pdib->iRShift	[2] 	=  		0 	; 

               			pdib->iLShift	[0] 	=  		0 	;
               			pdib->iLShift	[1] 	=  		0 	;
               			pdib->iLShift	[2] 	=  		0	;
          		}
	}
          		// Allocate an array of pointers to each row in the DIB
     	cy = DibHeight (pdib) ;
     	if (NULL == (pdib->ppRow = malloc (cy * sizeof (BYTE *))))
     	{
          			free (pdib) ;
          			DeleteObject (hBitmap) ;
          			return NULL ;
     	}

          		// Initialize them.
     	iRowLength = DibRowLength (pdib) ; 
     	if (pbmi->bmiHeader.biHeight > 0)       			// ie, bottom up
     	{
          			for (y = 0 ; y < cy ; y++)
               					pdib->ppRow[y] = pBits + (cy - y - 1) * iRowLength ;
     	}
     	else   														
// top down
     {
          			for (y = 0 ; y < cy ; y++)
               					pdib->ppRow[y] = pBits + y * iRowLength ;
     	}
     	return pdib ;
 }

/*--------------------------------------------------------------------------
   	DibDelete:  Frees all memory for the DIB section
----------------------------------------------------------------------------*/

BOOL DibDelete (HDIB hdib)
{
	DIBSTRUCT * pdib = hdib ;
     	if (!DibIsValid (hdib))
          			return FALSE ;
     	free (pdib->ppRow) ;
     	DeleteObject (pdib->hBitmap) ;
     	free (pdib) ;
     	return TRUE ;
}

/*----------------------------------------------------------------------------
   	DibCreate: Creates an HDIB from explicit arguments
-----------------------------------------------------------------------------*/ 

HDIB DibCreate (int cx, int cy, int cBits, int cColors)
{
     	BITMAPINFO 	* 	pbmi ;
     	DWORD        				dwInfoSize ;
     	HDIB         				hDib ;
     	int          				cEntries ;

     	if (cx <= 0 || cy <= 0 || 
         			((cBits !=  1) && (cBits !=  4) && (cBits !=	8) && 
          				(cBits != 16) && (cBits != 24) && (cBits != 32)))
    	{
          		return NULL ;
  	}

 	if (	cColors != 0)
          			cEntries = cColors ;
  	else	if (cBits <= 8)
          			cEntries = 1 << cBits ;

     	dwInfoSize = sizeof (BITMAPINFOHEADER) + (cEntries - 1) * sizeof (RGBQUAD);

     	if (NULL == (pbmi = malloc (dwInfoSize)))
     	{
          		return NULL ;
     	}

     	ZeroMemory (pbmi, dwInfoSize) ;

     	pbmi->bmiHeader.biSize          		= sizeof (BITMAPINFOHEADER) ;
     	pbmi->bmiHeader.biWidth         		= cx ;
     	pbmi->bmiHeader.biHeight        		= cy ;
     	pbmi->bmiHeader.biPlanes        		= 1 ;
     	pbmi->bmiHeader.biBitCount      		= cBits ;
     	pbmi->bmiHeader.biCompression   		= BI_RGB ;
     	pbmi->bmiHeader.biSizeImage     		= 0 ;
     	pbmi->bmiHeader.biXPelsPerMeter 		= 0 ;
     	pbmi->bmiHeader.biYPelsPerMeter 		= 0 ;
     	pbmi->bmiHeader.biClrUsed       		= cColors ;
     	pbmi->bmiHeader.biClrImportant  		= 0 ;

     	hDib = DibCreateFromInfo (pbmi) ;
     	free (pbmi) ;

     	return hDib ;
}

/*----------------------------------------------------------------------------
	DibCopyToInfo:  		Builds BITMAPINFO structure.
                   							Used by DibCopy and DibCopyToDdb
-----------------------------------------------------------------------------*/

static BITMAPINFO * DibCopyToInfo (HDIB hdib)
{
     	BITMAPINFO 		*	pbmi ;
     	int          					i, iNumColors ;
     	RGBQUAD    			* 	prgb ;
     	if (!DibIsValid (hdib))
          			return NULL ;
          			// Allocate the memory
     	if (NULL == (pbmi = malloc (DibInfoSize (hdib))))
          			return NULL ;
          			// Copy the information header
     	CopyMemory (pbmi, DibInfoHeaderPtr	(hdib), sizeof (BITMAPINFOHEADER));
          
          			// Copy the possible color masks

     	prgb = (RGBQUAD *) ((BYTE *) pbmi + sizeof (BITMAPINFOHEADER)) ;
     	if (DibMaskSize (hdib))
     	{
          			CopyMemory (prgb, DibMaskPtr (hdib), 3 * sizeof (DWORD)) ;
          			prgb = (RGBQUAD *) ((BYTE *) prgb + 3 * sizeof (DWORD)) ;
 	}
          			// Copy the color table
     	iNumColors = DibNumColors (hdib) ;
     	for (i = 0 ; i < iNumColors ; i++)
          			DibGetColor (hdib, i, prgb + i) ;
     	return pbmi ;
}

/*--------------------------------------------------------------------------
   	DibCopy:  Creates a new DIB section from an existing DIB section,
     		possibly swapping the DIB width and height.
---------------------------------------------------------------------------*/

HDIB DibCopy (HDIB hdibSrc, BOOL fRotate)
{
     	BITMAPINFO 		* 	pbmi ;
     	BYTE       		* 	pBitsSrc, * pBitsDst ;
     	HDIB         	hdibDst ;

     	if (!DibIsValid (hdibSrc))
          			return NULL ;
     	if (NULL == (pbmi = DibCopyToInfo (hdibSrc)))
          			return NULL ;
     	if (fRotate)
     	{
          			pbmi->bmiHeader.biWidth = DibHeight (hdibSrc) ;
          			pbmi->bmiHeader.biHeight = DibWidth (hdibSrc) ;
     	}

     	hdibDst = DibCreateFromInfo (pbmi) ;
     	free (pbmi) ;

     	if (	hdibDst == NULL)
          			return NULL ;

          				// Copy the bits

     	if (!fRotate)
     	{
          				pBitsSrc = DibBitsPtr (hdibSrc) ;
          				pBitsDst = DibBitsPtr (hdibDst) ;

          				CopyMemory (pBitsDst, pBitsSrc, DibBitsSize (hdibSrc)) ;
     	}
	return hdibDst ;
}

/*----------------------------------------------------------------------------
   	DibCopyToPackedDib is generally used for saving DIBs and for 
 	transferring DIBs to the clipboard. In the second case, the second 
  	argument should be set to TRUE so that the memory is allocated
  	with the GMEM_SHARE flag.
-----------------------------------------------------------------------------*/

BITMAPINFO * DibCopyToPackedDib (HDIB hdib, BOOL fUseGlobal)
{
     	BITMAPINFO 		* 	pPackedDib ;
     	BYTE       		* 	pBits ;
     	DWORD        		dwDibSize ;
     	HDC          		hdcMem ;
     	HGLOBAL      		hGlobal ;
     	int          		iNumColors ;
     	PDIBSTRUCT   		pdib = hdib ;
     	RGBQUAD    		* 	prgb ;

     	if (!DibIsValid (hdib))
          			return NULL ;
          				// Allocate memory for packed DIB
     	dwDibSize = DibTotalSize (hdib) ;
     	if (fUseGlobal)
     	{
          			hGlobal = GlobalAlloc (GHND | GMEM_SHARE, dwDibSize) ;
          			pPackedDib = GlobalLock (hGlobal) ;
     	}
     	else
   	{
          			pPackedDib = malloc (dwDibSize) ;
     	}

     	if (pPackedDib == NULL) 
          			return NULL ;
          			// Copy the information header
     	CopyMemory (pPackedDib, &pdib->ds.dsBmih, sizeof (BITMAPINFOHEADER)) ;
     	prgb = (RGBQUAD *) ((BYTE *) pPackedDib + sizeof (BITMAPINFOHEADER)) ;
          			// Copy the possible color masks
     	if (pdib->ds.dsBmih.biCompression == BI_BITFIELDS)
     	{
          		CopyMemory (prgb, pdib->ds.dsBitfields, 3 * sizeof (DWORD)) ;
          		prgb = (RGBQUAD *) ((BYTE *) prgb + 3 * sizeof (DWORD)) ;
     	}
          			// Copy the color table
     	if (iNumColors = DibNumColors (hdib))
     	{
          			hdcMem = CreateCompatibleDC (NULL) ;
          			SelectObject (hdcMem, pdib->hBitmap) ;
          			GetDIBColorTable (hdcMem, 0, iNumColors, prgb) ;
          			DeleteDC (hdcMem) ;
     	}

     	pBits = (BYTE *) (prgb + iNumColors) ;
          			// Copy the bits
     	CopyMemory (pBits, pdib->pBits, DibBitsSize (pdib)) ;
          			// If last argument is TRUE, unlock global memory block and 
          			//   cast it to pointer in preparation for return

     	if (fUseGlobal)
     	{
          			GlobalUnlock (hGlobal) ;
          			pPackedDib = (BITMAPINFO *) hGlobal ;     
     	}
	return pPackedDib ;
}

/*--------------------------------------------------------------------------
   DibCopyFromPackedDib is generally used for pasting DIBs from the 
     clipboard.
  ------------------------------------------------------------------------*/

HDIB DibCopyFromPackedDib (BITMAPINFO * pPackedDib)
{
     	BYTE     			* 	pBits ;     
     	DWORD      				dwInfoSize, dwMaskSize, dwColorSize ;
     	int        				iBitCount ;
     	PDIBSTRUCT 		pdib ;

          			// Get the size of the information header and do validity check
     
     	dwInfoSize = pPackedDib->bmiHeader.biSize ;
     	if (	dwInfoSize != sizeof (BITMAPCOREHEADER) &&
         			dwInfoSize != sizeof (BITMAPINFOHEADER) &&
         			dwInfoSize != sizeof (BITMAPV4HEADER) &&
         			dwInfoSize != sizeof (BITMAPV5HEADER))
     	{
          			return NULL ;
     	}
          			// Get the possible size of the color masks

     	if (dwInfoSize == sizeof (BITMAPINFOHEADER) &&
          			pPackedDib->bmiHeader.biCompression == BI_BITFIELDS)
     	{
          			dwMaskSize = 3 * sizeof (DWORD) ;
     	}
     	else
     	{
          			dwMaskSize = 0 ;
     	}
          			// Get the size of the color table
     	if (dwInfoSize == sizeof (BITMAPCOREHEADER))
     	{
          			iBitCount = ((BITMAPCOREHEADER *) pPackedDib)->bcBitCount ;

          			if (iBitCount <= 8)
          			{
               		dwColorSize = (1 << iBitCount) * sizeof (RGBTRIPLE) ;
          			}
          			else
               					dwColorSize = 0 ;
   	}
     	else           				// all non-OS/2 compatible DIBs
     	{
          			if (pPackedDib->bmiHeader.biClrUsed > 0)
          			{
              dwColorSize = pPackedDib->bmiHeader.biClrUsed * sizeof (RGBQUAD);
          			}
          			else if (pPackedDib->bmiHeader.biBitCount <= 8)
          			{
               					dwColorSize = (1 << pPackedDib->bmiHeader.biBitCount) * sizeof (RGBQUAD) ;
          			}
          			else
          			{
               					dwColorSize = 0 ;
          			}
     	}
          			// Finally, get the pointer to the bits in the packed DIB
     	pBits = (BYTE *) pPackedDib + dwInfoSize + dwMaskSize + dwColorSize ;
          			// Create the HDIB from the packed-DIB pointer
     	pdib = DibCreateFromInfo (pPackedDib) ;
          			// Copy the pixel bits
     	CopyMemory (pdib->pBits, pBits, DibBitsSize (pdib)) ;
     	return pdib ;
}

/*----------------------------------------------------------------------------
   	DibFileLoad:  Creates a DIB section from a DIB file
-----------------------------------------------------------------------------*/
HDIB DibFileLoad (const TCHAR * szFileName)
{
     	BITMAPFILEHEADER 		bmfh ;
     	BITMAPINFO     			* 	pbmi ;
     	BOOL             						bSuccess ;
     	DWORD            						dwInfoSize, dwBitsSize, dwBytesRead ;
     	HANDLE           					hFile ;
     	HDIB             						hDib ;

		// Open the file: read access, prohibit write access

     	hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
                            OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL) ;
     	if (hFile == INVALID_HANDLE_VALUE)
          			return NULL ;
          			// Read in the BITMAPFILEHEADER
     	bSuccess = ReadFile (	hFile, &bmfh, sizeof (BITMAPFILEHEADER), 
                          			&dwBytesRead, NULL) ;

     	if (!bSuccess 	|| (dwBytesRead != sizeof (BITMAPFILEHEADER))         
                   						|| (bmfh.bfType != * (WORD *) "BM"))
     	{
          			CloseHandle (hFile) ;
          			return NULL ;
     }
          			// Allocate memory for the information structure & read it in
     	dwInfoSize = bmfh.bfOffBits - sizeof (BITMAPFILEHEADER) ;
     	if (NULL == (pbmi = malloc (dwInfoSize)))
     	{
          			CloseHandle (hFile) ;
          			return NULL ;
     	}

     	bSuccess = ReadFile (hFile, pbmi, dwInfoSize, &dwBytesRead, NULL) ;
     	if (!bSuccess || (dwBytesRead != dwInfoSize))
     {
          		CloseHandle (hFile) ;
          		free (pbmi) ;
          		return NULL ;
     	}
          		// Create the DIB
     	hDib = DibCreateFromInfo (pbmi) ;
     	free (pbmi) ;

     	if (hDib == NULL)
     	{
          		CloseHandle (hFile) ;
          		return NULL ;
     	}
          		// Read in the bits
     	dwBitsSize = bmfh.bfSize - bmfh.bfOffBits ;
     	bSuccess = ReadFile (	hFile, ((PDIBSTRUCT) hDib)->pBits, 
                          		dwBitsSize, &dwBytesRead, NULL) ;
     	CloseHandle (hFile) ;
     	if (!bSuccess || (dwBytesRead != dwBitsSize))
     	{
          		DibDelete (hDib) ;
          		return NULL ;
     	}
     	return hDib ;
}

/*--------------------------------------------------------------------------
   	DibFileSave:  Saves a DIB section to a file
----------------------------------------------------------------------------*/

BOOL DibFileSave (HDIB hdib, const TCHAR * szFileName)
{
     	BITMAPFILEHEADER 		bmfh ;
     	BITMAPINFO     			* 	pbmi ;
     	BOOL             		bSuccess ;
     	DWORD            		dwTotalSize, dwBytesWritten ;
     	HANDLE           		hFile ;

     	hFile = CreateFile (szFileName, GENERIC_WRITE, 0, NULL,
                         		CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ;
     	if (hFile == INVALID_HANDLE_VALUE)
          			return FALSE ;
     	dwTotalSize  				= DibTotalSize (hdib) ;
     	bmfh.bfType      			= * (WORD *) "BM" ;
     	bmfh.bfSize      			= sizeof (BITMAPFILEHEADER) + dwTotalSize ;
     	bmfh.bfReserved1 		= 0 ;
     	bmfh.bfReserved2 		= 0 ;
     	bmfh.bfOffBits   		= bmfh.bfSize - DibBitsSize (hdib) ;

          			// Write the BITMAPFILEHEADER

     	bSuccess = WriteFile (	hFile, &bmfh, sizeof (BITMAPFILEHEADER), 
                           		&dwBytesWritten, NULL) ;

     	if (!bSuccess || (dwBytesWritten != sizeof (BITMAPFILEHEADER)))
     	{
          			CloseHandle (hFile) ;
          			DeleteFile (szFileName) ;
          			return FALSE ;
     	}
          			// Get entire DIB in packed-DIB format
     	if (NULL == (pbmi = DibCopyToPackedDib (hdib, FALSE)))
     {
          			CloseHandle (hFile) ;
          			DeleteFile (szFileName) ;
          			return FALSE ;
     	}
          			// Write out the packed DIB
     	bSuccess = WriteFile (hFile, pbmi, dwTotalSize, &dwBytesWritten, NULL) ;
     	CloseHandle (hFile) ;
     	free (pbmi) ;

     	if (!bSuccess || (dwBytesWritten != dwTotalSize))
     	{
          			DeleteFile (szFileName) ;
          			return FALSE ;
     	}
     	return TRUE ;
}

/*---------------------------------------------------------------------------
   	DibCopyToDdb:  For more efficient screen displays
---------------------------------------------------------------------------*/
HBITMAP DibCopyToDdb (HDIB hdib, HWND hwnd, HPALETTE hPalette)
{
     	BITMAPINFO 		* 	pbmi ;
     	HBITMAP      				hBitmap ;
     	HDC          					hdc ;

     	if (!DibIsValid (hdib))
          			return NULL ;
     	if (NULL == (pbmi = DibCopyToInfo (hdib)))
          			return NULL ;
     	hdc = GetDC (hwnd) ;
     	if (hPalette)
     	{
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
     	}
     
     	hBitmap = CreateDIBitmap (hdc, DibInfoHeaderPtr (hdib), CBM_INIT,
									   DibBitsPtr (hdib), pbmi, DIB_RGB_COLORS) ;

     	ReleaseDC (hwnd, hdc) ;
     	free (pbmi) ;

     	return hBitmap ;
}

�ⲿ�ֵ�DIBHELP.C����������С��ʽ��ʼ����������ʽ����16λԪ��32λԪDIB����ɫ���ֵõ�������λֵ����Щ��ʽ�ڵ�ʮ���¡���ɫ���֡�һ��˵����

DibCreateFromInfo��ʽ��DIBHELP��Ψһ����CreateDIBSection��ΪDIBSTRUCT�ṹ���ü�����ĺ�ʽ���������н����͸��ƺ�ʽ���ظ��˺�ʽ��DibCreateFromInfoΨһ�IJ�����ָ��BITMAPINFO�ṹ��ָ�ꡣ�˽ṹ����ɫ��������ڣ���������������Ч��ֵ��䡣����CreateDIBSection֮�ᣬ�ú�ʽ����ʼ��DIBSTRUCT�ṹ��������λ��ע�⣬���趨DIBSTRUCT�ṹ��ppRow��λ��ֵʱ��ָ��DIB��λַ��ָ�꣩��DIB�����¶��Ϻ����϶��µIJ�ͬ���淽ʽ��ppRow��ͷ��Ԫ�ؾ���DIB�Ķ��С�

DibDeleteɾ��DibCreateFromInfo�н����ĵ���ͼ��ͬʱ�ͷ��ڸú�ʽ�����õļ����塣

DibCreate���ܱ�DibCreateFromInfo����һ����Ӧ�ó�ʽ���еĺ�ʽ��ǰ���������ṩͼ�صĿ��ȡ��߶Ⱥ�ÿͼ�ص�λ��������һ�����������趨Ϊ0�������ɫ�����ڶ��ߴ磩�������趨Ϊ��0����ʾ��ÿͼ��λԪ������Ҫ����ɫ����С����ɫ������

DibCopy��ʽ�����ִ��DIB���齨���µ�DIB���飬����DibCreateInfo��ʽΪBITMAPINFO�ṹ�����˼����壬���������е����ϡ�DibCopy��ʽ��һ��BOOL����ָ���Ƿ��ڽ����µ�DIBʱ������DIB�Ŀ��Ⱥ͸߶ȡ����ǽ������濴���˺�ʽ���÷���

DibCopyToPackedDib��DibCopyFromPackedDib��ʽ��ʹ��ͨ����͸������������DIB��ء�DibFileLoad��ʽ��DIB��������DIB���飻DibFileSave��ʽ�����ϴ��浽DIB������

���ᣬDibCopyToDdb��ʽ����DIB����GDI����ͼ�����ע�⣬�ú�ʽ��ҪĿǰ��ɫ�̵Ĵ��źͳ�ʽ�Ӵ��Ĵ��š���ʽ�Ӵ�������춻��ѡ�������ֵ�ɫ�̵�װ�����ݡ�ֻ����������ʽ�ſ��Ժ���CreateDIBitmap�������ڱ���ǰ���SHOWDIB7��չʾ��

DIBHELP��ͷ�����;޼�
��

DIBHELP.H��ͷ�������ʽ16-22��ʾ��

 ï¿½ï¿½Ê½16-22  DIBHELP.H����
DIBHELP.H
/*--------------------------------------------------------------------------
   	DIBHELP.H header file for DIBHELP.C
----------------------------------------------------------------------------*/

typedef void * HDIB ;
     	// Functions in DIBHELP.C
BOOL DibIsValid (HDIB hdib) ;	
HBITMAP DibBitmapHandle (HDIB hdib) ;
int DibWidth (HDIB hdib) ;
int DibHeight (HDIB hdib) ;
int DibBitCount (HDIB hdib) ;
int DibRowLength (HDIB hdib) ;
int DibNumColors (HDIB hdib) ;
DWORD DibMask (HDIB hdib, int i) ;
int DibRShift (HDIB hdib, int i) ;
int DibLShift (HDIB hdib, int i) ;
int DibCompression (HDIB hdib) ;
BOOL DibIsAddressable (HDIB hdib) ;
DWORD DibInfoHeaderSize (HDIB hdib) ;
DWORD DibMaskSize (HDIB hdib) ;
DWORD DibColorSize (HDIB hdib) ;
DWORD DibInfoSize (HDIB hdib) ;
DWORD DibBitsSize (HDIB hdib) ;
DWORD DibTotalSize (HDIB hdib) ;
BITMAPINFOHEADER * DibInfoHeaderPtr (HDIB hdib) ;
DWORD * DibMaskPtr (HDIB hdib) ;
void * DibBitsPtr (HDIB hdib) ;
BOOL DibGetColor (HDIB hdib, int index, RGBQUAD * prgb) ;
BOOL DibSetColor (HDIB hdib, int index, RGBQUAD * prgb) ;
BYTE * DibPixelPtr (HDIB hdib, int x, int y) ;
DWORD DibGetPixel (HDIB hdib, int x, int y) ;
BOOL DibSetPixel (HDIB hdib, int x, int y, DWORD dwPixel) ;
BOOL DibGetPixelColor (HDIB hdib, int x, int y, RGBQUAD * prgb) ;
BOOL DibSetPixelColor (HDIB hdib, int x, int y, RGBQUAD * prgb) ;
HDIB DibCreateFromInfo (BITMAPINFO * pbmi) ;
BOOL DibDelete (HDIB hdib) ;
HDIB DibCreate (int cx, int cy, int cBits, int cColors) ;
HDIB DibCopy (HDIB hdibSrc, BOOL fRotate) ;
BITMAPINFO * DibCopyToPackedDib (HDIB hdib, BOOL fUseGlobal) ;
HDIB DibCopyFromPackedDib (BITMAPINFO * pPackedDib) ;
HDIB DibFileLoad (const TCHAR * szFileName) ;
BOOL DibFileSave (HDIB hdib, const TCHAR * szFileName) ;
HBITMAP DibCopyToDdb (HDIB hdib, HWND hwnd, HPALETTE hPalette) ;
HDIB DibCreateFromDdb (HBITMAP hBitmap) ;

/*---------------------------------------------------------------------------
   	Quickie no-bounds-checked pixel gets and sets
-----------------------------------------------------------------------------*/

#define 	DibPixelPtr1(hdib, x, y)	(((* (PBYTE **) hdib) [y]) + ((x) >> 3))
#define 	DibPixelPtr4(hdib, x, y)	(((* (PBYTE **) hdib) [y]) + ((x) >> 1))
#define 	DibPixelPtr8(hdib, x, y)	(((* (PBYTE **) hdib) [y]) +  (x)  		)
#define 	DibPixelPtr16(hdib, x, y)  \
                        				 ((WORD *) (((* (PBYTE **) hdib) [y]) +  (x) *  2))

#define DibPixelPtr24(hdib, x, y)  \
                   						((RGBTRIPLE *) (((* (PBYTE **) hdib) [y]) +  (x) *  3))
#define DibPixelPtr32(hdib, x, y)  \
                       						((DWORD *) (((* (PBYTE **) hdib) [y]) +  (x) *  4))

#define DibGetPixel1(hdib, x, y)   \
               				(0x01 & (* DibPixelPtr1 (hdib, x, y) >> (7 - ((x) & 7))))

#define DibGetPixel4(hdib, x, y)   \
               				(0x0F & (* DibPixelPtr4 (hdib, x, y) >> ((x) & 1 ? 0 : 4)))

#define 	DibGetPixel8(hdib, x, y)     			(* DibPixelPtr8  			(hdib, x, y))
#define 	DibGetPixel16(hdib, x, y)  	(* DibPixelPtr16 	(hdib, x, y))
#define 	DibGetPixel24(hdib, x, y)    	(* DibPixelPtr24 	(hdib, x, y))
#define 	DibGetPixel32(hdib, x, y)    	(* DibPixelPtr32	(hdib, x, y))

#define DibSetPixel1(hdib, x, y, p)														\
          		((* DibPixelPtr1 (hdib, x, y) &= ~( 1	<< (7 - ((x) & 7)))), 			\
           		(* DibPixelPtr1 (hdib, x, y) |=	((p) << (7 - ((x) & 7)))))

#define DibSetPixel4(hdib, x, y, p)														\
          		((* DibPixelPtr4 (hdib, x, y) &= (0x0F <<	((x) & 1 ? 4 : 0))),	\
         		(* DibPixelPtr4 (hdib, x, y) |= ((p)	<<	((x) & 1 ? 0 : 4))))

#define DibSetPixel8(hdib, x, y, p)  (* DibPixelPtr8 (hdib, x, y) = p)
#define DibSetPixel16(hdib, x, y, p) (* DibPixelPtr16 (hdib, x, y) = p)
#define DibSetPixel24(hdib, x, y, p) (* DibPixelPtr24 (hdib, x, y) = p)
#define DibSetPixel32(hdib, x, y, p) (* DibPixelPtr32 (hdib, x, y) = p)

�����ͷ������HDIB����Ϊ��ָ��(void* )��Ӧ�ó�ʽ��ȷ����Ҫ�˽�HDIB��ָ�ṹ���ڲ��ṹ���˱�ͷ����������DIBHELP.C�����к�ʽ��˵��������һЩ�޼����dz�����ľ޼���

����ٿ�һ��DIBHELP.C�е�DibPixelPtr��DibGetPixel��DibSetPixel��ʽ������ͼ������ǵ�ִ���ٶȱ��֣���ô�����������ֿ��ܵĽ����������һ�֣�����ɾ�����еļ�鱣����������Ӧ�ó�ʽ����ʹ����Ч�������к�ʽ��������ɾ��һЩ��ʽ���У�����DibBitCount����ʹ��ָ��DIBSTRUCT�ṹ�ڲ���ָ����ֱ�ӻ����Ѷ��

���ִ���ٶȱ�����һ��ϲ����Եķ�����ɾ�����ж�ÿͼ��λԪ���Ĵ�����ʽ��ͬʱ�����������ͬDIB��ʽ������DibGetPixel1��DibGetPixel4��DibGetPixel8�ȵȡ���һ����ѻ�������ɾ��������ʽ���У����䴦������͸��inline function��޼��н��кϲ���

DIBHELP.H���þ޼��ķ�����������DibPixelPtr��DibGetPixel��DibSetPixel��ʽ��������׾޼�����Щ�޼�����ȷ��Ӧ������ͼ��λԪ����

DIBBLE��ʽ
��

DIBBLE��ʽ�����ʽ16-23��ʾ��ʹ��DIBHELP��ʽ�;޼�����������DIBBLE�DZ�������ij�ʽ����ȷʵֻ��һЩ��ҵ�Ĵ��Է�������Щ��ҵ�����ڼ򵥵���λӰ������ʽ���ҵ�����DIBBLE�����ԸĽ���ת�����˶����ļ����棨MDI��multiple document interface�������ǽ��ڵ�ʮ����ѧϰ�йض����ļ������֪ʶ��

 ï¿½ï¿½Ê½16-23  DIBBLE
DIBBLE.C
/*---------------------------------------------------------------------------
   	DIBBLE.C -- 	Bitmap and Palette Program
               						(c) Charles Petzold, 1998
-----------------------------------------------------------------------------*/

#include <windows.h>
#include "dibhelp.h"
#include "dibpal.h"
#include "dibconv.h"
#include "resource.h"

#define WM_USER_SETSCROLLS    		(WM_USER + 1)
#define WM_USER_DELETEDIB     		(WM_USER + 2)
#define WM_USER_DELETEPAL     		(WM_USER + 3)
#define WM_USER_CREATEPAL     		(WM_USER + 4)

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("Dibble") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    							PSTR szCmdLine, int iCmdShow)
{
     	HACCEL   		hAccel ;
     	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 		= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     	wndclass.lpszMenuName  		= szAppName ;
     	wndclass.lpszClassName	 	= szAppName ;

     	if (!RegisterClass (&wndclass))
     	{
          			MessageBox (	NULL, TEXT ("This program requires Windows NT!"), 
                      								szAppName, MB_ICONERROR) ;
          			return 0 ;
     	}

     	hwnd	=	CreateWindow (	szAppName, szAppName,
                WS_OVERLAPPEDWINDOW | WM_VSCROLL | WM_HSCROLL,
                CW_USEDEFAULT, CW_USEDEFAULT,
                CW_USEDEFAULT, CW_USEDEFAULT, 
                NULL, NULL, hInstance, NULL) ;

     	ShowWindow (hwnd, iCmdShow) ;
     	UpdateWindow (hwnd) ;

     	hAccel = LoadAccelerators (hInstance, szAppName) ;

     	while (GetMessage (&msg, NULL, 0, 0))
     	{
          		if (!TranslateAccelerator (hwnd, hAccel, &msg))
          		{
               				TranslateMessage (&msg) ;
               				DispatchMessage (&msg) ;
          		}
     	}
     	return msg.wParam ;
}

/*----------------------------------------------------------------------------
   	DisplayDib: 		Displays or prints DIB actual size or stretched 
               						depending on menu selection
-----------------------------------------------------------------------------*/

int DisplayDib (	HDC hdc, HBITMAP hBitmap, int x, int y, 
                						int cxClient, int cyClient, 
                						WORD wShow, BOOL fHalftonePalette)
{
     	BITMAP 		bitmap ;
     	HDC    			hdcMem ; 
     	int    			cxBitmap, cyBitmap, iReturn ;
     	GetObject	(hBitmap, sizeof (BITMAP), &bitmap) ;
     	cxBitmap 		=	bitmap.bmWidth ;
     	cyBitmap 		=	bitmap.bmHeight ;

     	SaveDC (hdc) ;
     	if (fHalftonePalette)
          			SetStretchBltMode (hdc, HALFTONE) ;
     	else
          			SetStretchBltMode (hdc, COLORONCOLOR) ;
     	hdcMem = CreateCompatibleDC (hdc) ;
     	SelectObject (hdcMem, hBitmap) ;

     	switch (wShow)
     	{
     	case 	IDM_SHOW_NORMAL:
          			if (fHalftonePalette)
   					iReturn = StretchBlt (hdc,	0, 0, min (cxClient, cxBitmap - x), 
					min (cyClient, cyBitmap - y), 
                    hdcMem, x, y, min (cxClient, cxBitmap - x), 
                                  min (cyClient, cyBitmap - y), 
                    SRCCOPY);
          			else
               			iReturn = BitBlt (hdc,0, 0, min (cxClient, cxBitmap - x), 
                        min (cyClient, cyBitmap - y),
hdcMem, x, y, SRCCOPY) ;
          			break ;
               
     	case 	IDM_SHOW_CENTER:
          			if (fHalftonePalette)
               		iReturn = StretchBlt (	hdc, (cxClient - cxBitmap) / 2,
                                         (cyClient - cyBitmap) / 2, 
cxBitmap, cyBitmap,
                              hdcMem, 0, 0, cxBitmap, cyBitmap, SRCCOPY);
          			else
               				iReturn = BitBlt (hdc, 	(cxClient - cxBitmap) / 2,
                            cyClient - cyBitmap) / 2, 
                            cxBitmap, cyBitmap,
                            hdcMem, 0, 0, SRCCOPY) ;
          			break ;
     	case 	IDM_SHOW_STRETCH:
          			iReturn = StretchBlt (hdc,	0, 0, cxClient, cyClient, 
                    hdcMem, 	0, 0, cxBitmap, cyBitmap, SRCCOPY) ;
          			break ;

     	case 	IDM_SHOW_ISOSTRETCH:
         	 		SetMapMode (hdc, MM_ISOTROPIC) ;
          			SetWindowExtEx (hdc, cxBitmap, cyBitmap, NULL) ;
          			SetViewportExtEx (hdc, cxClient, cyClient, NULL) ;
          			SetWindowOrgEx (hdc, cxBitmap / 2, cyBitmap / 2, NULL) ;
          			SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;

          			iReturn = StretchBlt (hdc,	0, 0, cxBitmap, cyBitmap, 
                    hdcMem,	0, 0, cxBitmap, cyBitmap, SRCCOPY) ;
          			break ;
     	}
	DeleteDC (hdcMem) ;
	RestoreDC (hdc, -1) ;
	return iReturn ;
}

/*---------------------------------------------------------------------------
   	DibFlipHorizontal: Calls non-optimized DibSetPixel and DibGetPixel
----------------------------------------------------------------------------*/

HDIB DibFlipHorizontal (HDIB hdibSrc)
{
     	HDIB hdibDst ;
     	int  cx, cy, x, y ;

     	if (!DibIsAddressable (hdibSrc))
          			return NULL ;
     	if (NULL == (hdibDst = DibCopy (hdibSrc, FALSE)))
          			return NULL ;
     	cx = DibWidth  	(hdibSrc) ;
     	cy = DibHeight 	(hdibSrc) ;
     
	for (x = 0 ; x < cx ; x++)
     	for (y = 0 ; y < cy ; y++)
     	{
          		DibSetPixel (hdibDst, x, cy - 1 - y, DibGetPixel (hdibSrc, x, y)) ;
     	}

     	return hdibDst ;
}

/*---------------------------------------------------------------------------
   	DibRotateRight: Calls optimized DibSetPixelx and DibGetPixelx
-----------------------------------------------------------------------------*/

HDIB DibRotateRight (HDIB hdibSrc)
{
     	HDIB 	hdibDst ;
     	int 	cx, cy, x, y ;

     	if (!DibIsAddressable (hdibSrc))
          			return NULL ;

     	if (NULL == (hdibDst = DibCopy (hdibSrc, TRUE)))
          			return NULL ;

     	cx = DibWidth (hdibSrc) ;
     	cy = DibHeight (hdibSrc) ;

     	switch (DibBitCount (hdibSrc))
     {
     	case  		1:  
          				for (	x = 0 ; x < cx ; x++)
          				for (	y = 0 ; y < cy ; y++)
               							DibSetPixel1 (hdibDst, cy - y - 1, x, 
                    							DibGetPixel1 (hdibSrc, x, y)) ;
          				break ;

     	case  		4:  
          				for (	x = 0 ; x < cx ; x++)
          				for (	y = 0 ; y < cy ; y++)
               							DibSetPixel4 (hdibDst, cy - y - 1, x, 
                    							DibGetPixel4 (hdibSrc, x, y)) ;
          				break ;

     	case  		8:
          				for (	x = 0 ; x < cx ; x++)
          				for (	y = 0 ; y < cy ; y++)
               							DibSetPixel8 (hdibDst, cy - y - 1, x, 
                    							DibGetPixel8 (hdibSrc, x, y)) ;
          				break ;
     	case 		16:  
          				for (x = 0 ; x < cx ; x++)
          				for (y = 0 ; y < cy ; y++)
               						DibSetPixel16 (hdibDst, cy - y - 1, x, 
                    							DibGetPixel16 (hdibSrc, x, y)) ;
          				break ;

     	case 		24:
          				for (x = 0 ; x < cx ; x++)
          				for (y = 0 ; y < cy ; y++)
               						DibSetPixel24 (hdibDst, cy - y - 1, x, 
                    							DibGetPixel24 (hdibSrc, x, y)) ;
          				break ;

     	case 		32:  
          				for (x = 0 ; x < cx ; x++)
          				for (y = 0 ; y < cy ; y++)
               						DibSetPixel32 (hdibDst, cy - y - 1, x, 
                    							DibGetPixel32 (hdibSrc, x, y)) ;
          				break ;
     	}
     	return hdibDst ;
}

/*------------------------------------------------------------------------
   	PaletteMenu: Uncheck and check menu item on palette menu
--------------------------------------------------------------------------*/

void PaletteMenu (HMENU hMenu, WORD wItemNew)
{
     	static WORD wItem = IDM_PAL_NONE ;
     	CheckMenuItem (hMenu, wItem, MF_UNCHECKED) ;
     	wItem = wItemNew ;
     	CheckMenuItem (hMenu, wItem, MF_CHECKED) ;
}

LRESULT CALLBACK WndProc (	HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
     	static 	BOOL      				fHalftonePalette ;
     	static 		DOCINFO  			di = {sizeof(DOCINFO),TEXT("Dibble:Printing")} ;
     	static 	HBITMAP			hBitmap ;
     	static 	HDIB        				hdib ;
     	static 	HMENU        				hMenu ;
     	static 	HPALETTE			hPalette ;
     	static 	int          				cxClient, cyClient, iVscroll, iHscroll ;
     	static 	OPENFILENAME 	ofn ;
     	static 	PRINTDLG     			printdlg = { sizeof (PRINTDLG) } ;
     	static 	TCHAR        				szFileName [MAX_PATH], szTitleName [MAX_PATH] ;
     	static 	TCHAR        				szFilter[]=	TEXT ("Bitmap Files (*.BMP)\0*.bmp\0")
               TEXT ("All Files (*.*)\0*.*\0\0") ;
     	static TCHAR      		* 		szCompression[] = { 
                          TEXT("BI_RGB"),TEXT("BI_RLE8"),TEXT("BI_RLE4"), 
        TEXT("BI_BITFIELDS"),TEXT("Unknown")} ;
     	static WORD         	wShow = IDM_SHOW_NORMAL ;
     	BOOL                	fSuccess ;
     	BYTE              		*		pGlobal ;
     	HDC                 	hdc, hdcPrn ;
     	HGLOBAL             	hGlobal ;
     	HDIB                	hdibNew ;
     	int                 	iEnable, cxPage, cyPage, iConvert ;
     	PAINTSTRUCT         	ps ;
     	SCROLLINFO          	si ;
     	TCHAR               	szBuffer [256] ;

     	switch (message)
     	{
     	case 	WM_CREATE:
         
               				// Save the menu handle in a static variable

          			hMenu = GetMenu (hwnd) ;

               		// Initialize the OPENFILENAME structure for the File Open
               		//   and File Save dialog boxes.

          			ofn.lStructSize       	= sizeof (OPENFILENAME) ;
          			ofn.hwndOwner         	= hwnd ;
          			ofn.hInstance         	= NULL ;
          			ofn.lpstrFilter       	= szFilter ;
          			ofn.lpstrCustomFilter 	= NULL ;
          			ofn.nMaxCustFilter    	= 0 ;
          			ofn.nFilterIndex      	= 0 ;
          			ofn.lpstrFile         	= szFileName ;
          			ofn.nMaxFile          	= MAX_PATH ;
          			ofn.lpstrFileTitle    	= szTitleName ;
          			ofn.nMaxFileTitle     	= MAX_PATH ;
          			ofn.lpstrInitialDir   	= NULL ;
          			ofn.lpstrTitle        	= NULL ;
          			ofn.Flags             	= OFN_OVERWRITEPROMPT ;
          			ofn.nFileOffset       	= 0 ;
          			ofn.nFileExtension    	= 0 ;
          			ofn.lpstrDefExt       	= TEXT ("bmp") ;
          			ofn.lCustData         	= 0 ;
          			ofn.lpfnHook          	= NULL ;
          			ofn.lpTemplateName    	= NULL ;
          			return 0 ;

     	case 	WM_DISPLAYCHANGE:
          			SendMessage (hwnd, WM_USER_DELETEPAL, 0, 0) ;
          			SendMessage (hwnd, WM_USER_CREATEPAL, TRUE, 0) ;
          			return 0 ;

     	case 	WM_SIZE:
               			// Save the client area width and height in static variables.

          			cxClient = LOWORD (lParam) ;
          			cyClient = HIWORD (lParam) ;

          			wParam = FALSE ;
                        // fall through
               			// WM_USER_SETSCROLLS:  Programmer-defined Message!
               			// Set the scroll bars. If the display mode is not normal,
               			//   make them invisible. If wParam is TRUE, reset the 
               			//   scroll bar position.

     	case 	WM_USER_SETSCROLLS:
          			if (hdib == NULL || wShow != IDM_SHOW_NORMAL)
          			{
               					si.cbSize 		= sizeof (SCROLLINFO) ;
               					si.fMask  		= SIF_RANGE ;
               					si.nMin   		= 0 ;
               					si.nMax   		= 0 ;
               					SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
               					SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
          			}
          			else
          			{
                    					// First the vertical scroll

               					si.cbSize 		= sizeof (SCROLLINFO) ;
               					si.fMask  			= SIF_ALL ;

               				GetScrollInfo (hwnd, SB_VERT, &si) ;
               					si.nMin  			= 0 ;
               					si.nMax  			= DibHeight (hdib) ;
               					si.nPage 			= cyClient ;
               					if ((BOOL) wParam)
                    							si.nPos = 0 ;

               					SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
               					GetScrollInfo (hwnd, SB_VERT, &si) ;

               					iVscroll = si.nPos ;

                    						// Then the horizontal scroll

               					GetScrollInfo (hwnd, SB_HORZ, &si) ;
               					si.nMin  		= 0 ;
               					si.nMax  		= DibWidth (hdib) ;
               					si.nPage 		= cxClient ;
          
               					if ((BOOL) wParam)
                    							si.nPos = 0 ;

               					SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
               					GetScrollInfo (hwnd, SB_HORZ, &si) ;

               					iHscroll = si.nPos ;
          			}	
          			return 0 ;

          			// WM_VSCROLL: Vertically scroll the DIB

     	case 	WM_VSCROLL:
          			si.cbSize = sizeof (SCROLLINFO) ;
          			si.fMask  = SIF_ALL ;
          			GetScrollInfo (hwnd, SB_VERT, &si) ;
          
          			iVscroll = si.nPos ;

          			switch (LOWORD (wParam))
          			{
          			case SB_LINEUP:    si.nPos -	= 1 ; 		break ;
          			case SB_LINEDOWN:  si.nPos +	= 1 ;		break ;
          			case SB_PAGEUP:    si.nPos -	= si.nPage ;break ;
          			case SB_PAGEDOWN:  si.nPos +	= si.nPage ;break ;
          			case SB_THUMBTRACK:si.nPos		= si.nTrackPos ;break ;
          			default:   										break ;
          			}
          			si.fMask = SIF_POS ;
          			SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
          			GetScrollInfo (hwnd, SB_VERT, &si) ;
          			if (si.nPos != iVscroll)
          			{
               				ScrollWindow (hwnd, 0, iVscroll - si.nPos, NULL, NULL) ;
               				iVscroll = si.nPos ;
               				UpdateWindow (hwnd) ;
          			}
          			return 0 ;

          			// WM_HSCROLL: Horizontally scroll the DIB

     	case 	WM_HSCROLL:
          			si.cbSize = sizeof (SCROLLINFO) ;
          			si.fMask  = SIF_ALL ;
          			GetScrollInfo (hwnd, SB_HORZ, &si) ;
          
          			iHscroll = si.nPos ;

          			switch (LOWORD (wParam))
          			{
          			case SB_LINELEFT:  si.nPos -=1 ;	break ;
          			case SB_LINERIGHT: si.nPos +=1 ;	break ;
          			case SB_PAGELEFT:  si.nPos -=si.nPage ;break ;
          			case SB_PAGERIGHT: si.nPos +=si.nPage ;break ;
          			case SB_THUMBTRACK:si.nPos  =si.nTrackPos ;break ;
          			default:  								   break ;
          			}

          			si.fMask = SIF_POS ;
          			SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
          			GetScrollInfo (hwnd, SB_HORZ, &si) ;

          			if (si.nPos != iHscroll)
          			{
               				ScrollWindow (hwnd, iHscroll - si.nPos, 0, NULL, NULL) ;
               				iHscroll = si.nPos ;
               				UpdateWindow (hwnd) ;
          			}
          			return 0 ;

          			// WM_INITMENUPOPUP:  Enable or Gray menu items

	case 	WM_INITMENUPOPUP:
          			if (hdib)
               					iEnable = MF_ENABLED ;
          			else
               					iEnable = MF_GRAYED ;
       EnableMenuItem (hMenu, IDM_FILE_SAVE,       		iEnable) ;
       EnableMenuItem (hMenu, IDM_FILE_PRINT,      		iEnable) ;
       EnableMenuItem (hMenu, IDM_FILE_PROPERTIES, 		iEnable) ;
       EnableMenuItem (hMenu, IDM_EDIT_CUT,        		iEnable) ;
       EnableMenuItem (hMenu, IDM_EDIT_COPY,       		iEnable) ;
       EnableMenuItem (hMenu, IDM_EDIT_DELETE,     		iEnable) ;

          			if (DibIsAddressable (hdib))
               					iEnable = MF_ENABLED ;
          			else
               					iEnable = MF_GRAYED ;

          EnableMenuItem (hMenu, IDM_EDIT_ROTATE,    	iEnable) ;
          EnableMenuItem (hMenu, IDM_EDIT_FLIP,      	iEnable) ;
          EnableMenuItem (hMenu, IDM_CONVERT_01,     	iEnable) ;
          EnableMenuItem (hMenu, IDM_CONVERT_04,     	iEnable) ;
          EnableMenuItem (hMenu, IDM_CONVERT_08,     	iEnable) ;
          EnableMenuItem (hMenu, IDM_CONVERT_16,     	iEnable) ;
          EnableMenuItem (hMenu, IDM_CONVERT_24,     	iEnable) ;
          EnableMenuItem (hMenu, IDM_CONVERT_32,     	iEnable) ;

          			switch (DibBitCount (hdib))
          			{
          			case  	1: 	EnableMenuItem (hMenu, IDM_CONVERT_01, MF_GRAYED) ; 	break ;
          			case  	4: 	EnableMenuItem (hMenu, IDM_CONVERT_04, MF_GRAYED) ; 	break ;
          			case  	8: 	EnableMenuItem (hMenu, IDM_CONVERT_08, MF_GRAYED) ; 	break ;
          			case 	16: EnableMenuItem (hMenu, IDM_CONVERT_16, MF_GRAYED) ; 	break ;
          			case 	24: EnableMenuItem (hMenu, IDM_CONVERT_24, MF_GRAYED) ; 	break ;
          			case 	32: EnableMenuItem (hMenu, IDM_CONVERT_32, MF_GRAYED) ; 	break ;
          			}

          			if (hdib && DibColorSize (hdib) > 0)
               					iEnable = MF_ENABLED ;
          			else
               					iEnable = MF_GRAYED ;

          			EnableMenuItem (hMenu, IDM_PAL_DIBTABLE,    iEnable) ;
          		if (DibIsAddressable (hdib) && DibBitCount (hdib) > 8)
               					iEnable = MF_ENABLED ;
          			else
               					iEnable = MF_GRAYED ;

          	EnableMenuItem 		(hMenu, IDM_PAL_OPT_POP4,   		iEnable) ;
          	EnableMenuItem 		(hMenu, IDM_PAL_OPT_POP5,   		iEnable) ;
          	EnableMenuItem 		(hMenu, IDM_PAL_OPT_POP6,   		iEnable) ;
          	EnableMenuItem 		(hMenu, IDM_PAL_OPT_MEDCUT, 		iEnable) ;
          	EnableMenuItem 		(hMenu, IDM_EDIT_PASTE, 
               	IsClipboardFormatAvailable (CF_DIB) ? MF_ENABLED : MF_GRAYED) ;

          			return 0 ;

          			// WM_COMMAND:  Process all menu commands.

     	case 	WM_COMMAND:
          			iConvert = 0 ;

          			switch (LOWORD (wParam))
          			{
          			case 	IDM_FILE_OPEN:

                   // Show the File Open dialog box

               					if (!GetOpenFileName (&ofn))
                    							return 0 ;
               
                   // If there's an existing DIB and palette, delete them

               					SendMessage (hwnd, WM_USER_DELETEDIB, 0, 0) ;
               
                   // Load the DIB into memory

               					SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
               					ShowCursor (TRUE) ;

               					hdib = DibFileLoad (szFileName) ;

               					ShowCursor (FALSE) ;
               					SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

                    							// Reset the scroll bars

               					SendMessage (hwnd, WM_USER_SETSCROLLS, TRUE, 0) ;

                    							// Create the palette and DDB

               					SendMessage (hwnd, WM_USER_CREATEPAL, TRUE, 0) ;

               					if (!hdib)
               					{
                  MessageBox (hwnd, TEXT ("Cannot load DIB file!"), 
                              szAppName, MB_OK | MB_ICONEXCLAMATION) ;
               					}
               					InvalidateRect (hwnd, NULL, TRUE) ;
               					return 0 ;

   		case	IDM_FILE_SAVE:

                    			// Show the File Save dialog box

               					if 	(!	GetSaveFileName (&ofn))
                    							return 0 ;

                    			// Save the DIB to memory

               					SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
               					ShowCursor (TRUE) ;

               					fSuccess = DibFileSave (hdib, szFileName) ;

               					ShowCursor (FALSE) ;
               					SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               					if (!fSuccess)
                   MessageBox (	hwnd, TEXT ("Cannot save DIB file!"),
                                szAppName, MB_OK | MB_ICONEXCLAMATION) ;
               					return 0 ;

          			case 	IDM_FILE_PRINT:
               					if (!hdib)
                    							return 0 ;

                    							// Get printer DC

               		printdlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION ;

               					if (!PrintDlg (&printdlg))
                    							return 0 ;

               					if (NULL == (hdcPrn = printdlg.hDC))
               					{
                    MessageBox(	hwnd, TEXT ("Cannot obtain Printer DC"),
                                szAppName, MB_ICONEXCLAMATION | MB_OK) ;
                    							return 0 ;
               					}
                    		// Check if the printer can print bitmaps

          if (!(RC_BITBLT & GetDeviceCaps (hdcPrn, RASTERCAPS)))
               					{
                    						DeleteDC (hdcPrn) ;
          MessageBox (	hwnd, TEXT ("Printer cannot print bitmaps"),
                        szAppName, MB_ICONEXCLAMATION | MB_OK) ;
                    						return 0 ;
               					}
                    						// Get size of printable area of page

               					cxPage = GetDeviceCaps (hdcPrn, HORZRES) ;
               					cyPage = GetDeviceCaps (hdcPrn, VERTRES) ;

               					fSuccess = FALSE ;

                    						// Send the DIB to the printer

               				SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
               				ShowCursor (TRUE) ;

               				if ((StartDoc (hdcPrn, &di) > 0) && (StartPage (hdcPrn) > 0))
            				{
                    		DisplayDib (hdcPrn, DibBitmapHandle (hdib), 0, 0, 
                                        cxPage, cyPage, wShow, FALSE) ;
                    
                    						if (EndPage (hdcPrn) > 0)
                    						{
                         								fSuccess = TRUE ;
                         								EndDoc (hdcPrn) ;
                    						}
               				}
               				ShowCursor (FALSE) ;
               				SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               				DeleteDC (hdcPrn) ;

               				if (	!fSuccess)
                   MessageBox (	hwnd, TEXT ("Could not print bitmap"),
                                szAppName, MB_ICONEXCLAMATION | MB_OK) ;
               				return 0 ;

          		case	IDM_FILE_PROPERTIES:
               				if (!hdib)
                    						return 0 ;

				wsprintf (szBuffer, TEXT ("Pixel width:\t%i\n")
                                    TEXT ("Pixel height:\t%i\n")
                                   	TEXT ("Bits per pixel:\t%i\n")
                                   	TEXT ("Number of colors:\t%i\n")
                                   	TEXT ("Compression:\t%s\n"),
                        DibWidth (hdib), DibHeight (hdib),
                        DibBitCount (hdib), DibNumColors (hdib),
                        szCompression [min (3, DibCompression (hdib))]) ;

               			MessageBox (	hwnd, szBuffer, szAppName, 
                        MB_ICONEXCLAMATION | MB_OK) ;
               				return 0 ;

          		case 	IDM_APP_EXIT:
               				SendMessage (hwnd, WM_CLOSE, 0, 0) ;
               				return 0 ;

          		case 	IDM_EDIT_COPY:
          		case 	IDM_EDIT_CUT:
               				if (!(hGlobal = DibCopyToPackedDib (hdib, TRUE)))
                    						return 0 ;

               				OpenClipboard (hwnd) ;
               				EmptyClipboard () ;
               				SetClipboardData (CF_DIB, hGlobal) ;
               				CloseClipboard () ;

               				if (LOWORD (wParam) == IDM_EDIT_COPY)
                    		return 0 ;
                            // fall through for IDM_EDIT_CUT
          		case 	IDM_EDIT_DELETE:
               				SendMessage (hwnd, WM_USER_DELETEDIB, 0, 0) ;
               				InvalidateRect (hwnd, NULL, TRUE) ;
               				return 0 ;

          		case 	IDM_EDIT_PASTE:
               				OpenClipboard (hwnd) ;

               				hGlobal = GetClipboardData (CF_DIB) ;
               				pGlobal = GlobalLock (hGlobal) ;

                    		// If there's an existing DIB and palette,delete them.
                    		// Then convert the packed DIB to an HDIB.

               				if (pGlobal)
               				{
                    		SendMessage (hwnd, WM_USER_DELETEDIB, 0, 0) ;
                    		hdib = DibCopyFromPackedDib ((BITMAPINFO *) pGlobal) ;
                    		SendMessage (hwnd, WM_USER_CREATEPAL, TRUE, 0) ;
               				}

               				GlobalUnlock (hGlobal) ;
               				CloseClipboard () ;
                    					// Reset the scroll bars

               				SendMessage (hwnd, WM_USER_SETSCROLLS, TRUE, 0) ;
               				InvalidateRect (hwnd, NULL, TRUE) ;
               				return 0 ;

          		case 	IDM_EDIT_ROTATE:
               				if (hdibNew = DibRotateRight (hdib))
               				{
                    			DibDelete (hdib) ;
                    			DeleteObject (hBitmap) ;
                    			hdib = hdibNew ;
                    			hBitmap = DibCopyToDdb (hdib, hwnd, hPalette) ;
                    			SendMessage (hwnd, WM_USER_SETSCROLLS, TRUE, 0) ;
                    			InvalidateRect (hwnd, NULL, TRUE) ;
               				}
               				else
               				{
                    MessageBox (	hwnd, TEXT ("Not enough memory"),
                                	szAppName, MB_OK | MB_ICONEXCLAMATION) ;
               				}
               				return 0 ;

          		case 	IDM_EDIT_FLIP:
               				if (hdibNew = DibFlipHorizontal (hdib))
               				{
                    			DibDelete (hdib) ;
                    			DeleteObject (hBitmap) ;
                    			hdib = hdibNew ;
                    			hBitmap = DibCopyToDdb (hdib, hwnd, hPalette) ;
                    			InvalidateRect (hwnd, NULL, TRUE) ;
               				}
               				else
               				{
                    MessageBox (	hwnd, TEXT ("Not enough memory"),
                                	szAppName, MB_OK | MB_ICONEXCLAMATION) ;
               				}
               				return 0 ;

          		case 	IDM_SHOW_NORMAL:
          		case 	IDM_SHOW_CENTER:
          		case 	IDM_SHOW_STRETCH:
          		case 	IDM_SHOW_ISOSTRETCH:
               				CheckMenuItem (hMenu, wShow, MF_UNCHECKED) ;
               				wShow = LOWORD (wParam) ;
               				CheckMenuItem (hMenu, wShow, MF_CHECKED) ;
               				SendMessage (hwnd, WM_USER_SETSCROLLS, FALSE, 0) ;

               				InvalidateRect (hwnd, NULL, TRUE) ;
               				return 0 ;

          		case 	IDM_CONVERT_32:  iConvert += 8 ;
          		case 	IDM_CONVERT_24:  iConvert += 8 ;   
          		case 	IDM_CONVERT_16:  iConvert += 8 ;
          		case 	IDM_CONVERT_08:  iConvert += 4 ;
          		case	IDM_CONVERT_04:  iConvert += 3 ;
          		case 	IDM_CONVERT_01:  iConvert += 1 ;
               				SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
               				ShowCursor (TRUE) ;

               				hdibNew = DibConvert (hdib, iConvert) ;

               				ShowCursor (FALSE) ;
               				SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               				if (hdibNew)
               				{
                    	SendMessage (hwnd, WM_USER_DELETEDIB, 0, 0) ;
                    				hdib = hdibNew ;
                    	SendMessage (hwnd, WM_USER_CREATEPAL, TRUE, 0) ;
                    	InvalidateRect (hwnd, NULL, TRUE) ;
               				}
               				else
               				{
                     MessageBox (	hwnd, TEXT ("Not enough memory"),
                                	szAppName, MB_OK | MB_ICONEXCLAMATION) ;
               					}
               					return 0 ;

          			case 	IDM_APP_ABOUT:
           MessageBox (	hwnd, TEXT ("Dibble (c) Charles Petzold, 1998"),
                        szAppName, MB_OK | MB_ICONEXCLAMATION) ;
               			return 0 ;
          			}
     
               			// All the other WM_COMMAND messages are from the palette
               			//	 items. Any existing palette is deleted, and the cursor
               			//	 is set to the hourglass.

          			SendMessage (hwnd, WM_USER_DELETEPAL, 0, 0) ;
          			SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
          			ShowCursor (TRUE) ;
               			// Notice that all messages for palette items are ended
               			//	 with break rather than return. This is to allow 
               			//	 additional processing later on.

          			switch (LOWORD (wParam))
          			{
          			case 	IDM_PAL_DIBTABLE: 
               					hPalette = DibPalDibTable (hdib) ; 
               					break ;

          			case 	IDM_PAL_HALFTONE: 
               					hdc = GetDC (hwnd) ;

               					if (hPalette = CreateHalftonePalette (hdc))
                    							fHalftonePalette = TRUE ;

               					ReleaseDC (hwnd, hdc) ;
               					break ;

          			case 	IDM_PAL_ALLPURPOSE: 
               					hPalette = DibPalAllPurpose () ; 
               					break ;

       case IDM_PAL_GRAY2:hPalette	    = DibPalUniformGrays   (2)	;	break;
       case IDM_PAL_GRAY3:hPalette 	    = DibPalUniformGrays   (3)	;  	break;
       case IDM_PAL_GRAY4:hPalette 	    = DibPalUniformGrays   (4)	; 	break;
       case IDM_PAL_GRAY8:hPalette 	    = DibPalUniformGrays   (8)	; 	break;
       case	IDM_PAL_GRAY16:hPalette 	= DibPalUniformGrays  (16)	; 	break;
       case IDM_PAL_GRAY32:hPalette 	= DibPalUniformGrays  (32)	; 	break;
       case IDM_PAL_GRAY64:hPalette 	= DibPalUniformGrays  (64)	; 	break;
       case IDM_PAL_GRAY128:hPalette 	= DibPalUniformGrays (128)	; 	break;
       case IDM_PAL_GRAY256:hPalette 	= DibPalUniformGrays (256)	;	break;
       case IDM_PAL_RGB222:hPalette 	= DibPalUniformColors (2,2,2); 	break;
       case IDM_PAL_RGB333:hPalette 	= DibPalUniformColors (3,3,3); 	break;
       case IDM_PAL_RGB444:hPalette 	= DibPalUniformColors (4,4,4); 	break;
       case IDM_PAL_RGB555:hPalette 	= DibPalUniformColors (5,5,5); 	break;
       case IDM_PAL_RGB666:hPalette 	= DibPalUniformColors (6,6,6); 	break;
       case IDM_PAL_RGB775:hPalette 	= DibPalUniformColors (7,7,5); 	break;
       case IDM_PAL_RGB757:hPalette 	= DibPalUniformColors (7,5,7); 	break;
       case IDM_PAL_RGB577:hPalette 	= DibPalUniformColors (5,7,7); 	break;
       case IDM_PAL_RGB884:hPalette 	= DibPalUniformColors (8,8,4); 	break;
       case IDM_PAL_RGB848:hPalette 	= DibPalUniformColors (8,4,8); 	break;
       case IDM_PAL_RGB488:hPalette 	= DibPalUniformColors (4,8,8); 	break;
       case IDM_PAL_OPT_POP4:hPalette   = DibPalPopularity (hdib, 4) ;  break ;
       case IDM_PAL_OPT_POP5:hPalette   = DibPalPopularity (hdib, 5) ;  break ;
       case IDM_PAL_OPT_POP6:hPalette   = DibPalPopularity (hdib, 6) ;  break ;                   
       case IDM_PAL_OPT_MEDCUT:hPalette = DibPalMedianCut  (hdib, 6) ;  break ;
          			}

               		// After processing Palette items from the menu, the cursor
               		// 	is restored to an arrow, the menu item is checked, and
               		//	the window is invalidated.

          			hBitmap = DibCopyToDdb (hdib, hwnd, hPalette) ;

          			ShowCursor (FALSE) ;
          			SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

          			if (hPalette)
               					PaletteMenu (hMenu, (LOWORD (wParam))) ;

          			InvalidateRect (hwnd, NULL, TRUE) ;
          			return 0 ;

          			// This programmer-defined message deletes an existing DIB 
          			//   in preparation for getting a new one.  Invoked during 
          			//   File Open command, Edit Paste command, and others.

 	case	WM_USER_DELETEDIB:
          			if (hdib)
          			{
               					DibDelete (hdib) ;
               					hdib = NULL ;
          			}
          			SendMessage (hwnd, WM_USER_DELETEPAL, 0, 0) ;
          			return 0 ;

          			// This programmer-defined message deletes an existing palette
          			//		in preparation for defining a new one.

     	case 	WM_USER_DELETEPAL:
          			if (hPalette)
          			{
               					DeleteObject (hPalette) ;
               					hPalette = NULL ;
               					fHalftonePalette = FALSE ;
               					PaletteMenu (hMenu, IDM_PAL_NONE) ;
          			}
          			if (hBitmap)
               					DeleteObject (hBitmap) ;

          				return 0 ;

          			// Programmer-defined message to create a new palette based on 
          			//		a new DIB.  If wParam == TRUE, create a DDB as well.

     	case 	WM_USER_CREATEPAL:
          			if (hdib)
          			{
               					hdc = GetDC (hwnd) ;

               		if (!(RC_PALETTE & GetDeviceCaps (hdc, RASTERCAPS)))
               					{
                    PaletteMenu (hMenu, IDM_PAL_NONE) ;
               					}
               					else if (hPalette = DibPalDibTable (hdib))
        					{
                    PaletteMenu (hMenu, IDM_PAL_DIBTABLE) ;
               					}
               					else if (hPalette = CreateHalftonePalette (hdc))
               					{
                    							fHalftonePalette = TRUE ;
                    PaletteMenu (hMenu, IDM_PAL_HALFTONE) ;
               					}
               					ReleaseDC (hwnd, hdc) ;

               					if ((BOOL) wParam)
                    hBitmap = DibCopyToDdb (hdib, hwnd, hPalette) ;
          			}
          			return 0 ;

     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;

          			if (hPalette)
          			{
               					SelectPalette (hdc, hPalette, FALSE) ;
               					RealizePalette (hdc) ;
          			}
          			if (hBitmap)
  			{
               				DisplayDib (	hdc, 
                           	fHalftonePalette ? DibBitmapHandle (hdib) : hBitmap, 
                           	iHscroll, iVscroll, 
                           	cxClient, cyClient,
                           	wShow, fHalftonePalette) ;
          			}
          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_QUERYNEWPALETTE:
          			if (!hPalette)
               					return FALSE ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			InvalidateRect (hwnd, NULL, TRUE) ;

          			ReleaseDC (hwnd, hdc) ;
          			return TRUE ;

     	case 	WM_PALETTECHANGED:
          			if (!hPalette || (HWND) wParam == hwnd)
               					break ;

          			hdc = GetDC (hwnd) ;
          			SelectPalette (hdc, hPalette, FALSE) ;
          			RealizePalette (hdc) ;
          			UpdateColors (hdc) ;

          			ReleaseDC (hwnd, hdc) ;
          			break ;

     	case 	WM_DESTROY:
          			if (hdib)
               					DibDelete (hdib) ;

          			if (hBitmap)
               					DeleteObject (hBitmap) ;

          			if (hPalette)
               					DeleteObject (hPalette) ;

          			PostQuitMessage (0) ;
          			return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}
 DIBBLE.RC ��ժ¼��
//Microsoft Developer Studio generated resource script.
#include "resource.h"
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
// Menu
DIBBLE MENU DISCARDABLE BEGIN POPUP "&File"
    	BEGIN
		MENUITEM "&Open...\tCtrl+O",        IDM_FILE_OPEN
		MENUITEM "&Save...\tCtrl+S",        IDM_FILE_SAVE
 		MENUITEM SEPARATOR
		MENUITEM "&Print...\tCtrl+P",       IDM_FILE_PRINT
		MENUITEM SEPARATOR
		MENUITEM "Propert&ies...",          IDM_FILE_PROPERTIES
		MENUITEM SEPARATOR
		MENUITEM "E&xit",    				  IDM_APP_EXIT
	END
    	POPUP "&Edit"
    	BEGIN	
		MENUITEM "Cu&t\tCtrl+X",  	  IDM_EDIT_CUT
		MENUITEM "&Copy\tCtrl+C",       IDM_EDIT_COPY
    	MENUITEM "&Paste\tCtrl+V", 	  IDM_EDIT_PASTE
   		MENUITEM "&Delete\tDelete", 	  IDM_EDIT_DELETE
       	MENUITEM SEPARATOR		
        MENUITEM "&Flip",    			  IDM_EDIT_FLIP
      	MENUITEM "&Rotate",   		  IDM_EDIT_ROTATE
    	END
    	POPUP "&Show"
    	BEGIN
        MENUITEM "&Actual Size", 	IDM_SHOW_NORMAL, CHECKED
        MENUITEM "&Center",   	IDM_SHOW_CENTER
        MENUITEM "&Stretch to Window",  		IDM_SHOW_STRETCH
        MENUITEM "Stretch &Isotropically",	IDM_SHOW_ISOSTRETCH
    	END
    	POPUP "&Palette"
    	BEGIN
        MENUITEM "&None",				IDM_PAL_NONE, CHECKED
        MENUITEM "&Dib ColorTable", 	IDM_PAL_DIBTABLE
        MENUITEM "&Halftone",     	IDM_PAL_HALFTONE
        MENUITEM "&All-Purpose",    	IDM_PAL_ALLPURPOSE
      	POPUP "&Gray Shades"
        	BEGIN
        MENUITEM "&1. 2 Grays",  		IDM_PAL_GRAY2
        MENUITEM "&2. 3 Grays",       IDM_PAL_GRAY3
        MENUITEM "&3. 4 Grays",       IDM_PAL_GRAY4
        MENUITEM "&4. 8 Grays",       IDM_PAL_GRAY8
        MENUITEM "&5. 16 Grays",      IDM_PAL_GRAY16
        MENUITEM "&6. 32 Grays",      IDM_PAL_GRAY32
        MENUITEM "&7. 64 Grays",	    IDM_PAL_GRAY64
        MENUITEM "&8. 128 Grays",	    IDM_PAL_GRAY128
        MENUITEM "&9. 256 Grays",	    IDM_PAL_GRAY256
        	END
        	POPUP "&Uniform Colors"
     	BEGIN
        MENUITEM "&1. 2R x 2G x 2B (8)",			IDM_PAL_RGB222
        MENUITEM "&2. 3R x 3G x 3B (27)", 		IDM_PAL_RGB333
        MENUITEM "&3. 4R x 4G x 4B (64)",		    IDM_PAL_RGB444
        MENUITEM "&4. 5R x 5G x 5B (125)",      	IDM_PAL_RGB555
        MENUITEM "&5. 6R x 6G x 6B (216)",      	IDM_PAL_RGB666
        MENUITEM "&6. 7R x 7G x 5B (245)",      	IDM_PAL_RGB775
	    MENUITEM "&7. 7R x 5B x 7B (245)",      	IDM_PAL_RGB757
        MENUITEM "&8. 5R x 7G x 7B (245)",      	IDM_PAL_RGB577
        MENUITEM "&9. 8R x 8G x 4B (256)",      	IDM_PAL_RGB884
        MENUITEM "&A. 8R x 4G x 8B (256)",      	IDM_PAL_RGB848
      	MENUITEM "&B. 4R x 8G x 8B (256)",        IDM_PAL_RGB488
        	END
        	POPUP "&Optimized"
        	BEGIN
        MENUITEM "&1. Popularity Algorithm (4 bits)"IDM_PAL_OPT_POP4
        MENUITEM "&2. Popularity Algorithm (5 bits)"IDM_PAL_OPT_POP5
        MENUITEM "&3. Popularity Algorithm (6 bits)"IDM_PAL_OPT_POP6
        MENUITEM "&4. Median Cut Algorithm ", IDM_PAL_OPT_MEDCUT
        	END
    	END
    	POPUP "Con&vert"
    	BEGIN
        MENUITEM "&1. to 1 bit per pixel",      	IDM_CONVERT_01
        MENUITEM "&2. to 4 bits per pixel",     	IDM_CONVERT_04
        MENUITEM "&3. to 8 bits per pixel",     	IDM_CONVERT_08
        MENUITEM "&4. to 16 bits per pixel",    	IDM_CONVERT_16
        MENUITEM "&5. to 24 bits per pixel",    	IDM_CONVERT_24
        MENUITEM "&6. to 32 bits per pixel",    	IDM_CONVERT_32
    	END
    	POPUP "&Help"
    	BEGIN
     		MENUITEM "&About", 
			IDM_APP_ABOUT
    	END
END
/////////////////////////////////////////////////////////////////////////////
// Accelerator
DIBBLE ACCELERATORS DISCARDABLE 
BEGIN
 	"C",          IDM_EDIT_COPY,          VIRTKEY, CONTROL, NOINVERT
    	"O",      IDM_FILE_OPEN,          VIRTKEY, CONTROL, NOINVERT
    	"P",      IDM_FILE_PRINT,         VIRTKEY, CONTROL, NOINVERT
    	"S",      IDM_FILE_SAVE,          VIRTKEY, CONTROL, NOINVERT
    	"V",      IDM_EDIT_PASTE,         VIRTKEY, CONTROL, NOINVERT
    	VK_DELETE,      	IDM_EDIT_DELETE,        VIRTKEY, NOINVERT
    	"X",      IDM_EDIT_CUT,           VIRTKEY, CONTROL, NOINVERT
END
 RESOURCE.H ��ժ¼��
// Microsoft Developer Studio generated include file.
// Used by Dibble.rc

#define IDM_FILE_OPEN                40001
#define IDM_FILE_SAVE                40002
#define IDM_FILE_PRINT               40003
#define IDM_FILE_PROPERTIES          40004
#define IDM_APP_EXIT                 40005
#define IDM_EDIT_CUT                 40006
#define IDM_EDIT_COPY                40007
#define IDM_EDIT_PASTE               40008
#define IDM_EDIT_DELETE              40009
#define IDM_EDIT_FLIP                40010
#define IDM_EDIT_ROTATE              40011
#define IDM_SHOW_NORMAL              40012
#define IDM_SHOW_CENTER              40013
#define IDM_SHOW_STRETCH             40014
#define IDM_SHOW_ISOSTRETCH          40015
#define IDM_PAL_NONE                 40016
#define IDM_PAL_DIBTABLE             40017
#define IDM_PAL_HALFTONE             40018
#define IDM_PAL_ALLPURPOSE           40019
#define IDM_PAL_GRAY2                40020
#define IDM_PAL_GRAY3                40021
#define IDM_PAL_GRAY4                40022
#define IDM_PAL_GRAY8                40023
#define IDM_PAL_GRAY16               40024
#define IDM_PAL_GRAY32               40025
#define IDM_PAL_GRAY64               40026
#define IDM_PAL_GRAY128              40027
#define IDM_PAL_GRAY256              40028
#define IDM_PAL_RGB222               40029
#define IDM_PAL_RGB333               40030
#define IDM_PAL_RGB444               40031
#define IDM_PAL_RGB555               40032
#define IDM_PAL_RGB666               40033
#define IDM_PAL_RGB775               40034
#define IDM_PAL_RGB757               40035
#define IDM_PAL_RGB577               40036
#define IDM_PAL_RGB884               40037
#define IDM_PAL_RGB848               40038
#define IDM_PAL_RGB488               40039
#define IDM_PAL_OPT_POP4             40040
#define IDM_PAL_OPT_POP5             40041
#define IDM_PAL_OPT_POP6             40042
#define IDM_PAL_OPT_MEDCUT           40043
#define IDM_CONVERT_01               40044
#define IDM_CONVERT_04               40045
#define IDM_CONVERT_08               40046
#define IDM_CONVERT_16               40047
#define IDM_CONVERT_24               40048
#define IDM_CONVERT_32               40049
#define IDM_APP_ABOUT                40050

DIBBLEʹ�������������������ҽ���Ҫ��˵�����ǡ�DIBCONV������DIBCONV.C��DIBCONV.H�������ֲ�ͬ��ʽ֮��ת�������磬��ÿͼ��24λԪת����ÿͼ��8λԪ��DIBPAL������DIBPAL.C��DIBPAL.H��������ɫ�̡�

DIBBLEά��WndProc�е�������Ҫ�ľ�̬��������Щ�Ǻ���hdib��HDIB���š�����hPalette��HPALETTE���źͺ���hBitmap��HBITMAP���š�HDIB����DIBHELP�еIJ�ͬ��ʽ��HPALETTE����DIBPAL�еIJ�ͬ��ʽ��CreateHalftonePalette��ʽ����HBITMAP��������DIBHELP.C�е�DibCopyToDdb��ʽ����������өĻ��ʾ���ر�����256ɫ��ʾģʽ�¡������������ڳ�ʽ�����µġ�DIB Section�����Զ��׼��أ����ڳ�ʽ������ͬ�ĵ�ɫ�̣��������ԣ�ʱ��������Ŷ��������½�����

�����Ǵӹ����϶���ѭ�򽥽���������һ��DIBBLE��

��������ʹ���
��

DIBBLE�����ڻ�ӦIDM_FILE_LOAD��IDM_FILE_SAVE��WM_COMMANDѶϢ��������������DIB������������Щ�������ڴ�����ЩѶϢ�����ڼ䣬DIBBLEͨ���ֱ����GetOpenFileName��GetSaveFileName���������õ����Ի����顣

��춡�File������Save�����ܱ����DIBBLEֻ��Ҫ����DibFileSave����춡�File������Open�����ܱ����DIBBLE��������ɾ��ǰ���HDIB����ɫ�̺͵���ͼ�������͸������һ��WM_USER_DELETEDIBѶϢ���������£���ѶϢͨ������DibDelete��DeleteObject��������Ȼ��DIBBLE����DIBHELP�е�DibFileLoad��ʽ������WM_USER_SETSCROLLS��WM_USER_CREATEPALѶϢ�������趨�����в�������ɫ�̡�WM_USER_CREATEPALѶϢҲλ춳�ʽ��DIB���齨�����µ�DDBλ�á�

��ʾ����������ӡ
��

DIBBLE�Ĺ��ܱ���������ʵ�ʳߴ�����ʾ�������Ͻ���ʾDIB��������ʾ�����м���ʾDIB������չ�������ʾ���򣬻����ڱ����ݺ�ȵ�����¾��������ʾ������������DIBBLE�ġ�Show�����ܱ�����ѡ����Ҫ��ѡ�ע�⣬��Щ����һ�µ�SHOWDIB2��ʽ���ĸ�ѡ����ͬ��

��WM_PAINTѶϢ�����ڼ䣭Ҳ�Ǵ�����File������Print������Ĺ����У�DIBBLE����DisplayDib��ʽ��ע�⣬DisplayDibʹ��BitBlt��StretchBlt��������ʹ��SetDIBitsToDevice��StretchDIBits����WM_PAINTѶϢ�����ڼ䣬���ݸ���ʽ�ĵ���ͼ������DibCopyToDdb��ʽ����������WM_USER_CREATEPALѶϢ�����ڼ���С�����DDB����Ѷװ���������ݡ���������File������Print������ʱ��DIBBLE����DisplayDib�����п��õ�DIB�����������DIBHELP.C�е�DibBitmapHandle��ʽ��

����Ҫע�⣬DIBBLE����һ������fHalftonePalette�ľ�̬BOOL�����������CreateHalftonePalette��ʽ�л��hPalette����˱����趨ΪTRUE���⽫��ʹDisplayDib��ʽ����StretchBlt�����Ǻ���BitBlt����ʹDIB��ָ����ʵ�ʳߴ���ʾ��fHalftonePalette����Ҳ����WM_PAINT������ʽ��DIB������Ŵ��ݸ�DisplayDib��ʽ����������DibCopyToDdb��ʽ�����ĵ���ͼ���š�����ǰ�����۹��м�ɫ��ɫ�̵�ʹ�ã�����SHOWDIB5��ʽ�н�����չʾ��

��һ��ʹ�÷�����ʽʱ��DIBBLE��������ʾ�����о���DIB��ֻ�а�ʵ�ʳߴ���ʾDIBʱ������ʾ�����С��ڴ���WM_PAINTʱ��WndProc�򵥵ؽ������е�Ŀǰλ�ô��ݸ�DisplayDib��ʽ��

������
��

��춡�Cut���͡�Copy�����ܱ��DIBBLE����DIBHELP�е�DibCopyToPackedDib��ʽ���ú�ʽ��������е�DIBԪ���������Ƿ����ļ�������С�

��춵�һ��ʹ�ñ����е�ijЩ������ʽ��˵��DIBBLE�Ӽ�������ճ��DIB�����������DibCopyFromPackedDib��ʽ�����滻�Ӵ�ѶϢ������ʽǰ�洢���HDIB����ɫ�̺͵���ͼ��

��ת����ת
��

DIBBLE�еġ�Edit�����ܱ��г��˳����ġ�Cut������Copy������Paste���͡�Delete��ѡ��֮�⣬�����������������Flip���͡�Rotate������Flip��ѡ��ʹ����ͼ��ˮƽ�ᷭת�������µߵ���ת����Rotate��ѡ��ʹ����ͼ˳ʱ����ת90�ȡ���������ʽ����Ҫ͸�������Ǵ�һ��DIB���Ƶ���һ������ȡ���е�DIBͼ�أ���Ϊ��������ʽ����Ҫ�����µĵ�ɫ�̣����Բ�ɾ�������½�����ɫ�̣���

��Flip�����ܱ�ѡ��ʹ��DibFlipHorizontal��ʽ���˺�ʽҲλ�DIBBLE.C�������˺�ʽ����DibCopy�����DIB��ȷ�ĸ�����Ȼ�ᣬ���뽫ԭDIB�е�ͼ�ظ��Ƶ���DIB�Ļ�Ȧ�����Ǹ�����Щͼ����Ϊ�����·�תͼ��ע�⣬�˺�ʽ����DibGetPixel��DibSetPixel����Щ��DIBHELP.C�е�ͨ�ã�������������ϣ������ô�죩��ʽ��

Ϊ��˵��DibGetPixel��DibSetPixel��ʽ��DIBHELP.H��ִ�и����DibGetPixel��DibSetPixel�޼�֮�������DibRotateRight��ʽʹ���˾޼���Ȼ��������Ҫע����ǣ��ú�ʽ����DibCopyʱ���ڶ��������趨ΪTRUE���⵼��DibCopy��תԭDIB�Ŀ��Ⱥ͸߶��������µ�DIB�����⣬ͼ��λԪ������DibCopy��ʽ���ơ����ǣ�DibRotateRight��ʽ��������ͬ�Ļ�Ȧ��ͼ��λԪ��ԭDIB���Ƶ��µ�DIB��ÿһ������Ӧ��ͬ��DIBͼ�ؿ��ȣ�1λԪ��4λԪ��8λԪ��16λԪ��24λԪ��32λԪ������Ȼ�����˸���ij�ʽ�룬���Ǻ�ʽ�����ˡ�

���ܿ���ʹ�á�Flip Horizontal���͡�Rotate Right��ѡ����������Flip Vertical������Rotate Left���͡�Rotate 180�㡹���ܣ���ͨ����ʽ��ֱ��ִ������ѡ��Ͼ���DIBBLEֻ�Ǹ�չʾ��ʽ���ѡ�

�򵥵�ɫ�̣���ѻ���ɫ��
��

��DIBBLE�У���������256ɫ��Ѷ��ʾ����ѡ��ͬ�ĵ�ɫ������ʾDIB����Щ����DIBBLE�ġ�Palette�����ܱ����г��������м�ɫ��ɫ�����⣬����Ķ�ֱ����Windows��ʽ���н�����������ͬ��ɫ�̵����к�ʽ���ɳ�ʽ16-24��ʾ��DIBPAL�����ṩ��

 ï¿½ï¿½Ê½16-24  DIBPAL����
DIBPAL.H
/*--------------------------------------------------------------------------
   	DIBPAL.H header file for DIBPAL.C
----------------------------------------------------------------------------*/

HPALETTE DibPalDibTable (HDIB hdib) ;
HPALETTE DibPalAllPurpose (void) ;
HPALETTE DibPalUniformGrays (int iNum) ;
HPALETTE DibPalUniformColors (int iNumR, int iNumG, int iNumB) ;
HPALETTE DibPalVga (void) ;
HPALETTE DibPalPopularity (HDIB hdib, int iRes) ;
HPALETTE DibPalMedianCut (HDIB hdib, int iRes) ;
DIBPAL.C
/*----------------------------------------------------------------------------
   	DIBPAL.C -- 	Palette-Creation Functions
               						(c) Charles Petzold, 1998
  -------------------------------------------------------------------------*/

#include <windows.h>
#include "dibhelp.h"
#include "dibpal.h"

/*---------------------------------------------------------------------------
   	DibPalDibTable: Creates a palette from the DIB color table
-----------------------------------------------------------------------------*/

HPALETTE DibPalDibTable (HDIB hdib)
{
 	HPALETTE     			hPalette ;
     	int          				i, iNum ;
     	LOGPALETTE 	* 	plp ;
     	RGBQUAD      			rgb ;

     	if (0 == (iNum = DibNumColors (hdib)))
          			return NULL ;
     	plp = malloc (sizeof (LOGPALETTE) + (iNum - 1) * sizeof (PALETTEENTRY)) ;
     	plp->palVersion    		= 0x0300 ;
     	plp->palNumEntries 	= iNum ;

     	for (i = 0 ; i < iNum ; i++)
     	{
          			DibGetColor (hdib, i, &rgb) ;
          			plp->palPalEntry[i].peRed   = rgb.rgbRed ;
          			plp->palPalEntry[i].peGreen = rgb.rgbGreen ;
          			plp->palPalEntry[i].peBlue  = rgb.rgbBlue ;
          			plp->palPalEntry[i].peFlags = 0 ;
     	}
     	hPalette = CreatePalette (plp) ;
     	free (plp) ;
     	return hPalette ;
}
/*---------------------------------------------------------------------------
   	DibPalA	llPurpose: Creates a palette suitable for a wide variety
          				of images; the palette has 247 entries, but 15 of them are 
          				duplicates or match the standard 20 colors.
----------------------------------------------------------------------------*/

HPALETTE DibPalAllPurpose (void)
{
     	HPALETTE     			hPalette ;
     	int          				i, incr, R, G, B ;
     	LOGPALETTE * 	plp ;

     	plp = malloc (sizeof (LOGPALETTE) + 246 * sizeof (PALETTEENTRY)) ;
     	plp->palVersion    		= 0x0300 ;
     	plp->palNumEntries 	= 247 ;

         			// The following loop calculates 31 gray shades, but 3 of them
          			// 			will match the standard 20 colors

     	for (i = 0, G = 0, incr = 8 ; G <= 0xFF ; i++, G += incr)
     {
          			plp->palPalEntry[i].peRed   		= (BYTE) G ;
          			plp->palPalEntry[i].peGreen 	= (BYTE) G ;
          			plp->palPalEntry[i].peBlue  	= (BYTE) G ;
          			plp->palPalEntry[i].peFlags 	= 0 ;

          			incr = (incr == 9 ? 8 : 9) ;
	}

		// The following loop is responsible for 216 entries, but 8 of 
          		//   				them will match the standard 20 colors, and another
          		// 				4 of them will match the gray shades above.

	for (R = 0 ; R <= 0xFF ; R += 0x33)
     	for (G = 0 ; G <= 0xFF ; G += 0x33)
     	for (B = 0 ; B <= 0xFF ; B += 0x33)
     	{
          			plp->palPalEntry[i].peRed   			= (BYTE) R ;
          			plp->palPalEntry[i].peGreen 		= (BYTE) G ;
          			plp->palPalEntry[i].peBlue  		= (BYTE) B ;
          			plp->palPalEntry[i].peFlags 		= 0 ;

          			i++ ;
	}
	hPalette = CreatePalette (plp) ;
	free (plp) ;
	return hPalette ;
}

/*---------------------------------------------------------------------------
	DibPalUniformGrays:  Creates a palette of iNum grays, uniformly spaced
----------------------------------------------------------------------------*/

HPALETTE DibPalUniformGrays (int iNum)
{
     	HPALETTE     			hPalette ;
     	int          				i ;
     	LOGPALETTE 	* 	plp ;

     	plp = malloc (sizeof (LOGPALETTE) + (iNum - 1) * sizeof (PALETTEENTRY)) ;
     	plp->palVersion    			= 0x0300 ;
     	plp->palNumEntries 		= iNum ;

     	for (i = 0 ; i < iNum ; i++)
     	{
          			plp->palPalEntry[i].peRed   		=
          			plp->palPalEntry[i].peGreen 	= 
          			plp->palPalEntry[i].peBlue  	= (BYTE) (i * 255 / (iNum - 1)) ;
          			plp->palPalEntry[i].peFlags = 0 ;
     	}
     	hPalette = CreatePalette (plp) ;
     	free (plp) ;
     	return hPalette ;
}

/*--------------------------------------------------------------------------
	DibPalUniformColors: Creates a palette of iNumR x iNumG x iNumB colors
----------------------------------------------------------------------------*/

HPALETTE DibPalUniformColors (int iNumR, int iNumG, int iNumB)
{
     	HPALETTE     			hPalette ;
     	int          				i, iNum, R, G, B ;
     	LOGPALETTE * 	plp ;

     	iNum = iNumR * iNumG * iNumB ;
     	plp = malloc (sizeof (LOGPALETTE) + (iNum - 1) * sizeof (PALETTEENTRY)) ;
     	plp->palVersion    = 0x0300 ;
     	plp->palNumEntries = iNumR * iNumG * iNumB ;

     	i = 0 ;
     	for (R = 0 ; R < iNumR ; R++)
     	for (G = 0 ; G < iNumG ; G++)
     	for (B = 0 ; B < iNumB ; B++)
     	{
          		plp->palPalEntry[i].peRed   	= (BYTE) (R * 255 / (iNumR - 1)) ;
          		plp->palPalEntry[i].peGreen 	= (BYTE) (G * 255 / (iNumG - 1)) ;
          		plp->palPalEntry[i].peBlue  	= (BYTE) (B * 255 / (iNumB - 1)) ;
          		plp->palPalEntry[i].peFlags 	= 0 ;

          			i++ ;
     	}
     	hPalette = CreatePalette (plp) ;
     	free (plp) ;
     	return hPalette ;
}

/*---------------------------------------------------------------------------
	DibPalVga:  Creates a palette based on standard 16 VGA colors
----------------------------------------------------------------------------*/

HPALETTE DibPalVga (void)
{
	static RGBQUAD rgb [16] = { 0x00, 0x00, 0x00,	0x00,
                                0x00, 0x00, 0x80,	0x00,
                                0x00, 0x80, 0x00,	0x00,
                                0x00, 0x80, 0x80,	0x00,
                                0x80, 0x00, 0x00,	0x00,
                                0x80, 0x00, 0x80,	0x00,
                                0x80, 0x80, 0x00,	0x00,
                                0x80, 0x80, 0x80,	0x00,
                                0xC0, 0xC0, 0xC0,	0x00,
                                0x00, 0x00, 0xFF,	0x00,
                                0x00, 0xFF, 0x00,	0x00,
                                0x00, 0xFF, 0xFF,	0x00,
                                0xFF, 0x00, 0x00,	0x00,
                                0xFF, 0x00, 0xFF,	0x00,
                                0xFF, 0xFF, 0x00,	0x00,
                                0xFF, 0xFF, 0xFF,	0x00 } ;
     	HPALETTE       			hPalette ;
     	int            			i ;
     	LOGPALETTE   		    * 	plp ;

     	plp = malloc (sizeof (LOGPALETTE) + 15 * sizeof (PALETTEENTRY)) ;
     	plp->palVersion    		= 0x0300 ;
     	plp->palNumEntries 	= 16 ;

     	for (i = 0 ; i < 16 ; i++)
     	{
          			plp->palPalEntry[i].peRed   	= rgb[i].rgbRed ;
         			plp->palPalEntry[i].peGreen 	= rgb[i].rgbGreen ;
          			plp->palPalEntry[i].peBlue  	= rgb[i].rgbBlue ;
          			plp->palPalEntry[i].peFlags  = 0 ;
     	}
     	hPalette = CreatePalette (plp) ;
     	free (plp) ;
     	return hPalette ;
}

/*---------------------------------------------------------------------------
   	Macro used in palette optimization routines
  -------------------------------------------------------------------------*/

#define PACK_RGB(R,G,B,iRes) ((int) (R) | 	((int) (G) <<  (iRes)) |	\
                             ((int) (B) << ((iRes) + (iRes))))

/*----------------------------------------------------------------------------
   	AccumColorCounts: Fills up piCount (indexed by a packed RGB color)
    	with counts of pixels of that color.
-----------------------------------------------------------------------------*/

static void AccumColorCounts (HDIB hdib, int * piCount, int iRes)
{
     	int  		x, y, cx, cy ;
     	RGBQUAD	rgb ;

     	cx = DibWidth (hdib) ;
     	cy = DibHeight (hdib) ;

     	for (y = 0 ; y < cy ; y++)
     	for (x = 0 ; x < cx ; x++)
     	{
          			DibGetPixelColor (hdib, x, y, &rgb) ;

          			rgb.rgbRed   	>>= (8 - iRes) ;
          			rgb.rgbGreen 	>>= (8 - iRes) ;
          			rgb.rgbBlue  	>>= (8 - iRes) ;

          			++piCount [PACK_RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, iRes)] ;
     	}
}

/*---------------------------------------------------------------------------
   	DibPalPopularity:  Popularity algorithm for optimized colors
-----------------------------------------------------------------------------*/

HPALETTE DibPalPopularity (HDIB hdib, int iRes)
{
     	HPALETTE     			hPalette ;
     	int          				i, iArraySize, iEntry, iCount, iIndex, iMask, R, G, B ;
     	int        			* 	piCount ;
     	LOGPALETTE	* 	plp ;

          			// Validity checks
    
     	if (DibBitCount (hdib) < 16)
          			return NULL ;
     	if (iRes < 3 || iRes > 8)
  			return NULL ;
			// Allocate array for counting pixel colors
     	iArraySize = 1 << (3 * iRes) ;
     	iMask = (1 << iRes) - 1 ;

     	if (NULL == (piCount = calloc (iArraySize, sizeof (int))))
          			return NULL ;
          			// Get the color counts
     	AccumColorCounts (hdib, piCount, iRes) ;
          			// Set up a palette
     	plp = malloc (sizeof (LOGPALETTE) + 235 * sizeof (PALETTEENTRY)) ;
     	plp->palVersion = 0x0300 ;
     	for (iEntry = 0 ; iEntry < 236 ; iEntry++)
     	{
          			for (i = 0, iCount = 0 ; i < iArraySize ; i++)
               					if (piCount[i] > iCount)

               					{
                    							iCount = piCount[i] ;
                    							iIndex = i ;
               					}
          			if (iCount == 0)
               					break ;
          			R = (iMask &  iIndex) << (8 - iRes) ;
          	  G = (iMask & (iIndex >> iRes )) << (8 - iRes) ;
          	  B = (iMask & (iIndex >> (iRes + iRes)))<< (8 - iRes) ;

          			plp->palPalEntry[iEntry].peRed   	= (BYTE) R ; 
          			plp->palPalEntry[iEntry].peGreen 	= (BYTE) G ; 
          			plp->palPalEntry[iEntry].peBlue  	= (BYTE) B ; 
          			plp->palPalEntry[iEntry].peFlags 	= 0 ;

          			piCount [iIndex] = 0 ;
     }
          		// On exit from the loop iEntry will be the number of stored entries
     	plp->palNumEntries = iEntry ;
          		// Create the palette, clean up, and return the palette handle
     	hPalette = CreatePalette (plp) ;
     	free (piCount) ;
     	free (plp) ;

     	return hPalette ;
}

/*--------------------------------------------------------------------------
   	Structures used for implementing median cut algorithm
----------------------------------------------------------------------------*/

typedef struct           				// defines dimension of a box
{
     	int Rmin, Rmax, Gmin, Gmax, Bmin, Bmax ;
}
MINMAX ;
typedef struct           				// for Compare routine for qsort
{
     	int     		iBoxCount ;
     	RGBQUAD 	rgbBoxAv ;
}

BOXES ;
/*----------------------------------------------------------------------------
   	FindAverageColor: In a box
-----------------------------------------------------------------------------*/

static int FindAverageColor (	int * piCount, MINMAX mm, 
                             	int iRes, RGBQUAD * prgb)
{
     	int R, G, B, iR, iG, iB, iTotal, iCount ;
          			// Initialize some variables
     	iTotal = iR = iG = iB = 0 ;
          			// Loop through all colors in the box
     	for (R = mm.Rmin ; R <= mm.Rmax ; R++)
     	for (G = mm.Gmin ; G <= mm.Gmax ; G++)
     	for (B = mm.Bmin ; B <= mm.Bmax ; B++)
     	{
               				// Get the number of pixels of that color
          			iCount = piCount [PACK_RGB (R, G, B, iRes)] ;
               				// Weight the pixel count by the color value
          			iR += iCount * R ;
          			iG += iCount * G ;
          			iB += iCount * B ;

          			iTotal += iCount ;
     	}
          			// Find the average color
     	prgb->rgbRed   		= (BYTE) ((iR / iTotal) << (8 - iRes)) ;
     	prgb->rgbGreen 		= (BYTE) ((iG / iTotal) << (8 - iRes)) ;
     	prgb->rgbBlue  		= (BYTE) ((iB / iTotal) << (8 - iRes)) ;

          			// Return the total number of pixels in the box
     
     	return iTotal ;
}

/*---------------------------------------------------------------------------
   CutBox:  Divide a box in two
----------------------------------------------------------------------------*/
static void CutBox (int * piCount, int iBoxCount, MINMAX mm,
                    int iRes, int iLevel, BOXES * pboxes, int * piEntry)
{
     	int    		iCount, R, G, B ;
     	MINMAX 	mmNew ;
     
          			// If the box is empty, return 

     	if (iBoxCount == 0)
          			return ;

          			// If the nesting level is 8, or the box is one pixel, we're ready
          			// to find the average color in the box and save it along with
          			// the number of pixels of that color

     	if (iLevel == 8 || (	mm.Rmin == mm.Rmax && 
                         		mm.Gmin == mm.Gmax && 
                         		mm.Bmin == mm.Bmax))
     {
          		pboxes[*piEntry].iBoxCount = 
       			FindAverageColor (piCount, mm, iRes, &pboxes[*piEntry].rgbBoxAv) ;
          			(*piEntry) ++ ;
     	}
          			// Otherwise, if blue is the largest side, split it
     	else if ((mm.Bmax - mm.Bmin > mm.Rmax - mm.Rmin) && 
              					(mm.Bmax - mm.Bmin > mm.Gmax - mm.Gmin))
     	{
               				// Initialize a counter and loop through the blue side
          		iCount = 0 ;
          		for (B = mm.Bmin ; B < mm.Bmax ; B++)
          		{
                    					// Accumulate all the pixels for each successive blue value
               			for (	R = mm.Rmin ; R <= mm.Rmax ; R++)
               			for (	G = mm.Gmin ; G <= mm.Gmax ; G++)
                    			iCount += piCount [PACK_RGB (R, G, B, iRes)] ;

                    			// If it's more than half the box count, we're there

               			if (i	Count >= iBoxCount / 2)
                    					break ;

                    		//	If the next blue value will be the max, we're there
               							if (	B == mm.Bmax - 1)
                    								break ;
          		}
               				// Cut the two split boxes.
               				//   The second argument to CutBox is the new box count.
               				//   The third argument is the new min and max values.

          		mmNew = mm ;
          		mmNew.Bmin = mm.Bmin ;
          		mmNew.Bmax = B ;

          		CutBox (	piCount, iCount, mmNew, iRes, iLevel + 1, 
                  						pboxes, piEntry) ;

          		mmNew.Bmin = B + 1 ;
          		mmNew.Bmax = mm.Bmax ;

          		CutBox (	piCount, iBoxCount - iCount, mmNew, iRes, iLevel + 1,
                  						pboxes, piEntry) ;
	}
          		// Otherwise, if red is the largest side, split it (just like blue)
     	else if (mm.Rmax - mm.Rmin > mm.Gmax - mm.Gmin)
     {
          		iCount = 0 ;
          		for (R = mm.Rmin ; R < mm.Rmax ; R++)
          		{
               					for (B = mm.Bmin ; B <= mm.Bmax ; B++)
               					for (G = mm.Gmin ; G <= mm.Gmax ; G++)
                    				iCount += piCount [PACK_RGB (R, G, B, iRes)] ;
               					if (iCount >= iBoxCount / 2)
                    							break ;
               					if (R == mm.Rmax - 1)
                    							break ;
     		}
          		mmNew = mm ;
          		mmNew.Rmin = mm.Rmin ;
          		mmNew.Rmax = R ;

          		CutBox (	piCount, iCount, mmNew, iRes, iLevel + 1, 
                  						pboxes, piEntry) ;

          		mmNew.Rmin 	= R + 1 ;
          		mmNew.Rmax 	= mm.Rmax ;
          		CutBox (	piCount, iBoxCount - iCount, mmNew, iRes, iLevel + 1,
                  						pboxes, piEntry) ;
     }
          				// Otherwise, split along the green size
     	else 
     	{
          		iCount = 0 ;
          		for (G = mm.Gmin ; G < mm.Gmax ; G++)
          		{
               			for (	B = mm.Bmin ; B <= mm.Bmax ; B++)
               			for (	R = mm.Rmin ; R <= mm.Rmax ; R++)
                    			iCount += piCount [PACK_RGB (R, G, B, iRes)] ;

               			if (	iCount >= iBoxCount / 2)
                    					break ;

               			if (	G == mm.Gmax - 1)
                    					break ;
         		}
          		mmNew = mm ;
          		mmNew.Gmin = mm.Gmin ;
          		mmNew.Gmax = G ;

          		CutBox (	piCount, iCount, mmNew, iRes, iLevel + 1, 
                  						pboxes, piEntry) ;

          		mmNew.Gmin 	= G + 1 ;
          		mmNew.Gmax 	= mm.Gmax ;

          		CutBox (	piCount, iBoxCount - iCount, mmNew, iRes, iLevel + 1,
                  						pboxes, piEntry) ;
     	}
}

/*---------------------------------------------------------------------------
   	Compare routine for qsort
-----------------------------------------------------------------------------*/

static int Compare (const BOXES * pbox1, const BOXES * pbox2)
{
     	return pbox1->iBoxCount - pbox2->iBoxCount ;
}

/*---------------------------------------------------------------------------
   	DibPalMedianCut:  Creates palette based on median cut algorithm
  -------------------------------------------------------------------------*/
HPALETTE DibPalMedianCut (HDIB hdib, int iRes)
{
     	BOXES        			boxes [256] ;
     	HPALETTE     			hPalette ;
     	int          			i, iArraySize, iCount, R, G, B, iTotCount, iDim, iEntry = 0 ;
     	int        			* 	piCount ;
     	LOGPALETTE 	*	plp ;
     	MINMAX       			mm ;

          			// Validity checks
    
     	if (DibBitCount (hdib) < 16)
          			return NULL ;
     	if (iRes < 3 || iRes > 8)
          			return NULL ;
          			// Accumulate counts of pixel colors
	iArraySize = 1 << (3 * iRes) ;
	if (NULL == (piCount = calloc (iArraySize, sizeof (int))))
          			return NULL ;
	AccumColorCounts (hdib, piCount, iRes) ;
			// Find the dimensions of the total box
	iDim = 1 << iRes ;
	mm.Rmin = mm.Gmin = mm.Bmin = iDim - 1 ;
	mm.Rmax = mm.Gmax = mm.Bmax = 0 ;

	iTotCount = 0 ;
     	for (R = 0 ; R < iDim ; R++)
     	for (G = 0 ; G < iDim ; G++)
     	for (B = 0 ; B < iDim ; B++)
          			if ((iCount = piCount [PACK_RGB (R, G, B, iRes)]) > 0)
          			{
               					iTotCount += iCount ;
               					if (R < mm.Rmin) mm.Rmin = R ;
               					if (G < mm.Gmin) mm.Gmin = G ;
               					if (B < mm.Bmin) mm.Bmin = B ;
               					if (R > mm.Rmax) mm.Rmax = R ;
               					if (G > mm.Gmax) mm.Gmax = G ;
               					if (B > mm.Bmax) mm.Bmax = B ;
          			}

          		// Cut the first box (iterative function).
     		    // 	On return, the boxes structure will have up to 256 RGB values, 
          		// 	one for each of the boxes, and the number of pixels in
          		//  each box.
          		//  The iEntry value will indicate the number of non-empty boxes.

     	CutBox (piCount, iTotCount, mm, iRes, 0, boxes, &iEntry) ;
     	free (piCount) ;

          		// Sort the RGB table by the number of pixels for each color
     	qsort (boxes, iEntry, sizeof (BOXES), Compare) ;
     	plp = malloc (sizeof (LOGPALETTE) + (iEntry - 1) * sizeof (PALETTEENTRY)) ;
     	if (plp == NULL)
          			return NULL ;
     	plp->palVersion    		= 0x0300 ;
     	plp->palNumEntries 	= iEntry ;

     	for (i = 0 ; i < iEntry ; i++)
     	{
          			plp->palPalEntry[i].peRed  = boxes[i].rgbBoxAv.rgbRed ;
          			plp->palPalEntry[i].peGreen= boxes[i].rgbBoxAv.rgbGreen ;
          			plp->palPalEntry[i].peBlue = boxes[i].rgbBoxAv.rgbBlue ;
          			plp->palPalEntry[i].peFlags= 0 ;
     }

	hPalette = CreatePalette (plp) ;
	free (plp) ;
	return hPalette ;
}

��һ����ʽ��DibPalDibTable��������Ӧ�ú���Ϥ��������DIB����ɫ�������˵�ɫ�̡����뱾��ǰ���SHOWDIB3�����õ���PACKEDIB.C���PackedDibCreatePalette��ʽ���ơ���SHOWDIB3�У�ֻ�е�DIB����ɫ��ʱ��ִ�д˺�ʽ����8λԪ��ʾģʽ����ͼ��ʾ16λԪ��24λԪ��32λԪDIBʱ���˺�ʽ��û���ˡ�

Ԥ������£�ִ����256ɫ��ʾģʽ��ʱ��DIBBLE�����ȳ��Ժ���DibPalDibTable������DIB��ɫ��������ɫ�̡����DIBû����ɫ������DIBBLE������CreateHalftonePalette����fHalftonePalette�����趨ΪTRUE�����߼�������WM_USER_CREATEPALѶϢ�����ڼ䡣

DIBPAL.CҲִ�к�ʽDibPalAllPurpose����Ϊ�˺�ʽ��SHOWDIB4�е�CreateAllPurposePalette��ʽ�dz����ƣ�������������Ҳ����Ϥ����Ҳ���Դ�DIBBLE���ܱ���ѡ��˵�ɫ�̡�

��256ɫģʽ����ʾ����ͼ����Ȥ���ǣ�������ֱ�ӿ���Windows�����ʾͼ�����ɫ�������ѡ�����ֵ�ɫ�̣���Winsows��ʹ�ô˵�ɫ���е���ɫ��������������ɫ���е���ɫ��

���磬��������DibPalUniformGrays��ʽ����������һ�ֻҽ׵�ɫ�̡�ʹ�����ֻҽ׵ĵ�ɫ����ֻ����00-00-00����ɫ����FF-FF-FF����ɫ�����ô˵�ɫ�������ͼ���ṩijЩ��Ƭ�г��õĸ߶Աȡ��ڰס�Ч����ʹ��3�ֻҽ׽��ں�ɫ�Ͱ�ɫ�м������м��ɫ��ʹ��4�ֻҽ׽�����2�ֻҽס�

��8�ֻҽף������п��ܿ������Ե���������ͬ�ҽ׵��޹���ߵ㣬��Ȼ�����Ե�ִ������ӽ���ɫ���㷨������һ���Բ������κ������жϡ�ͨ����16�ֻҽ׾Ϳ������Ը���ͼ���ʡ�ʹ��32�ֻҽײ��Ϳ�������ȫ�������ˡ���Ŀǰ�ձ���Ϊ64�ֻҽ������ڴ������ʾ�豸�ļ��ޡ���������ϣ�������Ҳûʲô�߼�Ч���ˡ���6λԪ��ɫ�����ȵ��豸���ṩ����64�ֻҽ׿�������ʲô�Ľ�֮����

����Ϊֹ�����8λԪ��ʾģʽ����ʾ16λԪ��24λԪ��32λԪ��ɫDIB�������������ܹ����ͨ�õ�ɫ�̣���Իҽ�ͼ�����Ч����ͨ������춲�ɫͼ�񣩻���ʹ���м�ɫ��ɫ�̣����û�ɫ��ʾ��ͨ����ɫ��ɫ�̺��á�

��Ӧע�⣬������8λԪ��ɫģʽ��Ϊ����16λԪ��24λԪ��32λԪDIBѡ��ͨ�õ�ɫ��ʱ��Ϊ��Ҫ��ʾ��Щͼ�񣬳�ʽ������һЩʱ������DIB������������GDI����ͼ������������Ҫ��ɫ�̣����ʽ����DIB������DDB��ʱ�����٣���8λԪ��ɫģʽ��ʾ��24λԪDIBʱ���Ƚ�SHOWDIB1��SHOWDIB4�����ܣ���Ҳ�ܿ���������𣩡�����Ϊʲô�أ�

������ӽ���ɫ��Ѱ��ͨ������8λԪ��ʾģʽ��ʾ24λԪDIBʱ�����߽�DIBת��ΪDDB����GDI���뽫DIB�е�ÿ��ͼ�ض��뾲̬20����ɫ�е�һ������������ɴ˲�����Ψһ�����Ǿ������־�̬��ɫ��ͼ����ɫ��ӽ������������ͼ������άRGB��ɫ��ÿ�־�̬��ɫ�ľ��롣�⽫��Щʱ�䣬�ر�����DIBͼ�������ϰ����ͼ��ʱ��

�ڽ���232ɫ��ɫ��ʱ������DIBBLE��SHOWDIB4�е�ͨ�õ�ɫ�̣�����ܿ콫������ӽ���ɫ��ʱ�����ӵ�����11����GDI���ڱ��볹�׼��232����ɫ��������20�֡��Ǿ�����ʾDIB��������ҵ������ԭ��

����Ľ�ѵ�DZ�����8λԪ��ʾģʽ����ʾ24λԪ����16λԪ����32λԪ��DIB����Ӧ���ҳ���ӽ�DIBͼ����ɫ��Χ��256ɫ��ɫ�̣���������ת����8λԪDIB���⾭����Ϊ����ѵ�ɫ�̡��������о���������ʱ��Paul Heckbert��д�ġ�Color Image Quantization for Frame Buffer Displays����������1982��7�³���ġ�Computer Graphics�����Դ���������������

���ȷֲ�
��

����256ɫ��ɫ����򵥵ķ�����ѡ��Χͳһ��RGB��ɫֵ������DibPalAllPurpose�еķ������ơ��˷������ŵ��������ؼ��DIB�е�ʵ��ͼ�ء������ʽ��DibPalCreateUniformColors�������ݷ�Χͳһ��RGB��ԭɫ����������ɫ�̡�

һ�������ķֲ�����8�׺�ɫ����ɫ�Լ�4����ɫ�����۶���ɫ�ϲ����У�����ɫ����RGB��ɫֵ�ļ��ϣ����Ǻ�ɫ����ɫֵ0x00��0x24��0x49��0x6D��0x92��0xB6��0xDB��0xFF�Լ���ɫֵ0x00��0x55��0xAA��0xFF�����п��ܵ���ϣ�����256����ɫ����һ�ֿ��ܵ�ͳһ�ֲ���ɫ��ʹ��6�׺�ɫ����ɫ����ɫ���˵�ɫ���Ǻ�ɫ����ɫ����ɫֵΪ0x00��0x33��0x66��0x99��0xCC��0xFF�����п��ܵ���ϣ���ɫ���е���ɫ����6��3�η�����216��

������ѡ�����������ѡ���DIBBLE�ṩ��

��Popularity�����㷨
��

��Popularity�����㷨��256ɫ��ɫ�������൱���ԵĽ����������Ҫ���ľ����߱����ͼ�е�����ͼ�أ����ҳ�256������ͨ��RGB��ɫֵ����Щ�������ڵ�ɫ����ʹ�õ�ֵ��DIBPAL��DibPalPopularity��ʽ��ʵ�����������㷨��

���������ÿ����ɫ��ʹ������24λԪ�����Ҽ�����Ҫ���������������е���ɫ����ô���н�ռ��64MB�����塣���⣬�����Է��ֵ���ͼ��ʵ����û�У�����٣��ظ���24λԪͼ��ֵ��������û����ν��������ɫ�ˡ�

Ҫ���������⣬������ֻʹ��ÿ����ɫ����ɫ����ɫֵ������Ҫ��nλԪ�����磬6λԪ������8λԪ����Ϊ������IJ�ɫɨ��������Ѷ��ʾ����ֻ��6λԪ�Ľ����ȣ����������涨�������塣�⽫���м��ٵ���С��������256KB��1MB��ֻʹ��5λԪ�ܽ����õ���ɫ�������ٵ�32,768��ͨ����ʹ��5λԪҪ��6λԪ�����ܸ��á��Դˣ���������DIBBLE��һЩͼ����ɫ���Լ����顣

��Median Cut�����㷨
��

DIBPAL.C�е�DibPalMedianCut��ʽִ��Paul Heckbert��Median Cut���㷨�������㷨�ڸ������൱�򵥣����ڳ�ʽ����ʵ��Ҫ��Popularity���㷨�����ѣ����ʺϵݻغ�ʽ��

����RGB��ɫ�����塣ͼ���е�ÿ��ͼ�ض��Ǵ��������е�һ���㡣һЩ����ܴ���ͼ���еĶ��ͼ�ء��ҳ�����ͼ��������ͼ�ص����巽�飬�ҳ��˷�������ߴ磬��������ֳ�������ÿ�����鶼������ͬ������ͼ�ء�������������飬ִ����ͬ�IJ���������������4�����飬����4������ֳ�8����Ȼ���ٷֳ�16����32����64����128����256����

��������256�����飬ÿ�����鶼������ͬ������ͼ�ء�ȡÿ��������ͼ��RGB��ɫֵ��ƽ��ֵ�����������춵�ɫ�̡�

ʵ���ϣ���Щ����ͨ������ͼ�ص�����������ͬ�����磬ͨ������������ķ�����и����ͼ�ء��ⷢ���ں�ɫ�Ͱ�ɫ�ϡ���ʱ��һЩ������ͷ����û��ͼ�ء�������������Ϳ���ʡ�¸���ķ��飬�����Ҿ�������������

��һ����ѻ���ɫ�̵ļ�����Ϊ��octree quantization�����˼�����Jeff Prosise��������1996��8�·����ڡ�Microsoft Systems Journal���ϣ�������MSDN��CD�У���

ת����ʽ
��

DIBBLE��������DIB��һ�ָ�ʽת������һ�ָ�ʽ�����õ���DIBCONV�����е�DibConvert��ʽ�����ʽ16-25��ʾ��

 ï¿½ï¿½Ê½16-25  DIBCONV����
DIBCONV.H

/*----------------------------------------------------------------------------
   	DIBCONV.H header file for DIBCONV.C
-----------------------------------------------------------------------------*/

HDIB DibConvert (HDIB hdibSrc, int iBitCountDst) ;
DIBCONV.C
/*---------------------------------------------------------------------------
   	DIBCONV.C --	Converts DIBs from one format to another
                						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>
#include "dibhelp.h"
#include "dibpal.h"
#include "dibconv.h"

HDIB DibConvert (HDIB hdibSrc, int iBitCountDst)
{
     	HDIB         				hdibDst ;
     	HPALETTE     			hPalette ;
     	int          				i, x, y, cx, cy, iBitCountSrc, cColors ;
     	PALETTEENTRY pe ;
     	RGBQUAD      			rgb ;
     	WORD         				wNumEntries ;

     	cx = DibWidth (hdibSrc) ;
     	cy = DibHeight (hdibSrc) ;
     	iBitCountSrc = DibBitCount (hdibSrc) ;

     	if (iBitCountSrc == iBitCountDst)
          			return NULL ;
          		// DIB with color table to DIB with larger color table:
     	if ((iBitCountSrc < iBitCountDst) && (iBitCountDst <= 8))
     	{
          		cColors = DibNumColors (hdibSrc) ;
          		hdibDst = DibCreate (cx, cy, iBitCountDst, cColors) ;

          		for (i = 0 ; i < cColors ; i++)
          		{
               				DibGetColor (hdibSrc, i, &rgb) ;
               				DibSetColor (hdibDst, i, &rgb) ;
          		}

          		for (x = 0 ; x < cx ; x++)
          		for (y = 0 ; y < cy ; y++)
          		{
               		DibSetPixel (hdibDst, x, y, DibGetPixel (hdibSrc, x, y)) ;
          		}
     	}
          		// Any DIB to DIB with no color table
     	else if (iBitCountDst >= 16)
     	{
          		hdibDst = DibCreate (cx, cy, iBitCountDst, 0) ;
          		for (x = 0 ; x < cx ; x++)
          		for (y = 0 ; y < cy ; y++)
          		{
               				DibGetPixelColor (hdibSrc, x, y, &rgb) ;
              	 			DibSetPixelColor (hdibDst, x, y, &rgb) ;
		}
     	}
          		// DIB with no color table to 8-bit DIB
     	else if (iBitCountSrc >= 16 && iBitCountDst == 8)
     	{
          			hPalette = DibPalMedianCut (hdibSrc, 6) ;
          			GetObject (hPalette, sizeof (WORD), &wNumEntries) ;

          			hdibDst = DibCreate (cx, cy, 8, wNumEntries) ;
          			for (i = 0 ; i < (int) wNumEntries ; i++)
          			{
               				GetPaletteEntries (hPalette, i, 1, &pe) ;
               				rgb.rgbRed   			= pe.peRed ;
               				rgb.rgbGreen 			= pe.peGreen ;
               				rgb.rgbBlue  			= pe.peBlue ;
               				rgb.rgbReserved 		= 0 ;

               				DibSetColor (hdibDst, i, &rgb) ;
          			}

          			for (x = 0 ; x < cx ; x++)
          			for (y = 0 ; y < cy ; y++)
          			{
               					DibGetPixelColor (hdibSrc, x, y, &rgb) ;

               					DibSetPixel (hdibDst, x, y,
                    			GetNearestPaletteIndex (hPalette, 
                         		RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))) ;
          			}
          			DeleteObject (hPalette) ;
     		}
          				// Any DIB to monochrome DIB

     		else if (iBitCountDst == 1)
     		{
          			hdibDst = DibCreate (cx, cy, 1, 0) ;
          			hPalette = DibPalUniformGrays (2) ;

          			for (i = 0 ; i < 2 ; i++)
          			{
               					GetPaletteEntries (hPalette, i, 1, &pe) ;

               					rgb.rgbRed   = pe.peRed ;
               					rgb.rgbGreen = pe.peGreen ;
               					rgb.rgbBlue  = pe.peBlue ;
               					rgb.rgbReserved = 0 ;

               					DibSetColor (hdibDst, i, &rgb) ;
          			}

          			for (x = 0 ; x < cx ; x++)
          			for (y = 0 ; y < cy ; y++)
          			{
               					DibGetPixelColor (hdibSrc, x, y, &rgb) ;

               					DibSetPixel (hdibDst, x, y,
                    			GetNearestPaletteIndex (hPalette, 
                         		RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))) ;
          			}
          			DeleteObject (hPalette) ;
     	}
          			// All non-monochrome DIBs to 4-bit DIB
     	else if (iBitCountSrc >= 8 && iBitCountDst == 4)
     	{
          			hdibDst = DibCreate (cx, cy, 4, 0) ;
          			hPalette = DibPalVga () ;

          			for (i = 0 ; i < 16 ; i++)
          			{
               					GetPaletteEntries (hPalette, i, 1, &pe) ;
               					rgb.rgbRed   				= pe.peRed ;
               					rgb.rgbGreen 			= pe.peGreen ;
               					rgb.rgbBlue  				= pe.peBlue ;
               					rgb.rgbReserved 		= 0 ;

               					DibSetColor (hdibDst, i, &rgb) ;
          			}

          			for (x = 0 ; x < cx ; x++)
          			for (y = 0 ; y < cy ; y++)
          			{
               					DibGetPixelColor (hdibSrc, x, y, &rgb) ;

               				DibSetPixel (hdibDst, x, y,
                    		GetNearestPaletteIndex (hPalette, 
                         	RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))) ;
          			}
          			DeleteObject (hPalette) ;
     	}
          			// Should not be necessary
     	else
          			hdibDst = NULL ;
     	return hdibDst ;
}

��DIB��һ�ָ�ʽת������һ�ָ�ʽ��Ҫ���ֲ�ͬ�ķ�����

Ҫ��������ɫ����DIBת������һ��Ҳ������ɫ�����нϴ��ͼ�ؿ��ȵ�DIB���༴����1λԪDIBת����4λԪ��8λԪDIB����4λԪDIBת����8λԪDIB��������Ҫ���ľ���͸������DibCreate�������µ�DIB�����ں���ʱ����ϣ����λԪ���Լ���ԭʼDIB�е���ɫ����ȵ���ɫ����Ȼ�ắʽ����ͼ��λԪ����ɫ����Ŀ��

����µ�DIBû����ɫ������λԪ����16��24��32������ôDIBֻ��Ҫ���¸�ʽ����������ͨ������DibGetPixelColor��DibSetPixelColor�����е�DIB�и���ͼ��λԪ��

�����������ܸ��ձ飺���е�DIBû����ɫ������λԪ����16��24��32�������µ�DIBÿͼ��ռ8λԪ����������£�DibConvert����DibPalMedianCut��Ϊͼ������ѻ��ĵ�ɫ�̡���DIB����ɫ���趨Ϊ��ɫ���е�RGBֵ��DibGetPixelColor��ʽ�����е�DIB�л��ͼ����ɫ��͸������GetNearestPaletteIndex��ת����8λԪDIB�е�ͼ��ֵ����͸������DibSetPixel��ͼ��ֵ���浽DIB��

��DIB��Ҫת���ɵ�ɫDIBʱ���ð���������Ŀ����ɫ�Ͱ�ɫ������ɫ�������µ�DIB�����⣬GetNearestPaletteIndex����춽�����DIB�е���ɫת����ͼ��ֵ0��1�����Ƶأ���8��ͼ��λԪ�����λԪ��DIBҪת����4λԪDIBʱ���ɴ�DibPalVga��ʽ���DIB��ɫ����ͬʱGetNearestPaletteIndexҲ����춼���ͼ��ֵ��

����DIBBLEʾ������ο�ʼдһ��ͼ������ʽ���������dz�ʽ���ỹ��û��ȫ����ɣ��������ǻ��뵽����Щ����û�мӽ�ȥ��ͷ�����Ǻܿ�ϧ���ǣ��������ڵ�ֹͣ�����о���Щ���������������۱�Ķ����ˡ�