753 lines
21 KiB
C++
753 lines
21 KiB
C++
// dibapi.cpp
|
|
//
|
|
// Source file for Device-Independent Bitmap (DIB) API. Provides
|
|
// the following functions:
|
|
//
|
|
// PaintDIB() - Painting routine for a DIB
|
|
// CreateDIBPalette() - Creates a palette from a DIB
|
|
// FindDIBBits() - Returns a pointer to the DIB bits
|
|
// DIBWidth() - Gets the width of the DIB
|
|
// DIBHeight() - Gets the height of the DIB
|
|
// PaletteSize() - Gets the size required to store the DIB's palette
|
|
// DIBNumColors() - Calculates the number of colors
|
|
// in the DIB's color table
|
|
// CopyHandle() - Makes a copy of the given global memory block
|
|
//
|
|
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
#include "StdAfx.h"
|
|
#include "dibapi.h"
|
|
#include <io.h>
|
|
#include <errno.h>
|
|
|
|
// No Msg file is required
|
|
|
|
/*************************************************************************
|
|
*
|
|
* PaintDIB()
|
|
*
|
|
* Parameters:
|
|
*
|
|
* HDC hDC - DC to do output to
|
|
*
|
|
* LPRECT lpDCRect - rectangle on DC to do output to
|
|
*
|
|
* HDIB hDIB - handle to global memory with a DIB spec
|
|
* in it followed by the DIB bits
|
|
*
|
|
* LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
|
|
*
|
|
* CPalette* pPal - pointer to CPalette containing DIB's palette
|
|
*
|
|
* Return Value:
|
|
*
|
|
* BOOL - TRUE if DIB was drawn, FALSE otherwise
|
|
*
|
|
* Description:
|
|
* Painting routine for a DIB. Calls StretchDIBits() or
|
|
* SetDIBitsToDevice() to paint the DIB. The DIB is
|
|
* output to the specified DC, at the coordinates given
|
|
* in lpDCRect. The area of the DIB to be output is
|
|
* given by lpDIBRect.
|
|
*
|
|
************************************************************************/
|
|
#define DIB_HEADER_MARKER ((WORD) (_T('M') << 8) | _T('B'))
|
|
|
|
HDIB WINAPI ReadDIBFile(CFile& file)
|
|
{
|
|
BITMAPFILEHEADER bmfHeader;
|
|
DWORD dwBitsSize;
|
|
HDIB hDIB;
|
|
LPSTR pDIB;
|
|
|
|
/*
|
|
* get length of DIB in bytes for use when reading
|
|
*/
|
|
|
|
dwBitsSize = (DWORD)file.GetLength();
|
|
|
|
/*
|
|
* Go read the DIB file header and check if it's valid.
|
|
*/
|
|
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
|
|
return NULL;
|
|
|
|
if (bmfHeader.bfType != DIB_HEADER_MARKER)
|
|
return NULL;
|
|
|
|
/*
|
|
* Allocate memory for DIB
|
|
*/
|
|
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
|
|
if (hDIB == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
|
|
|
|
/*
|
|
* Go read the bits. use Read instead of ReadHuge, 2003/6/9
|
|
*/
|
|
if (file.Read(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
|
|
dwBitsSize - sizeof(BITMAPFILEHEADER) )
|
|
{
|
|
::GlobalUnlock((HGLOBAL) hDIB);
|
|
::GlobalFree((HGLOBAL) hDIB);
|
|
return NULL;
|
|
}
|
|
::GlobalUnlock((HGLOBAL) hDIB);
|
|
return hDIB;
|
|
}
|
|
|
|
|
|
BOOL WINAPI PaintDIB(HDC hDC,
|
|
LPRECT lpDCRect,
|
|
HDIB hDIB,
|
|
LPRECT lpDIBRect,
|
|
CPalette* pPal)
|
|
{
|
|
LPSTR lpDIBHdr; // Pointer to BITMAPINFOHEADER
|
|
LPSTR lpDIBBits; // Pointer to DIB bits
|
|
BOOL bSuccess=FALSE; // Success/fail flag
|
|
HPALETTE hPal=NULL; // Our DIB's palette
|
|
HPALETTE hOldPal=NULL; // Previous palette
|
|
|
|
/* Check for valid DIB handle */
|
|
if (hDIB == NULL)
|
|
return FALSE;
|
|
|
|
/* Lock down the DIB, and get a pointer to the beginning of the bit
|
|
* buffer
|
|
*/
|
|
lpDIBHdr = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
|
|
lpDIBBits = ::FindDIBBits(lpDIBHdr);
|
|
|
|
// Get the DIB's palette, then select it into DC
|
|
if (pPal != NULL)
|
|
{
|
|
hPal = (HPALETTE) pPal->m_hObject;
|
|
|
|
// Select as background since we have
|
|
// already realized in forground if needed
|
|
hOldPal = ::SelectPalette(hDC, hPal, TRUE);
|
|
}
|
|
|
|
/* Make sure to use the stretching mode best for color pictures */
|
|
::SetStretchBltMode(hDC, COLORONCOLOR);
|
|
|
|
/* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
|
|
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&
|
|
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
|
|
bSuccess = ::SetDIBitsToDevice(hDC, // hDC
|
|
lpDCRect->left, // DestX
|
|
lpDCRect->top, // DestY
|
|
RECTWIDTH(lpDCRect), // nDestWidth
|
|
RECTHEIGHT(lpDCRect), // nDestHeight
|
|
lpDIBRect->left, // SrcX
|
|
(int)DIBHeight(lpDIBHdr) -
|
|
lpDIBRect->top -
|
|
RECTHEIGHT(lpDIBRect), // SrcY
|
|
0, // nStartScan
|
|
(WORD)DIBHeight(lpDIBHdr), // nNumScans
|
|
lpDIBBits, // lpBits
|
|
(LPBITMAPINFO)lpDIBHdr, // lpBitsInfo
|
|
DIB_RGB_COLORS); // wUsage
|
|
else
|
|
bSuccess = ::StretchDIBits(hDC, // hDC
|
|
lpDCRect->left, // DestX
|
|
lpDCRect->top, // DestY
|
|
RECTWIDTH(lpDCRect), // nDestWidth
|
|
RECTHEIGHT(lpDCRect), // nDestHeight
|
|
lpDIBRect->left, // SrcX
|
|
lpDIBRect->top, // SrcY
|
|
RECTWIDTH(lpDIBRect), // wSrcWidth
|
|
RECTHEIGHT(lpDIBRect), // wSrcHeight
|
|
lpDIBBits, // lpBits
|
|
(LPBITMAPINFO)lpDIBHdr, // lpBitsInfo
|
|
DIB_RGB_COLORS, // wUsage
|
|
SRCCOPY); // dwROP
|
|
|
|
::GlobalUnlock((HGLOBAL) hDIB);
|
|
|
|
/* Reselect old palette */
|
|
if (hOldPal != NULL)
|
|
{
|
|
::SelectPalette(hDC, hOldPal, TRUE);
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
/*************************************************************************
|
|
*
|
|
* 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).
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal)
|
|
{
|
|
LPLOGPALETTE lpPal; // pointer to a logical palette
|
|
HANDLE hLogPal; // handle to a logical palette
|
|
HPALETTE hPal = NULL; // handle to a palette
|
|
int i; // loop index
|
|
WORD wNumColors; // number of colors in color table
|
|
LPSTR lpbi; // pointer to packed-DIB
|
|
LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0)
|
|
LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (old)
|
|
BOOL bWinStyleDIB; // flag which signifies whether this is a Win3.0 DIB
|
|
BOOL bResult = FALSE;
|
|
|
|
/* if handle to DIB is invalid, return FALSE */
|
|
|
|
if (hDIB == NULL)
|
|
return FALSE;
|
|
|
|
lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
|
|
|
|
/* get pointer to BITMAPINFO (Win 3.0) */
|
|
lpbmi = (LPBITMAPINFO)lpbi;
|
|
|
|
/* get pointer to BITMAPCOREINFO (old 1.x) */
|
|
lpbmc = (LPBITMAPCOREINFO)lpbi;
|
|
|
|
/* get the number of colors in the DIB */
|
|
wNumColors = ::DIBNumColors(lpbi);
|
|
|
|
if (wNumColors != 0)
|
|
{
|
|
/* 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 == 0)
|
|
{
|
|
::GlobalUnlock((HGLOBAL) hDIB);
|
|
return FALSE;
|
|
}
|
|
|
|
lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
|
|
|
|
/* set version and number of palette entries */
|
|
lpPal->palVersion = PALVERSION;
|
|
lpPal->palNumEntries = (WORD)wNumColors;
|
|
|
|
/* is this a Win 3.0 DIB? */
|
|
bWinStyleDIB = IS_WIN30_DIB(lpbi);
|
|
for (i = 0; i < (int)wNumColors; i++)
|
|
{
|
|
if (bWinStyleDIB)
|
|
{
|
|
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
|
|
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
|
|
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
|
|
lpPal->palPalEntry[i].peFlags = 0;
|
|
}
|
|
else
|
|
{
|
|
lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
|
|
lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
|
|
lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
|
|
lpPal->palPalEntry[i].peFlags = 0;
|
|
}
|
|
}
|
|
|
|
/* create the palette and get handle to it */
|
|
bResult = pPal->CreatePalette(lpPal);
|
|
::GlobalUnlock((HGLOBAL) hLogPal);
|
|
::GlobalFree((HGLOBAL) hLogPal);
|
|
}
|
|
|
|
::GlobalUnlock((HGLOBAL) hDIB);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
/*************************************************************************
|
|
*
|
|
* FindDIBBits()
|
|
*
|
|
* Parameter:
|
|
*
|
|
* LPSTR lpbi - pointer to packed-DIB memory block
|
|
*
|
|
* Return Value:
|
|
*
|
|
* LPSTR - pointer to the DIB bits
|
|
*
|
|
* Description:
|
|
*
|
|
* This function calculates the address of the DIB's bits and returns a
|
|
* pointer to the DIB bits.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
LPSTR WINAPI FindDIBBits(LPSTR lpbi)
|
|
{
|
|
return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi));
|
|
}
|
|
|
|
|
|
/*************************************************************************
|
|
*
|
|
* DIBWidth()
|
|
*
|
|
* Parameter:
|
|
*
|
|
* LPSTR lpbi - 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 other-style DIB.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
DWORD WINAPI DIBWidth(LPSTR lpDIB)
|
|
{
|
|
LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
|
|
LPBITMAPCOREHEADER lpbmc; // pointer to an other-style DIB
|
|
|
|
/* point to the header (whether Win 3.0 and old) */
|
|
|
|
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
|
|
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
|
|
|
|
/* return the DIB width if it is a Win 3.0 DIB */
|
|
if (IS_WIN30_DIB(lpDIB))
|
|
return lpbmi->biWidth;
|
|
else /* it is an other-style DIB, so return its width */
|
|
return (DWORD)lpbmc->bcWidth;
|
|
}
|
|
|
|
|
|
/*************************************************************************
|
|
*
|
|
* DIBHeight()
|
|
*
|
|
* Parameter:
|
|
*
|
|
* LPSTR lpbi - 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 other-style DIB.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
DWORD WINAPI DIBHeight(LPSTR lpDIB)
|
|
{
|
|
LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
|
|
LPBITMAPCOREHEADER lpbmc; // pointer to an other-style DIB
|
|
|
|
/* point to the header (whether old or Win 3.0 */
|
|
|
|
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
|
|
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
|
|
|
|
/* return the DIB height if it is a Win 3.0 DIB */
|
|
if (IS_WIN30_DIB(lpDIB))
|
|
return lpbmi->biHeight;
|
|
else /* it is an other-style DIB, so return its height */
|
|
return (DWORD)lpbmc->bcHeight;
|
|
}
|
|
|
|
|
|
/*************************************************************************
|
|
*
|
|
* PaletteSize()
|
|
*
|
|
* Parameter:
|
|
*
|
|
* LPSTR lpbi - 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 other-
|
|
* style DIB).
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
WORD WINAPI PaletteSize(LPSTR lpbi)
|
|
{
|
|
/* calculate the size required by the palette */
|
|
if (IS_WIN30_DIB (lpbi))
|
|
return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
|
|
else
|
|
return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
|
|
}
|
|
|
|
|
|
/*************************************************************************
|
|
*
|
|
* DIBNumColors()
|
|
*
|
|
* Parameter:
|
|
*
|
|
* LPSTR lpbi - 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 other-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 WINAPI DIBNumColors(LPSTR lpbi)
|
|
{
|
|
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(lpbi))
|
|
{
|
|
DWORD dwClrUsed;
|
|
|
|
dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
|
|
if (dwClrUsed != 0)
|
|
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(lpbi))
|
|
wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
|
|
else
|
|
wBitCount = ((LPBITMAPCOREHEADER)lpbi)->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;
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//// Clipboard support
|
|
|
|
//---------------------------------------------------------------------
|
|
//
|
|
// Function: CopyHandle (from SDK DibView sample clipbrd.c)
|
|
//
|
|
// Purpose: Makes a copy of the given global memory block. Returns
|
|
// a handle to the new memory block (NULL on error).
|
|
//
|
|
// Routine stolen verbatim out of ShowDIB.
|
|
//
|
|
// Parms: h == Handle to global memory to duplicate.
|
|
//
|
|
// Returns: Handle to new global memory block.
|
|
//
|
|
//---------------------------------------------------------------------
|
|
|
|
HGLOBAL WINAPI CopyHandle (HGLOBAL h)
|
|
{
|
|
if (h == NULL)
|
|
return NULL;
|
|
|
|
DWORD dwLen = ::GlobalSize((HGLOBAL) h);
|
|
HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen);
|
|
|
|
if (hCopy != NULL)
|
|
{
|
|
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
|
|
void* lp = ::GlobalLock((HGLOBAL) h);
|
|
memcpy(lpCopy, lp, dwLen);
|
|
::GlobalUnlock(hCopy);
|
|
::GlobalUnlock(h);
|
|
}
|
|
|
|
return hCopy;
|
|
}
|
|
|
|
GEOAPI HDIB Bitmap2Dib(HBITMAP hBitmap)
|
|
{
|
|
int iBits; //当前显示分辨率下每个像素所占字节数
|
|
WORD wBitCount; //位图中每个像素所占字节数
|
|
DWORD dwPaletteSize=0, //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
|
|
dwBmBitsSize;
|
|
BITMAP Bitmap; //位图属性结构
|
|
BITMAPINFOHEADER bi; //位图信息头结构
|
|
LPBITMAPINFOHEADER lpbi; //指向位图信息头结构
|
|
HANDLE hDib, hPal,hOldPal=NULL; //定义文件,分配内存句柄,调色板句柄
|
|
|
|
ASSERT(hBitmap);
|
|
//设置位图信息头结构
|
|
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
|
|
iBits = Bitmap.bmPlanes * Bitmap.bmBitsPixel;
|
|
|
|
|
|
if (iBits <= 1)
|
|
wBitCount = 1;
|
|
else if (iBits <= 4)
|
|
wBitCount = 4;
|
|
else if (iBits <= 8)
|
|
wBitCount = 8;
|
|
else if (iBits <= 24)
|
|
wBitCount = 24;
|
|
else {
|
|
wBitCount=24;
|
|
}
|
|
|
|
//计算调色板大小
|
|
if (wBitCount <= 8)
|
|
dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD);
|
|
|
|
|
|
bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
bi.biWidth = Bitmap.bmWidth;
|
|
bi.biHeight = Bitmap.bmHeight;
|
|
bi.biPlanes = 1;
|
|
bi.biBitCount = wBitCount;
|
|
bi.biCompression = BI_RGB;
|
|
bi.biSizeImage = 0;
|
|
bi.biXPelsPerMeter = 0;
|
|
bi.biYPelsPerMeter = 0;
|
|
bi.biClrUsed = 0;
|
|
bi.biClrImportant = 0;
|
|
|
|
dwBmBitsSize = ((Bitmap.bmWidth * wBitCount+31)/32) * 4 * Bitmap.bmHeight ;
|
|
//dwBmBitsSize = ((rectImg.Width() * wBitCount+31)/32) * 4 * rectImg.Height() ;
|
|
|
|
//为位图内容分配内存
|
|
DWORD dwSize=dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER);
|
|
hDib = GlobalAlloc(GHND, dwSize);
|
|
if(!hDib) {
|
|
CString csMsg;
|
|
csMsg.Format(_T("不能分配%d大小的内存,其中bsize=%d;palSize=%d;infoSize=%d"),
|
|
int(dwSize), int(dwBmBitsSize), int(sizeof(BITMAPINFOHEADER)));
|
|
AfxMessageBox(csMsg);
|
|
//ASSERT(hDib);
|
|
return NULL;
|
|
}
|
|
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
|
|
ASSERT(lpbi);
|
|
*lpbi = bi;
|
|
|
|
HDC hDC = ::GetDC(NULL);
|
|
// 处理调色板
|
|
hPal = GetStockObject(DEFAULT_PALETTE);
|
|
if (hPal)
|
|
{
|
|
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
|
|
RealizePalette(hDC);
|
|
}
|
|
|
|
// 获取该调色板下新的像素值
|
|
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
|
|
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
|
|
+dwPaletteSize,
|
|
(LPBITMAPINFO )
|
|
lpbi, DIB_RGB_COLORS);
|
|
|
|
//恢复调色板
|
|
if (hOldPal)
|
|
{
|
|
SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
|
|
RealizePalette(hDC);
|
|
}
|
|
::ReleaseDC(NULL, hDC);
|
|
|
|
|
|
|
|
//清除
|
|
GlobalUnlock(hDib);
|
|
|
|
return (HDIB)hDib;
|
|
}
|
|
|
|
GEOAPI BOOL SaveBitmapToFile(HBITMAP hBitmap,LPTSTR lpFileName) //hBitmap 为刚才的屏幕位图句柄 lpFileName 为位图文件名
|
|
{
|
|
int iBits; //当前显示分辨率下每个像素所占字节数
|
|
WORD wBitCount; //位图中每个像素所占字节数
|
|
DWORD dwPaletteSize=0, //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
|
|
dwBmBitsSize,
|
|
dwDIBSize, dwWritten;
|
|
BITMAP Bitmap; //位图属性结构
|
|
BITMAPFILEHEADER bmfHdr; //位图文件头结构
|
|
BITMAPINFOHEADER bi; //位图信息头结构
|
|
LPBITMAPINFOHEADER lpbi; //指向位图信息头结构
|
|
HANDLE fh, hDib, hPal,hOldPal=NULL; //定义文件,分配内存句柄,调色板句柄
|
|
|
|
ASSERT(hBitmap);
|
|
//设置位图信息头结构
|
|
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
|
|
iBits = Bitmap.bmPlanes * Bitmap.bmBitsPixel;
|
|
|
|
|
|
if (iBits <= 1)
|
|
wBitCount = 1;
|
|
else if (iBits <= 4)
|
|
wBitCount = 4;
|
|
else if (iBits <= 8)
|
|
wBitCount = 8;
|
|
else if (iBits <= 24)
|
|
wBitCount = 24;
|
|
else {
|
|
wBitCount=24;
|
|
}
|
|
|
|
//计算调色板大小
|
|
if (wBitCount <= 8)
|
|
dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD);
|
|
|
|
|
|
bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
bi.biWidth = Bitmap.bmWidth;
|
|
bi.biHeight = Bitmap.bmHeight;
|
|
bi.biPlanes = 1;
|
|
bi.biBitCount = wBitCount;
|
|
bi.biCompression = BI_RGB;
|
|
bi.biSizeImage = 0;
|
|
bi.biXPelsPerMeter = 0;
|
|
bi.biYPelsPerMeter = 0;
|
|
bi.biClrUsed = 0;
|
|
bi.biClrImportant = 0;
|
|
|
|
dwBmBitsSize = ((Bitmap.bmWidth * wBitCount+31)/32) * 4 * Bitmap.bmHeight ;
|
|
//dwBmBitsSize = ((rectImg.Width() * wBitCount+31)/32) * 4 * rectImg.Height() ;
|
|
|
|
//为位图内容分配内存
|
|
DWORD dwSize=dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER);
|
|
hDib = GlobalAlloc(GHND, dwSize);
|
|
if(!hDib) {
|
|
CString csMsg;
|
|
csMsg.Format(_T("不能分配%d大小的内存,其中bsize=%d;palSize=%d;infoSize=%d"),
|
|
int(dwSize), int(dwBmBitsSize), int(sizeof(BITMAPINFOHEADER)));
|
|
AfxMessageBox(csMsg);
|
|
//ASSERT(hDib);
|
|
return FALSE;
|
|
}
|
|
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
|
|
ASSERT(lpbi);
|
|
*lpbi = bi;
|
|
|
|
HDC hDC = ::GetDC(NULL);
|
|
// 处理调色板
|
|
hPal = GetStockObject(DEFAULT_PALETTE);
|
|
if (hPal)
|
|
{
|
|
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
|
|
RealizePalette(hDC);
|
|
}
|
|
|
|
// 获取该调色板下新的像素值
|
|
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
|
|
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
|
|
+dwPaletteSize,
|
|
(LPBITMAPINFO )
|
|
lpbi, DIB_RGB_COLORS);
|
|
|
|
//恢复调色板
|
|
if (hOldPal)
|
|
{
|
|
SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
|
|
RealizePalette(hDC);
|
|
}
|
|
::ReleaseDC(NULL, hDC);
|
|
|
|
//创建位图文件
|
|
fh = CreateFile(lpFileName, GENERIC_WRITE,
|
|
0, NULL, CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
|
|
|
if (fh == INVALID_HANDLE_VALUE)
|
|
return FALSE;
|
|
|
|
// 设置位图文件头
|
|
bmfHdr.bfType = 0x4D42; // _T("BM")
|
|
dwDIBSize = sizeof(BITMAPFILEHEADER)
|
|
+ sizeof(BITMAPINFOHEADER)
|
|
+ dwPaletteSize + dwBmBitsSize;
|
|
bmfHdr.bfSize = dwDIBSize;
|
|
bmfHdr.bfReserved1 = 0;
|
|
bmfHdr.bfReserved2 = 0;
|
|
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)
|
|
+ (DWORD)sizeof(BITMAPINFOHEADER)
|
|
+ dwPaletteSize;
|
|
|
|
// 写入位图文件头
|
|
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
|
|
|
|
// 写入位图文件其余内容
|
|
WriteFile(fh, (LPSTR)lpbi, dwDIBSize,
|
|
&dwWritten, NULL);
|
|
|
|
//清除
|
|
GlobalUnlock(hDib);
|
|
GlobalFree(hDib);
|
|
CloseHandle(fh);
|
|
|
|
return TRUE;
|
|
}
|