📄 dib.c
字号:
/*************************************************************************
/* This is a 'best of' choice of DIB functions taken from Microsoft
/* examples files (examples wincap32 : file.c, dibutil.c ...)
/*************************************************************************/
#include <windows.h>
#include <windowsx.h>
#include "dib.h"
/****************************************************************************
* *
* FUNCTION : DibNumColors(VOID FAR * pv) *
* *
* PURPOSE : Determines the number of colors in the DIB by looking at *
* the BitCount filed in the info block. *
* *
* RETURNS : The number of colors in the DIB. *
* if bitmap is in 8 bit mode but use only 4 colors *
* function can return 4 (number of color really used) *
* Use DibGetPaletteSize instead... *
* *
****************************************************************************/
WORD DibNumColors (VOID FAR * pv)
{
INT bits;
LPBITMAPINFOHEADER lpbi;
LPBITMAPCOREHEADER lpbc;
lpbi = ((LPBITMAPINFOHEADER)pv);
lpbc = ((LPBITMAPCOREHEADER)pv);
/* With the BITMAPINFO format headers, the size of the palette
* is in biClrUsed, whereas in the BITMAPCORE - style headers, it
* is dependent on the bits per pixel ( = 2 raised to the power of
* bits/pixel).
*/
if (lpbi->biSize != sizeof(BITMAPCOREHEADER)){
if (lpbi->biClrUsed != 0)
return (WORD)lpbi->biClrUsed;
bits = lpbi->biBitCount;
}
else
bits = lpbc->bcBitCount;
switch (bits){
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
/* A 24 bitcount DIB has no color table */
return 0;
}
}
/****************************************************************************
* *
* FUNCTION : DibGetPaletteSize(VOID FAR * pv) *
* *
* PURPOSE : Return the bitmap encoding type (8 bit, 24 bit... *
* the BitCount filed in the info block. *
* *
* RETURNS : the encoding type of the bitmap. *
* *
****************************************************************************/
WORD DibGetPaletteSize (VOID FAR * pv)
{
INT bits;
LPBITMAPINFOHEADER lpbi;
LPBITMAPCOREHEADER lpbc;
lpbi = ((LPBITMAPINFOHEADER)pv);
lpbc = ((LPBITMAPCOREHEADER)pv);
/* With the BITMAPINFO format headers, the size of the palette
* is in biClrUsed, whereas in the BITMAPCORE - style headers, it
* is dependent on the bits per pixel ( = 2 raised to the power of
* bits/pixel).
*/
if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
bits = lpbi->biBitCount;
else
bits = lpbc->bcBitCount;
return bits;
}
/****************************************************************************
* *
* FUNCTION : DibCopyPalette(HBITMAP src, HBITMAP dst) *
* *
* PURPOSE : Copy the palette from src to dst if possible * *
* *
****************************************************************************/
VOID
DibCopyPalette(HBITMAP dst, HBITMAP src)
{
LPBITMAPINFO src_header, dst_header;
RGBQUAD *src_rgb, *dst_rgb;
WORD colorMode;
src_header = (LPBITMAPINFO) GlobalLock((HGLOBAL)src);
dst_header = (LPBITMAPINFO) GlobalLock((HGLOBAL)dst);
src_rgb = (RGBQUAD FAR *)((LPSTR)src_header + (WORD)src_header->bmiHeader.biSize);
dst_rgb = (RGBQUAD FAR *)((LPSTR)dst_header + (WORD)dst_header->bmiHeader.biSize);
colorMode = DibGetPaletteSize(src_header);
switch(colorMode)
{
case 4:
case 8:
memcpy(dst_rgb, src_rgb,PaletteSize(&src_header->bmiHeader));
break;
}
GlobalUnlock((HGLOBAL)src);
GlobalUnlock((HGLOBAL)dst);
}
/****************************************************************************
* *
* FUNCTION : PaletteSize(VOID FAR * pv) *
* *
* PURPOSE : Calculates the palette size in bytes. If the info. block *
* is of the BITMAPCOREHEADER type, the number of colors is *
* multiplied by 3 to give the palette size, otherwise the *
* number of colors is multiplied by 4. *
* *
* RETURNS : Palette size in number of bytes. *
* *
****************************************************************************/
WORD PaletteSize (VOID FAR * pv)
{
LPBITMAPINFOHEADER lpbi;
WORD NumColors;
lpbi = (LPBITMAPINFOHEADER)pv;
NumColors = DibNumColors(lpbi);
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
return (WORD)(NumColors * sizeof(RGBTRIPLE));
else
return (WORD)(NumColors * sizeof(RGBQUAD));
}
/****************************************************************************
* *
* FUNCTION : WriteMapFileHeaderandConvertFromDwordAlignToPacked(HFILE fh, LPBITMAPFILEHEADER pbf)
* *
* PURPOSE : write header structure (which NOT packed) and write it PACKED
* *
* RETURNS : VOID
* *
****************************************************************************/
VOID WriteMapFileHeaderandConvertFromDwordAlignToPacked(HFILE fh, LPBITMAPFILEHEADER pbf)
{
/* write bfType*/
_lwrite(fh, (LPSTR)&pbf->bfType, (UINT)sizeof (WORD));
/* now pass over extra word, and only write next 3 DWORDS!*/
_lwrite(fh, (LPSTR)&pbf->bfSize, sizeof(DWORD) * 3);
}
/*************************************************************************
*
* CreateDIB()
*
* Parameters:
*
* DWORD dwWidth - Width for new bitmap, in pixels
* DWORD dwHeight - Height for new bitmap
* WORD wBitCount - Bit Count for new DIB (1, 4, 8, or 24)
*
* Return Value:
*
* HDIB - Handle to new DIB
*
* Description:
*
* This function allocates memory for and initializes a new DIB by
* filling in the BITMAPINFOHEADER, allocating memory for the color
* table, and allocating memory for the bitmap bits. As with all
* HDIBs, the header, colortable and bits are all in one contiguous
* memory block. This function is similar to the CreateBitmap()
* Windows API.
*
* The colortable and bitmap bits are left uninitialized (zeroed) in the
* returned HDIB.
*
*
* History: Date Author Reason
* 3/20/92 Mark Bader Created
*
************************************************************************/
HBITMAP CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount, HPALETTE hPal)
{
BITMAPINFOHEADER bi; /* bitmap header */
LPBITMAPINFOHEADER lpbi; /* pointer to BITMAPINFOHEADER */
DWORD dwLen; /* size of memory block */
HBITMAP hDIB;
DWORD dwBytesPerLine; /* Number of bytes per scanline */
/* Make sure bits per pixel is valid */
if (wBitCount <= 1)
wBitCount = 1;
else if (wBitCount <= 4)
wBitCount = 4;
else if (wBitCount <= 8)
wBitCount = 8;
else if (wBitCount <= 24)
wBitCount = 24;
else
wBitCount = 4; /* set default value to 4 if parameter is bogus */
/* initialize BITMAPINFOHEADER */
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = dwWidth; /* fill in width from parameter */
bi.biHeight = dwHeight; /* fill in height from parameter */
bi.biPlanes = 1; /* must be 1 */
bi.biBitCount = wBitCount; /* from parameter */
bi.biCompression = BI_RGB;
bi.biSizeImage = 0; /* 0's here mean "default" */
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
/* calculate size of memory block required to store the DIB. This */
/* block should be big enough to hold the BITMAPINFOHEADER, the color */
/* table, and the bits */
dwBytesPerLine = WIDTHBYTES(wBitCount * dwWidth);
dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + (dwBytesPerLine * dwHeight);
/* alloc memory block to store our bitmap */
hDIB = GlobalAlloc(GHND, dwLen);
/* major bummer if we couldn't get memory block */
if (!hDIB)
return NULL;
/* lock memory and get pointer to it */
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
/* use our bitmap info structure to fill in first part of */
/* our DIB with the BITMAPINFOHEADER */
*lpbi = bi;
/*
* Copy the palette in the new created image
*/
if (wBitCount == 8)
{
PALETTEENTRY pal[256];
RGBQUAD *pRgb;
int i;
GetPaletteEntries(hPal, 0, 256, pal);
pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
/* Fill in the palette entries from the DIB color table and
* create a logical color palette.
*/
for (i = 0; i < 256; i++)
{
pRgb[i].rgbRed = pal[i].peRed;
pRgb[i].rgbGreen = pal[i].peGreen;
pRgb[i].rgbBlue = pal[i].peBlue;
}
}
// Since we don't know what the colortable and bits should contain,
// just leave these blank. Unlock the DIB and return the HDIB.
GlobalUnlock(hDIB);
//return handle to the DIB
return hDIB;
}
/*************************************************************************
*
* Function: ReadDIBFile (int)
*
* Purpose: Reads in the specified DIB file into a global chunk of
* memory.
*
* Returns: A handle to a dib (hDIB) if successful.
* NULL if an error occurs.
*
* Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything
* from the end of the BITMAPFILEHEADER structure on is
* returned in the global memory handle.
*
*
* NOTE: The DIB API were not written to handle OS/2 DIBs, so this
* function will reject any file that is not a Windows DIB.
*
* History: Date Author Reason
* 9/15/91 Mark Bader Based on DIBVIEW
* 6/25/92 Mark Bader Added check for OS/2 DIB
* 7/21/92 Mark Bader Added code to deal with bfOffBits
* field in BITMAPFILEHEADER
* 9/11/92 Mark Bader Fixed Realloc Code to free original mem
* 1/25/94 Hung Nguyen Changed file APIs to Win32 APIs
*
*************************************************************************/
HANDLE ReadDIBFile(HANDLE hFile)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize;
UINT nNumColors; /* Number of colors in table */
HANDLE hDIB;
HANDLE hDIBtmp; /* Used for GlobalRealloc() //MPB */
LPBITMAPINFOHEADER lpbi;
DWORD offBits;
DWORD dwRead;
/* get length of DIB in bytes for use when reading */
dwBitsSize = GetFileSize(hFile, NULL);
/* Allocate memory for header & color table. We'll enlarge this */
/* memory as needed. */
hDIB = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(sizeof(BITMAPINFOHEADER) +
256 * sizeof(RGBQUAD)));
if (!hDIB)
return NULL;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
if (!lpbi)
{
GlobalFree(hDIB);
return NULL;
}
/* read the BITMAPFILEHEADER from our file */
if (!ReadFile(hFile, (LPSTR)&bmfHeader, sizeof (BITMAPFILEHEADER),
&dwRead, NULL))
goto ErrExit;
if (sizeof (BITMAPFILEHEADER) != dwRead)
goto ErrExit;
if (bmfHeader.bfType != 0x4d42) /* 'BM' */
goto ErrExit;
/* read the BITMAPINFOHEADER */
if (!ReadFile(hFile, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER), &dwRead,
NULL))
goto ErrExit;
if (sizeof(BITMAPINFOHEADER) != dwRead)
goto ErrExit;
/* Check to see that it's a Windows DIB -- an OS/2 DIB would cause */
/* strange problems with the rest of the DIB API since the fields */
/* in the header are different and the color table entries are */
/* smaller. */
/* */
/* If it's not a Windows DIB (e.g. if biSize is wrong), return NULL. */
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
goto ErrExit;
/* Now determine the size of the color table and read it. Since the */
/* bitmap bits are offset in the file by bfOffBits, we need to do some */
/* special processing here to make sure the bits directly follow */
/* the color table (because that's the format we are susposed to pass */
/* back) */
if (!(nNumColors = (UINT)lpbi->biClrUsed))
{
/* no color table for 24-bit, default size otherwise */
if (lpbi->biBitCount != 24)
nNumColors = 1 << lpbi->biBitCount; /* standard size table */
}
/* fill in some default values if they are zero */
if (lpbi->biClrUsed == 0)
lpbi->biClrUsed = nNumColors;
if (lpbi->biSizeImage == 0)
{
lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) +
31) & ~31) >> 3) * lpbi->biHeight;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -