?? dib.cpp
字號:
//-----------------------------------------------------------------------------------//
// Windows Graphics Programming: Win32 GDI and DirectDraw //
// ISBN 0-13-086985-6 //
// //
// Written by Yuan, Feng www.fengyuan.com //
// Copyright (c) 2000 by Hewlett-Packard Company www.hp.com //
// Published by Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com //
// //
// FileName : dib.cpp //
// Description: Device independent Bitmap Handling //
// Version : 1.00.000, May 31, 2000 //
//-----------------------------------------------------------------------------------//
#define STRICT
#define _WIN32_WINNT 0x0500
#define WINVER 0x500
#define NOCRYPT
#define OEMRESOURCE
#include <windows.h>
#include <assert.h>
#include <tchar.h>
#include <math.h>
#include "Color.h"
#include "Dib.h"
#include "Affine.h"
#include "BitmapInfo.h"
#include "filedialog.h"
const TCHAR * mess_DIBFormat[] =
{
_T("DIB_1BPP"), // 2 color image, palette-based
_T("DIB_2BPP"), // 4 color image, palttte-based
_T("DIB_4BPP"), // 16 color image, palette-based
_T("DIB_4BPPRLE"), // 16 color image, palette-based, RLE compressed
_T("DIB_8BPP"), // 256 color image, palette-based
_T("DIB_8BPPRLE"), // 256 color image, palette-based, RLE compressed
_T("DIB_16RGB555"), // 15 bit RGB color image, 5-5-5
_T("DIB_16RGB565"), // 16 bit RGB color image, 5-6-5, 1 bit unused
_T("DIB_24RGB888"), // 24 bit RGB color image, 8-8-8
_T("DIB_32RGB888"), // 32 bit RGB color image, 8-8-8, 8 bit unused
_T("DIB_32RGBA8888"), // 32 bit RGBA color image, 8-8-8-8
_T("DIB_16RGBbitfields"), // 16 bit RGB color image, non-standard bit masks, NT-only
_T("DIB_32RGBbitfields"), // 32 bit RGB color image, non-standard bit masks, NT-only
_T("DIB_JPEG"), // embedded JPEG image
_T("DIB_PNG") // embedded PNG image
};
const TCHAR * PixelFormatName(int id)
{
if ( (id>=DIB_1BPP) && (id<=DIB_PNG) )
return mess_DIBFormat[id - DIB_1BPP];
else
return _T("Unknown Pixel Format");
}
KDIB::KDIB()
{
m_pBMI = NULL;
m_pBits = NULL;
m_Flags = 0;
m_nWidth = 0;
m_nHeight = 0;
m_nPlanes = 1;
m_nBitCount = 1;
m_nColorDepth = 1;
m_nImageSize = 0;
m_nImageFormat = DIB_1BPP;
m_pRGBTRIPLE = NULL;
m_pRGBQUAD = NULL;
}
void KDIB::ReleaseDIB(void)
{
if ( m_Flags & DIB_BMI_NEEDFREE )
{
delete [] (BYTE *) m_pBMI;
m_Flags &= ~ DIB_BMI_NEEDFREE;
m_pBMI = NULL;
}
if ( m_Flags & DIB_BITS_NEEDFREE )
{
delete [] m_pBits;
m_Flags &= ~ DIB_BITS_NEEDFREE;
m_pBits = NULL;
}
}
KDIB::~KDIB()
{
try
{
ReleaseDIB();
}
catch (...)
{
}
}
bool KDIB::AttachDIB(BITMAPINFO * pDIB, BYTE * pBits, int flags)
{
if ( IsBadReadPtr(pDIB, sizeof(BITMAPCOREHEADER)) )
return false;
ReleaseDIB();
m_pBMI = pDIB;
m_Flags = flags;
DWORD size = * (DWORD *) pDIB; // always DWORD size, key to information header
int compression;
// gather information from bitmap information header structures
switch ( size )
{
case sizeof(BITMAPCOREHEADER):
{
BITMAPCOREHEADER * pHeader = (BITMAPCOREHEADER *) pDIB;
m_nWidth = pHeader->bcWidth;
m_nHeight = pHeader->bcHeight;
m_nPlanes = pHeader->bcPlanes;
m_nBitCount = pHeader->bcBitCount;
m_nImageSize= 0;
compression = BI_RGB;
if ( m_nBitCount <= 8 )
{
m_nClrUsed = 1 << m_nBitCount;
m_nClrImpt = m_nClrUsed;
m_pRGBTRIPLE = (RGBTRIPLE *) ((BYTE *) m_pBMI + size);
m_pBits = (BYTE *) & m_pRGBTRIPLE[m_nClrUsed];
}
else
m_pBits = (BYTE *) m_pBMI + size;
break;
}
case sizeof(BITMAPINFOHEADER):
case sizeof(BITMAPV4HEADER):
case sizeof(BITMAPV5HEADER):
{
BITMAPINFOHEADER * pHeader = & m_pBMI->bmiHeader;
m_nWidth = pHeader->biWidth;
m_nHeight = pHeader->biHeight;
m_nPlanes = pHeader->biPlanes;
m_nBitCount = pHeader->biBitCount;
m_nImageSize= pHeader->biSizeImage;
compression = pHeader->biCompression;
m_nClrUsed = pHeader->biClrUsed;
m_nClrImpt = pHeader->biClrImportant;
if ( m_nBitCount<=8 )
if ( m_nClrUsed==0 ) // 0 means full color table
m_nClrUsed = 1 << m_nBitCount;
if ( m_nClrUsed ) // has a color table
{
if ( m_nClrImpt==0 ) // 0 means all important
m_nClrImpt = m_nClrUsed;
if ( compression==BI_BITFIELDS )
{
m_pBitFields = (DWORD *) ((BYTE *)pDIB+size);
m_pRGBQUAD = (RGBQUAD *) ((BYTE *)pDIB+size + 3*sizeof(DWORD));
}
else
m_pRGBQUAD = (RGBQUAD *) ((BYTE *)pDIB+size);
m_pBits = (BYTE *) & m_pRGBQUAD[m_nClrUsed];
}
else
{
if ( compression==BI_BITFIELDS )
{
m_pBitFields = (DWORD *) ((BYTE *)pDIB+size);
m_pBits = (BYTE *) m_pBMI + size + 3 * sizeof(DWORD);
}
else
m_pBits = (BYTE *) m_pBMI + size;
}
break;
}
default:
return false;
}
if ( pBits )
m_pBits = pBits;
// precalculate information DIB parameters
m_nColorDepth = m_nPlanes * m_nBitCount;
m_nBPS = (m_nWidth * m_nBitCount + 31) / 32 * 4;
if (m_nHeight < 0 ) // top-down bitmap
{
m_nHeight = - m_nHeight; // change to positive
m_nDelta = m_nBPS; // forward
m_pOrigin = m_pBits; // scan0 .. scanN-1
}
else
{
m_nDelta = - m_nBPS; // backward
m_pOrigin = m_pBits + (m_nHeight-1) * m_nBPS * m_nPlanes; // scanN-1..scan0
}
if ( m_nImageSize==0 )
m_nImageSize = m_nBPS * m_nPlanes * m_nHeight;
// convert compression mode to image format
switch ( m_nBitCount )
{
case 0:
if ( compression==BI_JPEG )
m_nImageFormat = DIB_JPEG;
else if ( compression==BI_PNG )
m_nImageFormat = DIB_PNG;
else
return false;
case 1:
m_nImageFormat = DIB_1BPP;
break;
case 2:
m_nImageFormat = DIB_2BPP;
break;
case 4:
if ( compression==BI_RLE4 )
m_nImageFormat = DIB_4BPPRLE;
else
m_nImageFormat = DIB_4BPP;
break;
case 8:
if ( compression==BI_RLE8 )
m_nImageFormat = DIB_8BPPRLE;
else
m_nImageFormat = DIB_8BPP;
break;
case 16:
if ( compression==BI_BITFIELDS )
m_nImageFormat = DIB_16RGBbitfields;
else
m_nImageFormat = DIB_16RGB555; // see below
break;
case 24:
m_nImageFormat = DIB_24RGB888;
break;
case 32:
if ( compression == BI_BITFIELDS )
m_nImageFormat = DIB_32RGBbitfields;
else
m_nImageFormat = DIB_32RGB888; // see below
break;
default:
return false;
}
// try to understand bit fields
if ( compression==BI_BITFIELDS )
{
DWORD red = m_pBitFields[0];
DWORD green = m_pBitFields[1];
DWORD blue = m_pBitFields[2];
if ( (blue==0x001F) && (green==0x03E0) && (red==0x7C00) )
m_nImageFormat = DIB_16RGB555;
else if ( (blue==0x001F) && (green==0x07E0) && (red==0xF800) )
m_nImageFormat = DIB_16RGB565;
else if ( (blue==0x00FF) && (green==0xFF00) && (red==0xFF0000) )
m_nImageFormat = DIB_32RGB888;
}
return true;
}
bool KDIB::LoadBitmap(HMODULE hModule, LPCTSTR pBitmapName)
{
HRSRC hRes = FindResource(hModule, pBitmapName, RT_BITMAP);
if ( hRes==NULL )
return false;
HGLOBAL hGlb = LoadResource(hModule, hRes);
if ( hGlb==NULL )
return false;
BITMAPINFO * pDIB = (BITMAPINFO *) LockResource(hGlb);
if ( pDIB==NULL )
return false;
return AttachDIB(pDIB, NULL, DIB_BMI_READONLY | DIB_BITS_READONLY);
}
bool KDIB::LoadFile(const TCHAR * pFileName)
{
if ( pFileName==NULL )
return false;
HANDLE handle = CreateFile(pFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if ( handle == INVALID_HANDLE_VALUE )
return false;
BITMAPFILEHEADER bmFH;
DWORD dwRead = 0;
ReadFile(handle, & bmFH, sizeof(bmFH), & dwRead, NULL);
if ( (bmFH.bfType == 0x4D42) && (bmFH.bfSize<=GetFileSize(handle, NULL)) )
{
BITMAPINFO * pDIB = (BITMAPINFO *) new BYTE[bmFH.bfSize];
if ( pDIB )
{
ReadFile(handle, pDIB, bmFH.bfSize, & dwRead, NULL);
CloseHandle(handle);
return AttachDIB(pDIB, NULL, DIB_BMI_NEEDFREE);
}
}
CloseHandle(handle);
return false;
}
BOOL KDIB::SaveFile(const TCHAR * pFileName)
{
if ( m_pBMI )
return SaveDIBToFile(pFileName, m_pBMI, m_pBits);
else
return FALSE;
}
void KDIB::DecodeDIBFormat(TCHAR mess[])
{
wsprintf(mess, _T("DIB %dx%dx%dx%d "), m_nWidth, m_nHeight,
m_nPlanes, m_nBitCount);
if ( m_nImageSize < 1024 )
wsprintf(mess+_tcslen(mess), _T(", %d b"), m_nImageSize);
else if ( m_nImageSize < 1024 * 1024 )
wsprintf(mess+_tcslen(mess), _T(", %d,%03d b"), m_nImageSize/1024, m_nImageSize%1024);
else
wsprintf(mess+_tcslen(mess), _T(", %d,%03d,%03d b"), m_nImageSize/1024/1024, m_nImageSize/1024%1024,
m_nImageSize%1024);
_tcscat(mess, PixelFormatName(m_nImageFormat));
_tcscat(mess, _T(" "));
}
int GetDIBPixelSize(const BITMAPINFOHEADER & bmih)
{
if ( bmih.biSizeImage )
return bmih.biSizeImage;
else
return ( bmih.biWidth * bmih.biBitCount + 31 ) / 32 * 4 * bmih.biPlanes * abs(bmih.biHeight);
}
int GetDIBColorCount(const BITMAPINFOHEADER & bmih)
{
if ( bmih.biBitCount <= 8 )
if ( bmih.biClrUsed )
return bmih.biClrUsed;
else
return 1 << bmih.biBitCount;
else if ( bmih.biCompression==BI_BITFIELDS )
return 3 + bmih.biClrUsed;
else
return bmih.biClrUsed;
}
BITMAPINFO * BitmapToDIB(HPALETTE hPal, // palette for color conversion
HBITMAP hBmp, // DDB for convert
int nBitCount, int nCompression) // format wanted
{
typedef struct
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256+3];
} DIBINFO;
BITMAP ddbinfo;
DIBINFO dibinfo;
// retrieve DDB information
if ( GetObject(hBmp, sizeof(BITMAP), & ddbinfo)==0 )
return NULL;
// fill out BITMAPINFOHEADER based on size and required format
memset(&dibinfo, 0, sizeof(dibinfo));
dibinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dibinfo.bmiHeader.biWidth = ddbinfo.bmWidth;
dibinfo.bmiHeader.biHeight = ddbinfo.bmHeight;
dibinfo.bmiHeader.biPlanes = 1;
dibinfo.bmiHeader.biBitCount = nBitCount;
dibinfo.bmiHeader.biCompression = nCompression;
HDC hDC = GetDC(NULL); // screen DC
HGDIOBJ hpalOld;
if ( hPal )
hpalOld = SelectPalette(hDC, hPal, FALSE);
else
hpalOld = NULL;
// query GDI for image size
GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, NULL, (BITMAPINFO *) & dibinfo, DIB_RGB_COLORS);
int nInfoSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * GetDIBColorCount(dibinfo.bmiHeader);
int nTotalSize = nInfoSize + GetDIBPixelSize(dibinfo.bmiHeader);
BYTE * pDIB = new BYTE[nTotalSize];
if ( pDIB )
{
memcpy(pDIB, & dibinfo, nInfoSize);
if ( ddbinfo.bmHeight != GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, pDIB + nInfoSize, (BITMAPINFO *) pDIB, DIB_RGB_COLORS) )
{
delete [] pDIB;
pDIB = NULL;
}
}
if ( hpalOld )
SelectObject(hDC, hpalOld);
ReleaseDC(NULL, hDC);
return (BITMAPINFO *) pDIB;
}
int PixelFormat(HDC hdc)
{
typedef struct
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256+3];
} DIBINFO;
DIBINFO dibinfo;
HBITMAP hBmp = CreateCompatibleBitmap(hdc, 1, 1);
if ( hBmp==NULL )
return -1;
memset(&dibinfo, 0, sizeof(dibinfo));
dibinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// 1st call to get hdc biBitCount.
GetDIBits(hdc, hBmp, 0, 1, NULL, (BITMAPINFO*) & dibinfo, DIB_RGB_COLORS);
// 2nd calls to get color table or bitfields
GetDIBits(hdc, hBmp, 0, 1, NULL, (BITMAPINFO*) & dibinfo, DIB_RGB_COLORS);
DeleteObject(hBmp);
// try to understand bit fields
if ( dibinfo.bmiHeader.biBitCount==BI_BITFIELDS )
{
DWORD * pBitFields = (DWORD *) dibinfo.bmiColors;
DWORD red = pBitFields[0];
DWORD green = pBitFields[1];
DWORD blue = pBitFields[2];
if ( (blue==0x001F) && (green==0x03E0) && (red==0x7C00) )
return DIB_16RGB555;
else if ( (blue==0x001F) && (green==0x007E) && (red==0xF800) )
return DIB_16RGB565;
else if ( (blue==0x00FF) && (green==0xFF00) && (red==0xFF0000) )
return DIB_32RGB888;
else
return -1;
}
switch ( dibinfo.bmiHeader.biBitCount )
{
case 1: return DIB_1BPP;
case 2: return DIB_2BPP;
case 4: return DIB_4BPP;
case 8: return DIB_8BPP;
case 24: return DIB_24RGB888;
case 16: return DIB_16RGB555;
case 32: return DIB_32RGB888;
default: return -1;
}
}
HBITMAP CaptureWindow(HWND hWnd)
{
RECT wnd;
if ( ! GetWindowRect(hWnd, & wnd) )
return NULL;
HDC hDC = GetWindowDC(hWnd);
HBITMAP hBmp = CreateCompatibleBitmap(hDC, wnd.right - wnd.left, wnd.bottom - wnd.top);
if ( hBmp )
{
HDC hMemDC = CreateCompatibleDC(hDC);
HGDIOBJ hOld = SelectObject(hMemDC, hBmp);
BitBlt(hMemDC, 0, 0, wnd.right - wnd.left, wnd.bottom - wnd.top,
hDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOld);
DeleteObject(hMemDC);
}
ReleaseDC(hWnd, hDC);
return hBmp;
}
BOOL SaveDIBToFile(const TCHAR * pFileName, const BITMAPINFO * pBMI, const void * pBits)
{
KFileDialog fi;
if ( pFileName==NULL )
{
if ( ! fi.GetSaveFileName(NULL, _T("bmp"), _T("Bitmap Files")) )
return FALSE;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -