home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-386-Vol-2of3.iso
/
t
/
triq.zip
/
DIB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
43KB
|
1,720 lines
/*----------------------------------------------------------------------------*\
| Routines for dealing with Device independent bitmaps |
| |
| |
\*----------------------------------------------------------------------------*/
/*
(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 "gmem.h"
#include "dib.h"
void FAR * FAR PASCAL lmemcpy(LPSTR dest, LPSTR source, WORD count);
//void FAR * FAR PASCAL hmemcpy(char huge *dest, char huge *source, LONG count);
//#include "errprop.h"
//extern BOOL fErrProp;
//extern BOOL bMonoBitmap;
HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal);
DWORD NEAR PASCAL lread(int fh, VOID FAR *pv, DWORD ul);
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
/*
* Open a DIB file and return a MEMORY DIB, a memory handle containing..
*
* BITMAP INFO bi
* palette data
* bits....
*
*/
HANDLE OpenDIB(LPSTR szFile)
{
unsigned fh;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen;
DWORD dwBits;
HANDLE hdib;
HANDLE h;
OFSTRUCT of;
if (HIWORD((DWORD)szFile) == 0)
{
fh = LOWORD((DWORD)szFile);
}
else
{
fh = OpenFile(szFile, &of, OF_READ);
}
if (fh == -1)
return NULL;
hdib = ReadDibBitmapInfo(fh);
if (!hdib)
return NULL;
DibInfo(hdib,&bi);
/* How much memory do we need to hold the DIB */
dwBits = bi.biSizeImage;
dwLen = bi.biSize + PaletteSize(&bi) + dwBits;
/* Can we get more memory? */
h = GReAlloc(hdib,dwLen);
if (!h)
{
GFree(hdib);
hdib = NULL;
}
else
{
hdib = h;
}
if (hdib)
{
lpbi = GLock(hdib);
/* read in the bits */
lread(fh, (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi), dwBits);
GUnlock(hdib);
}
exit:
if (HIWORD((DWORD)szFile) != 0)
_lclose(fh);
return hdib;
}
/*
* Write a global handle in CF_DIB format to a file.
*
*/
BOOL WriteDIB(LPSTR szFile,HANDLE hdib)
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;
BITMAPINFOHEADER bi;
int fh;
OFSTRUCT of;
DWORD dwSize;
if (!hdib)
return FALSE;
if (HIWORD((DWORD)szFile) == 0)
{
fh = LOWORD((DWORD)szFile);
}
else
{
fh = OpenFile(szFile,&of,OF_CREATE|OF_READWRITE);
}
if (fh == -1)
return FALSE;
DibInfo(hdib,&bi);
dwSize = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
lpbi = GLock(hdib);
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);
GUnlock(hdib);
if (HIWORD((DWORD)szFile) != 0)
_lclose(fh);
return TRUE;
}
/*
* DibInfo(hbi, lpbi)
*
* retrives the DIB info associated with a CF_DIB format memory block.
*/
BOOL DibInfo(HANDLE hbi,LPBITMAPINFOHEADER lpbi)
{
if (hbi)
{
*lpbi = *(LPBITMAPINFOHEADER)GLock(hbi);
GUnlock(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->biSizeImage == 0L)
lpbi->biSizeImage = lpbi->biHeight * DIBWIDTHBYTES(*lpbi);
if (lpbi->biClrUsed == 0L)
lpbi->biClrUsed = DibNumColors(lpbi);
return TRUE;
}
return FALSE;
}
/*
* CreateBIPalette()
*
* Given a Pointer to a BITMAPINFO struct will create a
* a GDI palette object from the color table.
*
* works with "old" and "new" DIB's
*
*/
HPALETTE CreateBIPalette(LPBITMAPINFOHEADER lpbi)
{
LOGPALETTE *pPal;
HPALETTE hpal = NULL;
WORD nNumColors;
BYTE red;
BYTE green;
BYTE blue;
int 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)
{
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)
{
hpal = CreateColorPalette();
}
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)GLock(hbi));
GUnlock(hbi);
return hpal;
}
//
// create a 6*6*6 rainbow palette
//
HPALETTE CreateColorPalette()
{
LOGPALETTE *pPal;
PALETTEENTRY *ppe;
HPALETTE hpal = NULL;
WORD nNumColors;
BYTE r,g,b;
nNumColors = 6*6*6;
pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
if (!pPal)
goto exit;
pPal->palNumEntries = nNumColors;
pPal->palVersion = PALVERSION;
ppe = pPal->palPalEntry;
for (r=0; r<6; r++)
for (g=0; g<6; g++)
for (b=0; b<6; b++)
{
ppe->peRed = (BYTE)((WORD)r * 255 / 6);
ppe->peGreen = (BYTE)((WORD)g * 255 / 6);
ppe->peBlue = (BYTE)((WORD)b * 255 / 6);
ppe->peFlags = (BYTE)0;
ppe++;
}
hpal = CreatePalette(pPal);
LocalFree((HANDLE)pPal);
exit:
return hpal;
}
HPALETTE CreateExplicitPalette(void)
{
PLOGPALETTE ppal;
HPALETTE hpal;
int i;
#define NPAL 256
ppal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * NPAL);
ppal->palVersion = 0x300;
ppal->palNumEntries = NPAL;
for (i=0; i<NPAL; i++)
{
ppal->palPalEntry[i].peFlags = (BYTE)PC_EXPLICIT;
ppal->palPalEntry[i].peRed = (BYTE)i;
ppal->palPalEntry[i].peGreen = (BYTE)0;
ppal->palPalEntry[i].peBlue = (BYTE)0;
}
hpal = CreatePalette(ppal);
LocalFree((HANDLE)ppal);
return hpal;
}
/* CreateSystemPalette()
*
* Return a palette which represents the system (physical) palette.
* By selecting this palette into a screen DC and realizing the palette,
* the exact physical mapping will be restored
*
* one use for this is when "snaping" the screen as a bitmap
*
* On error (e.g. out of memory), NULL is returned.
*/
HPALETTE CreateSystemPalette(void)
{
HDC hdc; // DC onto the screen
int iSizePalette; // size of entire palette
int iFixedPalette; // number of reserved colors
NPLOGPALETTE pLogPal = NULL;
HPALETTE hpal = NULL;
int i;
hdc = GetDC(NULL);
iSizePalette = GetDeviceCaps(hdc, SIZEPALETTE);
//
// determine the number of 'static' system colors that
// are currently reserved
//
// this is the correct number of parms... bug in windows.h
if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
iFixedPalette = GetDeviceCaps(hdc, NUMCOLORS);
else
iFixedPalette = 2;
//
// create a logical palette containing the system colors;
// this palette has all entries except fixed (system) colors
// flagged as PC_NOCOLLAPSE
//
pLogPal = (NPLOGPALETTE)LocalAlloc(LPTR, sizeof(LOGPALETTE)
+ iSizePalette * sizeof(PALETTEENTRY));
if (pLogPal)
{
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = iSizePalette;
GetSystemPaletteEntries(hdc, 0, iSizePalette, pLogPal->palPalEntry);
for (i = iFixedPalette/2; i < iSizePalette-iFixedPalette/2; i++)
pLogPal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
hpal = CreatePalette(pLogPal);
LocalFree((HANDLE)pLogPal);
}
ReleaseDC(NULL,hdc);
return hpal;
}
/*
* ReadDibBitmapInfo()
*
* Will read a file in DIB format and return a global HANDLE to it's
* BITMAPINFO. This function will work with both "old" and "new"
* bitmap formats, but will allways return a "new" BITMAPINFO
*
*/
HANDLE ReadDibBitmapInfo(int fh)
{
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);
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);
}
if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
return FALSE;
nNumColors = DibNumColors(&bi);
/*
* what type of bitmap info is this?
*/
switch (size = (int)bi.biSize)
{
case sizeof(BITMAPINFOHEADER):
break;
case sizeof(BITMAPCOREHEADER):
bc = *(LPBITMAPCOREHEADER)&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 = bi.biHeight * DIBWIDTHBYTES(bi);
}
if (bi.biXPelsPerMeter == 0)
{
bi.biXPelsPerMeter = 0; // ??????????????
}
if (bi.biYPelsPerMeter == 0)
{
bi.biYPelsPerMeter = 0; // ??????????????
}
if (bi.biClrUsed == 0)
{
bi.biClrUsed = DibNumColors(&bi);
}
hbi = GAlloc((LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
if (!hbi)
return NULL;
lpbi = (VOID FAR *)GLock(hbi);
*lpbi = bi;
pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + bi.biSize);
if (nNumColors)
{
if (size == sizeof(BITMAPCOREHEADER))
{
/*
* convert a old color table (3 byte entries) to a new
* color table (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
{
_lread(fh,(LPSTR)pRgb,nNumColors * sizeof(RGBQUAD));
}
}
if (bf.bfOffBits != 0L)
_llseek(fh,off + bf.bfOffBits,SEEK_SET);
GUnlock(hbi);
return hbi;
}
/* How big is the palette? if bits per pel not 24
* no of bytes to read is 6 for 1 bit, 48 for 4 bits
* 256*3 for 8 bits and 0 for 24 bits
*/
WORD PaletteSize(VOID FAR * pv)
{
#define lpbi ((LPBITMAPINFOHEADER)pv)
#define lpbc ((LPBITMAPCOREHEADER)pv)
WORD NumColors;
NumColors = DibNumColors(lpbi);
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
return NumColors * sizeof(RGBTRIPLE);
else
return NumColors * sizeof(RGBQUAD);
#undef lpbi
#undef lpbc
}
/* How Many colors does this DIB have?
* this will work on both PM and Windows bitmap info structures.
*/
WORD DibNumColors(VOID FAR * pv)
{
#define lpbi ((LPBITMAPINFOHEADER)pv)
#define lpbc ((LPBITMAPCOREHEADER)pv)
int bits;
/*
* with the new format headers, the size of the palette is in biClrUsed
* else is dependent on bits per 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:
return 0;
}
#undef lpbi
#undef lpbc
}
/*
* DibFromBitmap()
*
* Will create a global memory block in DIB format that represents the DDB
* passed in
*
*/
HANDLE DibFromBitmap(HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal, WORD wUsage)
{
BITMAP bm;
BITMAPINFOHEADER bi;
BITMAPINFOHEADER FAR *lpbi;
DWORD dwLen;
int nColors;
HANDLE hdib;
HANDLE h;
HDC hdc;
if (wUsage == 0)
wUsage = DIB_RGB_COLORS;
if (!hbm)
return NULL;
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); // why is this needed on a MEMORY DC? GDI bug??
hdib = GAlloc(dwLen);
if (!hdib)
goto exit;
lpbi = GLock(hdib);
*lpbi = bi;
/*
* call GetDIBits with a NULL lpBits param, so it will calculate the
* biSizeImage field for us
*/
GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
NULL, (LPBITMAPINFO)lpbi, wUsage);
bi = *lpbi;
GUnlock(hdib);
/*
* HACK! if the driver did not fill in the biSizeImage field, make one up
*/
if (bi.biSizeImage == 0)
{
bi.biSizeImage = (DWORD)WIDTHBYTES(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 = GReAlloc(hdib,dwLen))
{
hdib = h;
}
else
{
GFree(hdib);
hdib = NULL;
goto exit;
}
/*
* call GetDIBits with a NON-NULL lpBits param, and actualy get the
* bits this time
*/
lpbi = GLock(hdib);
GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
(LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi),
(LPBITMAPINFO)lpbi, wUsage);
bi = *lpbi;
GUnlock(hdib);
exit:
SelectPalette(hdc,hpal,FALSE);
DeleteDC(hdc);
return hdib;
}
/*
* BitmapFromDib()
*
* Will create a DDB (Device Dependent Bitmap) given a global handle to
* a memory block in CF_DIB format
*
*/
HBITMAP BitmapFromDib(HANDLE hdib, HPALETTE hpal, WORD wUsage)
{
LPBITMAPINFOHEADER lpbi;
HPALETTE hpalT;
HDC hdc;
HBITMAP hbm;
WORD dx,dy,bits;
if (!hdib)
return NULL;
if (wUsage == 0)
wUsage = DIB_RGB_COLORS;
lpbi = GLock(hdib);
if (!lpbi)
return NULL;
hdc = GetDC(NULL);
// hdc = CreateCompatibleDC(NULL);
if (hpal)
{
hpalT = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc); // why is this needed on a MEMORY DC? GDI bug??
}
#if 0
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
{
dx = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
dy = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
bits = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
}
else
{
dx = (WORD)lpbi->biWidth;
dy = (WORD)lpbi->biHeight;
bits = (WORD)lpbi->biBitCount;
}
if (bMonoBitmap /* || bits == 1 */)
{
hbm = CreateBitmap(dx,dy,1,1,NULL);
}
else
{
HDC hdcScreen = GetDC(NULL);
hbm = CreateCompatibleBitmap(hdcScreen,dx,dy);
ReleaseDC(NULL,hdcScreen);
}
if (hbm)
{
if (fErrProp)
SetDIBitsErrProp(hdc,hbm,0,dy,
(LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
(LPBITMAPINFO)lpbi,wUsage);
else
SetDIBits(hdc,hbm,0,dy,
(LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
(LPBITMAPINFO)lpbi,wUsage);
}
#else
hbm = CreateDIBitmap(hdc,
(LPBITMAPINFOHEADER)lpbi,
(LONG)CBM_INIT,
(LPSTR)lpbi + (int)lpbi->biSize + PaletteSize(lpbi),
(LPBITMAPINFO)lpbi,
wUsage );
#endif
if (hpal && hpalT)
SelectPalette(hdc,hpalT,FALSE);
// DeleteDC(hdc);
ReleaseDC(NULL,hdc);
GUnlock(hdib);
return hbm;
}
/*
* DibFromDib()
*
* Will convert a DIB in 1 format to a DIB in the specifed format
*
*/
HANDLE DibFromDib(HANDLE hdib, DWORD biStyle, WORD biBits, HPALETTE hpal, WORD wUsage)
{
BITMAPINFOHEADER bi;
HBITMAP hbm;
BOOL fKillPalette=FALSE;
if (!hdib)
return NULL;
DibInfo(hdib,&bi);
/*
* do we have the requested format already?
*/
if (bi.biCompression == biStyle && bi.biBitCount == biBits)
return hdib;
if (hpal == NULL)
{
hpal = CreateDibPalette(hdib);
fKillPalette++;
}
hbm = BitmapFromDib(hdib,hpal,wUsage);
if (hbm == NULL)
{
hdib = NULL;
}
else
{
hdib = DibFromBitmap(hbm,biStyle,biBits,hpal,wUsage);
DeleteObject(hbm);
}
if (fKillPalette && hpal)
DeleteObject(hpal);
return hdib;
}
/*
* CreateLogicalDib
*
* Given a DDB and a HPALETTE create a "logical" DIB
*
* if the HBITMAP is NULL create a DIB from the system "stock" bitmap
* This is used to save a logical palette to a disk file as a DIB
*
* if the HPALETTE is NULL use the system "stock" palette (ie 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 DIB
* block, and a pixel value of <n> in the DIB will correspond to logical
* palette index <n>.
*
* This is accomplished by doing a GetDIBits() with the DIB_PAL_COLORS
* option then converting the palindexes returned in the color table
* from palette indexes to logical RGB values. The entire passed logical
* palette is always copied to the DIB color table.
*
* The DIB color table will have exactly the same number of entries as
* the logical palette. Normaly GetDIBits() will always set biClrUsed to
* the maximum colors supported by the device regardless of the number of
* colors in the logical palette
*
* Why would you want to do this? The major reason for a "logical" DIB
* is so when the DIB is written to a disk file then reloaded the logical
* palette created from the DIB color table will be the same as one used
* originaly to create the bitmap. It also will prevent GDI from doing
* nearest color matching on PC_RESERVED palettes.
*
* ** What do we do if the logical palette has more than 256 entries!!!!!
* ** GetDIBits() may return logical palette index's that are greater than
* ** 256, we cant represent these colors in the "logical" DIB
* **
* ** for now hose the caller?????
*
*/
HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal)
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpDib; // pointer to DIB
LPBITMAPINFOHEADER lpbi; // temp pointer to BITMAPINFO
DWORD dwLen;
DWORD dw;
int n;
int nColors;
HANDLE hdib;
HDC hdc;
BYTE FAR * lpBits;
WORD FAR * lpCT;
RGBQUAD FAR * lpRgb;
PALETTEENTRY peT;
HPALETTE hpalT;
if (hpal == NULL)
hpal = GetStockObject(DEFAULT_PALETTE);
if (hbm == NULL)
hbm = NULL; // ????GetStockObject(STOCK_BITMAP);
GetObject(hpal,sizeof(nColors),(LPSTR)&nColors);
GetObject(hbm,sizeof(bm),(LPSTR)&bm);
if (biBits == 0)
biBits = nColors > 16 ? 8 : 4;
if (nColors > 256) // ACK!
; // How do we handle this????
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = biBits;
bi.biCompression = BI_RGB;
bi.biSizeImage = (DWORD)WIDTHBYTES(bm.bmWidth * biBits) * bm.bmHeight;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = nColors;
bi.biClrImportant = 0;
dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
hdib = GAlloc(dwLen);
if (!hdib)
return NULL;
lpbi = GAllocPtr(bi.biSize + 256 * sizeof(RGBQUAD));
if (!lpbi)
{
GFree(hdib);
return NULL;
}
hdc = GetDC(NULL);
hpalT = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc); // why is this needed on a MEMORY DC? GDI bug??
lpDib = GLock(hdib);
*lpbi = bi;
*lpDib = bi;
lpCT = (WORD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
lpRgb = (RGBQUAD FAR *)((LPSTR)lpDib + (WORD)lpDib->biSize);
lpBits = (LPSTR)lpDib + (WORD)lpDib->biSize + PaletteSize(lpDib);
/*
* call GetDIBits to get the DIB bits and fill the color table with
* logical palette index's
*/
GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
lpBits,(LPBITMAPINFO)lpbi, DIB_PAL_COLORS);
/*
* Now convert the DIB bits into "real" logical palette index's
*
* lpCT points to the DIB color table wich is a WORD array of
* logical palette index's
*
* lpBits points to the DIB bits, each DIB pixel is a index into
* the DIB color table.
*
*/
if (biBits == 8)
{
for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpBits)++)
*lpBits = (BYTE)lpCT[*lpBits];
}
else // biBits == 4
{
for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpBits)++)
*lpBits = lpCT[*lpBits & 0x0F] | (lpCT[(*lpBits >> 4) & 0x0F] << 4);
}
/*
* Now copy the RGBs in the logical palette to the dib color table
*/
for (n=0; n<nColors; n++,lpRgb++)
{
GetPaletteEntries(hpal,n,1,&peT);
lpRgb->rgbRed = peT.peRed;
lpRgb->rgbGreen = peT.peGreen;
lpRgb->rgbBlue = peT.peBlue;
lpRgb->rgbReserved = (BYTE)0;
}
GUnlock(hdib);
GFreePtr(lpbi);
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return hdib;
}
void xlatClut8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
{
DWORD dw;
for (dw = 0; dw < dwSize; dw++, ((BYTE huge *)pb)++)
*pb = xlat[*pb];
}
void xlatClut4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
{
DWORD dw;
for (dw = 0; dw < dwSize; dw++, ((BYTE huge *)pb)++)
*pb = xlat[*pb & 0x0F] | (xlat[(*pb >> 4) & 0x0F] << 4);
}
#define RLE_ESCAPE 0
#define RLE_EOL 0
#define RLE_EOF 1
#define RLE_JMP 2
void xlatRle8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
{
BYTE cnt;
BYTE b;
BYTE huge *prle = pb;
for(;;)
{
cnt = *prle++;
b = *prle;
if (cnt == RLE_ESCAPE)
{
prle++;
switch (b)
{
case RLE_EOF:
return;
case RLE_EOL:
break;
case RLE_JMP:
prle++; // skip dX
prle++; // skip dY
break;
default:
cnt = b;
for (b=0; b<cnt; b++,prle++)
*prle = xlat[*prle];
if (cnt & 1)
prle++;
break;
}
}
else
{
*prle++ = xlat[b];
}
}
}
void xlatRle4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
{
}
//
// MapDib - map the given DIB so it matches the specifed palette
//
BOOL MapDib(HANDLE hdib, HPALETTE hpal)
{
LPBITMAPINFOHEADER lpbi;
PALETTEENTRY pe;
int n;
int nDibColors;
int nPalColors;
BYTE FAR * lpBits;
WORD FAR * lpCT;
RGBQUAD FAR * lpRgb;
BYTE xlat[256];
DWORD dw;
DWORD dwSize;
if (!hpal || !hdib)
return FALSE;
lpbi = GLock(hdib);
lpRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
lpBits = DibXY(lpbi,0,0);
GetObject(hpal,sizeof(int),(LPSTR)&nPalColors);
nDibColors = DibNumColors(lpbi);
if (nPalColors > nDibColors)
{
//
// This is bad, we need to grow the dib! punt for now
//
nPalColors = nDibColors;
}
//
// build a xlat table. from the current DIB colors to the given
// palette.
//
for (n=0; n<nDibColors; n++)
xlat[n] = (BYTE)GetNearestPaletteIndex(hpal,RGB(lpRgb[n].rgbRed,lpRgb[n].rgbGreen,lpRgb[n].rgbBlue));
//
// translate the DIB bits
//
if ((dwSize = lpbi->biSizeImage) == 0)
dwSize = lpbi->biHeight * DIBWIDTHBYTES(*lpbi);
switch ((WORD)lpbi->biCompression)
{
case BI_RLE8:
xlatRle8(lpBits, dwSize, xlat);
break;
case BI_RLE4:
xlatRle4(lpBits, dwSize, xlat);
break;
case BI_RGB:
if (lpbi->biBitCount == 8)
xlatClut8(lpBits, dwSize, xlat);
else
xlatClut4(lpBits, dwSize, xlat);
break;
}
//
// Now copy the RGBs in the logical palette to the dib color table
//
for (n=0; n<nPalColors; n++)
{
GetPaletteEntries(hpal,n,1,&pe);
lpRgb[n].rgbRed = pe.peRed;
lpRgb[n].rgbGreen = pe.peGreen;
lpRgb[n].rgbBlue = pe.peBlue;
lpRgb[n].rgbReserved = (BYTE)0;
}
for (n=nPalColors; n<nDibColors; n++)
{
lpRgb[n].rgbRed = (BYTE)0;
lpRgb[n].rgbGreen = (BYTE)0;
lpRgb[n].rgbBlue = (BYTE)0;
lpRgb[n].rgbReserved = (BYTE)0;
}
GUnlock(hdib);
return TRUE;
}
/*
* Draws bitmap <hbm> at the specifed position in DC <hdc>
*
*/
BOOL StretchBitmap(HDC hdc, int x, int y, int dx, int dy, HBITMAP hbm, int x0, int y0, int dx0, int dy0, DWORD rop)
{
HDC hdcBits;
BITMAP bm;
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,x0,y0,dx0,dy0,rop);
SelectPalette(hdcBits,hpalT,FALSE);
DeleteDC(hdcBits);
return f;
}
/*
* Draws bitmap <hbm> at the specifed position in DC <hdc>
*
*/
BOOL DrawBitmap(HDC hdc, int x, int y, HBITMAP hbm, DWORD rop)
{
HDC hdcBits;
BITMAP bm;
HPALETTE hpalT;
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;
}
/*
* Draws HDIB <hdib> at the specifed position in DC <hdc>
*
*/
BOOL DrawDib(HDC hdc, int x, int y, HANDLE hdib, HPALETTE hpal, WORD wUsage)
{
HPALETTE hpalT;
if (hpal)
{
hpalT = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc);
}
DibBlt(hdc,x,y,-1,-1,hdib,0,0,SRCCOPY,wUsage);
if (hpal)
{
SelectPalette(hdc,hpalT,FALSE);
}
}
/*
* 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, HPALETTE hpal,WORD wUsage)
{
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 = GLock(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;
}
}
GUnlock(hdib);
return TRUE;
}
/*
* SetPalFlags(hpal,iIndex, cnt, wFlags)
*
* Modifies the palette flags of all indexs in the range (iIndex - nIndex+cnt)
* to the parameter specifed.
*
*/
BOOL SetPalFlags(HPALETTE hpal, int iIndex, int cntEntries, WORD wFlags)
{
int i;
BOOL f;
PALETTEENTRY FAR *lppe;
if (hpal == NULL)
return FALSE;
if (cntEntries < 0)
GetObject(hpal,sizeof(int),(LPSTR)&cntEntries);
lppe = GAllocPtr((LONG)cntEntries * sizeof(PALETTEENTRY));
if (!lppe)
return FALSE;
GetPaletteEntries(hpal, iIndex, cntEntries, lppe);
for (i=0; i<cntEntries; i++)
{
lppe[i].peFlags = (BYTE)wFlags;
}
f = SetPaletteEntries(hpal, iIndex, cntEntries, lppe);
GFreePtr(lppe);
return f;
}
/*
* PalEq(hpal1,hpal2)
*
* return TRUE if the palette's 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 = GAllocPtr(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);
}
GFreePtr(ppe);
return f;
}
/*
* StretchDibBlt()
*
* draws a bitmap in CF_DIB format, using StretchDIBits()
*
* takes the same parameters as StretchBlt()
*/
BOOL StretchDibBlt(HDC hdc, int x, int y, int dx, int dy, HANDLE hdib, int x0, int y0, int dx0, int dy0, LONG rop, WORD wUsage)
{
LPBITMAPINFOHEADER lpbi;
LPSTR pBuf;
BOOL f;
if (!hdib)
return PatBlt(hdc,x,y,dx,dy,rop);
if (wUsage == 0)
wUsage = DIB_RGB_COLORS;
lpbi = GLock(hdib);
if (!lpbi)
return FALSE;
if (dx0 == -1 && dy0 == -1)
{
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
{
dx0 = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
dy0 = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
}
else
{
dx0 = (int)lpbi->biWidth;
dy0 = (int)lpbi->biHeight;
}
}
if (dx < 0 && dy < 0)
{
dx = dx0 * -dx;
dy = dy0 * -dy;
}
pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
f = StretchDIBits (
hdc,
x,y,
dx,dy,
x0,y0,
dx0,dy0,
pBuf, (LPBITMAPINFO)lpbi,
wUsage,
rop);
GUnlock(hdib);
return f;
}
/*
* DibBlt()
*
* draws a bitmap in CF_DIB format, using SetDIBits to device.
*
* takes the same parameters as BitBlt()
*/
BOOL DibBlt(HDC hdc, int x0, int y0, int dx, int dy, HANDLE hdib, int x1, int y1, LONG rop, WORD wUsage)
{
LPBITMAPINFOHEADER lpbi;
LPSTR pBuf;
BOOL f;
if (!hdib)
return PatBlt(hdc,x0,y0,dx,dy,rop);
if (wUsage == 0)
wUsage = DIB_RGB_COLORS;
lpbi = GLock(hdib);
if (!lpbi)
return FALSE;
if (dx == -1 && dy == -1)
{
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
{
dx = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
dy = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
}
else
{
dx = (int)lpbi->biWidth;
dy = (int)lpbi->biHeight;
}
}
pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
#if 0
f = SetDIBitsToDevice(hdc, x0, y0, dx, dy,
x1,y1,
x1,
dy,
pBuf, (LPBITMAPINFO)lpbi,
wUsage );
#else
f = StretchDIBits (
hdc,
x0,y0,
dx,dy,
x1,y1,
dx,dy,
pBuf, (LPBITMAPINFO)lpbi,
wUsage,
rop);
#endif
GUnlock(hdib);
return f;
}
LPVOID DibLock(HANDLE hdib,int x, int y)
{
return DibXY((LPBITMAPINFOHEADER)GLock(hdib),x,y);
}
VOID DibUnlock(HANDLE hdib)
{
GUnlock(hdib);
}
LPVOID DibXY(LPBITMAPINFOHEADER lpbi,int x, int y)
{
BYTE huge *pBits;
DWORD ulWidthBytes;
pBits = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
ulWidthBytes = DIBWIDTHBYTES(*lpbi);
pBits += (ulWidthBytes * (long)y) + (x * (int)lpbi->biBitCount / 8);
return (LPVOID)pBits;
}
HANDLE CreateDib(int bits, int dx, int dy)
{
HANDLE hdib;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD FAR * pRgb;
int i;
//
// These are the standard VGA colors, we will be stuck with until the
// end of time!
//
static DWORD CosmicColors[16] = {
0x00000000 // 0000 black
,0x00800000 // 0001 dark red
,0x00008000 // 0010 dark green
,0x00808000 // 0011 mustard
,0x00000080 // 0100 dark blue
,0x00800080 // 0101 purple
,0x00008080 // 0110 dark turquoise
,0x00C0C0C0 // 1000 gray
,0x00808080 // 0111 dark gray
,0x00FF0000 // 1001 red
,0x0000FF00 // 1010 green
,0x00FFFF00 // 1011 yellow
,0x000000FF // 1100 blue
,0x00FF00FF // 1101 pink (magenta)
,0x0000FFFF // 1110 cyan
,0x00FFFFFF // 1111 white
};
if (bits <= 0)
bits = 8;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biPlanes = 1;
bi.biBitCount = bits;
bi.biWidth = dx;
bi.biHeight = dy;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bi.biClrUsed = DibNumColors(&bi);
hdib = GAllocF(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(BITMAPINFOHEADER)
+ (long)bi.biClrUsed * sizeof(RGBQUAD)
+ (long)dy * DIBWIDTHBYTES(bi));
if (hdib)
{
lpbi = GLock(hdib);
*lpbi = bi;
pRgb = (LPVOID)((LPSTR)lpbi + (int)lpbi->biSize);
//
// setup the color table
//
if (bits == 1)
{
pRgb[0] = CosmicColors[0];
pRgb[1] = CosmicColors[15];
}
else
{
for (i=0; i<bi.biClrUsed; i++)
pRgb[i] = CosmicColors[i % 16];
}
GUnlock(hdib);
}
return hdib;
}
HANDLE CopyDib (HANDLE hdib)
{
BYTE huge *ps;
BYTE huge *pd;
HANDLE h;
DWORD cnt;
if (h = GAlloc(cnt = GSize(hdib)))
{
ps = GLock(hdib);
pd = GLock(h);
#if 1
hmemcpy(pd,ps,cnt);
#else
while (cnt-- > 0)
*pd++ = *ps++;
#endif
GUnlock(hdib);
GUnlock(h);
}
return h;
}
/*
* Private routines to read/write more than 64k
*/
#define MAXREAD (WORD)(32 * 1024)
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;
}
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;
}