/******************************************************************************* * * * MODULE : DIB.C * * * * DESCRIPTION : Routines for dealing with Device Independent Bitmaps. * * * * PaletteSize() - Calculates the palette size in bytes * * of given DIB * * * * DibNumColors() - Determines the number of colors in DIB * * * * BitmapFromDib() - Creates a DDB given a global handle to * * a block in CF_DIB format. * * * * DibFromBitmap() - Creates a DIB repr. the DDB passed in. * * * *******************************************************************************/ #include #include "dib.h" static HCURSOR hcurSave; /**************************************************************************** * * * FUNCTION : PaletteSize(VOID FAR * pv) * * * * PURPOSE : Calculates the palette size in bytes. If the info. block * * is of the BITMAPCOREHEADER type, the number of colors is * * multiplied by 3 to give the palette size, otherwise the * * number of colors is multiplied by 4. * * * * RETURNS : Palette size in number of bytes. * * * ****************************************************************************/ WORD PaletteSize (pv) VOID FAR * pv; { LPBITMAPINFOHEADER lpbi; WORD NumColors; lpbi = (LPBITMAPINFOHEADER)pv; NumColors = DibNumColors(lpbi); if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) return NumColors * sizeof(RGBTRIPLE); else return NumColors * sizeof(RGBQUAD); } /**************************************************************************** * * * FUNCTION : DibNumColors(VOID FAR * pv) * * * * PURPOSE : Determines the number of colors in the DIB by looking at * * the BitCount filed in the info block. * * * * RETURNS : The number of colors in the DIB. * * * ****************************************************************************/ WORD DibNumColors (pv) VOID FAR * pv; { int bits; LPBITMAPINFOHEADER lpbi; LPBITMAPCOREHEADER lpbc; lpbi = ((LPBITMAPINFOHEADER)pv); lpbc = ((LPBITMAPCOREHEADER)pv); /* With the BITMAPINFO format headers, the size of the palette * is in biClrUsed, whereas in the BITMAPCORE - style headers, it * is dependent on the bits per pixel ( = 2 raised to the power of * bits/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: /* A 24 bitcount DIB has no color table */ return 0; } } /**************************************************************************** * * * FUNCTION : DibFromBitmap() * * * * PURPOSE : Will create a global memory block in DIB format that * * represents the Device-dependent bitmap (DDB) passed in. * * * * RETURNS : A handle to the DIB * * * ****************************************************************************/ HANDLE DibFromBitmap (hbm, biStyle, biBits, hpal) HBITMAP hbm; DWORD biStyle; WORD biBits; HPALETTE hpal; { BITMAP bm; BITMAPINFOHEADER bi; BITMAPINFOHEADER FAR *lpbi; DWORD dwLen; HANDLE hdib; HANDLE h; HDC hdc; if (!hbm) return NULL; if (hpal == NULL) hpal = GetStockObject(DEFAULT_PALETTE); GetObject(hbm,sizeof(bm),(LPSTR)&bm); 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 = GetDC(NULL); hpal = SelectPalette(hdc,hpal,FALSE); RealizePalette(hdc); hdib = GlobalAlloc(GHND,dwLen); if (!hdib){ SelectPalette(hdc,hpal,FALSE); ReleaseDC(NULL,hdc); return NULL; } lpbi = (VOID FAR *)GlobalLock(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, DIB_RGB_COLORS); 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; SelectPalette(hdc,hpal,FALSE); ReleaseDC(NULL,hdc); return hdib; } /* call GetDIBits with a NON-NULL lpBits param, and actualy get the * bits this time */ lpbi = (VOID FAR *)GlobalLock(hdib); if (GetDIBits( hdc, hbm, 0, (WORD)bi.biHeight, (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi), (LPBITMAPINFO)lpbi, DIB_RGB_COLORS) == 0){ GlobalUnlock(hdib); hdib = NULL; SelectPalette(hdc,hpal,FALSE); ReleaseDC(NULL,hdc); return NULL; } bi = *lpbi; GlobalUnlock(hdib); SelectPalette(hdc,hpal,FALSE); ReleaseDC(NULL,hdc); return hdib; } /**************************************************************************** * * * FUNCTION : BitmapFromDib(HANDLE hdib, HPALETTE hpal) * * * * PURPOSE : Will create 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,HPALETTE hpal) { LPBITMAPINFOHEADER lpbi; HPALETTE hpalT; HDC hdc; HBITMAP hbm; StartWait(); if (!hdib) return NULL; lpbi = (VOID FAR *)GlobalLock(hdib); if (!lpbi) return NULL; hdc = GetDC(NULL); if (hpal){ hpalT = SelectPalette(hdc,hpal,FALSE); RealizePalette(hdc); // GDI Bug...???? } hbm = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)lpbi, (LONG)CBM_INIT, (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi), (LPBITMAPINFO)lpbi, DIB_RGB_COLORS ); if (hpal) SelectPalette(hdc,hpalT,FALSE); ReleaseDC(NULL,hdc); GlobalUnlock(hdib); EndWait(); return hbm; }