|
|
/*----------------------------------------------------------------------------*\
| Routines for dealing with Device independent bitmaps | | | | History: | | 06/23/89 toddla Created | | | \*----------------------------------------------------------------------------*/
#include <windows.h>
#include <stdio.h>
#include "dib.h"
#define HUGE_T
/*
* 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 == -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; }
/*
* 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; }
/*
* 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 == -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. */ UINT 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 (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; }
/*
* 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);
f = StretchDIBits ( hdc, x0,y0, dx,dy, x1,y1, dx,dy, pBuf, (LPBITMAPINFO)lpbi, wUsage, rop);
GlobalUnlock(hdib); return f; }
|