home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Microsoft Multimedia Jumpstart 1.1a
/
CD_ROM.BIN
/
develpmt
/
source
/
cropdib
/
dib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-11
|
40KB
|
1,445 lines
/*
* DIB.C contains routines for working with device-independent bitmaps.
* This module is adapted from the DIB.C module included with the ShowDIB
* sample application shipped with the Windows 3.0 SDK. This module includes
* improved handling for Presentation Manager DIBs, as well as several new
* functions for working with DIBs and DIB palettes.
*
* (C) Copyright Microsoft Corp. 1991. All rights reserved.
*
* You have a royalty-free right to use, modify, reproduce and
* distribute the Sample Files (and/or any modified version) in
* any way you find useful, provided that you agree that
* Microsoft has no warranty obligations or liability for any
* Sample Application Files which are modified.
*/
#include <windows.h>
#include "dib.h"
#define MAKEP(sel,off) ((VOID FAR *)MAKELONG(off,sel))
#define ALLOCP(ulBytes) ((VOID FAR*)MAKELONG(0, GlobalAlloc(GPTR,(DWORD)(ulBytes))))
#define FREEP(lp) GlobalFree((HANDLE)HIWORD((DWORD)(lp)));
HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal);
static DWORD NEAR PASCAL lread(int fh, VOID FAR *pv, DWORD ul);
static DWORD NEAR PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul);
/* flags for _lseek */
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
/* OpenDIB(szFile)
*
* Reads a DIB file and returns a handle to a memory DIB containing
* the BITMAPINFOHEADER, palette data, and bitmap bits.
*/
HANDLE OpenDIB(
int fh) // Input file handle
{
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen;
DWORD dwBits;
HANDLE hdib;
HANDLE h;
if (fh == -1)
return NULL;
/* Read the bitmap info header and palette from the file. */
hdib = ReadDibBitmapInfo(fh);
if (!hdib)
return NULL;
/* Get the bitmap header information. */
DibInfo(hdib,&bi);
/* Calculate memory needed to store the DIB bits, and attempt to
* allocate the memory. */
dwBits = bi.biSizeImage;
dwLen = bi.biSize + PaletteSize(&bi) + dwBits;
if (!(h = GlobalReAlloc(hdib,dwLen,0)))
{
GlobalFree(hdib);
hdib = NULL;
}
else
{
hdib = h;
}
/* If memory allocation successful, read the bitmap bits. */
if (hdib)
{
lpbi = (VOID FAR *)GlobalLock(hdib);
lread(fh, (LPSTR)lpbi+(WORD)lpbi->biSize+PaletteSize(lpbi), dwBits);
GlobalUnlock(hdib);
}
return hdib;
}
/*
* WriteDIB(szFile, hdib)
*
* Writes a global handle in CF_DIB format to a file.
*/
BOOL WriteDIB(
int fh, // Output file handle
HANDLE hdib) // DIB to write
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;
BITMAPINFOHEADER bi;
DWORD dwSize;
if (!hdib)
return FALSE;
if (fh == -1)
return FALSE;
/* Calculate total size of DIB. */
DibInfo(hdib, &bi);
dwSize = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
lpbi = (VOID FAR *)GlobalLock(hdib);
/* Construct the BITMAPFILEHEADER and write the DIB. */
hdr.bfType = BFT_BITMAP;
hdr.bfSize = dwSize + sizeof(BITMAPFILEHEADER);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize +
PaletteSize(lpbi);
_lwrite(fh, (LPVOID)&hdr, sizeof(BITMAPFILEHEADER));
lwrite(fh, (LPVOID)lpbi, dwSize);
GlobalUnlock(hdib);
return TRUE;
}
/*
* DibInfo(hbi, lpbi)
*
* Retrieves the DIB info associated with a CF_DIB format memory block.
* Works with both the BITMAPINFOHEADER and BITMAPCOREHEADER formats.
*/
BOOL DibInfo(
HANDLE hbi, // Handle to bitmap
LPBITMAPINFOHEADER lpbi) // Info header structure to fill in
{
if(!hbi)
return FALSE;
*lpbi = *(LPBITMAPINFOHEADER)GlobalLock(hbi);
GlobalUnlock(hbi);
if(lpbi->biSize == sizeof(BITMAPCOREHEADER))
{
BITMAPCOREHEADER bc;
bc = *(LPBITMAPCOREHEADER)lpbi;
lpbi->biSize = sizeof(BITMAPINFOHEADER);
lpbi->biWidth = (DWORD)bc.bcWidth;
lpbi->biHeight = (DWORD)bc.bcHeight;
lpbi->biPlanes = (WORD)bc.bcPlanes;
lpbi->biBitCount = (WORD)bc.bcBitCount;
lpbi->biCompression = BI_RGB;
lpbi->biSizeImage = 0;
lpbi->biXPelsPerMeter = 0;
lpbi->biYPelsPerMeter = 0;
lpbi->biClrUsed = 0;
lpbi->biClrImportant = 0;
}
/* Fill in the default fields
*/
if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
{
if (lpbi->biSizeImage == 0L)
lpbi->biSizeImage = WIDTHBYTES(lpbi->biWidth*lpbi->biBitCount) *
lpbi->biHeight;
if (lpbi->biClrUsed == 0L)
lpbi->biClrUsed = DibNumColors(lpbi);
}
return TRUE;
}
/*
* CreateBIPalette()
*
* Given a Pointer to a BITMAPINFO struct will create a
* a GDI palette object from the color table.
*
* Works with "old" (BITMAPCOREHEADER) and "new" (BITMAPINFOHEADER) DIBs.
*
*/
HPALETTE CreateBIPalette(
LPBITMAPINFOHEADER lpbi) // Info header containing color table
{
LOGPALETTE *pPal;
HPALETTE hpal = NULL;
WORD nNumColors;
BYTE red;
BYTE green;
BYTE blue;
WORD i;
RGBQUAD FAR *pRgb;
BOOL fCoreHeader;
if (!lpbi)
return NULL;
fCoreHeader = (lpbi->biSize == sizeof(BITMAPCOREHEADER));
pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
nNumColors = DibNumColors(lpbi);
if (nNumColors)
{
/* Allocate a new color table, copy the palette entries to
* it, and create the palette.
*/
pPal = (LOGPALETTE *)LocalAlloc(LPTR,
sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
if (!pPal)
goto exit;
pPal->palNumEntries = nNumColors;
pPal->palVersion = PALVERSION;
for (i = 0; i < nNumColors; i++)
{
pPal->palPalEntry[i].peRed = pRgb->rgbRed;
pPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
pPal->palPalEntry[i].peBlue = pRgb->rgbBlue;
pPal->palPalEntry[i].peFlags = (BYTE)0;
if (fCoreHeader)
((LPSTR)pRgb) += sizeof(RGBTRIPLE) ;
else
pRgb++;
}
hpal = CreatePalette(pPal);
LocalFree((HANDLE)pPal);
}
else if (lpbi->biBitCount == 24)
{
/* A DIB with a bit count of 24 has no color table entries. Set
* the number of entries to the maximum (256).
*/
nNumColors = MAXPALETTE;
pPal = (LOGPALETTE *)LocalAlloc(LPTR,
sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
if (!pPal)
goto exit;
pPal->palNumEntries = nNumColors;
pPal->palVersion = PALVERSION;
red = green = blue = 0;
/* Generate 256 (8 * 8 * 4) RGB combinations to fill the palette
* entries.
*/
for (i = 0; i < pPal->palNumEntries; i++)
{
pPal->palPalEntry[i].peRed = red;
pPal->palPalEntry[i].peGreen = green;
pPal->palPalEntry[i].peBlue = blue;
pPal->palPalEntry[i].peFlags = (BYTE)0;
if (!(red += 32))
if (!(green += 32))
blue += 64;
}
hpal = CreatePalette(pPal);
LocalFree((HANDLE)pPal);
}
exit:
return hpal;
}
/*
* CreateDibPalette()
*
* Given a Global HANDLE to a BITMAPINFO Struct
* will create a GDI palette object from the color table.
*
* works with "old" and "new" DIB's
*
*/
HPALETTE CreateDibPalette(HANDLE hbi)
{
HPALETTE hpal;
if (!hbi)
return NULL;
hpal = CreateBIPalette((LPBITMAPINFOHEADER)GlobalLock(hbi));
GlobalUnlock(hbi);
return hpal;
}
/* ReadDibBitmapInfo(fh)
*
* Reads a file in DIB format and returns a global HANDLE to its
* BITMAPINFO. This function works with both "old" (BITMAPCOREHEADER)
* and "new" (BITMAPINFOHEADER) formats, but always returns a "new"
* BITMAPINFO structure.
*/
HANDLE ReadDibBitmapInfo(
int fh) // Handle to open DIB file
{
DWORD off;
HANDLE hbi = NULL;
int size;
int i;
WORD nNumColors;
RGBQUAD FAR *pRgb;
BITMAPINFOHEADER bi;
BITMAPCOREHEADER bc;
LPBITMAPINFOHEADER lpbi;
BITMAPFILEHEADER bf;
if (fh == -1)
return NULL;
off = _llseek(fh,0L,SEEK_CUR);
/* Read bitmap file header.
*/
if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
return FALSE;
/*
* Do we have a RC HEADER?
*/
if (!ISDIB(bf.bfType))
{
bf.bfOffBits = 0L;
_llseek(fh,off,SEEK_SET);
}
/* Read bitmap info header.
*/
if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
return FALSE;
nNumColors = DibNumColors(&bi);
/* Determine type of bitmap info (BITMAPINFOHEADER or BITMAPCOREHEADER).
*/
switch (size = (int)bi.biSize)
{
case sizeof(BITMAPINFOHEADER):
break;
case sizeof(BITMAPCOREHEADER):
/* Fill in the missing fields and seek back to the start of
* the color table.
*/
bc = *(BITMAPCOREHEADER*)&bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = (DWORD)bc.bcWidth;
bi.biHeight = (DWORD)bc.bcHeight;
bi.biPlanes = (WORD)bc.bcPlanes;
bi.biBitCount = (WORD)bc.bcBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = nNumColors;
bi.biClrImportant = nNumColors;
_llseek(fh, (LONG)sizeof(BITMAPCOREHEADER)-
sizeof(BITMAPINFOHEADER), SEEK_CUR);
break;
default:
return NULL; /* not a DIB */
}
/* Fill in some default values.
*/
if(bi.biSizeImage == 0)
{
bi.biSizeImage = WIDTHBYTES((DWORD)bi.biWidth * bi.biBitCount) *
bi.biHeight;
}
if(bi.biClrUsed == 0)
{
bi.biClrUsed = DibNumColors(&bi);
}
/* Allocate space for the bitmap info header and color table.
*/
hbi = GlobalAlloc(GMEM_MOVEABLE,
(LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
if (!hbi)
return NULL;
lpbi = (VOID FAR *)GlobalLock(hbi);
*lpbi = bi; // Copy the bitmap header information.
/* Read the color table, if it exists. */
if(nNumColors)
{
pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + bi.biSize);
if (size == sizeof(BITMAPCOREHEADER))
{
/* Read an old color table (with 3-byte entries) and convert
* to the new color table format (with 4-byte entries).
*/
_lread(fh,(LPSTR)pRgb,nNumColors * sizeof(RGBTRIPLE));
for (i=nNumColors-1; i>=0; i--)
{
RGBQUAD rgb;
rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
rgb.rgbReserved = (BYTE)0;
pRgb[i] = rgb;
}
}
else
{
/* Read a new color table.
*/
_lread(fh,(LPSTR)pRgb,nNumColors * sizeof(RGBQUAD));
}
}
/* Seek to the start of the bitmap data.
*/
if (bf.bfOffBits != 0L)
_llseek(fh, off + bf.bfOffBits, SEEK_SET);
GlobalUnlock(hbi);
return hbi;
}
/* PaletteSize(pv)
*
* Returns the size of the palette in bytes. The <pv> parameter can point
* to a BITMAPINFOHEADER or BITMAPCOREHEADER structure.
*/
WORD PaletteSize(
VOID FAR * pv) // Pointer to the bitmap info header structure
{
#define lpbi ((LPBITMAPINFOHEADER)pv)
WORD NumColors;
NumColors = DibNumColors(lpbi);
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
return NumColors * sizeof(RGBTRIPLE);
else
return NumColors * sizeof(RGBQUAD);
#undef lpbi
}
/* DibNumColors(pv)
*
* Returns the number of palette entries in the palette. The <pv> parameter
* can point to a BITMAPINFOHEADER or BITMAPCOREHEADER structure.
*/
WORD DibNumColors(
VOID FAR * pv) // Pointer to the bitmap info header structure
{
#define lpbi ((LPBITMAPINFOHEADER)pv)
#define lpbc ((LPBITMAPCOREHEADER)pv)
int nBitCount;
/* With a BITMAPINFOHEADER structure, the number of palette entries
* is in biClrUsed; otherwise, the count depends on the number of bits
* per pixel.
*/
if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
{
if(lpbi->biClrUsed != 0)
return (WORD)lpbi->biClrUsed;
nBitCount = lpbi->biBitCount;
}
else
{
nBitCount = lpbc->bcBitCount;
}
switch (nBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
#undef lpbi
#undef lpbc
}
/* DibFromBitmap()
*
* Creates a global memory block in DIB format that represents the device-
* dependent bitmap passed in. Returns the handle to the DIB.
*/
HANDLE DibFromBitmap(
HBITMAP hbm, // Device-dependent bitmap to copy
DWORD biStyle, // New DIB: Format of bitmap bits (BI_RGB, etc.)
WORD biBits, // New DIB: Bits per pixel
HPALETTE hpal, // New DIB: Palette or NULL to use system palette
WORD wUsage) // New DIB: DIB palette usage (DIB_RGB_COLORS or
// DIB_PAL_COLORS)
{
BITMAP bm;
BITMAPINFOHEADER bi;
BITMAPINFOHEADER FAR *lpbi;
DWORD dwLen;
int nColors;
HANDLE hdib;
HANDLE h;
HDC hdc;
if (!hbm)
return NULL;
if (wUsage == 0)
wUsage = DIB_RGB_COLORS;
if (biStyle == BI_RGB && wUsage == DIB_RGB_COLORS)
return CreateLogicalDib(hbm,biBits,hpal);
if (hpal == NULL)
hpal = GetStockObject(DEFAULT_PALETTE);
GetObject(hbm,sizeof(bm),(LPSTR)&bm);
GetObject(hpal,sizeof(nColors),(LPSTR)&nColors);
if (biBits == 0)
biBits = bm.bmPlanes * bm.bmBitsPixel;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = biBits;
bi.biCompression = biStyle;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwLen = bi.biSize + PaletteSize(&bi);
hdc = CreateCompatibleDC(NULL);
hpal = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc);
hdib = GlobalAlloc(GMEM_MOVEABLE,dwLen);
if (!hdib)
goto exit;
/* Calculate the biSizeImage field by calling GetDIBits with a NULL
* lpBits param.
*/
lpbi = (VOID FAR *)GlobalLock(hdib);
*lpbi = bi;
GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
NULL, (LPBITMAPINFO)lpbi, wUsage);
bi = *lpbi;
GlobalUnlock(hdib);
/*
* If the driver did not fill in the biSizeImage field, make one up
*/
if (bi.biSizeImage == 0)
{
bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
if (biStyle != BI_RGB)
bi.biSizeImage = (bi.biSizeImage * 3) / 2;
}
/*
* Realloc the buffer big enough to hold all the bits
*/
dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
if (h = GlobalReAlloc(hdib,dwLen,0))
{
hdib = h;
}
else
{
GlobalFree(hdib);
hdib = NULL;
goto exit;
}
/* Get the bitmap bits.
*/
lpbi = (VOID FAR *)GlobalLock(hdib);
GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
(LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi),
(LPBITMAPINFO)lpbi, wUsage);
GlobalUnlock(hdib);
exit:
SelectPalette(hdc,hpal,FALSE);
DeleteDC(hdc);
return hdib;
}
/* BitmapFromDib()
*
* Creates a DDB (Device Dependent Bitmap) given a global handle to
* a memory block in CF_DIB format. Returns a handle to the DDB.
*/
HBITMAP BitmapFromDib(
HANDLE hdib, // Handle to original DIB
HPALETTE hpal, // Handle to original DIB palette
WORD wUsage) // Original DIB palette-entry usage
{
LPBITMAPINFOHEADER lpbi;
HPALETTE hpalT;
HDC hdc;
HBITMAP hbm;
if (!hdib)
return NULL;
if (wUsage == 0)
wUsage = DIB_RGB_COLORS;
lpbi = (VOID FAR *)GlobalLock(hdib);
if (!lpbi)
return NULL;
hdc = GetDC(NULL);
if (hpal)
{
hpalT = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc);
}
hbm = CreateDIBitmap(hdc,
(LPBITMAPINFOHEADER)lpbi,
(LONG)CBM_INIT,
(LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
(LPBITMAPINFO)lpbi,
wUsage );
if (hpal && hpalT)
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
GlobalUnlock(hdib);
return hbm;
}
/* DibFromDib()
*
* Converts a DIB to the specified format.
*
*/
HANDLE DibFromDib(
HANDLE hdib, // DIB to convert
DWORD biStyle, // New DIB: Compression format
WORD biBits, // New DIB: Bits per pixel
HPALETTE hpal, // New DIB: Palette (or NULL to use existing palette)
WORD wUsage) // New DIB: Palette usage
{
BITMAPINFOHEADER bi;
HBITMAP hbm;
BOOL fKillPalette=FALSE;
if (!hdib)
return NULL;
/* Determine whether the current format matches the requested format. */
DibInfo(hdib,&bi);
if (bi.biCompression == biStyle && bi.biBitCount == biBits)
return hdib;
/* If no palette is specified, use the existing DIB palette. */
if (hpal == NULL)
{
hpal = CreateDibPalette(hdib);
fKillPalette++;
}
/* First create a DDB from the DIB. */
hbm = BitmapFromDib(hdib,hpal,wUsage);
if (hbm == NULL)
{
hdib = NULL;
}
else
{
/* Then create the DIB from the DDB. */
hdib = DibFromBitmap(hbm,biStyle,biBits,hpal,wUsage);
DeleteObject(hbm);
}
/* Delete palette, if we created it. */
if (fKillPalette && hpal)
DeleteObject(hpal);
return hdib;
}
/* CreateLogicalDib(hbm, biBits, hPal)
*
* Given a DDB and a HPALETTE create a "logical" DIB. If the HPALETTE is
* NULL, it uses the system palette.
*
* A "logical" DIB is a DIB where the DIB color table *exactly* matches
* the passed logical palette. There will be no system colors in the
* color table, and a pixel value of <n> in the DIB corresponds to logical
* palette index <n>.
*
* Why create a "logical" DIB? When the DIB is written to a disk file and
* then reloaded, the logical palette created from the DIB color table
* exactly matches the one used originaly to create the bitmap. It also
* prevents GDI from doing nearest color matching on PC_RESERVED palettes.
*
* To create the logical DIB, we call GetDIBits() with the DIB_PAL_COLORS
* option. We then convert the palette indices returned in the color table
* to logical RGB values. The entire logical palette passed to <hpal>
* is always copied to the DIB color table.
*
* The DIB color table will have exactly the same number of entries as
* the logical palette. Normally GetDIBits() sets the biClrUsed field to
* the maximum colors supported by the device, regardless of the number of
* colors in the logical palette. If the logical palette contains more
* than 256 colors, the function truncates the color table at 256 entries.
*/
HANDLE CreateLogicalDib(
HBITMAP hbm, // DDB to copy
WORD biBits, // New DIB: bit count: 8, 4, or 0
HPALETTE hpal) // New DIB: palette
{
LPBITMAPINFOHEADER lpbiDDB; // Temporary pointer to DDB BITMAPINFO
WORD FAR * lpDDBClrTbl; // Pointer to DIB color table
HANDLE hLDib;
LPBITMAPINFOHEADER lpLDib; // Pointer to logical DIB header
BYTE FAR * lpLDibBits; // Pointer to logical DIB bits
RGBQUAD FAR * lpLDibRGB; // Pointer to logical DIB color table
int nLDibColors; // How many colors in logical DIB
DWORD dwLDibLen; // Size of logical DIB
HDC hdc; // Temp stuff, working variables
BITMAP bm;
BITMAPINFOHEADER bi;
PALETTEENTRY peT;
DWORD dw;
int n;
HPALETTE hpalT;
if (hbm == NULL)
return NULL;
if (hpal == NULL)
hpal = GetStockObject(DEFAULT_PALETTE);
GetObject(hpal,sizeof(nLDibColors),(LPSTR)&nLDibColors);
GetObject(hbm,sizeof(bm),(LPSTR)&bm);
/* Truncate palette entries at 256 if the logical palette has more
* than 256 entries.
*/
if (nLDibColors > 256)
nLDibColors = 256;
/* If bit count is zero, fill in bit count based on number of colors
* in palette.
*/
if (biBits == 0)
biBits = nLDibColors > 16 ? 8 : 4;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = biBits;
bi.biCompression = BI_RGB;
bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) *
bm.bmHeight;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = nLDibColors;
bi.biClrImportant = 0;
dwLDibLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
hLDib = GlobalAlloc(GMEM_MOVEABLE,dwLDibLen);
if (!hLDib)
return NULL;
lpbiDDB = MAKEP(GlobalAlloc(GMEM_FIXED,
bi.biSize + 256 * sizeof(RGBQUAD)),0);
if (!lpbiDDB)
{
GlobalFree(hLDib);
return NULL;
}
hdc = GetDC(NULL);
hpalT = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc);
lpLDib = (LPVOID)GlobalLock(hLDib);
*lpbiDDB = bi;
*lpLDib = bi;
/* Get the DIB bits. With DIB_PAL_COLORS flag, the color table is
* filled with logical palette indices.
*/
lpLDibBits = (LPSTR)lpLDib + (WORD)lpLDib->biSize + PaletteSize(lpLDib);
GetDIBits(hdc, // Device context
hbm, // Bitmap we're copying
0, // Starting scan line
(WORD)bi.biHeight, // Number of scan lines to copy
lpLDibBits, // Receives bitmap bits in DIB format
(LPBITMAPINFO)lpbiDDB, // Receives DDB color table
DIB_PAL_COLORS); // Usage--copy indices into the
// currently realized logical palette
/* Convert the DIB bits from indices into the color table (which
* contains indices into the logical palette) to direct indices
* into the logical palette.
*
* lpDDBClrTbl Points to the DIB color table, which is a WORD array of
* logical palette indices.
*
* lpLDibBits Points to the DIB bits. Each DIB pixel is a index into
* the DIB color table.
*/
lpDDBClrTbl = (WORD FAR *)((LPSTR)lpbiDDB + (WORD)lpbiDDB->biSize);
if (biBits == 8)
{
for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpLDibBits)++)
*lpLDibBits = (BYTE)lpDDBClrTbl[*lpLDibBits];
}
else // biBits == 4
{
for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpLDibBits)++)
*lpLDibBits = (BYTE)(lpDDBClrTbl[*lpLDibBits & 0x0F] |
(lpDDBClrTbl[(*lpLDibBits >> 4) & 0x0F] << 4));
}
/* Now copy the RGBs in the logical palette to the DIB color table.
*/
lpLDibRGB = (RGBQUAD FAR *)((LPSTR)lpLDib + (WORD)lpLDib->biSize);
for (n=0; n<nLDibColors; n++, lpLDibRGB++)
{
GetPaletteEntries(hpal,n,1,&peT);
lpLDibRGB->rgbRed = peT.peRed;
lpLDibRGB->rgbGreen = peT.peGreen;
lpLDibRGB->rgbBlue = peT.peBlue;
lpLDibRGB->rgbReserved = (BYTE)0;
}
GlobalUnlock(hLDib);
GlobalFree(HIWORD((DWORD)lpbiDDB));
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return hLDib;
}
/* StretchBitmap(hdc, x, y, dx, dy, hbm, xSrc, ySrc, dxSrc, dySrc, rop)
*
* Draws bitmap <hbm> at the specifed position in DC <hdc>, stretching
* or compressing the bitmap as necessary to fit the dimensions of the
* destination rectangle.
*/
BOOL StretchBitmap(
HDC hdc, // Destination device context
int x, int y, // Upper-left corner of destination rect
int dx, int dy, // Destination rect extents
HBITMAP hbm, // Bitmap to display
int xSrc, int ySrc, // Upper-left corner of source rect
int dxSrc, int dySrc, // Source rect extents
DWORD rop) // Raster operation
{
HDC hdcBits;
HPALETTE hpal,hpalT;
BOOL f;
if (!hdc || !hbm)
return FALSE;
hpal = SelectPalette(hdc,GetStockObject(DEFAULT_PALETTE),FALSE);
SelectPalette(hdc,hpal,FALSE);
hdcBits = CreateCompatibleDC(hdc);
SelectObject(hdcBits,hbm);
hpalT = SelectPalette(hdcBits,hpal,FALSE);
RealizePalette(hdcBits);
f = StretchBlt(hdc,x,y,dx,dy,hdcBits,xSrc,ySrc,dxSrc,dySrc,rop);
SelectPalette(hdcBits,hpalT,FALSE);
DeleteDC(hdcBits);
return f;
}
/* DrawBitmap(hdc, x, y, hbm, DWORD)
*
* Draws bitmap <hbm> at the specifed position in DC <hdc>
*
*/
BOOL DrawBitmap(
HDC hdc, // Destination device context
int x, int y, // Upper-left corner of destination rect
HBITMAP hbm, // Bitmap to display
DWORD rop) // Raster operation
{
HDC hdcBits;
BITMAP bm;
BOOL f;
if (!hdc || !hbm)
return FALSE;
hdcBits = CreateCompatibleDC(hdc);
GetObject(hbm,sizeof(BITMAP),(LPSTR)&bm);
SelectObject(hdcBits,hbm);
f = BitBlt(hdc,x,y,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop);
DeleteDC(hdcBits);
return f;
}
/* SetDibUsage(hdib,hpal,wUsage)
*
* Modifies the color table of the passed DIB for use with the wUsage
* parameter specifed.
*
* if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
* if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
* in the passed palette
*
*/
BOOL SetDibUsage(
HANDLE hdib, // DIB to modify
HPALETTE hpal, // DIB palette
WORD wUsage) // New palette usage
{
LPBITMAPINFOHEADER lpbi;
PALETTEENTRY ape[MAXPALETTE];
RGBQUAD FAR * pRgb;
WORD FAR * pw;
int nColors;
int n;
if (hpal == NULL)
hpal = GetStockObject(DEFAULT_PALETTE);
if (!hdib)
return FALSE;
lpbi = (VOID FAR *)GlobalLock(hdib);
if (!lpbi)
return FALSE;
nColors = DibNumColors(lpbi);
if (nColors > 0)
{
pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
switch (wUsage)
{
//
// Set the DIB color table to palette indexes
//
case DIB_PAL_COLORS:
for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
*pw = n;
break;
//
// Set the DIB color table to RGBQUADS
//
default:
case DIB_RGB_COLORS:
nColors = min(nColors,MAXPALETTE);
GetPaletteEntries(hpal,0,nColors,ape);
for (n=0; n<nColors; n++)
{
pRgb[n].rgbRed = ape[n].peRed;
pRgb[n].rgbGreen = ape[n].peGreen;
pRgb[n].rgbBlue = ape[n].peBlue;
pRgb[n].rgbReserved = 0;
}
break;
}
}
GlobalUnlock(hdib);
return TRUE;
}
/* SetPalFlags(hpal,iIndex, cnt, wFlags)
*
* Modifies the palette flags of all indices in the range
* (iIndex - nIndex+cnt) to the parameter specifed.
*/
BOOL SetPalFlags(
HPALETTE hpal, // Palette to modify
int iIndex, // Starting index number
int cntEntries, // How many entries to modify
WORD wFlags) // New flag setting for pal entries
{
int i;
BOOL f;
HANDLE hpe;
PALETTEENTRY FAR *lppe;
if (hpal == NULL)
return FALSE;
if (cntEntries < 0)
GetObject(hpal,sizeof(int),(LPSTR)&cntEntries);
hpe = GlobalAlloc(GMEM_MOVEABLE,(LONG)cntEntries * sizeof(PALETTEENTRY));
if (!hpe)
return FALSE;
lppe = (VOID FAR*)GlobalLock(hpe);
GetPaletteEntries(hpal, iIndex, cntEntries, lppe);
for (i=0; i<cntEntries; i++)
{
lppe[i].peFlags = (BYTE)wFlags;
}
f = SetPaletteEntries(hpal, iIndex, cntEntries, lppe);
GlobalUnlock(hpe);
GlobalFree(hpe);
return f;
}
/* PalEq(hpal1,hpal2)
*
* Returns TRUE if the pallettes are the same
*
*/
BOOL PalEq(HPALETTE hpal1, HPALETTE hpal2)
{
BOOL f;
int i;
int nPal1,nPal2;
PALETTEENTRY FAR *ppe;
if (hpal1 == hpal2)
return TRUE;
if (!hpal1 || !hpal2)
return FALSE;
GetObject(hpal1,sizeof(int),(LPSTR)&nPal1);
GetObject(hpal2,sizeof(int),(LPSTR)&nPal2);
if (nPal1 != nPal2)
return FALSE;
ppe = ALLOCP(nPal1 * 2 * sizeof(PALETTEENTRY));
if (!ppe)
return FALSE;
GetPaletteEntries(hpal1, 0, nPal1, ppe);
GetPaletteEntries(hpal2, 0, nPal2, ppe+nPal1);
for (f=TRUE,i=0; f && i<nPal1; i++)
{
f &= (ppe[i].peRed == ppe[i+nPal1].peRed &&
ppe[i].peBlue == ppe[i+nPal1].peBlue &&
ppe[i].peGreen == ppe[i+nPal1].peGreen);
}
FREEP(ppe);
return f;
}
/* StretchDibBlt(hdc, x, y, dx, dy, hdib, xSrc, ySrc, dxSrc, dySrc, rop, wUsage)
*
* Draws a bitmap in CF_DIB format StretchDIBits(). Uses the same
* parameters as StretchBlt(), except takes a DIB rather than a source
* device context.
*/
BOOL StretchDibBlt(
HDC hdc, // Destination device context
int x, int y, // Destination rect origin
int dx, int dy, // Destination rect extents
HANDLE hdib, // Bitmap to display
int xSrc, int ySrc, // Source rect origin
int dxSrc, int dySrc, // Source rect extents
LONG rop, // Raster operation
WORD wUsage) // Pal usage DIB_PAL_COLORS or DIB_RGB_COLORS
{
LPBITMAPINFOHEADER lpbi;
LPSTR pBuf;
BOOL f;
if (!hdib)
return PatBlt(hdc,x,y,dx,dy,rop);
if (wUsage == 0)
wUsage = DIB_RGB_COLORS;
lpbi = (VOID FAR *)GlobalLock(hdib);
if (!lpbi)
return FALSE;
if (dxSrc == -1 && dySrc == -1)
{
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
{
dxSrc = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
dySrc = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
}
else
{
dxSrc = (int)lpbi->biWidth;
dySrc = (int)lpbi->biHeight;
}
}
if (dx == -1 && dy == -1)
{
dx = dxSrc;
dy = dySrc;
}
pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
f = StretchDIBits (
hdc,
x,y,
dx,dy,
xSrc,ySrc,
dxSrc,dySrc,
pBuf,
(LPBITMAPINFO)lpbi,
wUsage,
rop);
GlobalUnlock(hdib);
return f;
}
/* DibBlt(hdc, xDest, yDest, dxDest, dyDest, hdib, xSrc, ySrc, rop, wUsage)
*
* Draws a bitmap in CF_DIB format, using SetDIBits to device.
*
* Takes the same parameters as BitBlt(), except takes a DIB instead of
* a source device context.
*/
BOOL DibBlt(
HDC hdc, // Destination device context
int xDest, int yDest, // Destination rect origin
int dxDest, int dyDest, // Destination rect extents
HANDLE hdib, // DIB to draw
int xSrc, int ySrc, // Source rect origin
LONG rop, // Raster op
WORD wUsage) // Pal usage (DIB_PAL_COLORS or DIB_RGB_COLORS)
{
LPBITMAPINFOHEADER lpbi;
LPSTR pBuf;
BOOL f;
if (!hdib)
return PatBlt(hdc,xDest,yDest,dxDest,dyDest,rop);
if (wUsage == 0)
wUsage = DIB_RGB_COLORS;
lpbi = (VOID FAR *)GlobalLock(hdib);
if (!lpbi)
return FALSE;
if (dxDest == -1 && dyDest == -1)
{
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
{
dxDest = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
dyDest = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
}
else
{
dxDest = (int)lpbi->biWidth;
dyDest = (int)lpbi->biHeight;
}
}
pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
f = StretchDIBits (
hdc,
xDest,yDest,
dxDest,dyDest,
xSrc,ySrc,
dxDest,dyDest,
pBuf, (LPBITMAPINFO)lpbi,
wUsage,
rop);
GlobalUnlock(hdib);
return f;
}
/* DibLock(hdib, x, y)
*
* Locks a DIB and returns a pointer to the bitmap bits at the specified
* coordinate.
*/
LPVOID DibLock(
HANDLE hdib, // DIB to lock
int x, int y) // Bit coordinates
{
return DibXY((LPBITMAPINFOHEADER)GlobalLock(hdib),x,y);
}
/* DibUnlock(hdib)
*
* Unlocks a DIB.
*/
VOID DibUnlock(HANDLE hdib)
{
GlobalUnlock(hdib);
}
/* DibXY(lpbi, x, y)
*
* Given a BITMAPINFOHEADER and a set of coordinates, returns a pointer
* to the bitmap bits at the specified coordinates.
*/
LPVOID DibXY(LPBITMAPINFOHEADER lpbi,int x, int y)
{
BYTE huge *pBits;
DWORD ulWidthBytes;
pBits = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
ulWidthBytes = WIDTHBYTES(lpbi->biWidth*lpbi->biBitCount);
pBits += (ulWidthBytes * (long)y) + x;
return (LPVOID)pBits;
}
/* fmemcpy(fpDst, fpSrc, uiCount)
*
* Copies the specified number of bytes from the source to the destination.
*/
static void fmemcpy(
void far *fpDst, // Destination address
void far *fpSrc, // Source address
unsigned int uiCount) // How many bytes to copy
{
while (uiCount-- > 0)
*((char far *) fpDst)++ = *((char far *) fpSrc)++;
}
/* CreateDib(hdib, dx, dy)
*
* Creates a DIB with the same header and color table as the original
* DIB, with sufficient space to hold the indicated region. If the <hdib>
* is NULL, creates a DIB header and uninitialized, 256-entry color table.
*/
HANDLE CreateDib(
HANDLE hdib, // DIB to copy or NULL
int dx, int dy) // Size of new DIB or -1 to use original DIB extents
{
HANDLE hdibN;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi1;
LPBITMAPINFOHEADER lpbi2;
RGBQUAD FAR * pRgb1;
RGBQUAD FAR * pRgb2;
if (hdib) // Copy DIB header or create a new one
{
DibInfo(hdib,&bi);
}
else
{
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biPlanes = 1;
bi.biBitCount = 8;
bi.biWidth = 0;
bi.biHeight = 0;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 256;
bi.biClrImportant = 0;
}
if (dx != -1) // Use specified measurements or original extents
bi.biWidth = dx;
if (dy != -1)
bi.biHeight = dy;
bi.biSizeImage = WIDTHBYTES(bi.biWidth*bi.biBitCount) * (long)dy;
hdibN = GlobalAlloc(GMEM_MOVEABLE,sizeof(BITMAPINFOHEADER) +
+ (long)bi.biClrUsed * sizeof(RGBQUAD) + bi.biSizeImage);
/* Copy the color table across
*/
if (hdibN && hdib)
{
lpbi1 = (VOID FAR*)GlobalLock(hdibN);
lpbi2 = (VOID FAR*)GlobalLock(hdib);
*lpbi1 = bi;
pRgb1 = (VOID FAR *)((LPSTR)lpbi1 + lpbi1->biSize);
pRgb2 = (VOID FAR *)((LPSTR)lpbi2 + lpbi2->biSize);
while (bi.biClrUsed-- > 0)
*pRgb1++ = *pRgb2++;
GlobalUnlock(hdib);
GlobalUnlock(hdibN);
}
return hdibN;
}
/*
* Private routines to read/write more than 64k
*/
#define MAXREAD (WORD)(32 * 1024)
static DWORD NEAR PASCAL lread(int fh, VOID FAR *pv, DWORD ul)
{
DWORD ulT = ul;
BYTE huge *hp = pv;
while (ul > MAXREAD) {
if (_lread(fh, (LPSTR)hp, MAXREAD) != MAXREAD)
return 0;
ul -= MAXREAD;
hp += MAXREAD;
}
if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
return 0;
return ulT;
}
static DWORD NEAR PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul)
{
DWORD ulT = ul;
BYTE huge *hp = pv;
while (ul > MAXREAD) {
if (_lwrite(fh, (LPSTR)hp, MAXREAD) != MAXREAD)
return 0;
ul -= MAXREAD;
hp += MAXREAD;
}
if (_lwrite(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
return 0;
return ulT;
}