diff options
Diffstat (limited to 'src/wincap/dibutil.c')
-rw-r--r-- | src/wincap/dibutil.c | 680 |
1 files changed, 680 insertions, 0 deletions
diff --git a/src/wincap/dibutil.c b/src/wincap/dibutil.c new file mode 100644 index 0000000..00d2aa1 --- /dev/null +++ b/src/wincap/dibutil.c @@ -0,0 +1,680 @@ +/* + * dibutil.c + * + * Source file for Device-Independent Bitmap (DIB) API. Provides + * the following functions: + * + * FindDIBBits() - Sets pointer to the DIB bits + * DIBWidth() - Gets the width of the DIB + * DIBHeight() - Gets the height of the DIB + * PaletteSize() - Calculates the buffer size required by a palette + * DIBNumColors() - Calculates number of colors in the DIB's color table + * CreateDIBPalette() - Creates a palette from a DIB + * DIBToBitmap() - Creates a bitmap from a DIB + * BitmapToDIB() - Creates a DIB from a bitmap + * + * Development Team: Mark Bader + * Patrick Schreiber + * Garrett Mcauliffe + * Eric Flo + * Tony Claflin + * + * Written by Microsoft Product Support Services, Developer Support. + * Copyright (c) 1991 Microsoft Corporation. All rights reserved. + */ + +/* header files */ +#include <windows.h> +#include <assert.h> +#include <stdio.h> +#include "dibutil.h" + + +/************************************************************************* + * + * FindDIBBits() + * + * Parameter: + * + * LPSTR lpbi - pointer to packed-DIB memory block + * + * Return Value: + * + * LPSTR - pointer to the DIB bits + * + * Description: + * + * This function calculates the address of the DIB's bits and returns a + * pointer to the DIB bits. + * + ************************************************************************/ + + +LPSTR FindDIBBits(LPSTR lpbi) +{ + return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi)); +} + + +/************************************************************************* + * + * DIBWidth() + * + * Parameter: + * + * LPSTR lpbi - pointer to packed-DIB memory block + * + * Return Value: + * + * DWORD - width of the DIB + * + * Description: + * + * This function gets the width of the DIB from the BITMAPINFOHEADER + * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER + * width field if it is an OS/2-style DIB. + * + ************************************************************************/ + + +DWORD DIBWidth(LPSTR lpDIB) +{ + LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB + LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB + + /* point to the header (whether Win 3.0 and OS/2) */ + + lpbmi = (LPBITMAPINFOHEADER)lpDIB; + lpbmc = (LPBITMAPCOREHEADER)lpDIB; + + /* return the DIB width if it is a Win 3.0 DIB */ + if (lpbmi->biSize == sizeof(BITMAPINFOHEADER)) + return lpbmi->biWidth; + else /* it is an OS/2 DIB, so return its width */ + return (DWORD)lpbmc->bcWidth; +} + + +/************************************************************************* + * + * DIBHeight() + * + * Parameter: + * + * LPSTR lpbi - pointer to packed-DIB memory block + * + * Return Value: + * + * DWORD - height of the DIB + * + * Description: + * + * This function gets the height of the DIB from the BITMAPINFOHEADER + * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER + * height field if it is an OS/2-style DIB. + * + ************************************************************************/ + + +DWORD DIBHeight(LPSTR lpDIB) +{ + LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB + LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB + + /* point to the header (whether OS/2 or Win 3.0 */ + + lpbmi = (LPBITMAPINFOHEADER)lpDIB; + lpbmc = (LPBITMAPCOREHEADER)lpDIB; + + /* return the DIB height if it is a Win 3.0 DIB */ + if (lpbmi->biSize == sizeof(BITMAPINFOHEADER)) + return lpbmi->biHeight; + else /* it is an OS/2 DIB, so return its height */ + return (DWORD)lpbmc->bcHeight; +} + + +/************************************************************************* + * + * PaletteSize() + * + * Parameter: + * + * LPSTR lpbi - pointer to packed-DIB memory block + * + * Return Value: + * + * WORD - size of the color palette of the DIB + * + * Description: + * + * This function gets the size required to store the DIB's palette by + * multiplying the number of colors by the size of an RGBQUAD (for a + * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an OS/2- + * style DIB). + * + ************************************************************************/ + + +WORD PaletteSize(LPSTR lpbi) +{ + /* calculate the size required by the palette */ + if (IS_WIN30_DIB (lpbi)) + return (DIBNumColors(lpbi) * sizeof(RGBQUAD)); + else + return (DIBNumColors(lpbi) * sizeof(RGBTRIPLE)); +} + + +/************************************************************************* + * + * DIBNumColors() + * + * Parameter: + * + * LPSTR lpbi - pointer to packed-DIB memory block + * + * Return Value: + * + * WORD - number of colors in the color table + * + * Description: + * + * This function calculates the number of colors in the DIB's color table + * by finding the bits per pixel for the DIB (whether Win3.0 or OS/2-style + * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256, + * if 24, no colors in color table. + * + ************************************************************************/ + + +WORD DIBNumColors(LPSTR lpbi) +{ + WORD wBitCount; // DIB bit count + + /* If this is a Windows-style DIB, the number of colors in the + * color table can be less than the number of bits per pixel + * allows for (i.e. lpbi->biClrUsed can be set to some value). + * If this is the case, return the appropriate value. + */ + + if (IS_WIN30_DIB(lpbi)) + { + DWORD dwClrUsed; + + dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; + if (dwClrUsed) + return (WORD)dwClrUsed; + } + + /* Calculate the number of colors in the color table based on + * the number of bits per pixel for the DIB. + */ + if (IS_WIN30_DIB(lpbi)) + wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; + else + wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; + + /* return number of colors based on bits per pixel */ + switch (wBitCount) + { + case 1: + return 2; + + case 4: + return 16; + + case 8: + return 256; + + default: + return 0; + } +} + + +/************************************************************************* + * + * CreateDIBPalette() + * + * Parameter: + * + * HDIB hDIB - specifies the DIB + * + * Return Value: + * + * HPALETTE - specifies the palette + * + * Description: + * + * This function creates a palette from a DIB by allocating memory for the + * logical palette, reading and storing the colors from the DIB's color table + * into the logical palette, creating a palette from this logical palette, + * and then returning the palette's handle. This allows the DIB to be + * displayed using the best possible colors (important for DIBs with 256 or + * more colors). + * + ************************************************************************/ + + +HPALETTE CreateDIBPalette(HDIB hDIB) +{ + LPLOGPALETTE lpPal; // pointer to a logical palette + HANDLE hLogPal; // handle to a logical palette + HPALETTE hPal = NULL; // handle to a palette + int i, wNumColors; // loop index, number of colors in color table + LPSTR lpbi; // pointer to packed-DIB + LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0) + LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (OS/2) + BOOL bWinStyleDIB; // flag which signifies whether this is a Win3.0 DIB + + /* if handle to DIB is invalid, return NULL */ + + if (!hDIB) + return NULL; + + /* lock DIB memory block and get a pointer to it */ + lpbi = (LPSTR) GlobalLock(hDIB); + + /* get pointer to BITMAPINFO (Win 3.0) */ + lpbmi = (LPBITMAPINFO)lpbi; + + /* get pointer to BITMAPCOREINFO (OS/2 1.x) */ + lpbmc = (LPBITMAPCOREINFO)lpbi; + + /* get the number of colors in the DIB */ + wNumColors = DIBNumColors(lpbi); + + /* is this a Win 3.0 DIB? */ + bWinStyleDIB = IS_WIN30_DIB(lpbi); + if (wNumColors) + { + /* allocate memory block for logical palette */ + hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * + wNumColors); + + /* if not enough memory, clean up and return NULL */ + if (!hLogPal) + { + GlobalUnlock(hDIB); + return NULL; + } + + /* lock memory block and get pointer to it */ + lpPal = (LPLOGPALETTE)GlobalLock(hLogPal); + + /* set version and number of palette entries */ + lpPal->palVersion = PALVERSION; + lpPal->palNumEntries = wNumColors; + + /* store RGB triples (if Win 3.0 DIB) or RGB quads (if OS/2 DIB) + * into palette + */ + for (i = 0; i < wNumColors; i++) + { + if (bWinStyleDIB) + { + lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; + lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; + lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; + lpPal->palPalEntry[i].peFlags = 0; + } + else + { + lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; + lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen; + lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue; + lpPal->palPalEntry[i].peFlags = 0; + } + } + + /* create the palette and get handle to it */ + hPal = CreatePalette(lpPal); + + /* if error getting handle to palette, clean up and return NULL */ + if (!hPal) + { + GlobalUnlock(hLogPal); + GlobalFree(hLogPal); + return NULL; + } + } + + /* clean up */ + GlobalUnlock(hLogPal); + GlobalFree(hLogPal); + GlobalUnlock(hDIB); + + /* return handle to DIB's palette */ + return hPal; +} + + +/************************************************************************* + * + * DIBToBitmap() + * + * Parameters: + * + * HDIB hDIB - specifies the DIB to convert + * + * HPALETTE hPal - specifies the palette to use with the bitmap + * + * Return Value: + * + * HBITMAP - identifies the device-dependent bitmap + * + * Description: + * + * This function creates a bitmap from a DIB using the specified palette. + * If no palette is specified, default is used. + * + ************************************************************************/ + + +HBITMAP DIBToBitmap(HDIB hDIB, HPALETTE hPal) +{ + LPSTR lpDIBHdr, lpDIBBits; // pointer to DIB header, pointer to DIB bits + HBITMAP hBitmap; // handle to device-dependent bitmap + HDC hDC; // handle to DC + HPALETTE hOldPal = NULL; // handle to a palette + + /* if invalid handle, return NULL */ + + if (!hDIB) { + return NULL; + } + + /* lock memory block and get a pointer to it */ + lpDIBHdr = (LPSTR) GlobalLock(hDIB); + + /* get a pointer to the DIB bits */ + lpDIBBits = FindDIBBits(lpDIBHdr); + + /* get a DC */ + hDC = GetDC(NULL); + if (!hDC) + { + /* clean up and return NULL */ + GlobalUnlock(hDIB); + return NULL; + } + + /* select and realize palette */ + if (hPal) + hOldPal = SelectPalette(hDC, hPal, FALSE); + RealizePalette(hDC); + + /* create bitmap from DIB info. and bits */ + hBitmap = CreateDIBitmap(hDC, (LPBITMAPINFOHEADER)lpDIBHdr, CBM_INIT, + lpDIBBits, (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS) + ; + + /* restore previous palette */ + if (hOldPal) + SelectPalette(hDC, hOldPal, FALSE); + + /* clean up */ + ReleaseDC(NULL, hDC); + GlobalUnlock(hDIB); + + /* return handle to the bitmap */ + return hBitmap; +} + + +/************************************************************************* + * + * BitmapToDIB() + * + * Parameters: + * + * HBITMAP hBitmap - specifies the bitmap to convert + * + * HPALETTE hPal - specifies the palette to use with the bitmap + * + * Return Value: + * + * HDIB - identifies the device-dependent bitmap + * + * Description: + * + * This function creates a DIB from a bitmap using the specified palette. + * + ************************************************************************/ + + +HDIB BitmapToDIB(HBITMAP hBitmap, HPALETTE hPal) +{ + BITMAP bm; // bitmap structure + BITMAPINFOHEADER bi; // bitmap header + BITMAPINFOHEADER FAR *lpbi; // pointer to BITMAPINFOHEADER + DWORD dwLen; // size of memory block + HANDLE hDIB, h; // handle to DIB, temp handle + HDC hDC; // handle to DC + WORD biBits; // bits per pixel + + /* check if bitmap handle is valid */ + + if (!hBitmap) + return NULL; + + /* if no palette is specified, use default palette */ + if (hPal == NULL) + hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE); + + /* fill in BITMAP structure */ + GetObject(hBitmap, sizeof(bm), (LPSTR)&bm); + + /* calculate bits per pixel */ + biBits = bm.bmPlanes * bm.bmBitsPixel; + + /* initialize BITMAPINFOHEADER */ + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = bm.bmWidth; + bi.biHeight = bm.bmHeight; + bi.biPlanes = 1; + bi.biBitCount = biBits; + bi.biCompression = DIB_RGB_COLORS; + bi.biSizeImage = 0; + bi.biXPelsPerMeter = 0; + bi.biYPelsPerMeter = 0; + bi.biClrUsed = 0; + bi.biClrImportant = 0; + + /* calculate size of memory block required to store BITMAPINFO */ + dwLen = bi.biSize + PaletteSize((LPSTR)&bi); + + /* get a DC */ + hDC = GetDC(NULL); + + /* select and realize our palette */ + hPal = SelectPalette(hDC, hPal, FALSE); + RealizePalette(hDC); + + /* alloc memory block to store our bitmap */ + hDIB = GlobalAlloc(GHND, dwLen); + + /* if we couldn't get memory block */ + if (!hDIB) + { + /* clean up and return NULL */ + SelectPalette(hDC, hPal, TRUE); + RealizePalette(hDC); + ReleaseDC(NULL, hDC); + return NULL; + } + + /* lock memory and get pointer to it */ + lpbi = (BITMAPINFOHEADER FAR *)GlobalLock(hDIB); + + /* use our bitmap info. to fill BITMAPINFOHEADER */ + *lpbi = bi; + + /* call GetDIBits with a NULL lpBits param, so it will calculate the + * biSizeImage field for us + */ + GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, NULL, (LPBITMAPINFO)lpbi, + DIB_RGB_COLORS); + + /* get the info. returned by GetDIBits and unlock memory block */ + 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; + + /* realloc the buffer big enough to hold all the bits */ + dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage; + if (h = GlobalReAlloc(hDIB, dwLen, 0)) + hDIB = h; + else + { + /* clean up and return NULL */ + GlobalFree(hDIB); + hDIB = NULL; + SelectPalette(hDC, hPal, TRUE); + RealizePalette(hDC); + ReleaseDC(NULL, hDC); + return NULL; + } + + /* lock memory block and get pointer to it */ + lpbi = (BITMAPINFOHEADER FAR *)GlobalLock(hDIB); + + /* call GetDIBits with a NON-NULL lpBits param, and actualy get the + * bits this time + */ + if (GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, (LPSTR)lpbi + (WORD)lpbi + ->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi, + DIB_RGB_COLORS) == 0) + { + /* clean up and return NULL */ + GlobalUnlock(hDIB); + hDIB = NULL; + SelectPalette(hDC, hPal, TRUE); + RealizePalette(hDC); + ReleaseDC(NULL, hDC); + return NULL; + } + bi = *lpbi; + + /* clean up */ + GlobalUnlock(hDIB); + SelectPalette(hDC, hPal, TRUE); + RealizePalette(hDC); + ReleaseDC(NULL, hDC); + + /* return handle to the DIB */ + return hDIB; +} + + +/************************************************************************* + * + * PalEntriesOnDevice() + * + * Parameter: + * + * HDC hDC - device context + * + * Return Value: + * + * int - number of palette entries on device + * + * Description: + * + * This function gets the number of palette entries on the specified device + * + ************************************************************************/ + + +int PalEntriesOnDevice(HDC hDC) +{ + int nColors; // number of colors + + /* Find out the number of palette entries on this + * device. + */ + + nColors = GetDeviceCaps(hDC, SIZEPALETTE); + + /* For non-palette devices, we'll use the # of system + * colors for our palette size. + */ + if (!nColors) + nColors = GetDeviceCaps(hDC, NUMCOLORS); + assert(nColors); + return nColors; +} + + +/************************************************************************* + * + * DIBHeight() + * + * Parameter: + * + * LPSTR lpbi - pointer to packed-DIB memory block + * + * Return Value: + * + * DWORD - height of the DIB + * + * Description: + * + * This function returns a handle to a palette which represents the system + * palette (each entry is an offset into the system palette instead of an + * RGB with a flag of PC_EXPLICIT). + * + ************************************************************************/ + + +HPALETTE GetSystemPalette(void) +{ + HDC hDC; // handle to a DC + HPALETTE hPal = NULL; // handle to a palette + HANDLE hLogPal; // handle to a logical palette + LPLOGPALETTE lpLogPal; // pointer to a logical palette + int i, nColors; // loop index, number of colors + + /* Find out how many palette entries we want. */ + + hDC = GetDC(NULL); + if (!hDC) + return NULL; + nColors = PalEntriesOnDevice(hDC); + ReleaseDC(NULL, hDC); + + /* Allocate room for the palette and lock it. */ + hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors * sizeof( + PALETTEENTRY)); + + /* if we didn't get a logical palette, return NULL */ + if (!hLogPal) + return NULL; + + /* get a pointer to the logical palette */ + lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal); + + /* set some important fields */ + lpLogPal->palVersion = PALVERSION; + lpLogPal->palNumEntries = nColors; + for (i = 0; i < nColors; i++) + { + lpLogPal->palPalEntry[i].peBlue = 0; + *((LPWORD)(&lpLogPal->palPalEntry[i].peRed)) = i; + lpLogPal->palPalEntry[i].peFlags = PC_EXPLICIT; + } + + /* Go ahead and create the palette. Once it's created, + * we no longer need the LOGPALETTE, so free it. + */ + hPal = CreatePalette(lpLogPal); + + /* clean up */ + GlobalUnlock(hLogPal); + GlobalFree(hLogPal); + return hPal; +} |