16.4.1自定义的 DIBSTRUCT结构体
字段 |
含义 |
PBYTE *ppRow |
①指向位图视觉上最上面的一行像素。(不管是自下而上,还是自上而下) ②放在第一个字段,为的是后面定义宏时可方便访问到 |
int iSignature |
=“Dib ”,是这个结构体的标志 |
HBITMAP hBitmap |
存储了由CreateDIBSection返回的位图句柄(注意,实质是DIB,但兼有DDB的特点,可直接BitBlt) |
BYTE *pBits |
指向像素阵列的指针,其指针值在CreateDIBSection中设定,而所指向的内存由操作系统管理,删除位图句柄后会自动释放。 |
DIBSECTION |
在DibCreateFromInfo中调用GetObject来填充该结构体,以方便使用(注意DibCreateFromInfo函数被本例所有创建DIB的函数所调用)。 |
int iRShift[3] |
是个数组,3个元素分别为R、G、B颜色遮罩需右移的位数 |
int iLShift[3] |
是个数组,3个元素分别为R、G、B颜色遮罩需左移的位数 |
16.4.2 信息获取函数
(1)DibIsValid函数——用来确保DIBSTRUCT结构的有效性
(2)DibIsAddressable(也可定义为DibIsNotCompression):判断位图是否被压缩
(3)DibInfoHeaderSize等一组函数用于获取DIB区块各部分大小,这些函数可用来将一个DIB Section转换为紧凑DIB。
(4)获得各类指针的函数:如DibInfoHeaderPtr(获取BITMAPINFOHEADER指针)
16.4.3 读写像素信息
(1)DibPixelPtr:用来获取像素的内存指针。注意DIBSTRUCT结构的ppRow是一个指向从上向下排列的DIB像素行的指针,即ppRow[0]是位图视觉上的最上面的一行。如果位图被压缩时返回NULL。
(2)DibGetColor和DibSetColor:像素点在颜色表的值。对于1、4、8位,其RGB值就是要通过颜色表来查找。(对于16、24、32位的,不能通过这两个函数获取,其RGB值要通过掩码和位移获得)
16.4.4 创建和转换
(1)DibCreateFromInfo函数:是DIBHELP库中唯一一个调用CreateDIBSection并为DIBSTRUCT分配内存的函数。其他所有创建或复制都要通过调用该函数来完成。
①参数:BITMAPINFO结构的指针
②该函数调用CreateDIBSeciton后会初始化DIBSTRUCT的所有字段,第一个字段ppRow总是指向DIB的最上面的一行。
(2)DibDelete用来删除由DibCreateFromInfo创建的位图,并释放内存。
(3)DibCopyToPackedDib和DibCopyFromPackedDib常用于应用程序与剪贴板交换DIB
(4)DibCopyToDdb:从一个DIB创建一个GDI位图对象。
16.4.5 宏——快速读写像素位的宏(在DIBHELP.H头文件中)
16.4.6 Dibble程序
(1)三个重要的静态变量hdib、hPalette、hBitmap
(2)WM_USER_SETSCROLL和WM_USER_CREATEPAL消息:用来重置滚动条和创建调色板
(3)DisplayDib:显示位图,提供正常、居中、满拉到客户区、各向同性等4种方式。
①WM_PAINT消息中:位图句柄来自于DibCopyToDdb函数。(因可能要用调色板来显示)
②打印时:从DitbitmapHandle得到DIB Section位图的句柄。
(4)剪贴板:调用DibCopyToPackedDib和DibCopyFromPackedDib函数
(5)Flip函数——上下翻转;Rotate——顺时针转90度。
①DibFlipHorizontal函数:演示通过DibGetPixel和DibSetPixel,效率较低
②DibRotateRight函数:通过DIBHELP.H中定义的宏来读写像素,效率高。
16.4.7 简单的调色板和优化的调色板——在256色的视频模式下,可选择不同调色板
(1)创建调色板的函数
①半色调调色板——系统API提供的。会使用万能调色板与抖动技术来实现该调色板。
②DibPalDibTable:根据DIB颜色表来创建调色板
③DibPalAllPurpose:创建通用的调色板,其颜色见DibPal.C文件
④DibPalUniformGrays:创建一个只有灰度色阶的调色板
(2)优化调色板
①均匀分布算法:DibPalUniformColors——创建iNumR×iNumG×iNumB调色板,一般8级红色、8级绿色和4级蓝色,因为人眼为蓝色比较不敏感。
②流行度算法——DibPalPopularity函数
A、使用位图中被使用最多的256种RGB色值来构成调色板。但24位RGB,可表示2^24种颜色,如果每种颜色用1个int型保存使用次数的话,共需要64M左右,内存消耗大。
B、解决办法是只用RGB权重最高的几位,如用6位而非8位表示R值(因为显示器的解析度也是6位)。这样只需1M,而5位时只需32768字节。
③中分算法——DibPalMedianCut(PaulHeckbert发明)
A、中分算法中RGB值被映射到一个三维坐标中,三个坐标轴分别表示R、G、B
B、每个像素点的RGB值都能在这个坐标系中找到相应的点
C、找到一个能包含所有图像像素的长方体,取最长的一条边,将长方体分成两部分,使划分后的每个部分含有相同的像素数量。
D、然后对这两个盒子做同样的划分,这样2个分为4个、4个分为8个,8个分为16个,然后是32个,64个、128个、256个。
E、现在得到256个盒子,每个都包含了相等的像素数。对每个盒子的颜色取其平均值,并利用这个结构来改变调色板。
16.4.8 格式转换——参考DIbConv.c文件
(1)GetNearestPaletteIndex返回获得调色板中最接近的颜色的索引值
UINT GetNearestPaletteIndex
(
HPALETTE hpal, // 逻辑调色板
COLORREF crColor // 要匹配的颜色
)
(2)DibPalVga:获取标准16色显示器颜色值
(3)HDIBDibConvert(HDIB hdibSrc, int iBitCountDst);用来进行格式转换的函数
【Dibble程序】
效果图
//Dibble.c主程序
/*------------------------------------------------------------ DIBBLE.C -- Bitmap and Palette Program (c) Charles Petzold, 1998 ------------------------------------------------------------*/ #include <windows.h> #include "resource.h" #include "DibHelp.h" #include "DibConv.h" #include "DibPal.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); static TCHAR szAppName[] = TEXT("Dibble"); 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 szAppName, // window caption WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, // 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; } /*------------------------------------------------------------------------------- DisplayDib:根据菜单项的选择来显示(打印)DIB的实际大小图像或缩放的图像 --------------------------------------------------------------------------------*/ 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); iReturn = BitBlt(hdc, 0, 0, cxBitmap, cyBitmap, hdcMem, 0, 0, SRCCOPY); break; } DeleteDC(hdcMem); RestoreDC(hdc, -1); return iReturn; } /*------------------------------------------------------------------------------- PaletteMenu:设置“Palette”各菜单项的Check属性 --------------------------------------------------------------------------------*/ 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 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"); static TCHAR* szCompression[] = { TEXT("BI_RGB"), TEXT("BI_RLE8"), TEXT("BI_RLE4"), TEXT("BI_BITFIELDS"), TEXT("Unknown") }; static HDIB hdib; static HPALETTE hPalette; static HBITMAP hBitmap; static BOOL fHalftonePalette; static HMENU hMenu; BOOL fSuccess; static int cxClient, cyClient, iHscroll, iVscroll; static WORD wShow = IDM_SHOW_NORMAL; static PRINTDLG printdlg = { sizeof(PRINTDLG) }; static DOCINFO di = { sizeof(DOCINFO), TEXT("Dibble:Printing") }; int cxPage, cyPage; HDC hdc, hdcPrn; HGLOBAL hGlobal; BYTE* pGlobal; HDIB hdibNew; PAINTSTRUCT ps; SCROLLINFO si; int iEnable, iConvert = 0; TCHAR szBuffer[256]; switch (message) { case WM_CREATE: //将菜单句柄保存在静态变量hMenu中 hMenu = GetMenu(hwnd); //初始化打开文件对话框 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.Flags = OFN_OVERWRITEPROMPT; ofn.lpstrDefExt = TEXT("bmp"); return 0; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); wParam = FALSE; //贯穿功能,继续执行下面的代码 //用户自定义消息,设置滚动条,如果显示模式是正常模式,则隐藏滚动条。如果 //wParam==TRUE,则复位滚动条的位置 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 { //垂直滚动条 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) //恢复到0的默认位置 si.nPos = 0; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); GetScrollInfo(hwnd, SB_VERT, &si); iVscroll = si.nPos; //水平滚动条 GetScrollInfo(hwnd, SB_HORZ, &si); si.nMin = 0; si.nMax = DibWidth(hdib); si.nPage = cxClient; if ((BOOL)wParam) //恢复到0的默认位置 si.nPos = 0; SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); GetScrollInfo(hwnd, SB_HORZ, &si); iHscroll = si.nPos; } return 0; 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.nPage -= si.nPage; break; case SB_PAGEDOWN: si.nPage += 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; 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.nPage -= si.nPage; break; case SB_PAGERIGHT: si.nPage += 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; 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; case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_FILE_OPEN: //显示“打开文件”对话框 if (!GetOpenFileName(&ofn)) return 0; //如果DIB和调色板己经存在,则删除它们 SendMessage(hwnd, WM_USER_DELETEDIB, 0, 0); //加载DIB文件到内存 SetCursor(LoadCursor(NULL, IDC_WAIT)); ShowCursor(TRUE); hdib = DibFileLoad(szFileName); SetCursor(LoadCursor(NULL, IDC_ARROW)); ShowCursor(FALSE); //重置滚动条 SendMessage(hwnd, WM_USER_SETSCROLLS, TRUE, 0); //创建调色板和DDB SendMessage(hwnd, WM_USER_CREATEPAL, TRUE, 0); //根据调色板,创建DDB——hBitmap if (!hdib) { MessageBox(hwnd, TEXT("Cannot load DIB file!"), szAppName, MB_OK | MB_ICONEXCLAMATION); } InvalidateRect(hwnd, NULL, TRUE); return 0; case IDM_FILE_SAVE: //打开“保存”对话框 if (!GetSaveFileName(&ofn)) return 0; //将DIB保存到文件中 SetCursor(LoadCursor(NULL, IDC_WAIT)); ShowCursor(TRUE); fSuccess = DibFileSave(hdib, szFileName); SetCursor(LoadCursor(NULL, IDC_ARROW)); ShowCursor(FALSE); if (!fSuccess) { MessageBox(hwnd, TEXT("Cannot Save DIB file!"), szAppName, MB_OK | MB_ICONEXCLAMATION); } return 0; case IDM_FILE_PRINT: if (!hdib) return 0; //获得打印机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; } //检查打印机是否支持打印位图 if (!(RC_BITBLT & GetDeviceCaps(hdcPrn, RASTERCAPS))) { DeleteDC(hdcPrn); MessageBox(hwnd, TEXT("Printer cannot print bitmaps"), szAppName, MB_ICONEXCLAMATION | MB_OK); return 0; } //获取打机印的可打印区域 cxPage = GetDeviceCaps(hdcPrn, HORZRES); cyPage = GetDeviceCaps(hdcPrn, VERTRES); fSuccess = FALSE; //将DIB发送到打印机 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("Cannot print bitmaps"), szAppName, MB_ICONEXCLAMATION | MB_OK); return 0; case IDM_FILE_PROPERTIES: if (!hdib) return 0; wsprintf(szBuffer, TEXT("Pixel width:\t%i\n") //%i与%d一样的 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; //剪切时,继续执行下去 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); //如果己经存在DIB位图和调色板,则删除它们 if (pGlobal) { SendMessage(hwnd, WM_USER_DELETEDIB, 0, 0); hdib = DibCopyFromPackedDib((BITMAPINFO*)pGlobal); SendMessage(hwnd, WM_USER_CREATEPAL, TRUE, 0); } GlobalUnlock(hGlobal); CloseClipboard(); //重置滚动条 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_STRETCH: case IDM_SHOW_CENTER: case IDM_SHOW_ISOSTRETCH: CheckMenuItem(hMenu, wShow, MF_UNCHECKED); wShow = LOWORD(wParam); CheckMenuItem(hMenu, wShow, MF_CHECKED); SendMessage(hwnd, WM_USER_SETSCROLLS, TRUE, 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; } //其余所有的WM_COMMAND消息都是来自调色板项目。如果删除己经存在的调色板,光标将被 //设置为沙漏的形状 SendMessage(hwnd, WM_USER_DELETEPAL, 0, 0); SetCursor(LoadCursor(NULL, IDC_WAIT)); ShowCursor(TRUE); //提醒,所有的调色板消息都以break结束而不是return,这允许后面进行一些额外的处理 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; } //当处理完菜单中的调色板项目后,光标恢复为箭头的形状,该项被设为Checked,并 //且刷新客户区 hBitmap = DibCopyToDdb(hdib, hwnd, hPalette); ShowCursor(FALSE); SetCursor(LoadCursor(NULL, IDC_ARROW)); if (hPalette) PaletteMenu(hMenu, (LOWORD(wParam))); InvalidateRect(hwnd, NULL, TRUE); return 0; //WM_COMMAND消息处理完毕 //该消息中删除一个己经存在的DIB,为获取一个新DIB作准备。 //该消息会被打开、粘贴或其它菜单命令所调用 case WM_USER_DELETEDIB: if (hdib) { DibDelete(hdib); hdib = NULL; } SendMessage(hwnd, WM_USER_DELETEPAL, 0, 0); return 0; //基于一个新DIB创建一个调色板。如果wParam==TRUE,则同时创建DDB case WM_USER_CREATEPAL: if (hdib) { hdc = GetDC(hwnd); if (!(RC_PALETTE & GetDeviceCaps(hdc, RASTERCAPS))) //不支持调色调 { PaletteMenu(hMenu, IDM_PAL_NONE); } 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_USER_DELETEPAL: if (hPalette) { DeleteObject(hPalette); hPalette = NULL; fHalftonePalette = FALSE; PaletteMenu(hMenu, IDM_PAL_NONE); } if (hBitmap) { DeleteObject(hBitmap); } 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) return FALSE; 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); }
//resource.h
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ 生成的包含文件。 // 供 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_CONVERT_01 40040 #define IDM_CONVERT_04 40041 #define IDM_CONVERT_08 40042 #define IDM_CONVERT_16 40043 #define IDM_CONVERT_24 40044 #define IDM_CONVERT_32 40045 #define IDM_APP_ABOUT 40046 #define IDM_PAL_OPT_POP4 40047 #define IDM_PAL_OPT_POP5 40048 #define IDM_PAL_OPT_POP6 40049 #define IDM_PAL_OPT_MEDCUT 40050 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 103 #define _APS_NEXT_COMMAND_VALUE 40040 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
//Dibble.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 // DIBBLE MENU 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×2G×2B (8)", IDM_PAL_RGB222 MENUITEM "&2. 3R×3G×3B (27)", IDM_PAL_RGB333 MENUITEM "&3. 4R×4G×4B (64)", IDM_PAL_RGB444 MENUITEM "&4. 5R×5G×5B (125)", IDM_PAL_RGB555 MENUITEM "&5. 6R×6G×6B (216)", IDM_PAL_RGB666 MENUITEM "&6. 7R×7G×5B (245)", IDM_PAL_RGB775 MENUITEM "&7. 7R×5G×7B (245)", IDM_PAL_RGB757 MENUITEM "&8. 5R×7G×7B (245)", IDM_PAL_RGB577 MENUITEM "&9. 8R×8G×4B (256)", IDM_PAL_RGB884 MENUITEM "&A. 8R×4G×8B (256)", IDM_PAL_RGB848 MENUITEM "&B. 4R×8G×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 (4 bits)", 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 bit per pixel", IDM_CONVERT_08 MENUITEM "&4. to 16 bits per Pixel", IDM_CONVERT_16 MENUITEM "&5. to 24 bit 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 BEGIN "C", IDM_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT "X", IDM_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT VK_DELETE, IDM_EDIT_DELETE, VIRTKEY, NOINVERT "V", IDM_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT "O", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT "P", IDM_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT "S", IDM_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT END #endif // 中文(简体,中国) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/*-------------------------------------------------------- DIBHELP.H Header file for DIBHELP.C --------------------------------------------------------*/ #pragma once #include <windows.h> typedef void* HDIB; //DIBHELP.C中的函数 BOOL DibIsValid(HDIB hdib); //Dib文件是否有效 HBITMAP DibBitmapHandle(HDIB hdib); int DibWidth(HDIB hdib); int DibHeight(HDIB hdib); int DibBitCount(HDIB hdib); int DibRowLength(HDIB hdib); //每行像素数:4的倍数 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); //获取biCompression字段的值 BOOL DibIsAddressable(HDIB hdib);//是否被压缩,DibIsNotCompressed 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 fUsedGlobal); 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); //该函数课本没有给出实现 /*---------------------------------------------------------- DibFlipHorizontal:调用没有优化的DibSetPixel和DibGetPixel ----------------------------------------------------------*/ HDIB DibFlipHorizontal(HDIB hdibSrc); /*---------------------------------------------------------- DibRotateRight:调用优化过的DibSetPixelx和DibGetPixelx ----------------------------------------------------------*/ HDIB DibRotateRight(HDIB hdibSrc); /*---------------------------------------------------------- 快速无边界检查的gets和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)
//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; //像素位的行指针,必须是第一个字段,为后面的宏操作更容易设计的。 //第一个指针指向DIB位图视觉上最上面的一行像素,最后一个指针指向 //DIB图像最后一行的像素,和pBits字段一样(也就是pBits也要被存成 //这样的格式) int iSignature; //="Dib " HBITMAP hBitmap;//接收从CreateDIBSection返回的句柄,明显返回的是设备无关的位图, //但可以直接被BitBlt或StretchBlt BYTE* pBits; //指向位图的像素数据,其值在CreateDIBSection函数中被设定。其所指 //的内存块由操作系统管理,但应用程序可以访问该内存块。删除位图 //句柄后,该内存块自动被删除 DIBSECTION ds; //可以用GetObject获得位图信图,存入该结构体 int iRShift[3]; //分别存入R、G、B3种颜色遮罩需左移的值 int iLShift[3]; // }DIBSTRUCT, *PDIBSTRUCT; /*---------------------------------------------------------------------------------- DibIsValid:如果hdib指向一个有效的DIBSTRUCT结构体时返回TRUE -----------------------------------------------------------------------------------*/ BOOL DibIsValid(HDIB hdib) { DIBSTRUCT* pdib = hdib; if (pdib == NULL) return FALSE; //检查是否有读取指定内存的内容的权限,参数1为要检查的内存指针,参数2为要检查的内存块大小 if (IsBadReadPtr(pdib, sizeof(DIBSTRUCT))) return FALSE; if (pdib->iSignature != HDIB_SIGNATURE) //自定义的DIB位图标识符 return FALSE; return TRUE; } /*---------------------------------------------------------------------------------- DibBitmapHandle:返回DIB Section位图对象的句柄hBitmap -----------------------------------------------------------------------------------*/ HBITMAP DibBitmapHandle(HDIB hdib) { if (!DibIsValid(hdib)) return NULL; return ((PDIBSTRUCT)hdib)->hBitmap; } /*---------------------------------------------------------------------------------- DibWidth:返回位图的宽度(单位字节) -----------------------------------------------------------------------------------*/ int DibWidth(HDIB hdib) { if (!DibIsValid(hdib)) return 0; return ((PDIBSTRUCT)hdib)->ds.dsBm.bmWidth; } /*---------------------------------------------------------------------------------- DibHeight:返回位图的高度(单位字节) -----------------------------------------------------------------------------------*/ int DibHeight(HDIB hdib) { if (!DibIsValid(hdib)) return 0; return ((PDIBSTRUCT)hdib)->ds.dsBm.bmHeight; } /*---------------------------------------------------------------------------------- DibBitCount:返回每像素的位数 -----------------------------------------------------------------------------------*/ int DibBitCount(HDIB hdib) { if (!DibIsValid(hdib)) return 0; return ((PDIBSTRUCT)hdib)->ds.dsBm.bmBitsPixel; } /*---------------------------------------------------------------------------------- DibRowLength:返回每行像素的大小(单位:字节):4的倍数 -----------------------------------------------------------------------------------*/ int DibRowLength(HDIB hdib) { if (!DibIsValid(hdib)) return 0; return 4 * ((DibWidth(hdib)*DibBitCount(hdib) + 31) / 32); } /*---------------------------------------------------------------------------------- DibNumColors:返回颜色表的颜色数目,无颜色表时返回0 -----------------------------------------------------------------------------------*/ 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); //2^bBitCount,如1位则2种颜色,8位256色 } return 0; } /*---------------------------------------------------------------------------------- DibMask:返回3种颜色遮罩其中的一种,如红色遮罩 -----------------------------------------------------------------------------------*/ DWORD DibMask(HDIB hdib, int i) { PDIBSTRUCT pdib = hdib; if (!DibIsValid(hdib) || i<0 || i>2) return 0; return pdib->ds.dsBitfields[i];//0—红色;1—绿色;2—蓝色 } /*---------------------------------------------------------------------------------- DibRShift:返回需右移的位数 -----------------------------------------------------------------------------------*/ int DibRShift(HDIB hdib, int i) { PDIBSTRUCT pdib = hdib; if (!DibIsValid(hdib) || i<0 || i>2) return 0; return pdib->iRShift[i]; } /*---------------------------------------------------------------------------------- DibLShift:返回需左移的位数 -----------------------------------------------------------------------------------*/ int DibLShift(HDIB hdib, int i) { PDIBSTRUCT pdib = hdib; if (!DibIsValid(hdib) || i<0 || i>2) return 0; return pdib->iLShift[i]; } /*---------------------------------------------------------------------------------- DibCompression: 获取biCompression字段的值 -----------------------------------------------------------------------------------*/ int DibCompression(HDIB hdib) { if (!DibIsValid(hdib)) return 0; return ((PDIBSTRUCT)hdib)->ds.dsBmih.biCompression; } //是否被压缩,DibIsNotCompressed /*---------------------------------------------------------------------------------- DibIsAddressable: 如果DIB没压缩则返回TRUE -----------------------------------------------------------------------------------*/ BOOL DibIsAddressable(HDIB hdib) { int iCompression; if (!DibIsValid(hdib)) return 0; iCompression = DibCompression(hdib); if (iCompression == BI_RGB || iCompression == BI_BITFIELDS) return TRUE; return FALSE; } /*---------------------------------------------------------------------------------- 下面这些函数返回DIB Section可能出现的各种变量信息,这些函数的目的是为了将DIB Section 转换为紧凑DIB或保存文件时使用 -----------------------------------------------------------------------------------*/ DWORD DibInfoHeaderSize(HDIB hdib) //文件信息头BITMAPINFOHEADER(不含颜色遮罩、颜色表)等 { 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) //整个紧凑型DIB的大小 { return DibInfoSize(hdib) + DibBitsSize(hdib); } /*---------------------------------------------------------------------------------- 下面这些函数返回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 NULL; return pdib->ds.dsBitfields;//因为这个字段是个数组,数组名是个指针。 } void* DibBitsPtr(HDIB hdib) { if (!DibIsValid(hdib)) return NULL; return ((PDIBSTRUCT)hdib)->pBits; } /*---------------------------------------------------------------------------------- DibGetColor:从DIB颜色表中获得指定索引号处的颜色,放在prgb结构体中 -----------------------------------------------------------------------------------*/ BOOL DibGetColor(HDIB hdib, int index, RGBQUAD* prgb) { PDIBSTRUCT pdib = hdib; HDC hdcMem; int iReturn; if (!DibIsValid(hdib)) return FALSE; hdcMem = CreateCompatibleDC(NULL); SelectObject(hdcMem, pdib->hBitmap); iReturn = GetDIBColorTable(hdcMem, index, 1, prgb); //API函数 DeleteDC(hdcMem); return iReturn ? TRUE : FALSE; } /*---------------------------------------------------------------------------------- DibSetColor:prgb结构体颜色设置到DIB颜色表中 -----------------------------------------------------------------------------------*/ BOOL DibSetColor(HDIB hdib, int index, RGBQUAD*prgb) { PDIBSTRUCT pdib = hdib; HDC hdcMem; int iReturn; if (!DibIsValid(hdib)) return FALSE; hdcMem = CreateCompatibleDC(NULL); SelectObject(hdcMem, pdib->hBitmap); iReturn = SetDIBColorTable(hdcMem, index, 1, prgb); //API函数 DeleteDC(hdcMem); return iReturn ? TRUE : FALSE; } /*---------------------------------------------------------------------------------- DibPixelPtr:返回(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; //x每次加1时,指针后移BitCount/8个字节,所以对于每像素1或4位时, //获取每个字节的像素还需移位才能读出像素值 //对于8、16、24或32位的,每bitCount/8个字节 //具体的处理 见DibGetPixel或DibSetPixel函数的处理。 return (((PDIBSTRUCT)hdib)->ppRow)[y] + (x* DibBitCount(hdib) >> 3); } /*---------------------------------------------------------------------------------- DibGetPixel:返回(x,y)处的像素值 -----------------------------------------------------------------------------------*/ DWORD DibGetPixel(HDIB hdib, int x, int y) { PBYTE pPixel; pPixel = DibPixelPtr(hdib, x, y); if (!pPixel) return 0; switch (DibBitCount(hdib)) { //快速求余法:X % (2^N) == X & (2^N - 1), case 1: return 0x01 & (*pPixel >> (7 - (x & 7))); case 4: return 0x0F & (*pPixel >> (x & 1 ? 0 : 4));//x为奇数是,取低4位,偶数取高4位 case 8: return *pPixel; case 16:return *(WORD*)pPixel; case 24:return 0x00FFFFFF & *(DWORD*)pPixel; case 32:return *(DWORD*)pPixel; } return 0; } /*---------------------------------------------------------------------------------- DibSetPixel:设置(x,y)处的像素值 -----------------------------------------------------------------------------------*/ BOOL DibSetPixel(HDIB hdib, int x, int y, DWORD dwPixel) { PBYTE pPixel; pPixel = DibPixelPtr(hdib, x, y); if (!pPixel) return FALSE; switch (DibBitCount(hdib)) { case 1: *pPixel &= ~(1 << (7 - (x & 7))); //取出该字节中除x处外的其余像素数 *pPixel |= dwPixel << (7 - (x & 7));//将颜色值加入上述的X处。 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:获得(x,y)处的颜色值,并放入prgb所指的结构体中 -----------------------------------------------------------------------------------*/ BOOL DibGetPixelColor(HDIB hdib, int x, int y, RGBQUAD* prgb) { DWORD dwPixel; int iBitCount; PDIBSTRUCT pdib = hdib; //获得每像素位的大小,也可以使用它来作有效性验证 if (0 == (iBitCount = DibBitCount(hdib))) return FALSE; //获取像素位的值,返回DWORD,该值可能是索引或里面含有RGB值 dwPixel = DibGetPixel(hdib, x, y); //如果是8位或以下的,该值为颜色表索引 if (iBitCount <= 8) return DibGetColor(hdib, (int)dwPixel, prgb); else if (iBitCount == 24) { *(RGBTRIPLE*)prgb = *(RGBTRIPLE*)&dwPixel; prgb->rgbReserved = 0; } else if (iBitCount == 32 && pdib->ds.dsBmih.biCompression == BI_RGB) { *prgb = *(RGBQUAD*)&dwPixel; } //此外的情况,使用颜色遮罩和移位 else { //下面等号右边的式子,执行顺序先用掩码取出dwPixel的相应颜色,再右移,最后左移。 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:获得(x,y)处的颜色值 -----------------------------------------------------------------------------------*/ BOOL DibSetPixelColor(HDIB hdib, int x, int y, RGBQUAD* prgb) { DWORD dwPixel; int iBitCount; PDIBSTRUCT pdib = hdib; //不要利用DIBs的颜色表来执行该函数的操作 iBitCount = DibBitCount(hdib); if (iBitCount <= 8) return FALSE; //剩下来的步骤与GetPixelColor相反 else if (iBitCount == 24) { *(RGBTRIPLE*)&dwPixel = *(RGBTRIPLE*)prgb; dwPixel &= 0x00FFFFFF; } else if (iBitCount == 32 && pdib->ds.dsBmih.biCompression == BI_RGB) { *(RGBQUAD*)&dwPixel = *prgb; } else { //先将rgbRed由字节转为DWORD,再右移,最后左移 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; } /*---------------------------------------------------------------------------------- 根据遮罩颜色计算移位值,这些颜色遮罩来自于DibCreateFromInfo函数 -----------------------------------------------------------------------------------*/ static int MaskToRShift(DWORD dwMask) { int iShift; if (0 == dwMask) return 0; for (iShift = 0; !(dwMask & 1); iShift++) //最低位为0,则右移1位 dwMask >>= 1; return iShift; } static int MaskToLShift(DWORD dwMask) { int iShift; if (0 == dwMask) return 0; while (!(dwMask & 1)) //dwMask右侧的0移掉 dwMask >>= 1; for (iShift = 0; dwMask & 1; iShift++) //统计1的个数 dwMask >>= 1; return 8 - iShift; } /*---------------------------------------------------------------------------------- DibCreateFromInfo: 所有创建DIB的函数最后都要调用该函数。这个函数负责调用CreateDIBSection, 为DIBSTRUCT分配内存,并设置行指针 -----------------------------------------------------------------------------------*/ HDIB DibCreateFromInfo(BITMAPINFO* pbmi) { DIBSTRUCT* pdib; BYTE* pBits; HBITMAP hBitmap; int i, y, cy, iRowLength; //根据pbmi创建DIB Section位图,pBits指向今后要存入的像素位的空间地址(由系统管理) hBitmap = CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0); if (NULL == hBitmap) return NULL; if (NULL == (pdib = malloc(sizeof(DIBSTRUCT)))) { DeleteObject(hBitmap); return NULL; } pdib->iSignature = HDIB_SIGNATURE; pdib->hBitmap = hBitmap; pdib->pBits = pBits; //填充DIBSECTION结构 GetObject(hBitmap, sizeof(DIBSECTION), &pdib->ds); //现在可以使用自定义的DIB信息函数,如DibCompression //如果压缩格式是BI_BITFIELDS,则计算掩码的移位 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]); } } //如果是BI_RGB,但是16位或32位的,则设置bitFields和masks字段 else if (DibCompression(pdib) == BI_RGB) { if (DibBitCount(pdib) == 16) //RGB分别使用5-5-5型遮罩 { pdib->ds.dsBitfields[0] = 0x00007C00; //R Mask pdib->ds.dsBitfields[1] = 0x000003E0; //G Mask pdib->ds.dsBitfields[2] = 0x0000001F; //B Mask 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) //使用8-8-8型 { pdib->ds.dsBitfields[0] = 0x00FF0000; //R Mask pdib->ds.dsBitfields[1] = 0x0000FF00; //G Mask pdib->ds.dsBitfields[2] = 0x000000FF; //B Mask pdib->iRShift[0] = 16; pdib->iRShift[1] = 8; pdib->iRShift[2] = 0; pdib->iLShift[0] = 0; pdib->iLShift[1] = 0; pdib->iLShift[2] = 0; } } //分配DIB像素行指针数组 cy = DibHeight(pdib); pdib->ppRow = malloc(cy*sizeof(BYTE*)); if (NULL == pdib->ppRow) { free(pdib); DeleteObject(hBitmap); return NULL; } //初始化像素行指针数组,ppRow[0]设为图像视觉上的最顶行。 iRowLength = DibRowLength(pdib); if (pbmi->bmiHeader.biHeight>0) //位图从下到上存储 { for (y = 0; y < cy; y++) pdib->ppRow[y] = pBits + (cy - 1 - y)*iRowLength; } else //从上到下存储 { for (y = 0; y < cy; y++) pdib->ppRow[y] = pBits + y*iRowLength; } return pdib; } /*---------------------------------------------------------------------------------- DibDelete:删除DIBSTRUCT和在其中分配的内存 -----------------------------------------------------------------------------------*/ BOOL DibDelete(HDIB hdib) { DIBSTRUCT* pdib = hdib; if (!DibIsValid(hdib)) return FALSE; free(pdib->ppRow); DeleteObject(pdib->hBitmap); free(pdib); return TRUE; } /*----------------------------------------------------------------------------------- DibCreate: 通过显式指定参数来构建HDIB() -----------------------------------------------------------------------------------*/ HDIB DibCreate(int cx, int cy, int cBits, int cColors) { HDIB hdib; BITMAPINFO* pbmi; DWORD dwInfoSize; int cEntries = 1; 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: 构建BITMAPINFO结构体.(主要供DibCopy和DibCopyToDdb函数使用) -----------------------------------------------------------------------------------*/ static BITMAPINFO* DibCopyToInfo(HDIB hdib) { BITMAPINFO* pbmi; RGBQUAD* prgb; int i, iNumColors; if (!DibIsValid(hdib)) return NULL; if (NULL == (pbmi = malloc(DibInfoSize(hdib)))) return NULL; //复制BITMAPINFO信息头部分 CopyMemory(pbmi, DibInfoHeaderPtr(hdib), sizeof(BITMAPINFOHEADER)); //复制可能的颜色遮罩 prgb = (RGBQUAD*)((BYTE*)pbmi + sizeof(BITMAPINFOHEADER)); if (DibMaskSize(hdib)) { CopyMemory(prgb, DibMaskPtr(hdib), 3 * sizeof(DWORD)); prgb = (RGBQUAD*)((BYTE*)prgb + 3 * sizeof(DWORD));//将指针移到遮罩后,指向颜色表 } //复制颜色表 iNumColors = DibNumColors(hdib); for (i = 0; i < iNumColors; i++) { DibGetColor(hdib, i, prgb + i); //每种颜色都是32位的。RGRQUAD也是32位的 } return pbmi; } /*----------------------------------------------------------------------------------- DibCopy: 从一个己经存在的DIB Section去创建一个新的DIB Section(注意:可以会交换 宽度与高度) -----------------------------------------------------------------------------------*/ 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 (!fRotate) //不旋转时直接复制像素数据。旋转时,需自行处理 { pBitsSrc = DibBitsPtr(hdibSrc); pBitsDst = DibBitsPtr(hdibDst); CopyMemory(pBitsDst, pBitsSrc, DibBitsSize(hdibSrc)); } return hdibDst; } /*----------------------------------------------------------------------------------- DibCopyToPackedDib: 通常用于保存DIBs或将DIBs传输到剪贴板。当传输到剪贴板时,第2个参数必须设为TRUE,以便 分配一个全局共享内存 -----------------------------------------------------------------------------------*/ BITMAPINFO* DibCopyToPackedDib(HDIB hdib, BOOL fUsedGlobal) { BITMAPINFO* pPackedDib; DWORD dwDibSize; HGLOBAL hGlobal = NULL; PDIBSTRUCT pdib = hdib; RGBQUAD* prgb; BYTE* pBits; int iNumColors; HDC hdcMem; if (!DibIsValid(hdib)) return NULL; //为紧凑型DIB分配内存 dwDibSize = DibTotalSize(hdib); if (fUsedGlobal) { hGlobal = GlobalAlloc(GHND | GMEM_SHARE, dwDibSize); pPackedDib = GlobalLock(hGlobal); } else { pPackedDib = malloc(dwDibSize); } if (NULL == pPackedDib) return NULL; //复制信息头 CopyMemory(pPackedDib, &pdib->ds.dsBmih, sizeof(BITMAPINFOHEADER)); prgb = (RGBQUAD*)((BYTE*)pPackedDib + sizeof(BITMAPINFOHEADER)); //复制可能的颜色遮罩 if (pdib->ds.dsBmih.biCompression == BI_BITFIELDS) { CopyMemory(prgb, pdib->ds.dsBitfields, 3 * sizeof(DWORD)); prgb = (RGBQUAD*)((BYTE*)prgb + 3 * sizeof(DWORD)); } //复制颜色表 if (iNumColors = DibNumColors(hdib)) { hdcMem = CreateCompatibleDC(NULL); SelectObject(hdcMem, pdib->hBitmap); GetDIBColorTable(hdcMem, 0, iNumColors, prgb); DeleteDC(hdcMem); } //复制像素数据 pBits = (BYTE*)(prgb + iNumColors); CopyMemory(pBits, pdib->pBits, DibBitsSize(hdib)); //如果最后一个参数是TRUE,解锁全局内存块,并将全局句块转化为指针返回 if (fUsedGlobal) { GlobalUnlock(hGlobal); pPackedDib = (BITMAPINFO*)hGlobal; } return pPackedDib; } /*----------------------------------------------------------------------------------- DibCopyFromPackedDib:通常用于从剪贴板中粘贴DIBs -----------------------------------------------------------------------------------*/ HDIB DibCopyFromPackedDib(BITMAPINFO* pPackedDib) { BYTE* pBits; DWORD dwInfoSize, dwMaskSize, dwColorSize; int iBitCount; PDIBSTRUCT pdib; //获取信息头类型,并做有效性验证 dwInfoSize = pPackedDib->bmiHeader.biSize; if (dwInfoSize != sizeof(BITMAPCOREHEADER) && dwInfoSize != sizeof(BITMAPINFOHEADER) && dwInfoSize != sizeof(BITMAPV4HEADER) && dwInfoSize != sizeof(BITMAPV5HEADER)) { return NULL; } //获取可能的颜色遮罩的大小 if (dwInfoSize == sizeof(BITMAPINFOHEADER) && pPackedDib->bmiHeader.biCompression == BI_BITFIELDS) { dwMaskSize = 3 * sizeof(DWORD); } else { dwMaskSize = 0; } //获取颜色表的大小 if (dwInfoSize == sizeof(BITMAPCOREHEADER)) { iBitCount = ((BITMAPCOREHEADER*)pPackedDib)->bcBitCount; if (iBitCount <= 8) { dwColorSize = (1 << (iBitCount))*sizeof(RGBTRIPLE); } else dwColorSize = 0; } else //所有非OS/2的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; } } //最后,获得pPackedDIB像素位的指针 pBits = (BYTE*)pPackedDib + dwInfoSize + dwMaskSize + dwColorSize; //创建HDIB pdib = DibCreateFromInfo(pPackedDib); //复制像素位数据 CopyMemory(pdib->pBits, pBits, DibBitsSize(pdib)); return pdib; } /*---------------------------------------------------------------------------------- DibFileLoad:从DIB文件中创建DIB Section -----------------------------------------------------------------------------------*/ HDIB DibFileLoad(const TCHAR* szFileName) { HANDLE hFile; BITMAPFILEHEADER bmfh; BITMAPINFO* pbmi; BOOL bSuccess; DWORD dwInfoSize, dwBytesRead, dwBitsSize; HDIB hDib; //打开文件(设为可读可写) 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; } //分配信息头大小,并读入数据 dwInfoSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER); pbmi = malloc(dwInfoSize); if (NULL == pbmi) { CloseHandle(hFile); return NULL; } bSuccess = ReadFile(hFile, pbmi, dwInfoSize, &dwBytesRead, NULL); if (!bSuccess || (dwBytesRead != dwInfoSize)) { CloseHandle(hFile); free(pbmi); return NULL; } //根据BITMAPINFO结构体来创建DIB hDib = DibCreateFromInfo(pbmi); free(pbmi); if (NULL == hDib) { CloseHandle(hFile); return NULL; } //读取像素位数据,放到DIBSTRUCT结构中pBits字段指向的空间中去 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:将DIB Section位图保存到文件中 -----------------------------------------------------------------------------------*/ 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 (INVALID_HANDLE_VALUE == hFile) 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); //写入BITMAPFILEHEADER bSuccess = WriteFile(hFile, &bmfh, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL); if (!bSuccess || (dwBytesWritten != sizeof(BITMAPFILEHEADER))) { CloseHandle(hFile); DeleteFile(szFileName); return FALSE; } //获取整个紧凑型DIB格式 pbmi = DibCopyToPackedDib(hdib, FALSE); if (NULL == pbmi) { CloseHandle(hFile); DeleteFile(szFileName); return FALSE; } //写入pbmi指定的整个紧凑型DIB bSuccess = WriteFile(hFile, pbmi, dwTotalSize, &dwBytesWritten, NULL); CloseHandle(hFile); free(pbmi); if (!bSuccess || (dwBytesWritten != dwTotalSize)) { DeleteFile(szFileName); return FALSE; } return TRUE; } /*---------------------------------------------------------------------------------- DibCopyToDdb:更高效的屏幕显示 -----------------------------------------------------------------------------------*/ HBITMAP DibCopyToDdb(HDIB hdib, HWND hwnd, HPALETTE hPalette) { HBITMAP hBitmap; BITMAPINFO* pbmi; 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; } /*---------------------------------------------------------------------------------- DibFlipHorizontal:调用没有优化的DibSetPixel和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:调用优化过的DibSetPixelx和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 - 1 - y, x, DibGetPixel1(hdibSrc, x, y)); //坐标旋转 } break; case 4: for (x = 0; x < cx; x++) for (y = 0; y < cy; y++) { DibSetPixel4(hdibDst, cy - 1 - y, x, DibGetPixel4(hdibSrc, x, y)); } break; case 8: for (x = 0; x < cx; x++) for (y = 0; y < cy; y++) { DibSetPixel8(hdibDst, cy - 1 - y, x, DibGetPixel8(hdibSrc, x, y)); } break; case 16: for (x = 0; x < cx; x++) for (y = 0; y < cy; y++) { DibSetPixel16(hdibDst, cy - 1 - y, x, DibGetPixel16(hdibSrc, x, y)); } break; case 24: for (x = 0; x < cx; x++) for (y = 0; y < cy; y++) { DibSetPixel24(hdibDst, cy - 1 - y, x, DibGetPixel24(hdibSrc, x, y)); } break; case 32: for (x = 0; x < cx; x++) for (y = 0; y < cy; y++) { DibSetPixel32(hdibDst, cy - 1 - y, x, DibGetPixel32(hdibSrc, x, y)); } break; } return hdibDst; }