📄 dibapi.cpp
字号:
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((LPSTR)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 = WIDTHBYTES((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.
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize +
PaletteSize((LPSTR)lpBI);
// Write the file header
WriteFile(fh, (LPSTR)&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, (LPSTR)lpBI, dwDIBSize, &dwWritten, NULL);
GlobalUnlock(hDib);
if (dwWritten == 0)
return FALSE; // oops, something happened in the write
else
return TRUE; // Success code
}
///////////////////////////////////////////////////////////////////////////////////////////////
/****************************************************************************
*
* FUNCTION: BytesPerLine
*
* PURPOSE: Calculates the number of bytes in one scan line.
*
* PARAMS: LPSTR lpDIB - pointer to the BITMAPINFOHEADER
that begins the CF_DIB block
*
* RETURNS: DWORD - number of bytes in one scan line (DWORD aligned)
*
\****************************************************************************/
DWORD BytesPerLine(LPSTR lpDIB)
{
return WIDTHBYTES(((LPBITMAPINFOHEADER)lpDIB)->biWidth *
((LPBITMAPINFOHEADER)lpDIB)->biPlanes *
((LPBITMAPINFOHEADER)lpDIB)->biBitCount);
}
/****************************************************************************
*
* FUNCTION: DIBlockSize
*
* PURPOSE: Calculates the number of bytes in one scan line.
*
* PARAMS: LPSTR lpDIB - pointer to the BITMAPINFOHEADER
that begins the CF_DIB block
*
* RETURNS: DWORD - DIB block size
*
\****************************************************************************/
DWORD DIBlockSize(LPSTR lpDIB)
{
if (((LPBITMAPINFOHEADER)lpDIB)->biSizeImage == 0)
((LPBITMAPINFOHEADER)lpDIB)->biSizeImage = BytesPerLine(lpDIB) * ((LPBITMAPINFOHEADER)lpDIB)->biHeight;
return ((LPBITMAPINFOHEADER)lpDIB)->biSize + PaletteSize(lpDIB) + ((LPBITMAPINFOHEADER)lpDIB)->biSizeImage;
}
/*************************************************************************
*
* DIBHeight()
*
* Parameter:
*
* LPSTR 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(LPSTR 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;
}
/*************************************************************************
*
* DIBWidth()
*
* Parameter:
*
* LPSTR 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(LPSTR 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;
}
/*************************************************************************
*
* DIBNumColors()
*
* Parameter:
*
* LPSTR 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(LPSTR 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(LPSTR
lpDIB)
{
if (IS_WIN30_DIB(lpDIB))
return ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
else
return ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
}
/*************************************************************************
*
* FindDIBBits()
*
* Parameter:
*
* LPSTR lpDIB - 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 FindDIBBits(LPSTR lpDIB)
{
return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));
}
/*************************************************************************
*
* PaletteSize()
*
* Parameter:
*
* LPSTR 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(LPSTR lpDIB)
{
// calculate the size required by the palette
if (IS_WIN30_DIB (lpDIB))
return (DIBNumColors(lpDIB) * sizeof(RGBQUAD));
else
return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
}
//////////////////////////////////////////////////////////////////////////////////////////////////
/*************************************************************************
*
* PaintBitmap()
*
* Parameters:
*
* HDC hDC - DC to do output to
*
* LPRECT lpDCRect - rectangle on DC to do output to
*
* HBITMAP hDDB - handle to device-dependent bitmap (DDB)
*
* LPRECT lpDDBRect - rectangle of DDB to output into lpDCRect
*
* HPALETTE hPalette - handle to the palette to use with hDDB
*
* Return Value:
*
* BOOL - TRUE if bitmap was drawn, FLASE otherwise
*
* Description:
*
* Painting routine for a DDB. Calls BitBlt() or
* StretchBlt() to paint the DDB. The DDB is
* output to the specified DC, at the coordinates given
* in lpDCRect. The area of the DDB to be output is
* given by lpDDBRect. The specified palette is used.
*
* NOTE: This function always selects the palette as background. Before
* calling this function, be sure your palette is selected to desired
* priority (foreground or background).
*
************************************************************************/
BOOL PaintBitmap(HDC hDC, LPRECT lpDCRect, HBITMAP hDDB, LPRECT lpDDBRect,
HPALETTE hPal, DWORD dwRop)
{
HDC hMemDC; // Handle to memory DC
HBITMAP hOldBitmap; // Handle to previous bitmap
HPALETTE hOldPal1 = NULL; // Handle to previous palette
HPALETTE hOldPal2 = NULL; // Handle to previous palette
BOOL bSuccess = FALSE; // Success/fail flag
// Create a memory DC
hMemDC = CreateCompatibleDC (hDC);
// If this failed, return FALSE
if (!hMemDC)
return FALSE;
// If we have a palette, select and realize it
if (hPal)
{
hOldPal1 = SelectPalette(hMemDC, hPal, TRUE);
hOldPal2 = SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
}
// Select bitmap into the memory DC
hOldBitmap = (HBITMAP)SelectObject (hMemDC, hDDB);
// Make sure to use the stretching mode best for color pictures
SetStretchBltMode (hDC, COLORONCOLOR);
// Determine whether to call StretchBlt() or BitBlt()
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDDBRect)) &&
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDDBRect)))
bSuccess = BitBlt(hDC, lpDCRect->left, lpDCRect->top,
lpDCRect->right - lpDCRect->left,
lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left,
lpDDBRect->top, dwRop);
else
bSuccess = StretchBlt(hDC, lpDCRect->left, lpDCRect->top,
lpDCRect->right - lpDCRect->left,
lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left,
lpDDBRect->top, lpDDBRect->right - lpDDBRect->left,
lpDDBRect->bottom - lpDDBRect->top, dwRop);
// Clean up
SelectObject(hMemDC, hOldBitmap);
if (hOldPal1)
SelectPalette (hMemDC, hOldPal1, FALSE);
if (hOldPal2)
SelectPalette (hDC, hOldPal2, FALSE);
DeleteDC (hMemDC);
// Return with success/fail flag
return bSuccess;
}
/*************************************************************************
*
* 函数名称:
* PaintDIB()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -