标签:
(1)对于16、24、32位的DIB,没有颜色表,就不必创建调色板。但在8位视频模式下,只会用标准的20种保留色来显示。由DIB颜色表创建的调色板被称为“原生调色板”
(2)dwPixel =PackedDibGetPixel(pPackedDib,x,y),当这类函数多次调用时会使程序变慢。
(3)很多函数,需要对OS/2兼容DIB作不同处理。
【ShowDib3程序】——原生(Native)调色板
/*------------------------------------------------------------------ PACKEDDIB.H -- Header file for PACKDIB.C (c) Charles Petzold,1998 ------------------------------------------------------------------*/ #pragma once #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); RGBQUAD* PackedDibGetColorTableSize(BITMAPINFO* pPackedDib); RGBQUAD* PackedDibGetColorTableEntry(BITMAPINFO*, int i); BYTE* PackedDibGetBitsPtr(BITMAPINFO* pPackedDib); int PackedDibGetBitsSize(BITMAPINFO* pPackedDib); HPALETTE PackedDibCreatePalette(BITMAPINFO* pPackedDib);
//PackedDIB.c文件
/*----------------------------------------------------------------- PACKEDDIB.C -- Routines for using packed DIBs (c) Charles Petzold,1998 -----------------------------------------------------------------*/ #include <windows.h> /*--------------------------------------------------------- PackedDibLoad:将DIB文件作以紧缩型格式加载进内存中 ---------------------------------------------------------*/ BITMAPINFO* PackedDibLoad(PTSTR szFileName) { BITMAPFILEHEADER bmfh; BITMAPINFO* pbmi; HANDLE hFile; BOOL bSuccess; DWORD dwBytesRead, dwPackedDibSize; //打开文件,指定读和写属性 hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) return NULL; //读取文件头 bSuccess = ReadFile(hFile, &bmfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL); if (!bSuccess || (dwBytesRead != sizeof(BITMAPFILEHEADER)) || (bmfh.bfType != *(WORD*)"BM")) { CloseHandle(hFile); return NULL; } //计算紧缩型DIB的大小 dwPackedDibSize = bmfh.bfSize - sizeof(BITMAPFILEHEADER); //文件大小减小文件头的大小 //分配内存,并读入信息(含信息头与像素数据) pbmi = malloc(dwPackedDibSize); bSuccess = ReadFile(hFile, pbmi, dwPackedDibSize, &dwBytesRead, NULL); CloseHandle(hFile); if (!bSuccess || (dwPackedDibSize != dwBytesRead)) { free(pbmi); return NULL; } return pbmi; } /*---------------------------------------------- 获取紧缩型DIB信息的函数 ----------------------------------------------*/ int PackedDibGetWidth(BITMAPINFO* pPackedDib) { if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) return ((BITMAPCOREINFO*)pPackedDib)->bmciHeader.bcWidth; else return pPackedDib->bmiHeader.biWidth; } int PackedDibGetHeight(BITMAPINFO* pPackedDib) { if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) return ((BITMAPCOREINFO*)pPackedDib)->bmciHeader.bcHeight; else return abs(pPackedDib->bmiHeader.biHeight); //取绝对值 } int PackedDibGetBitCount(BITMAPINFO* pPackedDib) { if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) return ((BITMAPCOREINFO*)pPackedDib)->bmciHeader.bcBitCount; else return pPackedDib->bmiHeader.biBitCount; } int PackedDibGetRowLength(BITMAPINFO* pPackedDib) { return ((PackedDibGetWidth(pPackedDib)*PackedDibGetBitCount(pPackedDib) + 31) & ~31) >> 3; } /*----------------------------------------------------------- 获取DIB信息头大小(含可能的颜色遮罩)——单位:字节 -----------------------------------------------------------*/ int PackedDibGetInfoHeaderSize(BITMAPINFO* pPackedDib) { if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) return ((BITMAPCOREINFO*)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:返回信息头中的bClrUse字段,表示用到的颜色数 如果没有颜色表,则该值为0 -------------------------------------------------------------*/ int PackedDibGetColorsUsed(BITMAPINFO* pPackedDib) { if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) return 0; else return pPackedDib->bmiHeader.biClrUsed; } /*------------------------------------------------------------------ PackedDibGetNumColors:颜色表中实际的条目数 ------------------------------------------------------------------*/ int PackedDibGetNumColors(BITMAPINFO* pPackedDib) { int iNumColors; iNumColors = PackedDibGetColorsUsed(pPackedDib); //iNumColor等于0时,说明实际使用的颜色由biBitCount计算出来 //16、24、32位时获得的iNumColors的一般为0 if (iNumColors == 0 && (PackedDibGetBitCount(pPackedDib) < 16)) iNumColors = 1 << (PackedDibGetBitCount(pPackedDib)); //2^biBitCount个 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 NULL; return (RGBQUAD*)(((BYTE*)pPackedDib) + PackedDibGetInfoHeaderSize(pPackedDib)); } RGBQUAD* PackedDibGetColorTableEntry(BITMAPINFO* pPackedDib, int i) { if (PackedDibGetNumColors(pPackedDib) == 0) return NULL; if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) return (RGBQUAD*)((RGBTRIPLE*)PackedDibGetColorTablePtr(pPackedDib) + i); else return PackedDibGetColorTablePtr(pPackedDib) + i; } /*---------------------------------- PackedDibGetBitsPtr:获取像素数据的指针 ----------------------------------*/ BYTE* PackedDibGetBitsPtr(BITMAPINFO* pPackedDib) { return (BYTE*)(pPackedDib)+PackedDibGetInfoHeaderSize(pPackedDib) + PackedDibGetColorTableSize(pPackedDib); } /*----------------------------------------------------------------------- PackedDibGetBitsSize: 自动计算像素数据的空间大小(即使biSizeImage字段没有显式的指定) -----------------------------------------------------------------------*/ int PackedDibGetBitsSize(BITMAPINFO* pPackedDib) { if ((pPackedDib->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) && (pPackedDib->bmiHeader.biSizeImage != 0)) return pPackedDib->bmiHeader.biSizeImage; return PackedDibGetHeight(pPackedDib)* PackedDibGetRowLength(pPackedDib); } /*---------------------------------------------------------------- PackedDibCreatePalette:从紧缩型DIB中创建逻辑调色板 ----------------------------------------------------------------*/ HPALETTE PackedDibCreatePalette(BITMAPINFO* pPackedDib) { HPALETTE hPalette; int i, iNumColors; LOGPALETTE* plp; RGBQUAD* prgb; iNumColors = PackedDibGetNumColors(pPackedDib); if (0 == iNumColors) //16、24、32位时获得的iNumColors的一般为0 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; }
//ShowDib3.c
/*------------------------------------------------------------ SHOWDIB3.C -- Displays DIB with native palette (c) Charles Petzold, 1998 ------------------------------------------------------------*/ #include <windows.h> #include "resource.h" #include "PackedDIB.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static TCHAR szAppName[] = TEXT("ShowDib3"); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; MSG msg; WNDCLASSEX wndclass; HACCEL hAccel; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, szAppName); wndclass.hIconSm = LoadIcon(hInstance, szAppName); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName; if (!RegisterClassEx(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name TEXT("Show DIB #3:Native Palette"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters 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; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static BITMAPINFO* pPackedDib; static HPALETTE hPalette; HDC hdc; PAINTSTRUCT ps; static OPENFILENAME ofn; static TCHAR szFilter[] = TEXT("Bitmap Files(*.BMP)\0*.bmp\0") TEXT("All Files(*.*)\0*.*\0\0"); static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH]; static int cxClient, cyClient; switch (message) { case WM_CREATE: memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hwnd; ofn.lpstrFilter = szFilter; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrDefExt = TEXT("bmp"); return 0; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_FILE_OPEN: //显示打开文件对话框 if (!GetOpenFileName(&ofn)) return 0; //如果图像己经存在,则释放内存 if (pPackedDib) { free(pPackedDib); pPackedDib = NULL; } //如果逻辑调色板己经存在,则删除 if (hPalette) { DeleteObject(hPalette); hPalette = NULL; } //加载紧缩型DIB到内存中 SetCursor(LoadCursor(NULL, IDC_WAIT)); ShowCursor(TRUE); pPackedDib = PackedDibLoad(szFileName); ShowCursor(FALSE); SetCursor(LoadCursor(NULL, IDC_ARROW)); if (pPackedDib) { //创建逻辑调色板 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) //16、24、32位的DIB没有颜色表,在8位视频模式下,只显示20种保留色 { 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); }
//resource.c
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ 生成的包含文件。 // 供 ShowDIB3.rc 使用 // #define IDM_FILE_OPEN 40001 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 103 #define _APS_NEXT_COMMAND_VALUE 40004 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
//ShowDib3.rc
// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "winres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // 中文(简体,中国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""winres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Menu // SHOWDIB3 MENU BEGIN POPUP "&File" BEGIN MENUITEM "&Open...\tCtrl+O", IDM_FILE_OPEN END END ///////////////////////////////////////////////////////////////////////////// // // Accelerator // SHOWDIB3 ACCELERATORS BEGIN "^O", IDM_FILE_OPEN, ASCII, NOINVERT END #endif // 中文(简体,中国) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED
(1)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种保留色之一)
(2)216种颜色,R、G、B分别由0x00、0x33、0x66、0x99、0xCC、0xFF的所有组合。(其中8种是系统20种保留色中的颜色,还有4种是前面灰度值的重复)。
【ShowDib4程序】——效果图与ShowDib3相似,但细节上有差异,还有在8位视频模式下,该程序正常显示!
256色下效果
/*------------------------------------------------------------ SHOWDIB4.C -- Displays DIB with “all - purpose” palette (c) Charles Petzold, 1998 ------------------------------------------------------------*/ #include <windows.h> #include "..\\ShowDib3\\resource.h" #include "..\\ShowDib3\\PackedDIB.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static TCHAR szAppName[] = TEXT("ShowDib4"); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; MSG msg; WNDCLASSEX wndclass; HACCEL hAccel; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, szAppName); wndclass.hIconSm = LoadIcon(hInstance, szAppName); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName; if (!RegisterClassEx(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name TEXT("Show DIB #4:All-Purpose Palette"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters 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; } /*------------------------------------------------------------------------ CreateAllPurposePalette: 创建一个通用的调色板,该调色板共有247个颜色条目,其中15种是从20种保留色中 复出或匹配的。 ------------------------------------------------------------------------*/ HPALETTE CreateAllPurposePalette(void) { HPALETTE hPalette; LOGPALETTE* plp; int i, incr, R, G, B; plp = malloc(sizeof(LOGPALETTE) + 246 * sizeof(PALETTEENTRY)); plp->palVersion = 0x0300; plp->palNumEntries = 247; //创建31级的灰阶颜色,其中3种匹配系统的20种保留色 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); } //创建216种颜色,但其中有8种匹配系统的20种保留色,另外4种匹配以上产生的灰色 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; HDC hdc; PAINTSTRUCT ps; static OPENFILENAME ofn; static TCHAR szFilter[] = TEXT("Bitmap Files(*.BMP)\0*.bmp\0") TEXT("All Files(*.*)\0*.*\0\0"); static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH]; static int cxClient, cyClient; switch (message) { case WM_CREATE: memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hwnd; ofn.lpstrFilter = szFilter; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrDefExt = TEXT("bmp"); // 创建通用调色板 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: //显示打开文件对话框 if (!GetOpenFileName(&ofn)) return 0; //如果图像己经存在,则释放内存 if (pPackedDib) { free(pPackedDib); pPackedDib = NULL; } //如果逻辑调色板己经存在,则删除 if (hPalette) { DeleteObject(hPalette); hPalette = NULL; } //加载紧缩型DIB到内存中 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: 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 ((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); DeleteObject(hPalette); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
16.3.3 半色调调色板——使用抖动模式,来更好地在8位视频上模拟原始图像的颜色。
(1)系统提供API来创建半色调的调色板
hPalette= CreateHalftonePalette(hdc);
(2)当使用SetDIBitsToDevice来显示DIB时,效果与ShowDib4程序差不多
(3)使用StretchDIBits效果会很明显,但须先设置
SetStretchBltMode(hdc,HALFTONE);
SetBrushOrgEx(hdc,x,y,NULL);//x、y是DIB左上角的设备坐标。
【ShowDib5程序】
256色下的效果(要比通用调色板效果好得多)
/*------------------------------------------------------------ SHOWDIB5.C -- Displays DIB with halftone palette (c) Charles Petzold, 1998 ------------------------------------------------------------*/ #include <windows.h> #include "..\\ShowDib3\\resource.h" #include "..\\ShowDib3\\PackedDIB.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static TCHAR szAppName[] = TEXT("ShowDib5"); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; MSG msg; WNDCLASSEX wndclass; HACCEL hAccel; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, szAppName); wndclass.hIconSm = LoadIcon(hInstance, szAppName); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName; if (!RegisterClassEx(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name TEXT("Show DIB #5:Halftone Palette"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters 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; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static BITMAPINFO* pPackedDib; static HPALETTE hPalette; HDC hdc; PAINTSTRUCT ps; static OPENFILENAME ofn; static TCHAR szFilter[] = TEXT("Bitmap Files(*.BMP)\0*.bmp\0") TEXT("All Files(*.*)\0*.*\0\0"); static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH]; static int cxClient, cyClient; switch (message) { case WM_CREATE: memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hwnd; ofn.lpstrFilter = szFilter; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrDefExt = TEXT("bmp"); // 创建通用调色板 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: //显示打开文件对话框 if (!GetOpenFileName(&ofn)) return 0; //如果图像己经存在,则释放内存 if (pPackedDib) { free(pPackedDib); pPackedDib = NULL; } //如果逻辑调色板己经存在,则删除 if (hPalette) { DeleteObject(hPalette); hPalette = NULL; } //加载紧缩型DIB到内存中 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) { //设置半色板模式 SetStretchBltMode(hdc, HALFTONE); SetBrushOrgEx(hdc, 0, 0, NULL); //选择并实现调色板 SelectPalette(hdc, hPalette, FALSE); RealizePalette(hdc); //用StretchDIBits而不是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: 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 ((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); DeleteObject(hPalette); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
标签:
原文地址:http://www.cnblogs.com/5iedu/p/4701023.html