|
|
/*----------------------------------------------------------------------------*\
| Routines for dealing with Device independent bitmaps | | | | History: | | 06/23/89 toddla Created | | | \*----------------------------------------------------------------------------*/
#include <windows.h>
#include "dib.h"
#define HUGE_T
HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal);
static DWORD NEAR PASCAL lread(HFILE fh, VOID FAR *pv, DWORD ul); static DWORD NEAR PASCAL lwrite(HFILE 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(LPTSTR szFile, HFILE fh) { BITMAPINFOHEADER bi; LPBITMAPINFOHEADER lpbi; DWORD dwLen; DWORD dwBits; HANDLE hdib; HANDLE h; #ifndef UNICODE
OFSTRUCT of; #endif
BOOL fOpened = FALSE;
if (szFile != NULL) { #ifdef UNICODE
fh = (HFILE)HandleToUlong(CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); #else
fh = OpenFile(szFile, &of, OF_READ); #endif
fOpened = TRUE; }
if (fh == (HFILE)-1) return NULL;
hdib = ReadDibBitmapInfo(fh);
if (!hdib) return NULL;
DibInfo((LPBITMAPINFOHEADER)GlobalLock(hdib),&bi); GlobalUnlock(hdib);
/* 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 = GlobalReAlloc(hdib,dwLen,GMEM_MOVEABLE);
if (!h) { GlobalFree(hdib); hdib = NULL; } else { hdib = h; }
if (hdib) { lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
/* read in the bits */ lread(fh, (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi), dwBits);
GlobalUnlock(hdib); }
if (fOpened) _lclose(fh);
return hdib; }
/*
* Write a global handle in CF_DIB format to a file. * */ BOOL WriteDIB(LPTSTR szFile,HFILE fh, HANDLE hdib) { BITMAPFILEHEADER hdr; LPBITMAPINFOHEADER lpbi; BITMAPINFOHEADER bi; DWORD dwSize; BOOL fOpened = FALSE;
if (!hdib) return FALSE;
if (szFile != NULL) { #ifdef UNICODE
fh = (HFILE)HandleToUlong(CreateFile(szFile,GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)); #else
OFSTRUCT of; fh = OpenFile(szFile,&of,OF_CREATE|OF_READWRITE); #endif
fOpened = TRUE; }
if (fh == (HFILE)-1) return FALSE;
lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib); DibInfo(lpbi,&bi);
dwSize = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
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,(const char*)&hdr,sizeof(BITMAPFILEHEADER)); lwrite(fh,(LPVOID)lpbi,dwSize);
GlobalUnlock(hdib);
if (fOpened) _lclose(fh);
return TRUE; }
/*
* DibInfo(hbi, lpbi) * * retrives the DIB info associated with a CF_DIB format memory block. */ BOOL DibInfo(LPBITMAPINFOHEADER lpbiSource, LPBITMAPINFOHEADER lpbiTarget) { if (lpbiSource) { *lpbiTarget = *lpbiSource;
if (lpbiTarget->biSize == sizeof(BITMAPCOREHEADER)) { BITMAPCOREHEADER bc;
bc = *(LPBITMAPCOREHEADER)lpbiTarget;
lpbiTarget->biSize = sizeof(BITMAPINFOHEADER); lpbiTarget->biWidth = (DWORD)bc.bcWidth; lpbiTarget->biHeight = (DWORD)bc.bcHeight; lpbiTarget->biPlanes = (UINT)bc.bcPlanes; lpbiTarget->biBitCount = (UINT)bc.bcBitCount; lpbiTarget->biCompression = BI_RGB; lpbiTarget->biSizeImage = 0; lpbiTarget->biXPelsPerMeter = 0; lpbiTarget->biYPelsPerMeter = 0; lpbiTarget->biClrUsed = 0; lpbiTarget->biClrImportant = 0; }
/*
* fill in the default fields */ if (lpbiTarget->biSize != sizeof(BITMAPCOREHEADER)) { if (lpbiTarget->biSizeImage == 0L) lpbiTarget->biSizeImage = (DWORD)DIBWIDTHBYTES(*lpbiTarget) * lpbiTarget->biHeight;
if (lpbiTarget->biClrUsed == 0L) lpbiTarget->biClrUsed = DibNumColors(lpbiTarget); } return TRUE; } return FALSE; }
HPALETTE CreateColorPalette() { LOGPALETTE *pPal; HPALETTE hpal = NULL; WORD nNumColors; BYTE red; BYTE green; BYTE blue; int i;
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;
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; }
/*
* 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; UINT i; RGBQUAD FAR *pRgb; BOOL fCoreHeader;
if (!lpbi) return NULL;
nNumColors = DibNumColors(lpbi);
if (nNumColors) { fCoreHeader = (lpbi->biSize == sizeof(BITMAPCOREHEADER));
pRgb = (RGBQUAD FAR *)((LPBYTE)lpbi + (UINT)lpbi->biSize); 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) //((LPBYTE)pRgb) += sizeof(RGBTRIPLE) ;
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)GlobalLock(hbi)); GlobalUnlock(hbi); return hpal; }
HPALETTE CreateExplicitPalette() { 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; }
/*
* 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 always return a "new" BITMAPINFO * */ HANDLE ReadDibBitmapInfo(HFILE fh) { DWORD off; HANDLE hbi = NULL; int size; int i; UINT nNumColors;
RGBQUAD FAR *pRgb; BITMAPINFOHEADER bi; BITMAPCOREHEADER bc; LPBITMAPINFOHEADER lpbi; BITMAPFILEHEADER bf;
if (fh == (HFILE)-1) return NULL;
off = _llseek(fh,0L,SEEK_CUR);
if (sizeof(bf) != _lread(fh,(LPBYTE)&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,(LPBYTE)&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 = *(BITMAPCOREHEADER*)&bi; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = (DWORD)bc.bcWidth; bi.biHeight = (DWORD)bc.bcHeight; bi.biPlanes = (UINT)bc.bcPlanes; bi.biBitCount = (UINT)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 = (DWORD)DIBWIDTHBYTES(bi) * bi.biHeight; }
if (bi.biXPelsPerMeter == 0) { bi.biXPelsPerMeter = 0; // ??????????????
}
if (bi.biYPelsPerMeter == 0) { bi.biYPelsPerMeter = 0; // ??????????????
}
if (bi.biClrUsed == 0) { bi.biClrUsed = DibNumColors(&bi); }
hbi = GlobalAlloc(GMEM_MOVEABLE,(LONG)bi.biSize + nNumColors * sizeof(RGBQUAD)); if (!hbi) return NULL;
lpbi = (BITMAPINFOHEADER *)GlobalLock(hbi); *lpbi = bi;
pRgb = (RGBQUAD FAR *)((LPBYTE)lpbi + bi.biSize);
if (nNumColors) { if (size == (int)sizeof(BITMAPCOREHEADER)) { /*
* convert a old color table (3 byte entries) to a new * color table (4 byte entries) */ _lread(fh,(LPBYTE)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,(LPBYTE)pRgb,nNumColors * sizeof(RGBQUAD)); } }
if (bf.bfOffBits != 0L) _llseek(fh,off + bf.bfOffBits,SEEK_SET);
GlobalUnlock(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 */ UINT PaletteSize(VOID FAR * pv) { #define lpbi ((LPBITMAPINFOHEADER)pv)
#define lpbc ((LPBITMAPCOREHEADER)pv)
UINT 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 (UINT)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, UINT 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 0
if (biStyle == BI_RGB && wUsage == DIB_RGB_COLORS) return CreateLogicalDib(hbm,biBits,hpal); #endif
if (hpal == NULL) hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
GetObject(hbm,sizeof(bm),(LPBYTE)&bm); #ifdef WIN32
nColors = 0; // GetObject only stores two bytes
#endif
GetObject(hpal,sizeof(nColors),(LPBYTE)&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,TRUE); RealizePalette(hdc); // why is this needed on a MEMORY DC? GDI bug??
hdib = GlobalAlloc(GMEM_MOVEABLE,dwLen);
if (!hdib) goto exit;
lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
*lpbi = bi;
/*
* call GetDIBits with a NULL lpBits param, so it will calculate the * biSizeImage field for us */ GetDIBits(hdc, hbm, 0, (UINT)bi.biHeight, NULL, (LPBITMAPINFO)lpbi, wUsage);
bi = *lpbi; GlobalUnlock(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 = GlobalReAlloc(hdib,dwLen,GMEM_MOVEABLE)) { hdib = h; } else { GlobalFree(hdib); hdib = NULL; goto exit; }
/*
* call GetDIBits with a NON-NULL lpBits param, and actualy get the * bits this time */ lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
GetDIBits(hdc, hbm, 0, (UINT)bi.biHeight, (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi), (LPBITMAPINFO)lpbi, wUsage);
bi = *lpbi; lpbi->biClrUsed = DibNumColors(lpbi) ; GlobalUnlock(hdib);
exit: SelectPalette(hdc,hpal,TRUE); 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, UINT wUsage) { LPBITMAPINFOHEADER lpbi; HPALETTE hpalT; HDC hdc; HBITMAP hbm; #if 0
UINT dx,dy,bits; #endif
if (!hdib) return NULL;
if (wUsage == 0) wUsage = DIB_RGB_COLORS;
lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
if (!lpbi) return NULL;
hdc = GetDC(NULL); // hdc = CreateCompatibleDC(NULL);
if (hpal) { hpalT = SelectPalette(hdc,hpal,TRUE); 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 = (UINT)lpbi->biWidth; dy = (UINT)lpbi->biHeight; bits = (UINT)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, (LPBYTE)lpbi + lpbi->biSize + PaletteSize(lpbi), (LPBITMAPINFO)lpbi,wUsage); else SetDIBits(hdc,hbm,0,dy, (LPBYTE)lpbi + lpbi->biSize + PaletteSize(lpbi), (LPBITMAPINFO)lpbi,wUsage); }
#else
hbm = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)lpbi, (LONG)CBM_INIT, (LPBYTE)lpbi + lpbi->biSize + PaletteSize(lpbi), (LPBITMAPINFO)lpbi, wUsage ); #endif
if (hpal && hpalT) SelectPalette(hdc,hpalT,TRUE);
// DeleteDC(hdc);
ReleaseDC(NULL,hdc);
GlobalUnlock(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, UINT wUsage) { BITMAPINFOHEADER bi; HBITMAP hbm; BOOL fKillPalette=FALSE;
if (!hdib) return NULL;
DibInfo((LPBITMAPINFOHEADER)GlobalLock(hdib),&bi); GlobalUnlock(hdib);
/*
* do we have the requested format already? */ if (bi.biCompression == biStyle && (UINT)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; }
#define MAKEP(sel,off) ((VOID FAR *)MAKELONG(off,sel))
/*
* 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; UINT FAR * lpCT; RGBQUAD FAR * lpRgb; PALETTEENTRY peT; HPALETTE hpalT;
if (hpal == NULL) hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
if (hbm == NULL) hbm = NULL; // ????GetStockObject(STOCK_BITMAP);
#ifdef WIN32
nColors = 0; // GetObject only stores two bytes
#endif
GetObject(hpal,sizeof(nColors),(LPBYTE)&nColors); GetObject(hbm,sizeof(bm),(LPBYTE)&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 = GlobalAlloc(GMEM_MOVEABLE,dwLen);
if (!hdib) return NULL;
lpbi = (BITMAPINFOHEADER*)MAKEP(GlobalAlloc(GMEM_FIXED,bi.biSize + 256 * sizeof(RGBQUAD)),0);
if (!lpbi) { GlobalFree(hdib); return NULL; }
hdc = GetDC(NULL); hpalT = SelectPalette(hdc,hpal,TRUE); RealizePalette(hdc); // why is this needed on a MEMORY DC? GDI bug??
lpDib = (BITMAPINFOHEADER*)GlobalLock(hdib);
*lpbi = bi; *lpDib = bi; lpCT = (UINT FAR *)((LPBYTE)lpbi + (UINT)lpbi->biSize); lpRgb = (RGBQUAD FAR *)((LPBYTE)lpDib + (UINT)lpDib->biSize); lpBits = (LPBYTE)lpDib + (UINT)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, (UINT)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 UINT 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_T *)lpBits)++) *lpBits = (BYTE)lpCT[*lpBits]; } else // biBits == 4
{ for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE HUGE_T *)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; }
GlobalUnlock(hdib); #ifdef WIN32
GlobalFree(GlobalHandle(lpbi)); #else
GlobalFree(SELECTOROF(lpbi)); #endif
SelectPalette(hdc,hpalT,TRUE); ReleaseDC(NULL,hdc);
return hdib; }
/*
* 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; HPALETTE hpal,hpalT; BOOL f;
if (!hdc || !hbm) return FALSE;
hpal = SelectPalette(hdc,(HPALETTE)GetStockObject(DEFAULT_PALETTE),TRUE); SelectPalette(hdc,hpal,TRUE);
hdcBits = CreateCompatibleDC(hdc); SelectObject(hdcBits,hbm); hpalT = SelectPalette(hdcBits,hpal,TRUE); RealizePalette(hdcBits); f = StretchBlt(hdc,x,y,dx,dy,hdcBits,x0,y0,dx0,dy0,rop); SelectPalette(hdcBits,hpalT,TRUE); 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; BOOL f;
if (!hdc || !hbm) return FALSE;
hdcBits = CreateCompatibleDC(hdc); GetObject(hbm,sizeof(BITMAP),(LPBYTE)&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, HPALETTE hpal,UINT wUsage) { LPBITMAPINFOHEADER lpbi; PALETTEENTRY ape[MAXPALETTE]; RGBQUAD FAR * pRgb; UINT FAR * pw; int nColors; int n;
if (hpal == NULL) hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
if (!hdib) return FALSE;
lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
if (!lpbi) return FALSE;
nColors = DibNumColors(lpbi);
if (nColors > 0) { pRgb = (RGBQUAD FAR *)((LPBYTE)lpbi + (UINT)lpbi->biSize);
switch (wUsage) { //
// Set the DIB color table to palette indexes
//
case DIB_PAL_COLORS: for (pw = (UINT 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 indexs in the range (iIndex - nIndex+cnt) * to the parameter specifed. * */ BOOL SetPalFlags(HPALETTE hpal, int iIndex, int cntEntries, UINT wFlags) { int i; BOOL f; HANDLE hpe; PALETTEENTRY FAR *lppe;
if (hpal == NULL) return FALSE;
if (cntEntries < 0) { #ifdef WIN32
cntEntries = 0; // GetObject only stores two bytes
#endif
GetObject(hpal,sizeof(int),(LPBYTE)&cntEntries); }
hpe = GlobalAlloc(GMEM_MOVEABLE,(LONG)cntEntries * sizeof(PALETTEENTRY));
if (!hpe) return FALSE;
lppe = (PALETTEENTRY*)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; }
/*
* 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, UINT wUsage) { LPBITMAPINFOHEADER lpbi; LPBYTE pBuf; BOOL f;
if (!hdib) { return PatBlt(hdc,x,y,dx,dy,rop); }
if (wUsage == 0) { wUsage = DIB_RGB_COLORS; }
lpbi = (BITMAPINFOHEADER*)GlobalLock(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 = (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi);
f = StretchDIBits ( hdc, x,y, dx,dy, x0,y0, dx0,dy0, pBuf, (LPBITMAPINFO)lpbi, wUsage, rop);
GlobalUnlock(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, UINT wUsage) { LPBITMAPINFOHEADER lpbi; LPBYTE pBuf; BOOL f;
if (!hdib) return PatBlt(hdc,x0,y0,dx,dy,rop);
if (wUsage == 0) wUsage = DIB_RGB_COLORS;
lpbi = (BITMAPINFOHEADER*)GlobalLock(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 = (LPBYTE)lpbi + (UINT)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
GlobalUnlock(hdib); return f; }
LPVOID DibLock(HANDLE hdib,int x, int y) { return DibXY((LPBITMAPINFOHEADER)GlobalLock(hdib),x,y); }
VOID DibUnlock(HANDLE hdib) { GlobalUnlock(hdib); }
LPVOID DibXY(LPBITMAPINFOHEADER lpbi,int x, int y) { BYTE HUGE_T *pBits; DWORD ulWidthBytes;
pBits = (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi);
ulWidthBytes = DIBWIDTHBYTES(*lpbi);
pBits += (ulWidthBytes * (long)y) + x;
return (LPVOID)pBits; }
//
// 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
};
HANDLE CreateDib(WORD bits, int dx, int dy) { HANDLE hdib; BITMAPINFOHEADER bi; LPBITMAPINFOHEADER lpbi; DWORD FAR * pRgb; UINT i;
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 = GlobalAlloc(GMEM_MOVEABLE,sizeof(BITMAPINFOHEADER) + + (long)bi.biClrUsed * sizeof(RGBQUAD) + (long)DIBWIDTHBYTES(bi) * (long)dy);
if (hdib) { lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib); *lpbi = bi;
pRgb = (unsigned long*)((LPBYTE)lpbi + 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]; }
GlobalUnlock(hdib); }
return hdib; }
/*
* Private routines to read/write more than 64k */
#define MAXREAD (UINT)(32u * 1024)
static DWORD NEAR PASCAL lread(HFILE fh, VOID FAR *pv, DWORD ul) { DWORD ulT = ul; BYTE HUGE_T *hp = (unsigned char*)pv;
while (ul > MAXREAD) { if (_lread(fh, (LPBYTE)hp, MAXREAD) != MAXREAD) return 0; ul -= MAXREAD; hp += MAXREAD; } if (_lread(fh, (LPBYTE)hp, (UINT)ul) != (UINT)ul) return 0; return ulT; }
static DWORD NEAR PASCAL lwrite(HFILE fh, VOID FAR *pv, DWORD ul) { DWORD ulT = ul; BYTE HUGE_T *hp = (unsigned char*)pv;
while (ul > MAXREAD) { if (_lwrite(fh, (const char*)hp, MAXREAD) != MAXREAD) return 0; ul -= MAXREAD; hp += MAXREAD; } if (_lwrite(fh, (const char*)hp, (UINT)ul) != (UINT)ul) return 0; return ulT; }
|