?? dibapi.cpp
字號:
// DIBAPI.cpp
//
#include "stdafx.h"
#include "dibapi.h"
#include <direct.h>
#include <math.h>
#include <io.h>
#include <errno.h>
BOOL PaintDIB(HDC hDC,
LPRECT lpDCRect,
HDIB hDIB,
LPRECT lpDIBRect,
CPalette* pPal)
{
LPSTR lpDIBHdr; // 指向BITMAPINFOHEADER的指針
LPSTR lpDIBBits; // 指向一個DIB位
BOOL bSuccess=FALSE; // 成功與失敗的標記
HPALETTE hPal=NULL; // DIB調色板
HPALETTE hOldPal=NULL; // 舊的調色板
// 檢查DIB句柄是否有效
if (hDIB == NULL)
return FALSE;
//鎖住DIB,取得一個起始指針
lpDIBHdr = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
lpDIBBits = ::FindDIBBits(lpDIBHdr);
// 取得DIB的調色板,并將其選進設備
if (pPal != NULL)
{
hPal = (HPALETTE) pPal->m_hObject;
// 選取背景
hOldPal = ::SelectPalette(hDC, hPal, TRUE);
}
// 確定使用模式
::SetStretchBltMode(hDC, COLORONCOLOR);
// 決定調用StretchDIBits()或SetDIBitsToDevice()函數
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
bSuccess = ::SetDIBitsToDevice(hDC, // 顯示設備上下文句柄
lpDCRect->left, // 目的區左上x坐標
lpDCRect->top, // 目的區左上y坐標
RECTWIDTH(lpDCRect), // 原矩形寬度
RECTHEIGHT(lpDCRect), // 原矩形高度
lpDIBRect->left, // 原矩形左下角x坐標
(int)DIBHeight(lpDIBHdr) -
lpDIBRect->top -
RECTHEIGHT(lpDIBRect), // 原矩形左下角y坐標
0, // 第一掃描線位置
(WORD)DIBHeight(lpDIBHdr),// 掃描線數
lpDIBBits, // DIB像素數據指針
(LPBITMAPINFO)lpDIBHdr, // BITMAPINFO結構指針
DIB_RGB_COLORS); // 使用顏色的方式
else
bSuccess = ::StretchDIBits(hDC, // 顯示設備上下文句柄
lpDCRect->left, // 目的區左上x坐標
lpDCRect->top, // 目的區左上y坐標
RECTWIDTH(lpDCRect), // 目的矩形寬度
RECTHEIGHT(lpDCRect), // 目的矩形高度
lpDIBRect->left, // 原矩形左下角x坐標
lpDIBRect->top, // 原矩形左下角y坐標
RECTWIDTH(lpDIBRect), // 原矩形寬度
RECTHEIGHT(lpDIBRect), // 原矩形高度
lpDIBBits, // DIB像素數據指針
(LPBITMAPINFO)lpDIBHdr, // BITMAPINFO結構指針
DIB_RGB_COLORS, // 使用顏色的方式
SRCCOPY); //光柵操作碼
::GlobalUnlock((HGLOBAL) hDIB);
// 重選舊的調色板
if (hOldPal != NULL)
{
::SelectPalette(hDC, hOldPal, TRUE);
}
return bSuccess;
}
BOOL CreateDIBPalette(HDIB hDIB, CPalette* pPal)
{
LPLOGPALETTE lpPal; // 指向邏輯調色板的指針
HANDLE hLogPal; // 邏輯調色板句柄
HPALETTE hPal = NULL; // 調色板句柄
int i; // 索引
WORD wNumColors; // 顏色表中的顏色數
LPSTR lpbi; // 指向一個DIB的指針
LPBITMAPINFO lpbmi; // 指向BITMAPINFO結構的指針
LPBITMAPCOREINFO lpbmc; // 指向BITMAPCOREINFO結構的指針
BOOL bWinStyleDIB; // 區分是否為Win3.0 DIB的一個標記
BOOL bResult = FALSE;
// 如果DIB句柄無效, 返回FALSE
if (hDIB == NULL)
return FALSE;
lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
// 得到BITMAPINFO (Win 3.0)指針
lpbmi = (LPBITMAPINFO)lpbi;
// 得到BITMAPCOREINFO (old 1.x)指針
lpbmc = (LPBITMAPCOREINFO)lpbi;
// 得到DIB的顏色數
wNumColors = ::DIBNumColors(lpbi);
if (wNumColors != 0)
{
// 為邏輯調色板分配內存
hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
+ sizeof(PALETTEENTRY)
* wNumColors);
// 如果沒有足夠得空間清除并返回 NULL
if (hLogPal == 0)
{
::GlobalUnlock((HGLOBAL) hDIB);
return FALSE;
}
lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
// 設置版本號和調色板口數目
lpPal->palVersion = PALVERSION;
lpPal->palNumEntries = (WORD)wNumColors;
// 是否為Win 3.0 DIB
bWinStyleDIB = IS_WIN30_DIB(lpbi);
for (i = 0; i < (int)wNumColors; i++)
{
if (bWinStyleDIB)
{
lpPal->palPalEntry[i].peRed =
lpbmi->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen =
lpbmi->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue =
lpbmi->bmiColors[i].rgbBlue;
lpPal->palPalEntry[i].peFlags = 0;
}
else
{
lpPal->palPalEntry[i].peRed =
lpbmc->bmciColors[i].rgbtRed;
lpPal->palPalEntry[i].peGreen =
lpbmc->bmciColors[i].rgbtGreen;
lpPal->palPalEntry[i].peBlue =
lpbmc->bmciColors[i].rgbtBlue;
lpPal->palPalEntry[i].peFlags = 0;
}
}
// 創建調色板并得到句柄
bResult = pPal->CreatePalette(lpPal);
::GlobalUnlock((HGLOBAL) hLogPal);
::GlobalFree((HGLOBAL) hLogPal);
}
::GlobalUnlock((HGLOBAL) hDIB);
return bResult;
}
LPSTR FindDIBBits(LPSTR lpbi)
{
return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi));
}
DWORD DIBWidth(LPSTR lpDIB)
{
LPBITMAPINFOHEADER lpbmi; // 指向Win 3.0 DIB
LPBITMAPCOREHEADER lpbmc; // 指向其它格式 DIB
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
// 如果為Win 3.0 DIB,則返回其寬度
if (IS_WIN30_DIB(lpDIB))
{
return lpbmi->biWidth;
}
else // 如果為其它格式的DIB, 也返回其寬度
{
return (DWORD)lpbmc->bcWidth;
}
}
DWORD DIBHeight(LPSTR lpDIB)
{
LPBITMAPINFOHEADER lpbmi; // 指向Win 3.0格式的DIB
LPBITMAPCOREHEADER lpbmc; // 指向其它格式的DIB
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
// 如果為Win 3.0 DIB,則返回其高度
if (IS_WIN30_DIB(lpDIB))
{
return lpbmi->biHeight;
}
else // i如果為其它格式DIB, 也返回其高度
{
return (DWORD)lpbmc->bcHeight;
}
}
WORD PaletteSize(LPSTR lpbi)
{
//計算必須的尺寸
if (IS_WIN30_DIB (lpbi))
return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
else
return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
}
WORD DIBNumColors(LPSTR lpbi)
{
WORD wBitCount; // DIB bit count
//如果為Windows格式的DIB,顏色數少于像素位數.
// 如果是這種情況,返回合適的值 。
if (IS_WIN30_DIB(lpbi))
{
DWORD dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
if (dwClrUsed != 0)
return (WORD)dwClrUsed;
}
// 計算基于像素的顏色數
if (IS_WIN30_DIB(lpbi))
wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
else
wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
// 返回基于像素的顏色數
if(wBitCount == 1 || wBitCount == 4 || wBitCount == 4)
return 2^wBitCount;//返回的是2的倍數
else
return 0;
}
HGLOBAL CopyHandle (HGLOBAL h)
{
if (h == NULL)
return NULL;
DWORD dwLen = ::GlobalSize((HGLOBAL) h);
HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen);
if (hCopy != NULL)
{
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
void* lp = ::GlobalLock((HGLOBAL) h);
memcpy(lpCopy, lp, dwLen);
::GlobalUnlock(hCopy);
::GlobalUnlock(h);
}
return hCopy;
}
BOOL SaveDIB(HDIB hDib, CFile& file)
{
BITMAPFILEHEADER bmfHdr; // 文件頭
LPBITMAPINFOHEADER lpBI; // 指向DIB信息結構的指針
DWORD dwDIBSize;
if (hDib == NULL)
return FALSE;
//得到指向DIB內存的指針, 包括一個BITMAPINFO結構
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if (lpBI == NULL)
return FALSE;
if (!IS_WIN30_DIB(lpBI))
{
::GlobalUnlock((HGLOBAL) hDib);
return FALSE; // 其它格式的DIB不支持
}
// 填寫文件頭區域
// 填寫文件類型
bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
// 計算DIB的大小。最簡單的方法是調用GlobalSize()函數
// 一般手工計算。
// 先計算頭和顏色表之和
dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);
// 計算圖像大小
if ((lpBI->biCompression == BI_RLE8)
|| (lpBI->biCompression == BI_RLE4))
{
// 為RLE位圖, 不能計算尺寸。
dwDIBSize += lpBI->biSizeImage;
}
else
{
DWORD dwBmBitsSize; // 位圖位的大小
// 非RLE, 大小為 寬度*高度
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*
((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
dwDIBSize += dwBmBitsSize;
lpBI->biSizeImage = dwBmBitsSize;
}
// 計算文件大小
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
// 計算真實的位圖位的偏移量,其等于文件頭+DIB頭+顏色表尺寸
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
lpBI->biSize + PaletteSize((LPSTR)lpBI);
TRY
{
// 寫文件頭
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
// 寫DIB頭內容和大小
file.WriteHuge(lpBI, dwDIBSize);
}
CATCH (CFileException, e)
{
::GlobalUnlock((HGLOBAL) hDib);
THROW_LAST();
}
END_CATCH
::GlobalUnlock((HGLOBAL) hDib);
return TRUE;
}
HDIB ReadDIBFile(CFile& file)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize;
HDIB hDIB;
LPSTR pDIB;
// 取得DIB的長度
dwBitsSize = file.GetLength();
// 讀DIB文件頭,檢查是否有效。
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
return NULL;
if (bmfHeader.bfType != DIB_HEADER_MARKER)
return NULL;
//為DIB分配內存
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
if (hDIB == 0)
{
return NULL;
}
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
// 讀位數
if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
dwBitsSize - sizeof(BITMAPFILEHEADER) )
{
::GlobalUnlock((HGLOBAL) hDIB);
::GlobalFree((HGLOBAL) hDIB);
return NULL;
}
::GlobalUnlock((HGLOBAL) hDIB);
return hDIB;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -