windows-nt/Source/XPSP1/NT/base/ntsetup/billbrd/dibutil.c
2020-09-26 16:20:57 +08:00

565 lines
16 KiB
C

/*---------------------------------------------------------------------------
**
**-------------------------------------------------------------------------*/
#include <pch.h>
#include "dibutil.h"
HANDLE ReadDIBFile(HANDLE hfile);
/*************************************************************************
*
* GetDeviceNumColors()
*
* Purpose: Determines how many colors the video device supports
*
* Returns: (int) Number of colors supported
*
* History: Date Author Reason
* 2/28/97 hanumany Created
*
*
*
*************************************************************************/
UINT GetDeviceNumColors(HDC hdc)
{
static UINT iNumColors = 0;
if(!iNumColors)
iNumColors = GetDeviceCaps(hdc, NUMCOLORS);
return iNumColors;
}
HANDLE LoadDIB(LPTSTR lpFileName)
{
HANDLE hDIB = NULL;
HANDLE hFile;
/*
* Set the cursor to a hourglass, in case the loading operation
* takes more than a sec, the user will know what's going on.
*/
SetCursor(LoadCursor(NULL, IDC_WAIT));
hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
hDIB = ReadDIBFile(hFile);
CloseHandle(hFile);
}
SetCursor(LoadCursor(NULL, IDC_ARROW));
return hDIB;
}
/*
* Dib Header Marker - used in writing DIBs to files
*/
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
HANDLE ReadDIBFile(HANDLE hFile)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize;
DWORD dwRead;
HANDLE hDIB;
/*
* get length of DIB in bytes for use when reading
*/
dwBitsSize = GetFileSize(hFile, NULL);
/*
* Go read the DIB file header and check if it's valid.
*/
if ((ReadFile(hFile, (LPVOID)&bmfHeader, sizeof(bmfHeader), &dwRead, NULL) == 0) ||
(sizeof (bmfHeader) != dwRead))
{
return NULL;
}
if (bmfHeader.bfType != DIB_HEADER_MARKER)
{
return NULL;
}
/*
* Allocate memory for DIB
*/
hDIB = (HANDLE) HeapAlloc(GetProcessHeap(), 0, dwBitsSize);
if (hDIB == NULL)
{
return NULL;
}
/*
* Go read the bits.
*/
if ((ReadFile(hFile, (LPVOID)hDIB, dwBitsSize - sizeof(BITMAPFILEHEADER), &dwRead, NULL) == 0) ||
(dwBitsSize - sizeof(BITMAPFILEHEADER)!= dwRead))
{
HeapFree(GetProcessHeap(), 0, hDIB);
return NULL;
}
return hDIB;
}
/*************************************************************************
*
* 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.
*
* History: Date Author Reason
* 6/01/91 Garrett McAuliffe Created
* 9/15/91 Patrick Schreiber Added header and comments
*
************************************************************************/
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;
}
}
//-------------------------------------------------------------------------
// B U I L D P A L E T T E
//
// Creates an HPALETTE from a bitmap in a DC
//-------------------------------------------------------------------------
HPALETTE BuildPalette(HDC hdc)
{
DWORD adw[257];
int i,n;
n = GetDIBColorTable(hdc, 0, 256, (LPRGBQUAD)&adw[1]);
if (n == 0)
return CreateHalftonePalette(hdc);
for (i=1; i<=n; i++)
{
adw[i] = RGB(GetBValue(adw[i]),GetGValue(adw[i]),GetRValue(adw[i]));
}
adw[0] = MAKELONG(0x300, n);
return CreatePalette((LPLOGPALETTE)&adw[0]);
}
/*************************************************************************
*
* 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).
*
* History: Date Author Reason
* 6/01/91 Garrett McAuliffe Created
* 9/15/91 Patrick Schreiber Added header and comments
* 10/08/97 hanumany check GlobalLock return code
*
************************************************************************/
HPALETTE CreateDIBPalette(HDIB hDIB)
{
LPLOGPALETTE lpPal = NULL; // pointer to a logical palette
HANDLE hLogPal = NULL; // handle to a logical palette
HPALETTE hPal = NULL; // handle to a palette
int i = 0, wNumColors = 0; // loop index, number of colors in color table
LPBYTE lpbi = NULL; // pointer to packed-DIB
LPBITMAPINFO lpbmi = NULL; // pointer to BITMAPINFO structure (Win3.0)
LPBITMAPCOREINFO lpbmc = NULL; // pointer to BITMAPCOREINFO structure (OS/2)
BOOL bWinStyleDIB; // flag which signifies whether this is a Win3.0 DIB
/* if handle to DIB is invalid, return NULL */
if (!hDIB)
return NULL;
/* get pointer to BITMAPINFO (Win 3.0) */
lpbmi = (LPBITMAPINFO)hDIB;
/* get pointer to BITMAPCOREINFO (OS/2 1.x) */
lpbmc = (LPBITMAPCOREINFO)hDIB;
/* get the number of colors in the DIB */
wNumColors = DIBNumColors(hDIB);
/* is this a Win 3.0 DIB? */
bWinStyleDIB = IS_WIN30_DIB(hDIB);
if (wNumColors)
{
/* allocate memory block for logical palette */
lpPal = (HANDLE) HeapAlloc(GetProcessHeap(), 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wNumColors);
/* if not enough memory, clean up and return NULL */
if (!lpPal)
{
return NULL;
}
/* set version and number of palette entries */
lpPal->palVersion = PALVERSION;
lpPal->palNumEntries = (WORD)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);
}
/* clean up */
HeapFree(GetProcessHeap(), 0, lpPal);
/* return handle to DIB's palette */
return hPal;
}
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));
}
/*************************************************************************
*
* 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.
*
* History: Date Author Reason
* 6/01/91 Garrett McAuliffe Created
* 9/15/91 Patrick Schreiber Added header and comments
*
************************************************************************/
LPBYTE FindDIBBits(LPBYTE lpDIB)
{
return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));
}
/*************************************************************************
*
* 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.
*
* History: Date Author Reason
* 6/01/91 Garrett McAuliffe Created
* 9/15/91 Patrick Schreiber Added header and comments
* 3/27/92 Mark Bader Added comments about resulting
* bitmap format
* 10/08/97 hanumany check GlobalLock return code.
*
************************************************************************/
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;
/* get a pointer to the DIB bits */
lpDIBBits = FindDIBBits(hDIB);
/* get a DC */
hDC = GetDC(NULL);
if (!hDC)
{
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)hDIB, CBM_INIT,
(LPCVOID)lpDIBBits, (LPBITMAPINFO)hDIB, DIB_RGB_COLORS);
/* restore previous palette */
if (hOldPal)
SelectPalette(hDC, hOldPal, FALSE);
/* clean up */
ReleaseDC(NULL, hDC);
/* return handle to the bitmap */
return hBitmap;
}
WORD DestroyDIB(HDIB hDib)
{
HeapFree(GetProcessHeap(), 0, hDib);
return 0;
}
/******************************************************************
*
* DrawBitmap()
*
* This function paints the given bitmap at the given coordinates.
*
******************************************************************/
void DrawBitmap (HDC hdc, HBITMAP hBitmap, int xStart, int yStart)
{
BITMAP bm;
HDC hdcMem;
POINT ptSize, ptOrg;
HBITMAP hBitmapOld = NULL;
if (hBitmap == NULL) {
return;
}
hdcMem = CreateCompatibleDC (hdc);
if (hdcMem == NULL)
{
return;
}
SetBkMode(hdcMem, TRANSPARENT);
hBitmapOld = SelectObject(hdcMem, hBitmap);
SetMapMode(hdcMem, GetMapMode(hdc));
GetObject(hBitmap, sizeof(BITMAP), (LPVOID)&bm);
ptSize.x = bm.bmWidth;
ptSize.y = bm.bmHeight;
DPtoLP(hdc, &ptSize, 1);
ptOrg.x = 0;
ptOrg.y = 0;
DPtoLP(hdcMem, &ptOrg, 1);
BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, ptOrg.x, ptOrg.y, SRCCOPY);
SelectObject(hdcMem, hBitmapOld);
DeleteDC(hdcMem);
}
/******************************************************************
*
* DrawTransparentBitmap()
*
* This function paints the given bitmap at the given coordinates.
* and allow for one transparent color
*
******************************************************************/
void DrawTransparentBitmap(
HDC hdc,
HBITMAP hBitmap,
int xStart,
int yStart,
COLORREF cTransparentColor )
{
BITMAP bm;
COLORREF cColor;
HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
POINT ptSize;
hdcTemp = CreateCompatibleDC(hdc);
SelectObject(hdcTemp, hBitmap);
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
ptSize.x = bm.bmWidth;
ptSize.y = bm.bmHeight;
DPtoLP(hdcTemp, &ptSize, 1);
hdcBack = CreateCompatibleDC(hdc);
hdcObject = CreateCompatibleDC(hdc);
hdcMem = CreateCompatibleDC(hdc);
hdcSave = CreateCompatibleDC(hdc);
bmAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
bmAndMem = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
bmSave = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
bmBackOld = SelectObject(hdcBack, bmAndBack);
bmObjectOld = SelectObject(hdcObject, bmAndObject);
bmMemOld = SelectObject(hdcMem, bmAndMem);
bmSaveOld = SelectObject(hdcSave, bmSave);
SetMapMode(hdcTemp, GetMapMode(hdc));
BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
cColor = SetBkColor(hdcTemp, cTransparentColor);
BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,
SRCCOPY);
SetBkColor(hdcTemp, cColor);
BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0,
NOTSRCCOPY);
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart,
SRCCOPY);
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0,
SRCCOPY);
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
DeleteObject(SelectObject(hdcBack, bmBackOld));
DeleteObject(SelectObject(hdcObject, bmObjectOld));
DeleteObject(SelectObject(hdcMem, bmMemOld));
DeleteObject(SelectObject(hdcSave, bmSaveOld));
DeleteDC(hdcMem);
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcSave);
DeleteDC(hdcTemp);
}