文件中引用文件及函数如下:
1)dibapi.h
/********************************************************************************
* DIBAPI.H
*
* Header file for Device-Independent Bitmap (DIB) API. Provides
* function prototypes and constants for DIB functions
********************************************************************************/
#ifndef __DIBAPI1_H_
#define __DIBAPI1_H_
//////////////////////////////////////////////////////////
/* Handle to a DIB */
#define HDIB HANDLE
// Dib Header Marker - used in writing DIBs to files
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
/* DIB constants */
#define PALVERSION 0x300
/* Gray Method */
#define MEAN_GRAY 0
#define MAXIMUM_GRAY 1
#define WEIGHT_GRAY 2
#define OTHER_GRAY 3
/* DIB Macros*/
// WIDTHBYTES performs DWORD-aligning of DIB scanlines. The "bits"
// parameter is the bit count for the scanline (biWidth * biBitCount),
// and this macro returns the number of DWORD-aligned bytes needed
// to hold those bits.
#define MYWIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
#define IS_WIN30_DIB(lpbi) ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))
#define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left)
#define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top)
#define WaitCursorBegin() HCURSOR hcURSOR = SetCursor(LoadCursor(NULL, IDC_WAIT))
#define WaitCursorEnd() SetCursor(hcURSOR)
#define BOUND(x, mn, mx) ((x) < (mn) ? (mn) : ((x) > (mx) ? (mx) : (x)))
// Structure use internally
typedef struct _NODE
{
BOOL bIsLeaf; // TRUE if node has no children
UINT nPixelCount; // Number of pixels represented by this leaf
UINT nRedSum; // Sum of red components
UINT nGreenSum; // Sum of green components
UINT nBlueSum; // Sum of blue components
struct _NODE* pChild[8]; // Pointers to child nodes
struct _NODE* pNext; // Pointer to next reducible node
} NODE;
/* function prototypes */
// DIB initialization
HANDLE LoadImgHandle(char* szImgFileName, char *strExt, int &nFileType) ;
BOOL SaveDIB (HDIB, LPCTSTR);
void DestroyDIB(HDIB hDib);
// DIB attributes
DWORD BytesPerLine(LPBYTE lpDIB);
DWORD DIBlockSize(LPBYTE lpDIB);
DWORD DIBHeight (LPBYTE lpDIB);
DWORD DIBWidth (LPBYTE lpDIB);
WORD DIBNumColors (LPBYTE lpDIB);
WORD DIBBitCount (LPBYTE lpDIB);
LPBYTE FindDIBBits (LPBYTE lpDIB);
WORD PaletteSize (LPBYTE lpDIB);
// DIB palette
HPALETTE CreateDIBPalette(LPBYTE lpDIB);
HPALETTE CreateDIBPalette(HDIB hDIB) ;
BOOL DisplayPalette(HDC hDC, LPRECT lpRect, HPALETTE hPal);
HPALETTE CopyPalette(HPALETTE hPalSrc);
HPALETTE GetSystemPalette(void);
HPALETTE CreateOctreePalette(HDIB hDIB, UINT nMaxColors, UINT nColorBits);
HPALETTE CreateOctreePalette(LPBYTE lpDIB, UINT nMaxColors, UINT nColorBits);
HPALETTE BuildOctreePalette(HANDLE hImage, UINT nMaxColors, UINT nColorBits);
//Relative functions with CreateOctreePalette
void AddColor (NODE**, BYTE, BYTE, BYTE, UINT, UINT, UINT*, NODE**);
NODE* CreateNode (UINT, UINT, UINT*, NODE**);
void ReduceTree (UINT, UINT*, NODE**);
void DeleteTree (NODE**);
void GetPaletteColors (NODE*, PALETTEENTRY*, UINT*);
int GetRightShiftCount (DWORD);
int GetLeftShiftCount (DWORD);
//Relative functions with CreateOctreePalette
//DIB operations
HDIB ConvertDIBFormat(LPBYTE lpSrcDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch, HPALETTE hPalSrc);
HDIB ConvertDIBFormat(HDIB hDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch, HPALETTE hPalSrc);
HDIB ConvertDIBFormat(LPBYTE lpSrcDIB, UINT nbpp, HPALETTE hPalSrc);
HDIB ConvertDIBFormat(HDIB hDIB, UINT nbpp, HPALETTE hPalSrc);
//
BOOL CopyColorTable( LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource, HPALETTE hPalSrc );
HBITMAP DIBToDIBSection(LPBYTE lpDIB);
HBITMAP DIBToDIBSection(HDIB hDIB);
HBITMAP DIBToBitmap(HDIB hDIB, HPALETTE hPal) ;
HDIB ChangeDIBFormat(HDIB hDIB, WORD wBitCount, DWORD dwCompression) ;
HDIB ChangeBitmapFormat (HBITMAP hbm, WORD biBits, DWORD biCompression, HPALETTE hpal);
bool GrayEqualize(HDIB hDib);
bool GrayStretchDIB(int nMethod, HDIB hDib,BYTE bX1,BYTE bY1,BYTE bX2,BYTE bY2);
bool EliminateDirtDIB(int nMethod, HDIB hDib, CRect rect);
bool EliminateDirtDIB(int nMethod, HDIB hDib, int nCircleX, int nCircleY, int nRadius);
void SaveTo8bit_BMP(const BYTE* pbInputMat, int Width, int Height, const char* szFileName, int nGrayLevel);
HDIB ChangeDIBSize(HDIB hDIB, int nWidth, int nHeight);
int PalEntriesOnDevice (HDC hDC);
HPALETTE CreateIdentifyPalette(HPALETTE hPalSrc);
BOOL MapDIBColorsToPalette(HDIB hDIB, HPALETTE hPalette);
LONG GetPixelOffsetValue(HDIB hDib,LONG y, LONG x);
HDIB CropDIB(HDIB hDIB, LPRECT lpRect);
HDIB ColorQuantizeDIB(HDIB hDIB, UINT nColorBits, UINT nMaxColors);
HPALETTE ConvertToGrayscale(HDIB hDib, int nMethod, double fRedWeight, double fGreenWeight, double fBlueWeight);
BOOL SaveBMPFile(LPCSTR lpFileName, BITMAPINFO *pBmpInfo, BYTE *pImageBuffer);
bool GetGrayHist(const BYTE * pbImg, const int nImgWid, const int nImgHei, int *pnHist );
bool GetCumulativeHist(const int *pnHist , int nLength, long *pnCuHist);
//
//////////////////////////////////////////////////////////
#endif //__DIBAPI_H_
2)dibapi.cpp
//**********************************************************************
//
// AIBAPI.CPP
//
// Source file for Device-Independent Bitmap (DIB) API.
//
//**********************************************************************
#define STRICT // enable strict type checking
#include "stdafx.h"
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <io.h>
#include <direct.h>
#include <stdlib.h>
#include <assert.h>
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
//#include <afxcoll.h>
#include <afxtempl.h>
#include "dibapi.h"
void DestroyDIB(HDIB hDib)
{
GlobalFree(hDib);
}
BOOL SaveDIB(HDIB hDib, LPCTSTR lpFileName)
{
BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
HANDLE fh; // file handle for opened file
DWORD dwDIBSize;
DWORD dwWritten;
if (!hDib)
return FALSE;
fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh == INVALID_HANDLE_VALUE)
return FALSE;
// Get a pointer to the DIB memory, the first of which contains
// a BITMAPINFO structure
lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);
if (!lpBI)
{
CloseHandle(fh);
return FALSE;
}
// Check to see if we're dealing with an OS/2 DIB. If so, don't
// save it because our functions aren't written to deal with these
// DIBs.
if (lpBI->biSize != sizeof(BITMAPINFOHEADER))
{
GlobalUnlock(hDib);
CloseHandle(fh);
return FALSE;
}
// Fill in the fields of the file header
// Fill in file type (first 2 bytes must be "BM" for a bitmap)
bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
// Calculating the size of the DIB is a bit tricky (if we want to
// do it right). The easiest way to do this is to call GlobalSize()
// on our global handle, but since the size of our global memory may have
// been padded a few bytes, we may end up writing out a few too
// many bytes to the file (which may cause problems with some apps,
// like HC 3.0).
//
// So, instead let's calculate the size manually.
//
// To do this, find size of header plus size of color table. Since the
// first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
// the size of the structure, let's use this.
// Partial Calculation
dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPBYTE)lpBI);
// Now calculate the size of the image
// It's an RLE bitmap, we can't calculate size, so trust the biSizeImage
// field
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
dwDIBSize += lpBI->biSizeImage;
else
{
DWORD dwBmBitsSize; // Size of Bitmap Bits only
// It's not RLE, so size is Width (DWORD aligned) * Height
dwBmBitsSize = MYWIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) *
lpBI->biHeight;
dwDIBSize += dwBmBitsSize;
// Now, since we have calculated the correct size, why don't we
// fill in the biSizeImage field (this will fix any .BMP files which
// have this field incorrect).
lpBI->biSizeImage = dwBmBitsSize;
}
// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
// Now, calculate the offset the actual bitmap bits will be in
// the file -- It's the Bitmap file header plus the DIB header,
// plus the size of the color table.
//bfOffBits specifies the offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize +
PaletteSize((LPBYTE)lpBI);
// Write the file header
WriteFile(fh, (LPBYTE)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
// Write the DIB header and the bits -- use local version of
// MyWrite, so we can write more than 32767 bytes of data
WriteFile(fh, (LPBYTE)lpBI, dwDIBSize, &dwWritten, NULL);
GlobalUnlock(hDib);
CloseHandle(fh);
if (dwWritten == 0)
return FALSE; // oops, something happened in the write
else
return TRUE; // Success code
}
/*************************************************************************
*
* FindDIBBits()
*
* Parameter:
*
* LPBYTE lpDIB - pointer to packed-DIB memory block
*
* Return Value:
*
* LPBYTE - pointer to the DIB bits
*
* Description:
*
* This function calculates the address of the DIB's bits and returns a
* pointer to the DIB bits.
*
************************************************************************/
LPBYTE FindDIBBits(LPBYTE lpDIB)
{
ASSERT(lpDIB);
return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));
}
/*************************************************************************
*
* DIBWidth()
*
* Parameter:
*
* LPBYTE lpDIB - pointer to packed-DIB memory block
*
* Return Value:
*
* DWORD - width of the DIB
*
* Description:
*
* This function gets the width of the DIB from the BITMAPINFOHEADER
* width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
* width field if it is an OS/2-style DIB.
*
************************************************************************/
DWORD DIBWidth(LPBYTE lpDIB)
{
LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB
// point to the header (whether Win 3.0 and OS/2)
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
// return the DIB width if it is a Win 3.0 DIB
if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))
return lpbmi->biWidth;
else // it is an OS/2 DIB, so return its width
return (DWORD)lpbmc->bcWidth;
}
/*************************************************************************
*
* DIBHeight()
*
* Parameter:
*
* LPBYTE lpDIB - pointer to packed-DIB memory block
*
* Return Value:
*
* DWORD - height of the DIB
*
* Description:
*
* This function gets the height of the DIB from the BITMAPINFOHEADER
* height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
* height field if it is an OS/2-style DIB.
*
************************************************************************/
DWORD DIBHeight(LPBYTE lpDIB)
{
LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB
// point to the header (whether OS/2 or Win 3.0
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
// return the DIB height if it is a Win 3.0 DIB
if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))
return lpbmi->biHeight;
else // it is an OS/2 DIB, so return its height
return (DWORD)lpbmc->bcHeight;
}
/*************************************************************************
*
* PaletteSize()
*
* Parameter:
*
* LPBYTE lpDIB - pointer to packed-DIB memory block
*
* Return Value:
*
* WORD - size of the color palette of the DIB
*
* Description:
*
* This function gets the size required to store the DIB's palette by
* multiplying the number of colors by the size of an RGBQUAD (for a
* Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an OS/2-
* style DIB).
*
************************************************************************/
WORD PaletteSize(LPBYTE lpDIB)
{
// calculate the size required by the palette
if (IS_WIN30_DIB (lpDIB))
return (DIBNumColors(lpDIB) * sizeof(RGBQUAD));
else
return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
}
WORD PaletteSize(HDIB hDIB)
{
LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB);
WORD wSize = PaletteSize(lpDIB);
GlobalUnlock(hDIB);
return wSize;
}
/*************************************************************************
*
* DIBNumColors()
*
* Parameter:
*
* LPBYTE lpDIB - pointer to packed-DIB memory block
*
* Return Value:
*
* WORD - number of colors in the color table
*
* Description:
*
* This function calculates the number of colors in the DIB's color table
* by finding the bits per pixel for the DIB (whether Win3.0 or OS/2-style
* DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
* if 24, no colors in color table.
*
************************************************************************/
WORD DIBNumColors(LPBYTE lpDIB)
{
WORD wBitCount; // DIB bit count
// If this is a Windows-style DIB, the number of colors in the
// color table can be less than the number of bits per pixel
// allows for (i.e. lpbi->biClrUsed can be set to some value).
// If this is the case, return the appropriate value.
if (IS_WIN30_DIB(lpDIB))
{
DWORD dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed;
if (dwClrUsed)
return (WORD)dwClrUsed;
}
// Calculate the number of colors in the color table based on
// the number of bits per pixel for the DIB.
if (IS_WIN30_DIB(lpDIB))
wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
else
wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
// return number of colors based on bits per pixel
switch (wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
WORD DIBBitCount(LPBYTE lpDIB)
{
if (IS_WIN30_DIB(lpDIB))
return ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
else
return ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
}
/****************************************************************************
*
* FUNCTION: BytesPerLine
*
* PURPOSE: Calculates the number of bytes in one scan line.
*
* 功能:计算DIB位图每条扫描线的字节数
*
* PARAMS: LPBYTE lpDIB - pointer to the BITMAPINFOHEADER
that begins the CF_DIB block
*
* 参数:指向BITMAPINFOHEADER 结构的指针
*
* RETURNS: DWORD - number of bytes in one scan line (DWORD aligned)
*
\****************************************************************************/
DWORD BytesPerLine(LPBYTE lpDIB)
{
return MYWIDTHBYTES(((LPBITMAPINFOHEADER)lpDIB)->biWidth * ((LPBITMAPINFOHEADER)lpDIB)->biPlanes * ((LPBITMAPINFOHEADER)lpDIB)->biBitCount);
}
/****************************************************************************
*
* FUNCTION: DIBlockSize
*
* PURPOSE: Calculates the number of bytes in one scan line.
*
* PARAMS: LPBYTE lpDIB - pointer to the BITMAPINFOHEADER
that begins the CF_DIB block
*
* RETURNS: DWORD - DIB block size
*
\****************************************************************************/
DWORD DIBlockSize(LPBYTE lpDIB)
{
if (((LPBITMAPINFOHEADER)lpDIB)->biSizeImage == 0)
((LPBITMAPINFOHEADER)lpDIB)->biSizeImage = BytesPerLine(lpDIB) * ((LPBITMAPINFOHEADER)lpDIB)->biHeight;
return ((LPBITMAPINFOHEADER)lpDIB)->biSize + PaletteSize(lpDIB) + ((LPBITMAPINFOHEADER)lpDIB)->biSizeImage;
}
/*************************************************************************
*
* DisplayPalette ()
*
* Parameter:
*
* HDC hDC - handle of device context to display palette
* LPRECT lpRect - rect range to show palette
* HPALETTE hPal - handle of palette to display
*
* Return Value:
*
* BOOL - TRUE, if success, else FALSE
*
* Description:
*
* This function displays palette on the specified rectangle in a device context
*
************************************************************************/
BOOL DisplayPalette(HDC hDC, LPRECT lpRect, HPALETTE hPal)
{
if (! hPal)
return FALSE;
int nEntries;
PALETTEENTRY pe[256];
nEntries = GetPaletteEntries(hPal, 0, 256, pe);
int nSqr = (int)sqrt((double)nEntries);
int nWidth = (lpRect->right-lpRect->left)/nSqr;
int nHeight = (lpRect->bottom-lpRect->top)/nSqr;
lpRect->right = lpRect->left + nWidth*nSqr;
lpRect->bottom = lpRect->top + nHeight*nSqr;
HPALETTE hOldPal = (HPALETTE)SelectPalette(hDC, hPal, FALSE);
RealizePalette(hDC);
HBRUSH hBrush, hOldBrush;
int x, y;
for (int i=0; i<nEntries; ++i)
{
x = i%nSqr;
y = i/nSqr;
hBrush = CreateSolidBrush(RGB(pe[i].peRed, pe[i].peGreen, pe[i].peBlue));
hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
Rectangle(hDC,
lpRect->left + x*nWidth,
lpRect->top + y*nHeight,
lpRect->left + (x+1)*nWidth,
lpRect->top + (y+1) *nHeight);
SelectObject(hDC, hOldBrush);
DeleteObject(hBrush);
}
SelectPalette(hDC, hOldPal, FALSE);
return TRUE;
}
/*************************************************************************
*
* CopyPalette ()
*
* Parameter:
*
* HPALETTE hPalSrc - source palette handle
*
* Return Value:
*
* HPALETTE - destination palette handle
*
* Description:
*
* This function copys the source palette to a new palette handle
*
************************************************************************/
HPALETTE CopyPalette(HPALETTE hPalSrc)
{
PLOGPALETTE plogPal;
int iNumEntries=0;
HPALETTE hPal;
HANDLE h;
iNumEntries = GetPaletteEntries(hPalSrc, 0, iNumEntries, NULL);
if (iNumEntries == 0)
return (HPALETTE) NULL;
h = GlobalAlloc(GHND, sizeof(DWORD) + sizeof(PALETTEENTRY)*iNumEntries);
if (! h)
return (HPALETTE) NULL;
plogPal = (PLOGPALETTE)GlobalLock(h);
if (! plogPal)
return (HPALETTE) NULL;
plogPal->palVersion = 0x300;
plogPal->palNumEntries = (WORD) iNumEntries;
GetPaletteEntries(hPalSrc, 0, iNumEntries, plogPal->palPalEntry);
hPal = CreatePalette(plogPal);
GlobalUnlock(h);
GlobalFree(h);
return hPal;
}
/*************************************************************************
*
* PalEntriesOnDevice()
*
* Parameter:
*
* HDC hDC - device context
*
* Return Value:
*
* int - number of palette entries on device
*
* Description:
*
* This function gets the number of palette entries on the specified device
*
************************************************************************/
int PalEntriesOnDevice(HDC hDC)
{
int nColors; // number of colors
// Find out the number of colors on this device.
nColors = (1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)));
assert(nColors);
return nColors;
}
/*************************************************************************
*
* GetSystemPalette()
*
* Parameters:
*
* None
*
* Return Value:
*
* HPALETTE - handle to a copy of the current system palette
*
* Description:
*
* This function returns a handle to a palette which represents the system
* palette. The system RGB values are copied into our logical palette using
* the GetSystemPaletteEntries function.
*
************************************************************************/
HPALETTE GetSystemPalette(void)
{
HDC hDC; // handle to a DC
static HPALETTE hPal = NULL; // handle to a palette
HANDLE hLogPal; // handle to a logical palette
LPLOGPALETTE lpLogPal; // pointer to a logical palette
int nColors; // number of colors
// Find out how many palette entries we want.
hDC = GetDC(NULL);
if (!hDC)
return NULL;
nColors = PalEntriesOnDevice(hDC); // Number of palette entries
// Allocate room for the palette and lock it.
hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors *
sizeof(PALETTEENTRY));
// if we didn't get a logical palette, return NULL
if (!hLogPal)
return NULL;
// get a pointer to the logical palette
lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);
// set some important fields
lpLogPal->palVersion = PALVERSION;
lpLogPal->palNumEntries = WORD(nColors);
// Copy the current system palette into our logical palette
GetSystemPaletteEntries(hDC, 0, nColors,
(LPPALETTEENTRY)(lpLogPal->palPalEntry));
// Go ahead and create the palette. Once it's created,
// we no longer need the LOGPALETTE, so free it.
hPal = CreatePalette(lpLogPal);
// clean up
GlobalUnlock(hLogPal);
GlobalFree(hLogPal);
ReleaseDC(NULL, hDC);
return hPal;
}
/*************************************************************************
*
* CreateIdentifyPalette ()
*
* Parameter:
*
* HPALETTE hPalSrc - source palette handle
*
* Return Value:
*
* HPALETTE - destination identify palette handle
*
* Description:
*
* This function creates an identify palette from the source palette handle
*
************************************************************************/
HPALETTE CreateIdentifyPalette(HPALETTE hPalSrc)
{
BOOL bResult = FALSE;
int i, iSysColors, iPalEntries;
HPALETTE hPalette, hpalOld;
if (! hPalSrc)
return NULL;
// create a new palette equal to input
hPalette = CopyPalette(hPalSrc);
// Get a screen DC to work with
HDC hdcScreen = GetDC(NULL);
ASSERT(hdcScreen);
// Make sure we are on a palettized device
if (!(GetDeviceCaps(hdcScreen, RASTERCAPS) & RC_PALETTE))
{
TRACE("Not a palettized device");
goto abort;
}
// Get the number of system colors and the number of palette entries
// Note that on a palletized device the number of colors is the
// number of guaranteed colors. I.e. the number of reserved system colors
iSysColors = GetDeviceCaps(hdcScreen, NUMCOLORS);
iPalEntries = GetDeviceCaps(hdcScreen, SIZEPALETTE);
// if there are more than 256 colors we are wasting our time
if (iSysColors > 256) goto abort;
// Now we force the palette manager to reset its tables so that
// the next palette to be realized will get its colors in the order they are
// in the logical palette. This is done by changing the number of
// reserved colors.
SetSystemPaletteUse(hdcScreen, SYSPAL_NOSTATIC);
SetSystemPaletteUse(hdcScreen, SYSPAL_STATIC);
// Select our palette into the screen DC and realize it so that
// its colors will be entered into the free slots in the physical palette
hpalOld = ::SelectPalette(hdcScreen,
hPalette, // our hpal
FALSE);
::RealizePalette(hdcScreen);
// Now replace the old palette (but don't realize it)
::SelectPalette(hdcScreen, hpalOld, FALSE);
// The physical palette now has our colors set in place and its own
// reserved colors at either end. We can grab the lot now
PALETTEENTRY pe[256];
GetSystemPaletteEntries(hdcScreen,
0,
iPalEntries,
pe);
// Set the PC_NOCOLLAPSE flag for each of our colors so that GDI
// won't merge them together. Be careful not to set PC_NOCOLLAPSE for the
// sys color entries or we'll get multpile copies of these colors in
// the palette when we realize it.
for (i = 0; i < iSysColors/2; i++) {
pe[i].peFlags = 0;
}
for (; i < iPalEntries-iSysColors/2; i++) {
pe[i].peFlags = PC_NOCOLLAPSE;
}
for (; i < iPalEntries; i++) {
pe[i].peFlags = 0;
}
// Resize the palette in case it was smaller
ResizePalette(hPalette, iPalEntries);
// Update the palette entries with what is now in the physical palette
SetPaletteEntries(hPalette, 0, iPalEntries, pe);
bResult = TRUE;
abort:
::ReleaseDC(NULL, hdcScreen);
return bResult ? hPalette : NULL;
}
/*************************************************************************
*
* CopyHandle()
*
* Parameters:
*
* HANDLE h - source handle
*
* Return Value:
*
* HANDLE - duplicated handle
*
* Description:
*
* Copy memory handle to another
************************************************************************/
HANDLE CopyHandle(HANDLE h)
{
if (h == NULL)
return NULL;
SIZE_T dwLen = ::GlobalSize((HGLOBAL)h);
HANDLE hCopy = ::GlobalAlloc(GHND, dwLen);
if (hCopy == NULL)
return NULL;
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
void* lp = ::GlobalLock((HGLOBAL) h);
::CopyMemory(lpCopy, lp, dwLen);
::GlobalUnlock(hCopy);
::GlobalUnlock(h);
return hCopy;
}
LONG GetPixelOffsetValue(HDIB hDib,LONG y, LONG x)
{
WaitCursorBegin();
LPBYTE lpDIB,lpDIBBits;
DWORD lHeight;
lpDIB = (LPBYTE) GlobalLock( hDib );
lpDIBBits = FindDIBBits( lpDIB );
lHeight = DIBHeight( lpDIB );
LONG lLineBytes = BytesPerLine(lpDIB);
GlobalUnlock( hDib );
WaitCursorEnd();
return *(lpDIBBits + (lHeight-y-1)*lLineBytes+x);
}
HDIB CropDIB(HDIB hDIB, LPRECT lpRect)
{
LPBITMAPINFO lpbmi = NULL;
LPBYTE lpSourceBits, lpTargetBits, lpResult;
HDC hDC = NULL, hSourceDC, hTargetDC;
HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap;
DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize;
int nWidth, nHeight;
HDIB hNewDIB;
DWORD dwSize;
WaitCursorBegin();
// Get DIB pointer
if (! hDIB)
{
WaitCursorEnd();
return NULL;
}
LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
if (! lpSrcDIB)
{
WaitCursorEnd();
return NULL;
}
// Allocate and fill out a BITMAPINFO struct for the new DIB
dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) + PaletteSize(lpSrcDIB);
lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize );
memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize);
nWidth = RECTWIDTH(lpRect);
nHeight = RECTHEIGHT(lpRect);
lpbmi->bmiHeader.biWidth = nWidth;
lpbmi->bmiHeader.biHeight = nHeight;
// Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
hDC = GetDC( NULL );
hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 );
hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 );
hSourceDC = CreateCompatibleDC( hDC );
hTargetDC = CreateCompatibleDC( hDC );
// Flip the bits on the source DIBSection to match the source DIB
dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader));
dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader));
memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize );
lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize;
// Select DIBSections into DCs
hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );
hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap );
// put old bitmap in new bitmap
BitBlt(hTargetDC, 0, 0, nWidth, nHeight, hSourceDC, lpRect->left, lpRect->top, SRCCOPY);
// Clean up and delete the DCs
SelectObject( hSourceDC, hOldSourceBitmap );
SelectObject( hTargetDC, hOldTargetBitmap );
DeleteDC( hSourceDC );
DeleteDC( hTargetDC );
ReleaseDC( NULL, hDC );
// Flush the GDI batch, so we can play with the bits
GdiFlush();
// Allocate enough memory for the new CF_DIB, and copy bits
dwSize = dwTargetHeaderSize + dwTargetBitsSize;
hNewDIB = GlobalAlloc(GHND, dwSize);
lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize );
memcpy( lpResult, lpbmi, dwTargetHeaderSize );
memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize );
// final cleanup
DeleteObject( hTargetBitmap );
DeleteObject( hSourceBitmap );
free( lpbmi );
GlobalUnlock(hDIB);
GlobalUnlock(hNewDIB);
WaitCursorEnd();
return hNewDIB;
}
//对原来图像进行灰度化
BOOL SaveBMPFile(LPCSTR lpFileName, BITMAPINFO *pBmpInfo, BYTE *pImageBuffer)
{
BOOL bRVal = TRUE;
DWORD dwBytesRead = 0;
DWORD dwSize = 0;
BITMAPFILEHEADER bfh = {0};
int nTable = 0;
DWORD dwImageSize = 0;
if (pBmpInfo->bmiHeader.biBitCount > 8) {
nTable = 0;
}
else{
nTable = 256;
}
dwImageSize = MYWIDTHBYTES(pBmpInfo->bmiHeader.biWidth * pBmpInfo->bmiHeader.biBitCount) *
pBmpInfo->bmiHeader.biHeight;
if (dwImageSize <= 0) {
bRVal = FALSE;
}
else{
bfh.bfType = (WORD)'M' << 8 | 'B';
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nTable * sizeof(RGBQUAD);
bfh.bfSize = bfh.bfOffBits + dwImageSize;
HANDLE hFile = ::CreateFile(lpFileName,
GENERIC_WRITE ,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
bRVal = FALSE;
}
else{
dwSize = sizeof(BITMAPFILEHEADER);
::WriteFile(hFile, &bfh, dwSize, &dwBytesRead, NULL );
dwSize = sizeof(BITMAPINFOHEADER) + nTable * sizeof(RGBQUAD);
::WriteFile(hFile, pBmpInfo, dwSize, &dwBytesRead, NULL );
dwSize = dwImageSize;
WriteFile(hFile, pImageBuffer, dwSize, &dwBytesRead, NULL );
CloseHandle(hFile);
}
}
return bRVal;
}
// Add 2007-05-09
HANDLE LoadImgHandle(char* szImgFileName, char *strExt, int &nFileType)
{
typedef HANDLE (WINAPI * PGETDIBPROC)(HWND, char *, HANDLE);
PGETDIBPROC lpFun;
HANDLE hDib;
HINSTANCE hConvertLib = LoadLibrary("Convert.dll");
ASSERT(hConvertLib != NULL);
if(strcmp(strExt,".bmp") == 0)
{
lpFun = (PGETDIBPROC)GetProcAddress(hConvertLib, "Bmp2HDIB");
nFileType = 1;
}
else if(strcmp(strExt,".jpg") == 0)
{
lpFun = (PGETDIBPROC)GetProcAddress(hConvertLib, "Jpg2HDIB");
nFileType = 2;
}
else if(strcmp(strExt,".tif") == 0)
{
lpFun = (PGETDIBPROC)GetProcAddress(hConvertLib, "Tiff2HDIB");
nFileType = 3;
}
else
{
if(hConvertLib)
{
FreeLibrary(hConvertLib);
}
nFileType = -1;
return NULL;
}
ASSERT(lpFun != NULL);
freopen("nul", "w", stdout);
hDib = (*lpFun) ( NULL, szImgFileName, NULL);
freopen("con", "w", stdout);
if(hConvertLib)
{
FreeLibrary(hConvertLib);
}
return hDib;
}
HPALETTE ConvertToGrayscale(HDIB hDib, int nMethod,
double fRedWeight, double fGreenWeight, double fBlueWeight)
{
if (hDib == NULL)
return NULL;
BITMAPINFO* lpbi = (BITMAPINFO *)GlobalLock(hDib);
if (! lpbi)
return NULL;
WaitCursorBegin();
// get color number
WORD wNumColors = DIBNumColors((LPBYTE)lpbi);
if (wNumColors == 0) // There is no palette
{
GlobalUnlock(hDib);
// reduce colors to 256
HDIB hNewDib = ColorQuantizeDIB(hDib, 8, 256);
LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib);
if (! lpDIB)
{
WaitCursorEnd();
return NULL;
}
DWORD dwSize = DIBlockSize(lpDIB);
hDib = GlobalReAlloc(hDib, dwSize, 0);
lpbi = (BITMAPINFO *)GlobalLock(hDib);
CopyMemory((LPBYTE)lpbi, (LPBYTE)lpDIB, dwSize);
GlobalUnlock(hNewDib);
GlobalFree(hNewDib);
}
wNumColors = DIBNumColors((LPBYTE)lpbi);
BYTE GrayValue = 0;
WORD i;
switch (nMethod)
{
case MAXIMUM_GRAY:
for (i=0; i<wNumColors; i++)
{
GrayValue = max(max(lpbi->bmiColors[i].rgbRed,
lpbi->bmiColors[i].rgbGreen),
lpbi->bmiColors[i].rgbBlue);
lpbi->bmiColors[i].rgbRed =
lpbi->bmiColors[i].rgbGreen =
lpbi->bmiColors[i].rgbBlue = GrayValue;
}
break;
case MEAN_GRAY:
for (i=0; i<wNumColors; i++)
{
GrayValue = min(255,
(lpbi->bmiColors[i].rgbRed +
lpbi->bmiColors[i].rgbGreen +
lpbi->bmiColors[i].rgbBlue)/3);
lpbi->bmiColors[i].rgbRed =
lpbi->bmiColors[i].rgbGreen =
lpbi->bmiColors[i].rgbBlue = GrayValue;
}
break;
case WEIGHT_GRAY:
for (i=0; i<wNumColors; i++)
{
GrayValue = min(255,
(BYTE)(lpbi->bmiColors[i].rgbRed*fRedWeight +
lpbi->bmiColors[i].rgbGreen*fGreenWeight +
lpbi->bmiColors[i].rgbBlue*fBlueWeight));
lpbi->bmiColors[i].rgbRed =
lpbi->bmiColors[i].rgbGreen =
lpbi->bmiColors[i].rgbBlue = GrayValue;
}
break;
case OTHER_GRAY: //该法旨在通过有选择的灰度化。
for ( i = 0; i<wNumColors; i++)
{
BYTE b,g,r;
r = lpbi->bmiColors[i].rgbRed;
g = lpbi->bmiColors[i].rgbGreen;
b = lpbi->bmiColors[i].rgbBlue;
double h,s;
h = 180.0/3.1415926*acos((2*r-g-b)/2.0/sqrt(pow(float(r-g),2)+(r-b)*(g-b)));
s = 1 - 3.0/(r+g+b)*min((r,g),(r,b));
if( b >(r+g))//为蓝色降低蓝色比例
GrayValue = 0;
else
GrayValue = min(255,
(BYTE)(lpbi->bmiColors[i].rgbRed*0.5 +
lpbi->bmiColors[i].rgbGreen*0.4 +
lpbi->bmiColors[i].rgbBlue*0.1));
lpbi->bmiColors[i].rgbRed =
lpbi->bmiColors[i].rgbGreen =
lpbi->bmiColors[i].rgbBlue = GrayValue;
}
break;
}
GlobalUnlock(hDib);
WaitCursorEnd();
return CreateDIBPalette(hDib);
}
HDIB ColorQuantizeDIB(HDIB hDIB, UINT nColorBits, UINT nMaxColors)
{
HPALETTE hPal = NULL;
WaitCursorBegin();
// color quantization palette
LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB);
hPal = CreateOctreePalette(lpDIB, nMaxColors, nColorBits);
GlobalUnlock(hDIB);
// convert DIB to new format
HDIB hNewDIB = ConvertDIBFormat(hDIB, nColorBits, hPal);
WaitCursorEnd();
return hNewDIB;
}
/*************************************************************************
*
* CreateDIBPalette()
*
* Parameter:
*
* LPBYTE lpbi - specifies the DIB
*
* Return Value:
*
* HPALETTE - specifies the palette
*
* Description:
*
* This function creates a palette from a DIB by allocating memory for the
* logical palette, reading and storing the colors from the DIB's color table
* into the logical palette, creating a palette from this logical palette,
* and then returning the palette's handle. This allows the DIB to be
* displayed using the best possible colors (important for DIBs with 256 or
* more colors).
*
************************************************************************/
HPALETTE CreateDIBPalette(LPBYTE lpbi)
{
LPLOGPALETTE lpPal; // pointer to a logical palette
HANDLE hLogPal; // handle to a logical palette
HPALETTE hPal = NULL; // handle to a palette
int i, wNumColors; // loop index, number of colors in color table
LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0)
LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (OS/2)
BOOL bWinStyleDIB; // Win3.0 DIB?
// if handle to DIB is invalid, return NULL
if (! lpbi)
return NULL;
// get pointer to BITMAPINFO (Win 3.0)
lpbmi = (LPBITMAPINFO)lpbi;
// get pointer to BITMAPCOREINFO (OS/2 1.x)
lpbmc = (LPBITMAPCOREINFO)lpbi;
// get the number of colors in the DIB
wNumColors = DIBNumColors(lpbi);
// is this a Win 3.0 DIB?
bWinStyleDIB = IS_WIN30_DIB(lpbi);
if (wNumColors)
{
// allocate memory block for logical palette
hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) +
sizeof(PALETTEENTRY) * wNumColors);
// if not enough memory, clean up and return NULL
if (!hLogPal)
return NULL;
// lock memory block and get pointer to it
lpPal = (LPLOGPALETTE)GlobalLock(hLogPal);
// set version and number of palette entries
lpPal->palVersion = PALVERSION;
lpPal->palNumEntries = wNumColors;
// store RGB triples (if Win 3.0 DIB) or RGB quads (if OS/2 DIB)
// into palette
for (i = 0; i < 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;
}
}
// create the palette and get handle to it
hPal = CreatePalette(lpPal);
// if error getting handle to palette, clean up and return NULL
if (!hPal)
{
GlobalUnlock(hLogPal);
GlobalFree(hLogPal);
return NULL;
}
}
// return handle to DIB's palette
return hPal;
}
/*************************************************************************
*
* CreateDIBPalette()
*
* Parameter:
*
* HDIB hDIB - specifies the DIB
*
* Return Value:
*
* HPALETTE - specifies the palette
*
* Description:
*
* This function creates a palette from a DIB by allocating memory for the
* logical palette, reading and storing the colors from the DIB's color table
* into the logical palette, creating a palette from this logical palette,
* and then returning the palette's handle. This allows the DIB to be
* displayed using the best possible colors (important for DIBs with 256 or
* more colors).
*
************************************************************************/
HPALETTE CreateDIBPalette(HDIB hDIB)
{
HPALETTE hPal = NULL; // handle to a palette
LPBYTE lpbi; // pointer to packed-DIB
// if handle to DIB is invalid, return NULL
if (!hDIB)
return NULL;
// lock DIB memory block and get a pointer to it
lpbi = (LPBYTE)GlobalLock(hDIB);
hPal = CreateDIBPalette(lpbi);
// Unlock hDIB
GlobalUnlock(hDIB);
// return handle to DIB's palette
return hPal;
}
HPALETTE CreateOctreePalette(HDIB hDIB, UINT nMaxColors, UINT nColorBits)
{
HANDLE hImage;
hImage = DIBToDIBSection(hDIB);
if (! hImage)
return NULL;
return BuildOctreePalette(hImage, nMaxColors, nColorBits);
}
HPALETTE CreateOctreePalette(LPBYTE lpDIB, UINT nMaxColors, UINT nColorBits)
{
HANDLE hImage;
hImage = DIBToDIBSection(lpDIB);
if (! hImage)
return NULL;
return BuildOctreePalette(hImage, nMaxColors, nColorBits);
}
HPALETTE BuildOctreePalette(HANDLE hImage, UINT nMaxColors, UINT nColorBits)
{
DIBSECTION ds;
int i, j, nPad;
BYTE* pbBits;
WORD* pwBits;
DWORD* pdwBits;
DWORD rmask, gmask, bmask;
int rright, gright, bright;
int rleft, gleft, bleft;
BYTE r, g, b;
WORD wColor;
DWORD dwColor, dwSize;
LOGPALETTE* plp;
HPALETTE hPalette;
NODE* pTree;
UINT nLeafCount, nIndex;
NODE* pReducibleNodes[9];
HDC hdc;
BYTE* pBuffer;
BITMAPINFO bmi;
// Initialize octree variables
pTree = NULL;
nLeafCount = 0;
if (nColorBits > 8) // Just in case
return NULL;
for (i=0; i<=(int) nColorBits; i++)
pReducibleNodes[i] = NULL;
// Scan the DIB and build the octree
GetObject (hImage, sizeof (ds), &ds);
nPad = ds.dsBm.bmWidthBytes - (((ds.dsBmih.biWidth *
ds.dsBmih.biBitCount) + 7) / 8);
switch (ds.dsBmih.biBitCount) {
case 1: // 1-bit DIB
case 4: // 4-bit DIB
case 8: // 8-bit DIB
//
// The strategy here is to use ::GetDIBits to convert the
// image into a 24-bit DIB one scan line at a time. A pleasant
// side effect of using ::GetDIBits in this manner is that RLE-
// encoded 4-bit and 8-bit DIBs will be uncompressed. //
hdc = GetDC (NULL);
pBuffer = new BYTE[ds.dsBmih.biWidth * 3];
ZeroMemory (&bmi, sizeof (bmi));
bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = ds.dsBmih.biWidth;
bmi.bmiHeader.biHeight = ds.dsBmih.biHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;
for (i=0; i<ds.dsBmih.biHeight; i++)
{
GetDIBits (hdc, (HBITMAP) hImage, i, 1, pBuffer, &bmi,
DIB_RGB_COLORS);
pbBits = pBuffer;
for (j=0; j<ds.dsBmih.biWidth; j++)
{
b = *pbBits++;
g = *pbBits++;
r = *pbBits++;
AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
pReducibleNodes);
while (nLeafCount > nMaxColors)
ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
}
}
delete pBuffer;
ReleaseDC (NULL, hdc);
break;
case 16: // One case for 16-bit DIBs
if (ds.dsBmih.biCompression == BI_BITFIELDS) {
rmask = ds.dsBitfields[0];
gmask = ds.dsBitfields[1];
bmask = ds.dsBitfields[2];
}
else {
rmask = 0x7C00;
gmask = 0x03E0;
bmask = 0x001F;
}
rright = GetRightShiftCount (rmask);
gright = GetRightShiftCount (gmask);
bright = GetRightShiftCount (bmask);
rleft = GetLeftShiftCount (rmask);
gleft = GetLeftShiftCount (gmask);
bleft = GetLeftShiftCount (bmask);
pwBits = (WORD*) ds.dsBm.bmBits;
for (i=0; i<ds.dsBmih.biHeight; i++) {
for (j=0; j<ds.dsBmih.biWidth; j++) {
wColor = *pwBits++;
b = (BYTE) (((wColor & (WORD) bmask) >> bright) << bleft);
g = (BYTE) (((wColor & (WORD) gmask) >> gright) << gleft);
r = (BYTE) (((wColor & (WORD) rmask) >> rright) << rleft);
AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
pReducibleNodes);
while (nLeafCount > nMaxColors)
ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
}
pwBits = (WORD*) (((BYTE*) pwBits) + nPad);
}
break;
case 24: // Another for 24-bit DIBs
pbBits = (BYTE*) ds.dsBm.bmBits;
for (i=0; i<ds.dsBmih.biHeight; i++) {
for (j=0; j<ds.dsBmih.biWidth; j++) {
b = *pbBits++;
g = *pbBits++;
r = *pbBits++;
AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
pReducibleNodes);
while (nLeafCount > nMaxColors)
ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
}
pbBits += nPad;
}
break;
case 32: // And another for 32-bit DIBs
if (ds.dsBmih.biCompression == BI_BITFIELDS) {
rmask = ds.dsBitfields[0];
gmask = ds.dsBitfields[1];
bmask = ds.dsBitfields[2];
}
else {
rmask = 0x00FF0000;
gmask = 0x0000FF00;
bmask = 0x000000FF;
}
rright = GetRightShiftCount (rmask);
gright = GetRightShiftCount (gmask);
bright = GetRightShiftCount (bmask);
pdwBits = (DWORD*) ds.dsBm.bmBits;
for (i=0; i<ds.dsBmih.biHeight; i++) {
for (j=0; j<ds.dsBmih.biWidth; j++) {
dwColor = *pdwBits++;
b = (BYTE) ((dwColor & bmask) >> bright);
g = (BYTE) ((dwColor & gmask) >> gright);
r = (BYTE) ((dwColor & rmask) >> rright);
AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
pReducibleNodes);
while (nLeafCount > nMaxColors)
ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
}
pdwBits = (DWORD*) (((BYTE*) pdwBits) + nPad);
}
break;
default: // DIB must be 16, 24, or 32-bit!
return NULL;
}
if (nLeafCount > nMaxColors) { // Sanity check
DeleteTree (&pTree);
return NULL;
}
// Create a logical palette from the colors in the octree
dwSize = sizeof (LOGPALETTE) + ((nLeafCount - 1) * sizeof (PALETTEENTRY));
if ((plp = (LOGPALETTE*) HeapAlloc (GetProcessHeap (), 0,
dwSize)) == NULL) {
DeleteTree (&pTree);
return NULL;
}
plp->palVersion = 0x300;
plp->palNumEntries = (WORD) nLeafCount;
nIndex = 0;
GetPaletteColors (pTree, plp->palPalEntry, &nIndex);
hPalette = CreatePalette (plp);
HeapFree (GetProcessHeap (), 0, plp);
DeleteTree (&pTree);
return hPalette;
}
void AddColor (NODE** ppNode, BYTE r, BYTE g, BYTE b, UINT nColorBits,
UINT nLevel, UINT* pLeafCount, NODE** pReducibleNodes)
{
int nIndex, shift;
static BYTE mask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
// If the node doesn't exist, create it
if (*ppNode == NULL)
*ppNode = CreateNode (nLevel, nColorBits, pLeafCount,
pReducibleNodes);
// Update color information if it's a leaf node
if ((*ppNode)->bIsLeaf) {
(*ppNode)->nPixelCount++;
(*ppNode)->nRedSum += r;
(*ppNode)->nGreenSum += g;
(*ppNode)->nBlueSum += b;
}
// Recurse a level deeper if the node is not a leaf
else {
shift = 7 - nLevel;
nIndex = (((r & mask[nLevel]) >> shift) << 2) |
(((g & mask[nLevel]) >> shift) << 1) |
((b & mask[nLevel]) >> shift);
AddColor (&((*ppNode)->pChild[nIndex]), r, g, b, nColorBits,
nLevel + 1, pLeafCount, pReducibleNodes);
}
}
NODE* CreateNode (UINT nLevel, UINT nColorBits, UINT* pLeafCount,
NODE** pReducibleNodes)
{
NODE* pNode;
if ((pNode = (NODE*) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
sizeof (NODE))) == NULL)
return NULL;
pNode->bIsLeaf = (nLevel == nColorBits) ? TRUE : FALSE;
if (pNode->bIsLeaf)
(*pLeafCount)++;
else { // Add the node to the reducible list for this level
pNode->pNext = pReducibleNodes[nLevel];
pReducibleNodes[nLevel] = pNode;
}
return pNode;
}
void ReduceTree (UINT nColorBits, UINT* pLeafCount, NODE** pReducibleNodes)
{
int i;
NODE* pNode;
UINT nRedSum, nGreenSum, nBlueSum, nChildren;
// Find the deepest level containing at least one reducible node
for (i=nColorBits - 1; (i>0) && (pReducibleNodes[i] == NULL); i--);
// Reduce the node most recently added to the list at level i
pNode = pReducibleNodes[i];
pReducibleNodes[i] = pNode->pNext;
nRedSum = nGreenSum = nBlueSum = nChildren = 0;
for (i=0; i<8; i++) {
if (pNode->pChild[i] != NULL) {
nRedSum += pNode->pChild[i]->nRedSum;
nGreenSum += pNode->pChild[i]->nGreenSum;
nBlueSum += pNode->pChild[i]->nBlueSum;
pNode->nPixelCount += pNode->pChild[i]->nPixelCount;
HeapFree (GetProcessHeap (), 0, pNode->pChild[i]);
pNode->pChild[i] = NULL;
nChildren++;
}
}
pNode->bIsLeaf = TRUE;
pNode->nRedSum = nRedSum;
pNode->nGreenSum = nGreenSum;
pNode->nBlueSum = nBlueSum;
*pLeafCount -= (nChildren - 1);
}
void DeleteTree (NODE** ppNode)
{
int i;
for (i=0; i<8; i++) {
if ((*ppNode)->pChild[i] != NULL)
DeleteTree (&((*ppNode)->pChild[i]));
}
HeapFree (GetProcessHeap (), 0, *ppNode);
*ppNode = NULL;
}
void GetPaletteColors (NODE* pTree, PALETTEENTRY* pPalEntries, UINT* pIndex)
{
int i;
if (pTree->bIsLeaf) {
pPalEntries[*pIndex].peRed =
(BYTE) ((pTree->nRedSum) / (pTree->nPixelCount));
pPalEntries[*pIndex].peGreen =
(BYTE) ((pTree->nGreenSum) / (pTree->nPixelCount));
pPalEntries[*pIndex].peBlue =
(BYTE) ((pTree->nBlueSum) / (pTree->nPixelCount));
(*pIndex)++;
}
else {
for (i=0; i<8; i++) {
if (pTree->pChild[i] != NULL)
GetPaletteColors (pTree->pChild[i], pPalEntries, pIndex);
}
}
}
int GetRightShiftCount (DWORD dwVal)
{
int i;
for (i=0; i<sizeof (DWORD) * 8; i++) {
if (dwVal & 1)
return i;
dwVal >>= 1;
}
return -1;
}
int GetLeftShiftCount (DWORD dwVal)
{
int nCount, i;
nCount = 0;
for (i=0; i<sizeof (DWORD) * 8; i++) {
if (dwVal & 1)
nCount++;
dwVal >>= 1;
}
return (8 - nCount);
}
/*************************************************************************
*
* ChangeDIBFormat()
*
* Parameter:
*
* HDIB - handle to packed-DIB in memory
*
* -DIB内存块句柄
*
* WORD - desired bits per pixel
* -希望的每像素位数
*
* DWORD - desired compression format
* -希望的压缩格式
*
* Return Value:
*
* HDIB - handle to the new DIB if successful, else NULL
* -新的位图句柄
*
* Description:
*
* This function will convert the bits per pixel and/or the compression
* format of the specified DIB. Note: If the conversion was unsuccessful,
* we return NULL. The original DIB is left alone. Don't use code like the
* following:
*
* hMyDIB = ChangeDIBFormat(hMyDIB, 8, BI_RLE4);
*
* The conversion will fail, but hMyDIB will now be NULL and the original
* DIB will now hang around in memory. We could have returned the old
* DIB, but we wanted to allow the programmer to check whether this
* conversion succeeded or failed.
* 注意:本函数将DIB转化为指定格式DDB,源位图将不被修改,不要象下例一样调用
* hMyDIB = ChangeDIBFormat(hMyDIB,8,BI_RLE4)
* 否则转化将失败,hMyDIB将为NULL,而源位图所站的内存将不被释放。
*
*
************************************************************************/
HDIB ChangeDIBFormat(HDIB hDIB, WORD wBitCount, DWORD dwCompression)
{
HBITMAP hBitmap; // Handle to bitmap
HDIB hNewDIB = NULL; // Handle to new DIB
HPALETTE hPal; // Handle to palette
// Check for a valid DIB handle
if (!hDIB)
return NULL;
// Save the old DIB's palette
hPal = CreateDIBPalette(hDIB);
if (hPal == NULL)
hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
// Convert old DIB to a bitmap
hBitmap = DIBToBitmap(hDIB, hPal);
if (!hBitmap)
{
DeleteObject(hPal);
return NULL;
}
// Change bitmap format
hNewDIB = ChangeBitmapFormat(hBitmap, wBitCount, dwCompression, hPal);
// Clean up and return
DeleteObject(hBitmap);
DeleteObject(hPal);
return hNewDIB;
}
/****************************************************************************
*
* FUNCTION: ConvertDIBFormat
*
* PURPOSE: Creates a new DIB of the requested format, copies the source
* image to the new DIB.
*
* 功能:用指定的格式来创建DIB,将源图像拷贝到新DIB中
*
* PARAMS: LPBITMAPINFO lpSrcDIB - the source CF_DIB
* UINT nWidth - width for new DIB
* UINT nHeight - height for new DIB
* UINT nbpp - bpp for new DIB
* BOOL bStretch - TRUE to stretch source to dest
* FALSE to take upper left of image
* TRUE:伸缩源位图到目标位图,FALSE:按原图像大小进行显示,起点为左上角
HPALETTE hPalSrc - Palette used to set new DIB
* DWORD dwSize - return the size of new DIB pointer
*
* RETURNS: HDIB - Handle of CF_DIB memory block with new image
* NULL on failure
*
\****************************************************************************/
HDIB ConvertDIBFormat(LPBYTE lpDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch, HPALETTE hPalSrc)
{
LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)lpDIB;
LPBITMAPINFO lpbmi = NULL;
LPBYTE lpSourceBits, lpTargetBits, lpResult;
HDC hDC = NULL, hSourceDC, hTargetDC;
HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap;
DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum;
HDIB hDib;
// Allocate and fill out a BITMAPINFO struct for the new DIB
if (nbpp <= 8)
dwColorNum = 1 << nbpp;
else
dwColorNum = 0;
dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) );
lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize );
lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
lpbmi->bmiHeader.biWidth = nWidth;
lpbmi->bmiHeader.biHeight = nHeight;
lpbmi->bmiHeader.biPlanes = 1;
lpbmi->bmiHeader.biBitCount = nbpp;
lpbmi->bmiHeader.biCompression = BI_RGB;
lpbmi->bmiHeader.biSizeImage = 0;
lpbmi->bmiHeader.biXPelsPerMeter = 0;
lpbmi->bmiHeader.biYPelsPerMeter = 0;
lpbmi->bmiHeader.biClrUsed = 0;
lpbmi->bmiHeader.biClrImportant = 0;
// Fill in the color table
if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) )
{
free( lpbmi );
return NULL;
}
// Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
hDC = GetDC( NULL );
hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 );
hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 );
hSourceDC = CreateCompatibleDC( hDC );
hTargetDC = CreateCompatibleDC( hDC );
// Flip the bits on the source DIBSection to match the source DIB
dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader));
dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader));
memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize );
lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize;
// Select DIBSections into DCs
hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );
hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap );
// Set the color tables for the DIBSections
if( lpSrcDIB->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors );
if( lpbmi->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors );
// If we are asking for a straight copy, do it
if( (lpSrcDIB->bmiHeader.biWidth==lpbmi->bmiHeader.biWidth) && (lpSrcDIB->bmiHeader.biHeight==lpbmi->bmiHeader.biHeight) )
{
BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY );
}
else
{
// else, should we stretch it?
if( bStretch )
{
SetStretchBltMode( hTargetDC, COLORONCOLOR );
StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY );
}
else
{
// or just take the upper left corner of the source
BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY );
}
}
// Clean up and delete the DCs
SelectObject( hSourceDC, hOldSourceBitmap );
SelectObject( hTargetDC, hOldTargetBitmap );
DeleteDC( hSourceDC );
DeleteDC( hTargetDC );
ReleaseDC( NULL, hDC );
// Flush the GDI batch, so we can play with the bits
GdiFlush();
// Allocate enough memory for the new CF_DIB, and copy bits
hDib = GlobalAlloc(GHND, dwTargetHeaderSize + dwTargetBitsSize );
lpResult = (LPBYTE)GlobalLock(hDib);
memcpy( lpResult, lpbmi, dwTargetHeaderSize );
memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize );
// final cleanup
DeleteObject( hTargetBitmap );
DeleteObject( hSourceBitmap );
free( lpbmi );
GlobalUnlock(hDib);
return hDib;
}
/* End ConvertDIBFormat() 1***************************************************/
/****************************************************************************
*
* FUNCTION: ConvertDIBFormat
*
* PURPOSE: Creates a new DIB of the requested format, copies the source
* image to the new DIB.
*
* PARAMS: HDIB hDIB - the source CF_DIB
* UINT nWidth - width for new DIB
* UINT nHeight - height for new DIB
* UINT nbpp - bpp for new DIB
* BOOL bStretch - TRUE to stretch source to dest
* FALSE to take upper left of image
* HPALETTE hPalSrc - Palette used to set new DIB
*
* RETURNS: HDIB - new CF_DIB handle
*
\****************************************************************************/
HDIB ConvertDIBFormat(HDIB hDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch, HPALETTE hPalSrc)
{
LPBITMAPINFO lpbmi = NULL;
LPBYTE lpSourceBits, lpTargetBits, lpResult;
HDC hDC = NULL, hSourceDC, hTargetDC;
HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap;
DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum;
HDIB hNewDIB;
DWORD dwSize;
// Get DIB pointer
if (! hDIB)
return NULL;
LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
if (! lpSrcDIB)
return NULL;
// Allocate and fill out a BITMAPINFO struct for the new DIB
if (nbpp <= 8)
dwColorNum = 1 << nbpp;
else
dwColorNum = 0;
dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) );
lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize );
lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
lpbmi->bmiHeader.biWidth = nWidth;
lpbmi->bmiHeader.biHeight = nHeight;
lpbmi->bmiHeader.biPlanes = 1;
lpbmi->bmiHeader.biBitCount = nbpp;
lpbmi->bmiHeader.biCompression = BI_RGB;
lpbmi->bmiHeader.biSizeImage = 0;
lpbmi->bmiHeader.biXPelsPerMeter = 0;
lpbmi->bmiHeader.biYPelsPerMeter = 0;
lpbmi->bmiHeader.biClrUsed = 0;
lpbmi->bmiHeader.biClrImportant = 0;
// Fill in the color table
if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) )
{
free( lpbmi );
return NULL;
}
// Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
hDC = GetDC( NULL );
hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 );
hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 );
hSourceDC = CreateCompatibleDC( hDC );
hTargetDC = CreateCompatibleDC( hDC );
// Flip the bits on the source DIBSection to match the source DIB
dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader));
dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader));
memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize );
lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize;
// Select DIBSections into DCs
hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );
hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap );
// Set the color tables for the DIBSections
if( lpSrcDIB->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors );
if( lpbmi->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors );
// If we are asking for a straight copy, do it
if( (lpSrcDIB->bmiHeader.biWidth==lpbmi->bmiHeader.biWidth) && (lpSrcDIB->bmiHeader.biHeight==lpbmi->bmiHeader.biHeight) )
{
BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY );
}
else
{
// else, should we stretch it?
if( bStretch )
{
SetStretchBltMode( hTargetDC, COLORONCOLOR );
StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY );
}
else
{
// or just take the upper left corner of the source
BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY );
}
}
// Clean up and delete the DCs
SelectObject( hSourceDC, hOldSourceBitmap );
SelectObject( hTargetDC, hOldTargetBitmap );
DeleteDC( hSourceDC );
DeleteDC( hTargetDC );
ReleaseDC( NULL, hDC );
// Flush the GDI batch, so we can play with the bits
GdiFlush();
// Allocate enough memory for the new CF_DIB, and copy bits
dwSize = dwTargetHeaderSize + dwTargetBitsSize;
hNewDIB = GlobalAlloc(GHND, dwSize);
lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize );
memcpy( lpResult, lpbmi, dwTargetHeaderSize );
memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize );
// final cleanup
DeleteObject( hTargetBitmap );
DeleteObject( hSourceBitmap );
free( lpbmi );
GlobalUnlock(hDIB);
GlobalUnlock(hNewDIB);
return hNewDIB;
}
/* End ConvertDIBFormat() 2***************************************************/
/****************************************************************************
*
* FUNCTION: ConvertDIBFormat
*
* PURPOSE: Creates a new DIB of the requested format, copies the source
* image to the new DIB.
*
* PARAMS: LPBYTE lpDIB - the source CF_DIB
* UINT nbpp - bpp for new DIB
* HPALETTE hPalSrc - Palette used to set new DIB
*
* RETURNS: HDIB - new CF_DIB handle
*
\****************************************************************************/
HDIB ConvertDIBFormat(LPBYTE lpDIB, UINT nbpp, HPALETTE hPalSrc)
{
LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)lpDIB;
LPBITMAPINFO lpbmi = NULL;
LPBYTE lpSourceBits, lpTargetBits, lpResult;
HDC hDC = NULL, hSourceDC, hTargetDC;
HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap;
DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum;
HDIB hNewDIB;
DWORD dwSize;
int nWidth, nHeight;
nWidth = lpSrcDIB->bmiHeader.biWidth;
nHeight = lpSrcDIB->bmiHeader.biHeight;
// Allocate and fill out a BITMAPINFO struct for the new DIB
if (nbpp <= 8)
dwColorNum = 1 << nbpp;
else
dwColorNum = 0;
dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) );
lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize );
lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
lpbmi->bmiHeader.biWidth = nWidth;
lpbmi->bmiHeader.biHeight = nHeight;
lpbmi->bmiHeader.biPlanes = 1;
lpbmi->bmiHeader.biBitCount = nbpp;
lpbmi->bmiHeader.biCompression = BI_RGB;
lpbmi->bmiHeader.biSizeImage = 0;
lpbmi->bmiHeader.biXPelsPerMeter = 0;
lpbmi->bmiHeader.biYPelsPerMeter = 0;
lpbmi->bmiHeader.biClrUsed = 0;
lpbmi->bmiHeader.biClrImportant = 0;
// Fill in the color table
if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) )
{
free( lpbmi );
return NULL;
}
// Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
hDC = GetDC( NULL );
hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 );
hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 );
hSourceDC = CreateCompatibleDC( hDC );
hTargetDC = CreateCompatibleDC( hDC );
// Flip the bits on the source DIBSection to match the source DIB
dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader));
dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader));
memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize );
lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize;
// Select DIBSections into DCs
hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );
hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap );
// Set the color tables for the DIBSections
if( lpSrcDIB->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors );
if( lpbmi->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors );
// We are asking for a straight copy, do it
BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY );
// Clean up and delete the DCs
SelectObject( hSourceDC, hOldSourceBitmap );
SelectObject( hTargetDC, hOldTargetBitmap );
DeleteDC( hSourceDC );
DeleteDC( hTargetDC );
ReleaseDC( NULL, hDC );
// Flush the GDI batch, so we can play with the bits
GdiFlush();
// Allocate enough memory for the new CF_DIB, and copy bits
dwSize = dwTargetHeaderSize + dwTargetBitsSize;
hNewDIB = GlobalAlloc(GHND, dwSize);
lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize );
memcpy( lpResult, lpbmi, dwTargetHeaderSize );
memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize );
// final cleanup
DeleteObject( hTargetBitmap );
DeleteObject( hSourceBitmap );
free( lpbmi );
GlobalUnlock(hNewDIB);
return hNewDIB;
}
/* End ConvertDIBFormat() 3***************************************************/
/****************************************************************************
*
* FUNCTION: ConvertDIBFormat
*
* PURPOSE: Creates a new DIB of the requested format, copies the source
* image to the new DIB.
*
* PARAMS: HDIB hDIB - the source CF_DIB
* UINT nbpp - bpp for new DIB
* HPALETTE hPalSrc - Palette used to set new DIB
*
* RETURNS: HDIB - new CF_DIB handle
*
\****************************************************************************/
HDIB ConvertDIBFormat(HDIB hDIB, UINT nbpp, HPALETTE hPalSrc)
{
LPBITMAPINFO lpbmi = NULL;
LPBYTE lpSourceBits, lpTargetBits, lpResult;
HDC hDC = NULL, hSourceDC, hTargetDC;
HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap;
DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum;
HANDLE hNewDIB;
DWORD dwSize;
int nWidth, nHeight;
// Get DIB pointer
if (! hDIB)
return NULL;
LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
if (! lpSrcDIB)
return NULL;
nWidth = lpSrcDIB->bmiHeader.biWidth;
nHeight = lpSrcDIB->bmiHeader.biHeight;
// Allocate and fill out a BITMAPINFO struct for the new DIB
if (nbpp <= 8)
dwColorNum = 1 << nbpp;
else
dwColorNum = 0;
dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) );
lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize );
lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
lpbmi->bmiHeader.biWidth = nWidth;
lpbmi->bmiHeader.biHeight = nHeight;
lpbmi->bmiHeader.biPlanes = 1;
lpbmi->bmiHeader.biBitCount = nbpp;
lpbmi->bmiHeader.biCompression = BI_RGB;
lpbmi->bmiHeader.biSizeImage = 0;
lpbmi->bmiHeader.biXPelsPerMeter = 0;
lpbmi->bmiHeader.biYPelsPerMeter = 0;
lpbmi->bmiHeader.biClrUsed = 0;
lpbmi->bmiHeader.biClrImportant = 0;
// Fill in the color table
if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) )
{
free( lpbmi );
return NULL;
}
// Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
hDC = GetDC( NULL );
hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 );
hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 );
hSourceDC = CreateCompatibleDC( hDC );
hTargetDC = CreateCompatibleDC( hDC );
// Flip the bits on the source DIBSection to match the source DIB
dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader));
dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader));
memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize );
lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize;
// Select DIBSections into DCs
hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );
hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap );
// Set the color tables for the DIBSections
if( lpSrcDIB->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors );
if( lpbmi->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors );
// We are asking for a straight copy, do it
BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY );
// Clean up and delete the DCs
SelectObject( hSourceDC, hOldSourceBitmap );
SelectObject( hTargetDC, hOldTargetBitmap );
DeleteDC( hSourceDC );
DeleteDC( hTargetDC );
ReleaseDC( NULL, hDC );
// Flush the GDI batch, so we can play with the bits
GdiFlush();
// Allocate enough memory for the new CF_DIB, and copy bits
dwSize = dwTargetHeaderSize + dwTargetBitsSize;
hNewDIB = GlobalAlloc(GHND, dwSize);
lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize );
memcpy( lpResult, lpbmi, dwTargetHeaderSize );
memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize );
// final cleanup
DeleteObject( hTargetBitmap );
DeleteObject( hSourceBitmap );
free( lpbmi );
GlobalUnlock(hDIB);
GlobalUnlock(hNewDIB);
return hNewDIB;
}
/* End ConvertDIBFormat() 4***************************************************/
/****************************************************************************
*
* FUNCTION: CopyColorTable
*
* PURPOSE: Copies the color table from one CF_DIB to another.
*
* 功能:用于格式转换时颜色表的拷贝,保证不丢失颜色,如果DIB从高颜色分辨率到
* 低颜色分辨率的转化时,用此函数进行量化,并调用创建相应调色板函数CreateOctreePalette
*
* PARAMS: LPBITMAPINFO lpTarget - pointer to target DIB
* LPBITMAPINFO lpSource - pointer to source DIB
*
* RETURNS: BOOL - TRUE for success, FALSE for failure
*
\****************************************************************************/
BOOL CopyColorTable( LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource, HPALETTE hPalSrc )
{
// What we do depends on the target's color depth
switch( lpTarget->bmiHeader.biBitCount )
{
// 8bpp - need 256 entry color table
case 8:
if (hPalSrc)
{ // Palette is provided, use it
PALETTEENTRY pe[256];
UINT i;
GetPaletteEntries( hPalSrc, 0, 256, pe );
for(i=0;i<256;i++)
{
lpTarget->bmiColors[i].rgbRed = pe[i].peRed;
lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen;
lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue;
lpTarget->bmiColors[i].rgbReserved = 0;
}
}
else
{ // no palette povided
if( lpSource->bmiHeader.biBitCount == 8 )
{ // Source is 8bpp too, copy color table
memcpy( lpTarget->bmiColors, lpSource->bmiColors, 256*sizeof(RGBQUAD) );
}
else
{ // Source is != 8bpp, use Octree algorithm to create palette
HPALETTE hPal;
HDC hDC = GetDC( NULL );
PALETTEENTRY pe[256];
UINT i;
hPal = CreateOctreePalette((LPBYTE)lpSource, 236, 8);
if (! hPal) // use halftone palette
hPal = CreateHalftonePalette( hDC );
ReleaseDC( NULL, hDC );
GetPaletteEntries( hPal, 0, 256, pe );
DeleteObject( hPal );
for(i=0;i<256;i++)
{
lpTarget->bmiColors[i].rgbRed = pe[i].peRed;
lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen;
lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue;
lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags;
}
}
}
break; // end 8bpp
// 4bpp - need 16 entry color table
case 4:
if (hPalSrc)
{ // Palette is provided, use it
PALETTEENTRY pe[16];
UINT i;
GetPaletteEntries( hPalSrc, 0, 16, pe );
for(i=0;i<16;i++)
{
lpTarget->bmiColors[i].rgbRed = pe[i].peRed;
lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen;
lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue;
lpTarget->bmiColors[i].rgbReserved = 0;
}
}
else
{ // No palette is provided
if( lpSource->bmiHeader.biBitCount == 4 )
{ // Source is 4bpp too, copy color table
memcpy( lpTarget->bmiColors, lpSource->bmiColors, 16*sizeof(RGBQUAD) );
}
else
{ // Source is != 4bpp, use system palette
HPALETTE hPal;
PALETTEENTRY pe[256];
UINT i;
hPal = (HPALETTE)GetStockObject( DEFAULT_PALETTE );
GetPaletteEntries( hPal, 0, 16, pe );
for(i=0;i<16;i++)
{
lpTarget->bmiColors[i].rgbRed = pe[i].peRed;
lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen;
lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue;
lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags;
}
}
}
break; // end 4bpp
// 1bpp - need 2 entry mono color table
case 1:
lpTarget->bmiColors[0].rgbRed = 0;
lpTarget->bmiColors[0].rgbGreen = 0;
lpTarget->bmiColors[0].rgbBlue = 0;
lpTarget->bmiColors[0].rgbReserved = 0;
lpTarget->bmiColors[1].rgbRed = 255;
lpTarget->bmiColors[1].rgbGreen = 255;
lpTarget->bmiColors[1].rgbBlue = 255;
lpTarget->bmiColors[1].rgbReserved = 0;
break; // end 1bpp
// no color table for the > 8bpp modes
case 32:
case 24:
case 16:
default:
break;
}
return TRUE;
}
/* End CopyColorTable() *****************************************************/
/****************************************************************************
*
* FUNCTION: DIBToDIBSection
*
* 功能:根据DIB创建DIBSection
*
* PURPOSE: Create DIBSECTION from DIB
*
* PARAMS: LPBYTE lpDIB - pointer to DIB data buffer
*
* 参数:DIB数据缓冲区地址
*
* RETURNS: HBITMAP - handle of DIBSECTION, or NULL for failure
*
\****************************************************************************/
HBITMAP DIBToDIBSection(LPBYTE lpDIB)
{
LPBYTE lpSourceBits;
HDC hDC = NULL, hSourceDC;
HBITMAP hSourceBitmap, hOldSourceBitmap;
DWORD dwSourceBitsSize;
LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)lpDIB;
if (! lpSrcDIB)
return NULL;
// Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
hDC = GetDC( NULL );
hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 );
hSourceDC = CreateCompatibleDC( hDC );
// Flip(变址浮点运算) the bits on the source DIBSection to match the source DIB
dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader));
memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize );
// Select DIBSections into DCs
hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );
// Set the color tables for the DIBSections
if( lpSrcDIB->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors );
// Clean up and delete the DCs
SelectObject( hSourceDC, hOldSourceBitmap );
DeleteDC( hSourceDC );
ReleaseDC( NULL, hDC );
// Flush the GDI batch, so we can play with the bits
GdiFlush();
return hSourceBitmap;
}
// Create DIBSECTION from DIB
HBITMAP DIBToDIBSection(HDIB hDIB)
{
HBITMAP hSourceBitmap;
// Get DIB pointer
if (! hDIB)
return NULL;
LPBYTE lpSrcDIB = (LPBYTE)GlobalLock(hDIB);
if (! lpSrcDIB)
return NULL;
hSourceBitmap = DIBToDIBSection(lpSrcDIB);
// final cleanup
GlobalUnlock(hDIB);
return hSourceBitmap;
}
/****************************************************************************
*
* FUNCTION: DIBSectionToDIB
*
* PURPOSE: Create DIB from DIBSECTION
*
* PARAMS: HBITMAP - handle of DIBSECTION, or NULL for failure
*
* RETURNS: HBITMAP hBitmap - DIB handle
*
\****************************************************************************/
HDIB DIBSectionToDIB(HBITMAP hBitmap)
{
HDC hDC = NULL, hSourceDC;
HBITMAP hOldSourceBitmap;
HANDLE hNewDIB;
LPBITMAPINFO lpbmi = NULL;
DWORD dwSize;
DIBSECTION ds;
DWORD dwColorNum;
// get DIB info
GetObject(hBitmap, sizeof(DIBSECTION), &ds);
dwColorNum = ds.dsBmih.biClrUsed;
if (dwColorNum == 0 && ds.dsBmih.biBitCount <= 8)
dwColorNum = 1 << ds.dsBmih.biBitCount;
// Allocate and fill out a BITMAPINFO struct for the new DIB
dwSize = sizeof(BITMAPINFOHEADER) + (dwColorNum * sizeof(RGBQUAD)) + ds.dsBmih.biSizeImage;
hNewDIB = GlobalAlloc(GHND, dwSize);
if (! hNewDIB)
return NULL;
lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB);
if (! lpbmi)
return NULL;
lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
lpbmi->bmiHeader.biWidth = ds.dsBm.bmWidth;
lpbmi->bmiHeader.biHeight = ds.dsBm.bmHeight;
lpbmi->bmiHeader.biPlanes = 1;
lpbmi->bmiHeader.biBitCount = ds.dsBmih.biBitCount;
lpbmi->bmiHeader.biCompression = ds.dsBmih.biCompression;
lpbmi->bmiHeader.biSizeImage = ds.dsBmih.biSizeImage;
lpbmi->bmiHeader.biXPelsPerMeter = ds.dsBmih.biXPelsPerMeter;
lpbmi->bmiHeader.biYPelsPerMeter = ds.dsBmih.biYPelsPerMeter;
lpbmi->bmiHeader.biClrUsed = ds.dsBmih.biClrUsed;
lpbmi->bmiHeader.biClrImportant = ds.dsBmih.biClrImportant;
// get DC for operation
hDC = GetDC( NULL );
// get DIB bits
if (! GetDIBits(hDC,
hBitmap,
0L,
(DWORD)ds.dsBm.bmHeight,
(LPBYTE)lpbmi + (WORD)lpbmi->bmiHeader.biSize + (dwColorNum*sizeof(RGBQUAD)),
(LPBITMAPINFO)lpbmi,
(DWORD)DIB_RGB_COLORS))
{
GlobalUnlock(hNewDIB);
ReleaseDC(NULL,hDC);
return NULL;
}
// memory DC
hSourceDC = CreateCompatibleDC( hDC );
// Select DIBSections into DCs
hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hBitmap );
// Fill in the color table from DIBSection
if( lpbmi->bmiHeader.biBitCount <= 8 )
GetDIBColorTable( hSourceDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors );
// Clean up and delete the DCs
SelectObject( hSourceDC, hOldSourceBitmap );
DeleteDC( hSourceDC );
ReleaseDC( NULL, hDC );
GlobalUnlock(hNewDIB);
return hNewDIB;
}
/*************************************************************************
*
* DIBToBitmap()
*
* Parameters:
*
* HDIB hDIB - specifies the DIB to convert
*
* HPALETTE hPal - specifies the palette to use with the bitmap
*
* Return Value:
*
* HBITMAP - identifies the device-dependent bitmap
*
* Description:
*
* This function creates a bitmap from a DIB using the specified palette.
* If no palette is specified, default is used.
*
* NOTE:
*
* The bitmap returned from this funciton is always a bitmap compatible
* with the screen (e.g. same bits/pixel and color planes) rather than
* a bitmap with the same attributes as the DIB. This behavior is by
* design, and occurs because this function calls CreateDIBitmap to
* do its work, and CreateDIBitmap always creates a bitmap compatible
* with the hDC parameter passed in (because it in turn calls
* CreateCompatibleBitmap).
*
* So for instance, if your DIB is a monochrome(单色) DIB and you call this
* function, you will not get back a monochrome HBITMAP -- you will
* get an HBITMAP compatible with the screen DC, but with only 2
* colors used in the bitmap.
*
* If your application requires a monochrome HBITMAP returned for a
* monochrome DIB, use the function SetDIBits().
*
* Also, the DIBpassed in to the function is not destroyed on exit. This
* must be done later, once it is no longer needed.
*
************************************************************************/
HBITMAP DIBToBitmap(HDIB hDIB, HPALETTE hPal)
{
LPBYTE lpDIBHdr, lpDIBBits; // pointer to DIB header, pointer to DIB bits
HBITMAP hBitmap; // handle to device-dependent bitmap
HDC hDC; // handle to DC
HPALETTE hOldPal = NULL; // handle to a palette
// if invalid handle, return NULL
if (!hDIB)
return NULL;
// lock memory block and get a pointer to it
lpDIBHdr = (LPBYTE)GlobalLock(hDIB);
// get a pointer to the DIB bits
lpDIBBits = FindDIBBits(lpDIBHdr);
// get a DC
hDC = GetDC(NULL);
if (!hDC)
{
// clean up and return NULL
GlobalUnlock(hDIB);
return NULL;
}
// select and realize palette
if (hPal)
{
hOldPal = SelectPalette(hDC, hPal, FALSE);
RealizePalette(hDC);
}
// create bitmap from DIB info and bits
hBitmap = CreateDIBitmap(hDC,
(LPBITMAPINFOHEADER)lpDIBHdr,
CBM_INIT,
lpDIBBits,
(LPBITMAPINFO)lpDIBHdr,
DIB_RGB_COLORS);
//The CreateDIBitmap function creates a compatible bitmap (DDB) from
//a DIB and, optionally, sets the bitmap bits.
// restore previous palette
if (hOldPal)
SelectPalette(hDC, hOldPal, FALSE);
// clean up
ReleaseDC(NULL, hDC);
GlobalUnlock(hDIB);
// return handle to the bitmap
return hBitmap;
}
/*************************************************************************
*
* ChangeBitmapFormat()
*
* Parameter:
*
* HBITMAP - handle to a bitmap
*
* WORD - desired bits per pixel
*
* DWORD - desired compression format
*
* HPALETTE - handle to palette
*
* Return Value:
*
* HDIB - handle to the new DIB if successful, else NULL
*
* Description:
*
* This function will convert a bitmap to the specified bits per pixel
* and compression format. The bitmap and it's palette will remain
* after calling this function.
*
************************************************************************/
HDIB ChangeBitmapFormat (HBITMAP hbm, WORD biBits, DWORD biCompression, HPALETTE hpal)
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen;
HANDLE hdib;
HANDLE h;
HDC hdc;
if (!hbm)
return NULL;
if (hpal == NULL)
hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
GetObject(hbm,sizeof(bm),(LPBYTE)&bm);
if (biBits == 0)
{
biBits = bm.bmPlanes * bm.bmBitsPixel;
// make sure bits per pixel is valid
if (biBits <= 1)
biBits = 1;
else if (biBits <= 4)
biBits = 4;
else if (biBits <= 8)
biBits = 8;
else // if greater than 8-bit, force to 24-bit
biBits = 24;
}
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = biBits;
bi.biCompression = biCompression;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwLen = bi.biSize + PaletteSize((LPBYTE)&bi);
hdc = GetDC(NULL);
HPALETTE hpalT = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc);
hdib = GlobalAlloc(GHND,dwLen);
if (!hdib)
{
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return NULL;
}
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
*lpbi = bi;
/* call GetDIBits with a NULL lpBits param, so it will calculate the
* biSizeImage field for us
*/
GetDIBits(hdc, hbm, 0L, (DWORD)bi.biHeight,
(LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);
bi = *lpbi;
GlobalUnlock(hdib);
/* If the driver did not fill in the biSizeImage field, make one up */
if (bi.biSizeImage == 0)
{
bi.biSizeImage = MYWIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
if (biCompression != BI_RGB)
bi.biSizeImage = (bi.biSizeImage * 3) / 2;
}
/* realloc the buffer big enough to hold all the bits */
dwLen = bi.biSize + PaletteSize((LPBYTE)&bi) + bi.biSizeImage;
if (h = GlobalReAlloc(hdib,dwLen,0))
hdib = h;
else
{
GlobalFree(hdib);
hdib = NULL;
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return hdib;
}
/* call GetDIBits with a NON-NULL lpBits param, and actualy get the
* bits this time
*/
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
if (! GetDIBits(hdc,
hbm,
0L,
(DWORD)bi.biHeight,
(LPBYTE)lpbi + (WORD)lpbi->biSize + PaletteSize((LPBYTE)lpbi),
(LPBITMAPINFO)lpbi,
(DWORD)DIB_RGB_COLORS))
{
GlobalUnlock(hdib);
hdib = NULL;
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return NULL;
}
bi = *lpbi;
GlobalUnlock(hdib);
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return hdib;
}
bool GrayEqualize(HDIB hDib)
{
int nHeight, nWidth, i, j, k;
// 指向源图像的指针
LPBYTE lpSrc = NULL;
WaitCursorBegin();
// 灰度映射表
int bGray[256];
long long bConvert[256],bHist[256];
memset(bGray, 0 , 256* sizeof(int));
memset(bHist, 0 , 256* sizeof(long));
memset(bConvert, 0 , 256* sizeof(long));
LPBYTE lpDIB = (LPBYTE) GlobalLock( hDib );
int nNumColors = DIBBitCount(lpDIB);
if( nNumColors != 8 )
return false;
LPBYTE lpDIBBits = FindDIBBits( lpDIB );
nHeight = DIBHeight( lpDIB );
nWidth = DIBWidth( lpDIB );
// 计算图像每行的字节数
LONG lLineBytes = BytesPerLine( lpDIB );
lpSrc = lpDIBBits;
for (i = 0, k = 0; i < nHeight; ++i, k += lLineBytes )
{
lpSrc = lpDIBBits + k;
for ( j = 0; j < nWidth; ++j, ++lpSrc )
{
bGray[*(lpSrc)]++;
}
}
bHist[0] = bGray[0];
long long *pHist = bHist;
int *pGray = bGray;
long long *pConver = bConvert;
int nTotal = nHeight * nWidth;
*pConver ++ = (long) (*pHist * 255)/nTotal;
pHist++;
pGray++;
for ( i = 1; i <= 255; i++, pHist++, pGray++ , pConver ++)
{
*pHist = *pGray + *(pHist-1); //形成累积直方图
*pConver =((long long ) (*pHist) )*255 / nTotal ;
}
for ( i = 0, k = 0; i < nHeight; i++, k+= lLineBytes )
{
lpSrc = lpDIBBits + k;
for ( j = 0; j < nWidth; j++, lpSrc ++ )
{
*lpSrc = bConvert[*lpSrc]; //更新原始位图数据
}
}
GlobalUnlock( hDib );
WaitCursorEnd();
return true;
}
bool GrayStretchDIB(int nMethod, HDIB hDib,BYTE bX1 = 0,BYTE bY1 = 0 ,BYTE bX2 = 255, BYTE bY2 = 255 )
{
WaitCursorBegin();
LPBYTE lpDIB,lpDIBBits;
DWORD lHeight,lWidth;
// 指向源图像的指针
unsigned char* lpSrc;
// 循环变量
LONG i = 0;
// LONG j;
// 灰度映射表
BYTE bMap[256];
// 图像每行的字节数
LONG lLineBytes;
lpDIB = (LPBYTE) GlobalLock( hDib );
lpDIBBits = FindDIBBits( lpDIB );
lHeight = DIBHeight( lpDIB );
lWidth = DIBWidth( lpDIB );
// 计算图像每行的字节数
lLineBytes = BytesPerLine( lpDIB);
if( nMethod == 0 ) //自动计算X1, Y1; X2,Y2;
{
int nHist[256];
if( !GetGrayHist(lpDIBBits, lWidth, lHeight, nHist))
return false;
long nCumulHist[256];
if( !GetCumulativeHist(nHist, 256, nCumulHist))
return false;
for( i = 0; i < 256; ++i )
{
if( nCumulHist[i] > lWidth * lHeight / 10 )
{
bX1 = i;
break;
}
}
for( i = 255; i > bX1; --i )
{
if(nCumulHist[i] < lHeight * lWidth * 9 / 10)
{
bX2 = i;
break;
}
}
}
// 计算灰度映射表
memset(bMap, 0 , bX1 * sizeof(BYTE));
float fTmp = 0;
if( bX1 > 0 )
{
fTmp = float(bY1)/int(bX1);
for (i = 0; i <= bX1; i++)
{
// 线性变换
bMap[i] = (BYTE) (i * fTmp);
}
}
if( bX2 == bX1 )//判断bX1是否等于bX2(防止分母为0)
{
memset(bMap+ i, bY1, (bX2 - bX1 + 1) *sizeof(BYTE));
}
else
{
fTmp = float(bY2 - bY1) / int(bX2- bX1);
for (; i <= bX2; i++)
{
// 线性变换
bMap[i] = bY1 + (BYTE) ( (i - bX1) / fTmp);
}
}
fTmp = float ( 255- bY2 ) / int(255- bX2);
if (bX2 == 255 )
{
memset(bMap + i, 255, (255-i +1) *sizeof(BYTE));
}
else
{
for (; i < 256; i++)
{
// 线性变换
bMap[i] = bY2 + (BYTE) (fTmp * (i - bX2));
}
}
// 每行
for(DWORD i1 = 0, k = 0; i1 < lHeight; i1++, k+= lLineBytes )
{
lpSrc = lpDIBBits + k;
// 每列
for(DWORD j1 = 0; j1 < lWidth; j1++, lpSrc++)
{
// 计算新的灰度值
*lpSrc = bMap[*lpSrc];
}
}
GlobalUnlock( hDib );
WaitCursorEnd();
// 返回
return TRUE;
}
bool GetGrayHist(const BYTE * pbImg, const int nImgWid, const int nImgHei, int *pnHist )
{
if( pbImg == NULL || pnHist == NULL || nImgWid < 1 || nImgHei < 1 )
return false;
int i, j, k, nBytePerLine;
const BYTE * lptmpBits = pbImg;
memset(pnHist, 0, 256 * sizeof(int));
nBytePerLine = MYWIDTHBYTES(nImgWid << 3);
for ( i = 0, k = 0; i < nImgHei; i++, k += nBytePerLine ) //ImageSize should be greater.
{
lptmpBits = pbImg + k;
for ( j = 0; j < nImgWid; j++ )
{
pnHist[*lptmpBits ]++;
lptmpBits++;
}
}
return true;
}
bool GetCumulativeHist(const int *pnHist, int nLength, long *pnCuHist)
{
if( pnHist == NULL || pnCuHist == NULL || nLength < 1 )
return false;
memset( pnCuHist, 0, nLength * sizeof(long) );
const int *pnIn = pnHist;
long * pnOut = pnCuHist;
*pnOut ++ = *pnIn ++;
for( int i = 1; i < 256; i++, pnOut++, pnIn++ )
{
*pnOut = *pnIn + *(pnOut - 1);
}
return true;
}
// nMethod: 0:去污,原来白色的变为黑色,原来黑色的变成白色
// nMethod: 1 :磨白,把选中的区域变成白色
// nMethod 2:填充, 把选中的区域变成黑色
bool EliminateDirtDIB(int nMethod, HDIB hDib, CRect rect)
{
WaitCursorBegin();
LPBYTE lpDIB,lpDIBBits;
lpDIB = lpDIBBits = NULL;
lpDIB = (LPBYTE) GlobalLock( hDib );
DWORD lHeight, lWidth;
lpDIBBits = FindDIBBits( lpDIB );
lHeight = DIBHeight( lpDIB );
lWidth = DIBWidth( lpDIB );
// 计算图像每行的字节数
LONG lLineBytes = BytesPerLine( lpDIB);
// 指向源图像的指针
unsigned char* lpSrc = lpDIBBits;
BYTE btmp = 0;
int i, j, k, nSum = 0;
if( nMethod == 0 )
{
for( i = lHeight - rect.bottom, k = i * lLineBytes; i < lHeight - rect.top; i++, k += lLineBytes )
{
lpSrc = lpDIBBits + k + rect.left/8;
for( j = rect.left/8; j < rect.right/8; j++, lpSrc++ )
{
if( *lpSrc == 255 )
nSum++;
}
}
if( nSum < rect.Width() * rect.Height() / 2 )
btmp = 255;
}
else if(nMethod == 1)
{
btmp = 255;
}
else
{
btmp = 0;
}
for( i = lHeight - rect.bottom, k = i * lLineBytes; i < lHeight - rect.top; i++, k += lLineBytes )
{
lpSrc = lpDIBBits + k + rect.left/8;
for( int j = rect.left/8; j < rect.right/8; j++, lpSrc++ )
{
*lpSrc = btmp;
}
}
GlobalUnlock( hDib );
WaitCursorEnd();
return true;
}
// nMethod: 0:去污,原来白色的变为黑色,原来黑色的变成白色
// nMethod:1 :磨白,把选中的区域变成白色
// nMethod 2:填充,把选中的区域变成黑色
bool EliminateDirtDIB(int nMethod, HDIB hDib, int nCircleX, int nCircleY, int nRadius )
{
WaitCursorBegin();
LPBYTE lpDIB,lpDIBBits;
lpDIB = lpDIBBits = NULL;
lpDIB = (LPBYTE) GlobalLock( hDib );
DWORD lHeight, lWidth;
lpDIBBits = FindDIBBits( lpDIB );
lHeight = DIBHeight( lpDIB );
lWidth = DIBWidth( lpDIB );
// 计算图像每行的字节数
LONG lLineBytes = BytesPerLine( lpDIB);
// 指向源图像的指针
unsigned char* lpSrc = lpDIBBits;
int nLeft, nRight, nTop, nBottom, nX2, nY2, nC2;
BYTE btmp = 0;
nLeft = nCircleX - nRadius > 0 ? nCircleX - nRadius : 0;
nRight = nCircleX + nRadius < lWidth ? nCircleX + nRadius : lWidth - 1;
nTop = lHeight - 1 - nCircleY - nRadius > 0 ? lHeight - 1 - nCircleY - nRadius : 0;
nBottom = lHeight - 1 - nCircleY + nRadius < lHeight ? lHeight - 1 - nCircleY + nRadius : lHeight - 1;
nC2 = nRadius * nRadius;
int i, j, k, nSum = 0;
if( nMethod == 0 )
{
for( i = nTop, k = i * lLineBytes; i < nBottom; i++, k += lLineBytes )
{
lpSrc = lpDIBBits + k + nLeft/8;
nY2 = (lHeight - 1 - nCircleY - i) * (lHeight - 1 - nCircleY - i);
for( j = nLeft/8; j < nRight/8; j++, lpSrc++ )
{
nX2 =( j * 8 - nCircleX ) * ( j * 8 - nCircleX);
if( nX2 + nY2 < nC2 && *lpSrc == 255 )
{
nSum++;
}
}
}
if(nSum < 3.14 * nRadius * nRadius/2 )
btmp = 255;
}
else if( nMethod == 1 )
{
btmp = 255;
}
else
{
btmp = 0;
}
for( i = nTop, k = i * lLineBytes; i < nBottom; i++, k += lLineBytes )
{
lpSrc = lpDIBBits + k + nLeft/8;
nY2 = (lHeight - 1 - nCircleY - i) * (lHeight - 1 - nCircleY - i);
for( j = nLeft/8; j < nRight/8; j++, lpSrc++ )
{
nX2 =( j * 8 - nCircleX ) * ( j * 8 - nCircleX);
if( nX2 + nY2 < nC2 )
{
*lpSrc = btmp;
}
}
}
GlobalUnlock( hDib );
WaitCursorEnd();
return true;
}
//saving bi-bitmap to file, only for debug
void SaveTo8bit_BMP(const BYTE* pbInputMat, int Width, int Height, const char* szFileName, int nGrayLevel)
{
const BYTE* pbInput = pbInputMat;
int nNewWidth = (Width + 3) / 4 * 4;
long imageSize = nNewWidth * Height;
BYTE* TmpImg = new BYTE[imageSize];
memset(TmpImg, 255, imageSize * sizeof(BYTE));
if (nGrayLevel == 2)
{
for (int i = 0; i < Height; ++i)
{
for (int j = 0; j < Width/8; ++j)
{
TmpImg[(Height-i-1)*nNewWidth + j] = 255 - pbInput[i*Width+j]*255;
}
}
}
else if (nGrayLevel == 8)
{
for (int i = 0; i < Height; ++i)
{
for (int j = 0; j < Width; ++j)
{
TmpImg[i*nNewWidth + j] = pbInput[i*nNewWidth+j];
}
}
}
else
{
return;
}
BYTE pbHead[1078];
memset(pbHead, 0, 1078 * sizeof(BYTE));
//设置各字段值
pbHead[0] = 0x42; //0x4d42
pbHead[1] = 0x4D;
DWORD nSize = imageSize + 1078;
memcpy(pbHead + 2, &nSize, sizeof(DWORD));//size
pbHead[10] = 0x36; //offset
pbHead[11] = 0x04;
pbHead[12] = 0;
pbHead[13] = 0;
pbHead[14] = 0x28;
LONG nxSize = nNewWidth;
memcpy(pbHead + 18, &nxSize, sizeof(LONG));//WIDTH
nxSize = Height;
memcpy(pbHead + 22, &nxSize, sizeof(LONG));//HEIGHT
pbHead[26] = 0x1;
pbHead[28] = 0x8;
memcpy(pbHead + 34, &nSize, sizeof(DWORD));
//pbHead[47] = 0x1;
for (int i = 0 ; i < 256 ; i++)
{
pbHead[54 + i * 4] = i;
pbHead[54 + i * 4 + 1] = i;
pbHead[54 + i * 4 + 2] = i;
pbHead[54 + i * 4 + 3] = 0;
}
FILE* mFile = fopen(szFileName, ("wb"));
if (!mFile)
{
delete[] TmpImg;
return;
}
LPBITMAPFILEHEADER ph = (LPBITMAPFILEHEADER)pbHead;
LPBITMAPINFOHEADER pinfo = (LPBITMAPINFOHEADER) (pbHead + 14);
fwrite(pbHead, sizeof(BYTE), 1078, mFile);
fwrite(TmpImg, sizeof(BYTE), imageSize, mFile);
fclose(mFile);
delete[] TmpImg;
}
HDIB ChangeDIBSize(HDIB hDIB, int nWidth, int nHeight)
{
LPBITMAPINFO lpbmi = NULL;
LPBYTE lpSourceBits, lpTargetBits, lpResult;
HDC hDC = NULL, hSourceDC, hTargetDC;
HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap;
DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize;
HDIB hNewDIB;
DWORD dwSize;
WaitCursorBegin();
// Get DIB pointer
if (! hDIB)
{
WaitCursorEnd();
return NULL;
}
LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
if (! lpSrcDIB)
{
WaitCursorEnd();
return NULL;
}
// Allocate and fill out a BITMAPINFO struct for the new DIB
dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) + PaletteSize(lpSrcDIB);
lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize );
memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize);
lpbmi->bmiHeader.biWidth = nWidth;
lpbmi->bmiHeader.biHeight = nHeight;
// Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
hDC = GetDC( NULL );
hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 );
hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 );
hSourceDC = CreateCompatibleDC( hDC );
hTargetDC = CreateCompatibleDC( hDC );
// Flip the bits on the source DIBSection to match the source DIB
dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader));
dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader));
memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize );
lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize;
// Select DIBSections into DCs
hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );
hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap );
// put old bitmap in new bitmap
SetStretchBltMode( hTargetDC, COLORONCOLOR );
StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY );
// Clean up and delete the DCs
SelectObject( hSourceDC, hOldSourceBitmap );
SelectObject( hTargetDC, hOldTargetBitmap );
DeleteDC( hSourceDC );
DeleteDC( hTargetDC );
ReleaseDC( NULL, hDC );
// Flush the GDI batch, so we can play with the bits
GdiFlush();
// Allocate enough memory for the new CF_DIB, and copy bits
dwSize = dwTargetHeaderSize + dwTargetBitsSize;
hNewDIB = GlobalAlloc(GHND, dwSize);
lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize );
memcpy( lpResult, lpbmi, dwTargetHeaderSize );
memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize );
// final cleanup
DeleteObject( hTargetBitmap );
DeleteObject( hSourceBitmap );
free( lpbmi );
GlobalUnlock(hDIB);
GlobalUnlock(hNewDIB);
WaitCursorEnd();
return hNewDIB;
}
3)CompConnect.h
#pragma once
#ifndef COMPCONNECT_H
#define COMPCONNECT_H
const UINT COMP_NUM = 1024; //允许连通体的个数
//提取连通体为黑色区域
const BYTE CC_START = 255;
const BYTE CC_CUR = 0;
struct component
{
CRect bound;
int count;
component *cnext;
component()
{
count=0;
cnext=NULL;
}
};
struct Line
{
int StartY;
int EndY;
int StartX;
int EndX;
int LenghthX;
int LenghthY;
int TotalSize;
//Line *Next;
//float Type_Flag;
component *cp;
//Block *pBlkStart;
//float AveComH;
Line()
{
StartX =0;
EndX =0;
StartY = 0;
EndY = 0;
LenghthX = 0;
LenghthY = 0;
TotalSize = 0;
cp = NULL;
}
~Line()
{
component *temp;
while(cp!=NULL)
{
temp = cp;
cp = cp->cnext;
delete temp;
}
}
};
#endif
4)ImgCov.h 用于将jpg、tif等格式的文件转换成DIB格式
#ifndef IMGCONV_H
#define IMGCONV_H
extern "C"
{
#ifdef GENERATE_DLL
#define DLL_EXPORT __declspec(dllexport)
#else // #ifdef GENERATE_DLL
#define DLL_EXPORT
#endif // #ifdef GENERATE_DLL
/* Format Description Qt's support
* BMP Windows Bitmap Read/Write
* GIF Graphic Interchange Format (optional) Read
* JPG Joint Photographic Experts Group Read/Write
* JPEG Joint Photographic Experts Group Read/Write
* PNG Portable Network Graphics Read/Write
* PBM Portable Bitmap Read
* PGM Portable Graymap Read
* PPM Portable Pixmap Read/Write
* TIFF Tagged Image File Format Read/write
* XBM X11 Bitmap Read/Write
* XPM X11 Pixmap Read/Write
* note: this lib's support is exactly same as Qt's.
*/
enum ImageType
{
imgBMP = 0,
imgGIF = 1,
imgJPG = 2,
imgJPEG = 3,
imgPNG = 4,
imgPBM = 5,
imgPGM = 6,
imgPPM = 7,
imgTIFF = 8,
imgXBM = 9,
imgXPM = 10,
imgMax = 10,
};
// ppDestData and pDestDataLen are for outputs;
// when succeeded, *ppDestData is new-ed inside the function, and should be delete-ed by caller calling ImageDelete.
bool DLL_EXPORT ImageConvert(const unsigned char * pSrcData, int nSrcDataLen, ImageType itSrcImageType,
unsigned char * * ppDestData, int * pnDestDataLen, ImageType itDestImageType);
bool DLL_EXPORT ImageDelete(unsigned char * * ppImageData);
}
#endif // #ifndef IMGCONV_H