第16章 调色板管理器_16.4 一个DIB位图库的实现(1)

时间:2023-03-08 22:35:25
第16章 调色板管理器_16.4 一个DIB位图库的实现(1)
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程序】
效果图

第16章 调色板管理器_16.4 一个DIB位图库的实现(1)第16章 调色板管理器_16.4 一个DIB位图库的实现(1)第16章 调色板管理器_16.4 一个DIB位图库的实现(1)

第16章 调色板管理器_16.4 一个DIB位图库的实现(1)第16章 调色板管理器_16.4 一个DIB位图库的实现(1)

第16章 调色板管理器_16.4 一个DIB位图库的实现(1)第16章 调色板管理器_16.4 一个DIB位图库的实现(1)

第16章 调色板管理器_16.4 一个DIB位图库的实现(1)

//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 = ;
wndclass.cbWndExtra = ;
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 ;
} 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, , ))
{
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, , ,
min(cxClient, cxBitmap - x),
min(cyClient, cyBitmap - y),
hdcMem, x, y,
min(cxClient, cxBitmap - x),
min(cyClient, cyBitmap - y),
SRCCOPY);
} else
{
iReturn = BitBlt(hdc, , ,
min(cxClient, cxBitmap - x),
min(cyClient, cyBitmap - y),
hdcMem, x, y, SRCCOPY);
}
break;
case IDM_SHOW_CENTER:
if (fHalftonePalette)
{
iReturn = StretchBlt(hdc, (cxClient - cxBitmap) / , (cyClient - cyBitmap) / ,
cxBitmap, cyBitmap,
hdcMem, , ,
cxBitmap, cyBitmap,
SRCCOPY);
} else
{
iReturn = BitBlt(hdc, (cxClient - cxBitmap) / , (cyClient - cyBitmap) / ,
cxBitmap, cyBitmap,
hdcMem, , , SRCCOPY);
}
break;
case IDM_SHOW_STRETCH:
iReturn = StretchBlt(hdc, , ,
cxClient, cyClient,
hdcMem, , ,
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 / , cyBitmap / , NULL);
SetViewportOrgEx(hdc, cxClient / , cyClient / , NULL);
//iReturn = StretchBlt(hdc, 0, 0,
// cxBitmap, cyBitmap,
// hdcMem, 0, 0,
// cxBitmap, cyBitmap,
// SRCCOPY);
iReturn = BitBlt(hdc, , ,
cxBitmap, cyBitmap,
hdcMem, , ,
SRCCOPY);
break;
}
DeleteDC(hdcMem);
RestoreDC(hdc, -);
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 = ;
TCHAR szBuffer[];
switch (message)
{
case WM_CREATE:
//将菜单句柄保存在静态变量hMenu中
hMenu = GetMenu(hwnd);
//初始化打开文件对话框
memset(&ofn, , 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 ;
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 = ;
si.nMax = ;
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 = ;
si.nMax = DibHeight(hdib);
si.nPage = cyClient;
if ((BOOL)wParam) //恢复到0的默认位置
si.nPos = ;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
GetScrollInfo(hwnd, SB_VERT, &si);
iVscroll = si.nPos;
//水平滚动条
GetScrollInfo(hwnd, SB_HORZ, &si);
si.nMin = ;
si.nMax = DibWidth(hdib);
si.nPage = cxClient;
if ((BOOL)wParam) //恢复到0的默认位置
si.nPos = ;
SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
GetScrollInfo(hwnd, SB_HORZ, &si);
iHscroll = si.nPos;
}
return ;
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 -= ; break;
case SB_LINEDOWN: si.nPos += ; 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, , iVscroll - si.nPos, NULL, NULL);
iVscroll = si.nPos;
UpdateWindow(hwnd); //立即更新窗口,这行可以注释掉
}
return ;
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 -= ; break;
case SB_LINERIGHT: si.nPos += ; 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, , NULL, NULL);
iHscroll = si.nPos;
UpdateWindow(hwnd); //立即更新窗口,这行可以注释掉
}
return ;
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 : EnableMenuItem(hMenu, IDM_CONVERT_01, MF_GRAYED); break;
case : EnableMenuItem(hMenu, IDM_CONVERT_04, MF_GRAYED); break;
case : EnableMenuItem(hMenu, IDM_CONVERT_08, MF_GRAYED); break;
case : EnableMenuItem(hMenu, IDM_CONVERT_16, MF_GRAYED); break;
case : EnableMenuItem(hMenu, IDM_CONVERT_24, MF_GRAYED); break;
case : EnableMenuItem(hMenu, IDM_CONVERT_32, MF_GRAYED); break;
}
if (hdib && DibColorSize(hdib) > )
iEnable = MF_ENABLED;
else
iEnable = MF_GRAYED;
EnableMenuItem(hMenu, IDM_PAL_DIBTABLE, iEnable);
if (DibIsAddressable(hdib) && DibBitCount(hdib)>)
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 ;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_FILE_OPEN:
//显示“打开文件”对话框
if (!GetOpenFileName(&ofn))
return ;
//如果DIB和调色板己经存在,则删除它们
SendMessage(hwnd, WM_USER_DELETEDIB, , );
//加载DIB文件到内存
SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE);
hdib = DibFileLoad(szFileName);
SetCursor(LoadCursor(NULL, IDC_ARROW));
ShowCursor(FALSE);
//重置滚动条
SendMessage(hwnd, WM_USER_SETSCROLLS, TRUE, );
//创建调色板和DDB
SendMessage(hwnd, WM_USER_CREATEPAL, TRUE, ); //根据调色板,创建DDB——hBitmap if (!hdib)
{
MessageBox(hwnd, TEXT("Cannot load DIB file!"),
szAppName, MB_OK | MB_ICONEXCLAMATION);
}
InvalidateRect(hwnd, NULL, TRUE);
return ;
case IDM_FILE_SAVE:
//打开“保存”对话框
if (!GetSaveFileName(&ofn))
return ;
//将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 ;
case IDM_FILE_PRINT:
if (!hdib)
return ;
//获得打印机DC
printdlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION;
if (!PrintDlg(&printdlg))
return ;
if (NULL == (hdcPrn = printdlg.hDC))
{
MessageBox(hwnd, TEXT("Cannot obtain Printer DC"), szAppName, MB_ICONEXCLAMATION | MB_OK);
return ;
} //检查打印机是否支持打印位图
if (!(RC_BITBLT & GetDeviceCaps(hdcPrn, RASTERCAPS)))
{
DeleteDC(hdcPrn);
MessageBox(hwnd, TEXT("Printer cannot print bitmaps"), szAppName, MB_ICONEXCLAMATION | MB_OK);
return ;
}
//获取打机印的可打印区域
cxPage = GetDeviceCaps(hdcPrn, HORZRES);
cyPage = GetDeviceCaps(hdcPrn, VERTRES); fSuccess = FALSE;
//将DIB发送到打印机
SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE);
if ((StartDoc(hdcPrn, &di) > ) && (StartPage(hdcPrn) > ))
{
DisplayDib(hdcPrn, DibBitmapHandle(hdib), , , cxPage, cyPage, wShow, FALSE);
if (EndPage(hdcPrn) > )
{
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 ;
case IDM_FILE_PROPERTIES:
if (!hdib)
return ;
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(, DibCompression(hdib))]);
MessageBox(hwnd, szBuffer, szAppName, MB_ICONEXCLAMATION | MB_OK);
return ;
case IDM_APP_EXIT:
SendMessage(hwnd, WM_CLOSE, , );
return ;
case IDM_EDIT_COPY:
case IDM_EDIT_CUT:
if (!(hGlobal = DibCopyToPackedDib(hdib, TRUE)))
return ;
OpenClipboard(hwnd);
EmptyClipboard();
SetClipboardData(CF_DIB, hGlobal);
CloseClipboard();
if (LOWORD(wParam) == IDM_EDIT_COPY)
return ;
//剪切时,继续执行下去
case IDM_EDIT_DELETE:
SendMessage(hwnd, WM_USER_DELETEDIB, , );
InvalidateRect(hwnd, NULL, TRUE);
return ;
case IDM_EDIT_PASTE:
OpenClipboard(hwnd);
hGlobal = GetClipboardData(CF_DIB);
pGlobal = GlobalLock(hGlobal);
//如果己经存在DIB位图和调色板,则删除它们
if (pGlobal)
{
SendMessage(hwnd, WM_USER_DELETEDIB, , );
hdib = DibCopyFromPackedDib((BITMAPINFO*)pGlobal);
SendMessage(hwnd, WM_USER_CREATEPAL, TRUE, );
}
GlobalUnlock(hGlobal);
CloseClipboard();
//重置滚动条
SendMessage(hwnd, WM_USER_SETSCROLLS, TRUE, );
InvalidateRect(hwnd, NULL, TRUE);
return ;
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, );
InvalidateRect(hwnd, NULL, TRUE);
} else
{
MessageBox(hwnd, TEXT("Not enough memory"),
szAppName, MB_OK | MB_ICONEXCLAMATION);
}
return ;
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 ; 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, );
InvalidateRect(hwnd, NULL, TRUE);
return ;
case IDM_CONVERT_32:iConvert += ;
case IDM_CONVERT_24:iConvert += ;
case IDM_CONVERT_16:iConvert += ;
case IDM_CONVERT_08:iConvert += ;
case IDM_CONVERT_04:iConvert += ;
case IDM_CONVERT_01:iConvert += ;
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, , );
hdib = hdibNew;
SendMessage(hwnd, WM_USER_CREATEPAL, TRUE, );
InvalidateRect(hwnd, NULL, TRUE);
} else
{
MessageBox(hwnd, TEXT("Not enough memory"),
szAppName, MB_OK | MB_ICONEXCLAMATION);
}
return ;
case IDM_APP_ABOUT:
MessageBox(hwnd, TEXT("Dibble (c) Charles Petzold,1998"),
szAppName, MB_OK | MB_ICONEXCLAMATION);
return ;
} //其余所有的WM_COMMAND消息都是来自调色板项目。如果删除己经存在的调色板,光标将被
//设置为沙漏的形状
SendMessage(hwnd, WM_USER_DELETEPAL, , );
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(); break;
case IDM_PAL_GRAY3: hPalette = DibPalUniformGrays(); break;
case IDM_PAL_GRAY4: hPalette = DibPalUniformGrays(); break;
case IDM_PAL_GRAY8: hPalette = DibPalUniformGrays(); break;
case IDM_PAL_GRAY16: hPalette = DibPalUniformGrays(); break;
case IDM_PAL_GRAY32: hPalette = DibPalUniformGrays(); break;
case IDM_PAL_GRAY64: hPalette = DibPalUniformGrays(); break;
case IDM_PAL_GRAY128: hPalette = DibPalUniformGrays(); break;
case IDM_PAL_GRAY256: hPalette = DibPalUniformGrays(); break;
case IDM_PAL_RGB222: hPalette = DibPalUniformColors(, , ); break;
case IDM_PAL_RGB333: hPalette = DibPalUniformColors(, , ); break;
case IDM_PAL_RGB444: hPalette = DibPalUniformColors(, , ); break;
case IDM_PAL_RGB555: hPalette = DibPalUniformColors(, , ); break;
case IDM_PAL_RGB666: hPalette = DibPalUniformColors(, , ); break;
case IDM_PAL_RGB775: hPalette = DibPalUniformColors(, , ); break;
case IDM_PAL_RGB757: hPalette = DibPalUniformColors(, , ); break;
case IDM_PAL_RGB577: hPalette = DibPalUniformColors(, , ); break;
case IDM_PAL_RGB884: hPalette = DibPalUniformColors(, , ); break;
case IDM_PAL_RGB848: hPalette = DibPalUniformColors(, , ); break;
case IDM_PAL_RGB488: hPalette = DibPalUniformColors(, , ); break;
case IDM_PAL_OPT_POP4:
hPalette = DibPalPopularity(hdib, );
break;
case IDM_PAL_OPT_POP5:
hPalette = DibPalPopularity(hdib, );
break;
case IDM_PAL_OPT_POP6:
hPalette = DibPalPopularity(hdib, );
break;
case IDM_PAL_OPT_MEDCUT:
hPalette = DibPalMedianCut(hdib, );
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 ; //WM_COMMAND消息处理完毕
//该消息中删除一个己经存在的DIB,为获取一个新DIB作准备。
//该消息会被打开、粘贴或其它菜单命令所调用
case WM_USER_DELETEDIB:
if (hdib)
{
DibDelete(hdib);
hdib = NULL;
}
SendMessage(hwnd, WM_USER_DELETEPAL, , );
return ;
//基于一个新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 ; //删除一个己经存在的调色板,为创建新调色板做准备
case WM_USER_DELETEPAL:
if (hPalette)
{
DeleteObject(hPalette);
hPalette = NULL;
fHalftonePalette = FALSE;
PaletteMenu(hMenu, IDM_PAL_NONE);
}
if (hBitmap)
{
DeleteObject(hBitmap);
}
return ;
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 ;
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();
return ;
}
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
//
TEXTINCLUDE
BEGIN
"resource.h\0"
END
TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
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) &= ~( << ( - ((x)& )))), \
(*DibPixelPtr1(hdib, x, y) |= ((p) << ( - ((x)& )))))
#define DibSetPixel4(hdib, x, y, p) \
((*DibPixelPtr4(hdib, x, y) &= (0x0F << ((x)& ? : ))), \
(*DibPixelPtr4(hdib, x, y) |= ((p) << ((x)& ? : ))))
#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[]; //分别存入R、G、B3种颜色遮罩需左移的值
int iLShift[]; //
}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 ;
return ((PDIBSTRUCT)hdib)->ds.dsBm.bmWidth;
}
/*----------------------------------------------------------------------------------
DibHeight:返回位图的高度(单位字节)
-----------------------------------------------------------------------------------*/
int DibHeight(HDIB hdib)
{
if (!DibIsValid(hdib))
return ;
return ((PDIBSTRUCT)hdib)->ds.dsBm.bmHeight;
}
/*----------------------------------------------------------------------------------
DibBitCount:返回每像素的位数
-----------------------------------------------------------------------------------*/
int DibBitCount(HDIB hdib)
{
if (!DibIsValid(hdib))
return ;
return ((PDIBSTRUCT)hdib)->ds.dsBm.bmBitsPixel;
}
/*----------------------------------------------------------------------------------
DibRowLength:返回每行像素的大小(单位:字节):4的倍数
-----------------------------------------------------------------------------------*/
int DibRowLength(HDIB hdib)
{
if (!DibIsValid(hdib))
return ;
return * ((DibWidth(hdib)*DibBitCount(hdib) + ) / );
}
/*----------------------------------------------------------------------------------
DibNumColors:返回颜色表的颜色数目,无颜色表时返回0
-----------------------------------------------------------------------------------*/
int DibNumColors(HDIB hdib)
{
PDIBSTRUCT pdib = hdib;
if (!DibIsValid(hdib))
return ;
if (pdib->ds.dsBmih.biClrUsed != )
{
return pdib->ds.dsBmih.biClrUsed;
} else if (DibBitCount(hdib) <= )
{
return << DibBitCount(hdib); //2^bBitCount,如1位则2种颜色,8位256色
}
return ;
}
/*----------------------------------------------------------------------------------
DibMask:返回3种颜色遮罩其中的一种,如红色遮罩
-----------------------------------------------------------------------------------*/
DWORD DibMask(HDIB hdib, int i)
{
PDIBSTRUCT pdib = hdib;
if (!DibIsValid(hdib) || i< || i>)
return ;
return pdib->ds.dsBitfields[i];//0—红色;1—绿色;2—蓝色
}
/*----------------------------------------------------------------------------------
DibRShift:返回需右移的位数
-----------------------------------------------------------------------------------*/
int DibRShift(HDIB hdib, int i)
{
PDIBSTRUCT pdib = hdib;
if (!DibIsValid(hdib) || i< || i>)
return ;
return pdib->iRShift[i];
}
/*----------------------------------------------------------------------------------
DibLShift:返回需左移的位数
-----------------------------------------------------------------------------------*/
int DibLShift(HDIB hdib, int i)
{
PDIBSTRUCT pdib = hdib;
if (!DibIsValid(hdib) || i< || i>)
return ;
return pdib->iLShift[i];
}
/*----------------------------------------------------------------------------------
DibCompression: 获取biCompression字段的值
-----------------------------------------------------------------------------------*/
int DibCompression(HDIB hdib)
{
if (!DibIsValid(hdib))
return ;
return ((PDIBSTRUCT)hdib)->ds.dsBmih.biCompression;
}
//是否被压缩,DibIsNotCompressed
/*----------------------------------------------------------------------------------
DibIsAddressable: 如果DIB没压缩则返回TRUE
-----------------------------------------------------------------------------------*/
BOOL DibIsAddressable(HDIB hdib)
{
int iCompression;
if (!DibIsValid(hdib))
return ;
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 ; return ((PDIBSTRUCT)hdib)->ds.dsBmih.biSize;
}
DWORD DibMaskSize(HDIB hdib)
{
PDIBSTRUCT pdib = hdib;
if (!DibIsValid(hdib))
return ;
if (pdib->ds.dsBmih.biCompression == BI_BITFIELDS)
return * sizeof(DWORD);
return ;
}
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 ;
if (pdib->ds.dsBmih.biSizeImage != )
{
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, , 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, , 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 < || x >= DibWidth(hdib) || y < || 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) >> );
}
/*----------------------------------------------------------------------------------
DibGetPixel:返回(x,y)处的像素值
-----------------------------------------------------------------------------------*/
DWORD DibGetPixel(HDIB hdib, int x, int y)
{
PBYTE pPixel;
pPixel = DibPixelPtr(hdib, x, y);
if (!pPixel)
return ;
switch (DibBitCount(hdib))
{
//快速求余法:X % (2^N) == X & (2^N - 1),
case : return 0x01 & (*pPixel >> ( - (x & )));
case : return 0x0F & (*pPixel >> (x & ? : ));//x为奇数是,取低4位,偶数取高4位
case : return *pPixel;
case :return *(WORD*)pPixel;
case :return 0x00FFFFFF & *(DWORD*)pPixel;
case :return *(DWORD*)pPixel;
}
return ;
}
/*----------------------------------------------------------------------------------
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 :
*pPixel &= ~( << ( - (x & ))); //取出该字节中除x处外的其余像素数
*pPixel |= dwPixel << ( - (x & ));//将颜色值加入上述的X处。
break;
case :
*pPixel &= 0x0F << (x & ? : );
*pPixel |= dwPixel << (x & ? : );
break; case :
*pPixel = (BYTE)dwPixel;
break;
case :
*(WORD*)pPixel = (WORD)dwPixel;
break;
case :
*(RGBTRIPLE*)pPixel = *(RGBTRIPLE*)&dwPixel;
break;
case :
*(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 ( == (iBitCount = DibBitCount(hdib)))
return FALSE;
//获取像素位的值,返回DWORD,该值可能是索引或里面含有RGB值
dwPixel = DibGetPixel(hdib, x, y);
//如果是8位或以下的,该值为颜色表索引
if (iBitCount <= )
return DibGetColor(hdib, (int)dwPixel, prgb);
else if (iBitCount == )
{
*(RGBTRIPLE*)prgb = *(RGBTRIPLE*)&dwPixel;
prgb->rgbReserved = ;
} else if (iBitCount == && pdib->ds.dsBmih.biCompression == BI_RGB)
{
*prgb = *(RGBQUAD*)&dwPixel;
}
//此外的情况,使用颜色遮罩和移位
else
{
//下面等号右边的式子,执行顺序先用掩码取出dwPixel的相应颜色,再右移,最后左移。
prgb->rgbRed = (BYTE)((pdib->ds.dsBitfields[] & dwPixel) >> pdib->iRShift[] << pdib->iLShift[]);
prgb->rgbGreen = (BYTE)((pdib->ds.dsBitfields[] & dwPixel) >> pdib->iRShift[] << pdib->iLShift[]);
prgb->rgbBlue = (BYTE)((pdib->ds.dsBitfields[] & dwPixel) >> pdib->iRShift[] << pdib->iLShift[]);
}
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 <= )
return FALSE;
//剩下来的步骤与GetPixelColor相反
else if (iBitCount == )
{
*(RGBTRIPLE*)&dwPixel = *(RGBTRIPLE*)prgb;
dwPixel &= 0x00FFFFFF;
} else if (iBitCount == && pdib->ds.dsBmih.biCompression == BI_RGB)
{
*(RGBQUAD*)&dwPixel = *prgb;
} else
{
//先将rgbRed由字节转为DWORD,再右移,最后左移
dwPixel = (((DWORD)prgb->rgbRed >> pdib->iLShift[]) << pdib->iRShift[]);
dwPixel |= (((DWORD)prgb->rgbGreen >> pdib->iLShift[]) << pdib->iRShift[]);
dwPixel |= (((DWORD)prgb->rgbBlue >> pdib->iLShift[]) << pdib->iRShift[]);
}
DibSetPixel(hdib, x, y, dwPixel);
return TRUE;
}
/*----------------------------------------------------------------------------------
根据遮罩颜色计算移位值,这些颜色遮罩来自于DibCreateFromInfo函数
-----------------------------------------------------------------------------------*/
static int MaskToRShift(DWORD dwMask)
{
int iShift;
if ( == dwMask)
return ;
for (iShift = ; !(dwMask & ); iShift++) //最低位为0,则右移1位
dwMask >>= ;
return iShift;
}
static int MaskToLShift(DWORD dwMask)
{
int iShift;
if ( == dwMask)
return ;
while (!(dwMask & )) //dwMask右侧的0移掉
dwMask >>= ;
for (iShift = ; dwMask & ; iShift++) //统计1的个数
dwMask >>= ;
return - 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, );
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 = ; i < ; 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) == ) //RGB分别使用5-5-5型遮罩
{
pdib->ds.dsBitfields[] = 0x00007C00; //R Mask
pdib->ds.dsBitfields[] = 0x000003E0; //G Mask
pdib->ds.dsBitfields[] = 0x0000001F; //B Mask
pdib->iRShift[] = ;
pdib->iRShift[] = ;
pdib->iRShift[] = ;
pdib->iLShift[] = ;
pdib->iLShift[] = ;
pdib->iLShift[] = ;
} else if (DibBitCount(pdib) == || DibBitCount(pdib) == ) //使用8-8-8型
{
pdib->ds.dsBitfields[] = 0x00FF0000; //R Mask
pdib->ds.dsBitfields[] = 0x0000FF00; //G Mask
pdib->ds.dsBitfields[] = 0x000000FF; //B Mask
pdib->iRShift[] = ;
pdib->iRShift[] = ;
pdib->iRShift[] = ;
pdib->iLShift[] = ;
pdib->iLShift[] = ;
pdib->iLShift[] = ;
}
}
//分配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>) //位图从下到上存储
{
for (y = ; y < cy; y++)
pdib->ppRow[y] = pBits + (cy - - y)*iRowLength;
} else //从上到下存储
{
for (y = ; 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 = ;
if (cx <= || cy <= ||
((cBits != ) && (cBits != ) && (cBits != ) &&
(cBits != ) && (cBits != ) && (cBits != )))
{
return NULL;
}
if (cColors != )
cEntries = cColors;
else if (cBits <= )
cEntries = << cBits;
dwInfoSize = sizeof(BITMAPINFOHEADER) + (cEntries - )*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 = ;
pbmi->bmiHeader.biBitCount = cBits;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = ;
pbmi->bmiHeader.biXPelsPerMeter = ;
pbmi->bmiHeader.biYPelsPerMeter = ;
pbmi->bmiHeader.biClrUsed = cColors;
pbmi->bmiHeader.biClrImportant = ;
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), * sizeof(DWORD));
prgb = (RGBQUAD*)((BYTE*)prgb + * sizeof(DWORD));//将指针移到遮罩后,指向颜色表
}
//复制颜色表
iNumColors = DibNumColors(hdib);
for (i = ; 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, * sizeof(DWORD));
prgb = (RGBQUAD*)((BYTE*)prgb + * sizeof(DWORD));
}
//复制颜色表
if (iNumColors = DibNumColors(hdib))
{
hdcMem = CreateCompatibleDC(NULL);
SelectObject(hdcMem, pdib->hBitmap);
GetDIBColorTable(hdcMem, , 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 = * sizeof(DWORD);
} else
{
dwMaskSize = ;
}
//获取颜色表的大小
if (dwInfoSize == sizeof(BITMAPCOREHEADER))
{
iBitCount = ((BITMAPCOREHEADER*)pPackedDib)->bcBitCount;
if (iBitCount <= )
{
dwColorSize = ( << (iBitCount))*sizeof(RGBTRIPLE);
} else
dwColorSize = ;
} else //所有非OS/2的DIBs
{
if (pPackedDib->bmiHeader.biClrUsed >)
{
dwColorSize = pPackedDib->bmiHeader.biClrUsed*sizeof(RGBQUAD);
} else if (pPackedDib->bmiHeader.biBitCount <= )
{
dwColorSize = ( << pPackedDib->bmiHeader.biBitCount)*sizeof(RGBQUAD);
} else
{
dwColorSize = ;
}
}
//最后,获得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, , 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 = ;
bmfh.bfReserved2 = ;
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 = ; x < cx; x++)
for (y = ; y < cy; y++)
{
DibSetPixel(hdibDst, x, cy - - 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 :
for (x = ; x < cx; x++)
for (y = ; y < cy; y++)
{
DibSetPixel1(hdibDst, cy - - y, x, DibGetPixel1(hdibSrc, x, y)); //坐标旋转
}
break;
case :
for (x = ; x < cx; x++)
for (y = ; y < cy; y++)
{
DibSetPixel4(hdibDst, cy - - y, x, DibGetPixel4(hdibSrc, x, y));
}
break;
case :
for (x = ; x < cx; x++)
for (y = ; y < cy; y++)
{
DibSetPixel8(hdibDst, cy - - y, x, DibGetPixel8(hdibSrc, x, y));
}
break;
case :
for (x = ; x < cx; x++)
for (y = ; y < cy; y++)
{
DibSetPixel16(hdibDst, cy - - y, x, DibGetPixel16(hdibSrc, x, y));
}
break;
case :
for (x = ; x < cx; x++)
for (y = ; y < cy; y++)
{
DibSetPixel24(hdibDst, cy - - y, x, DibGetPixel24(hdibSrc, x, y));
}
break;
case :
for (x = ; x < cx; x++)
for (y = ; y < cy; y++)
{
DibSetPixel32(hdibDst, cy - - y, x, DibGetPixel32(hdibSrc, x, y));
}
break;
}
return hdibDst;
}

//未完,接下一篇