|
|
@@ -0,0 +1,1258 @@
|
|
|
+//**********************************************************************
|
|
|
+//
|
|
|
+// dibutil.c
|
|
|
+//
|
|
|
+// Source file for Device-Independent Bitmap (DIB) API. Provides
|
|
|
+// the following functions:
|
|
|
+//
|
|
|
+// CreateDIB() - Creates new DIB
|
|
|
+// 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
|
|
|
+// PalEntriesOnDevice()- Gets the number of palette entries of a device
|
|
|
+// GetSystemPalette() - Returns a handle to the current system palette
|
|
|
+// AllocRoomForDIB() - Allocates memory for a DIB
|
|
|
+// ChangeDIBFormat() - Changes a DIB's BPP and/or compression format
|
|
|
+// ChangeBitmapFormat()- Changes a bitmap to a DIB with specified BPP and
|
|
|
+// compression format
|
|
|
+//
|
|
|
+// Written by Microsoft Product Support Services, Developer Support.
|
|
|
+// Copyright 1991-1998 Microsoft Corporation. All rights reserved.
|
|
|
+//**********************************************************************
|
|
|
+
|
|
|
+#define STRICT // enable strict type checking
|
|
|
+
|
|
|
+#include "stdafx.h"
|
|
|
+#include <assert.h>
|
|
|
+#include "dibapi.h"
|
|
|
+#include "dibutil.h"
|
|
|
+#include <stdio.h>
|
|
|
+
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+ *
|
|
|
+ * CreateDIB()
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ *
|
|
|
+ * DWORD dwWidth - Width for new bitmap, in pixels
|
|
|
+ * DWORD dwHeight - Height for new bitmap
|
|
|
+ * WORD wBitCount - Bit Count for new DIB (1, 4, 8, or 24)
|
|
|
+ *
|
|
|
+ * Return Value:
|
|
|
+ *
|
|
|
+ * HDIB - Handle to new DIB
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ *
|
|
|
+ * This function allocates memory for and initializes a new DIB by
|
|
|
+ * filling in the BITMAPINFOHEADER, allocating memory for the color
|
|
|
+ * table, and allocating memory for the bitmap bits. As with all
|
|
|
+ * HDIBs, the header, colortable and bits are all in one contiguous
|
|
|
+ * memory block. This function is similar to the CreateBitmap()
|
|
|
+ * Windows API.
|
|
|
+ *
|
|
|
+ * The colortable and bitmap bits are left uninitialized (zeroed) in the
|
|
|
+ * returned HDIB.
|
|
|
+ *
|
|
|
+ *
|
|
|
+ ************************************************************************/
|
|
|
+
|
|
|
+HDIB CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount)
|
|
|
+{
|
|
|
+ BITMAPINFOHEADER bi; // bitmap header
|
|
|
+ LPBITMAPINFOHEADER lpbi; // pointer to BITMAPINFOHEADER
|
|
|
+ DWORD dwLen; // size of memory block
|
|
|
+ HDIB hDIB;
|
|
|
+ DWORD dwBytesPerLine; // Number of bytes per scanline
|
|
|
+
|
|
|
+
|
|
|
+ // Make sure bits per pixel is valid
|
|
|
+
|
|
|
+ if (wBitCount <= 1)
|
|
|
+ wBitCount = 1;
|
|
|
+ else if (wBitCount <= 4)
|
|
|
+ wBitCount = 4;
|
|
|
+ else if (wBitCount <= 8)
|
|
|
+ wBitCount = 8;
|
|
|
+ else if (wBitCount <= 24)
|
|
|
+ wBitCount = 24;
|
|
|
+ else
|
|
|
+ wBitCount = 4; // set default value to 4 if parameter is bogus
|
|
|
+
|
|
|
+ // initialize BITMAPINFOHEADER
|
|
|
+
|
|
|
+ bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
+ bi.biWidth = dwWidth; // fill in width from parameter
|
|
|
+ bi.biHeight = dwHeight; // fill in height from parameter
|
|
|
+ bi.biPlanes = 1; // must be 1
|
|
|
+ bi.biBitCount = wBitCount; // from parameter
|
|
|
+ bi.biCompression = BI_RGB;
|
|
|
+ bi.biSizeImage = 0; // 0's here mean "default"
|
|
|
+ bi.biXPelsPerMeter = 0;
|
|
|
+ bi.biYPelsPerMeter = 0;
|
|
|
+ bi.biClrUsed = 0;
|
|
|
+ bi.biClrImportant = 0;
|
|
|
+
|
|
|
+ // calculate size of memory block required to store the DIB. This
|
|
|
+ // block should be big enough to hold the BITMAPINFOHEADER, the color
|
|
|
+ // table, and the bits
|
|
|
+
|
|
|
+ dwBytesPerLine = WIDTHBYTES(wBitCount * dwWidth);
|
|
|
+ dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + (dwBytesPerLine * dwHeight);
|
|
|
+
|
|
|
+ // alloc memory block to store our bitmap
|
|
|
+
|
|
|
+ hDIB = GlobalAlloc(GHND, dwLen);
|
|
|
+
|
|
|
+ // major bummer if we couldn't get memory block
|
|
|
+
|
|
|
+ if (!hDIB)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ // lock memory and get pointer to it
|
|
|
+
|
|
|
+ lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
|
|
|
+
|
|
|
+ // use our bitmap info structure to fill in first part of
|
|
|
+ // our DIB with the BITMAPINFOHEADER
|
|
|
+
|
|
|
+ *lpbi = bi;
|
|
|
+
|
|
|
+ // Since we don't know what the colortable and bits should contain,
|
|
|
+ // just leave these blank. Unlock the DIB and return the HDIB.
|
|
|
+
|
|
|
+ GlobalUnlock(hDIB);
|
|
|
+
|
|
|
+ //return handle to the DIB
|
|
|
+
|
|
|
+ return hDIB;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+ *
|
|
|
+ * FindDIBBits()
|
|
|
+ *
|
|
|
+ * Parameter:
|
|
|
+ *
|
|
|
+ * LPSTR lpDIB - 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 lpDIB)
|
|
|
+{
|
|
|
+ return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+ *
|
|
|
+ * DIBWidth()
|
|
|
+ *
|
|
|
+ * Parameter:
|
|
|
+ *
|
|
|
+ * LPSTR lpDIB - 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 lpDIB - 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 lpDIB - 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 lpDIB)
|
|
|
+{
|
|
|
+ // calculate the size required by the palette
|
|
|
+ if (IS_WIN30_DIB (lpDIB))
|
|
|
+ return (DIBNumColors(lpDIB) * sizeof(RGBQUAD));
|
|
|
+ else
|
|
|
+ return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+ *
|
|
|
+ * DIBNumColors()
|
|
|
+ *
|
|
|
+ * Parameter:
|
|
|
+ *
|
|
|
+ * LPSTR lpDIB - 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 lpDIB)
|
|
|
+{
|
|
|
+ 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(lpDIB))
|
|
|
+ {
|
|
|
+ DWORD dwClrUsed;
|
|
|
+
|
|
|
+ dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->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(lpDIB))
|
|
|
+ wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
|
|
|
+ else
|
|
|
+ wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->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; // 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.
|
|
|
+ *
|
|
|
+ * NOTE:
|
|
|
+ *
|
|
|
+ * The bitmap returned from this funciton is always a bitmap compatible
|
|
|
+ * with the screen (e.g. same bits/pixel and color planes) rather than
|
|
|
+ * a bitmap with the same attributes as the DIB. This behavior is by
|
|
|
+ * design, and occurs because this function calls CreateDIBitmap to
|
|
|
+ * do its work, and CreateDIBitmap always creates a bitmap compatible
|
|
|
+ * with the hDC parameter passed in (because it in turn calls
|
|
|
+ * CreateCompatibleBitmap).
|
|
|
+ *
|
|
|
+ * So for instance, if your DIB is a monochrome DIB and you call this
|
|
|
+ * function, you will not get back a monochrome HBITMAP -- you will
|
|
|
+ * get an HBITMAP compatible with the screen DC, but with only 2
|
|
|
+ * colors used in the bitmap.
|
|
|
+ *
|
|
|
+ * If your application requires a monochrome HBITMAP returned for a
|
|
|
+ * monochrome DIB, use the function SetDIBits().
|
|
|
+ *
|
|
|
+ * Also, the DIBpassed in to the function is not destroyed on exit. This
|
|
|
+ * must be done later, once it is no longer needed.
|
|
|
+ *
|
|
|
+ ************************************************************************/
|
|
|
+
|
|
|
+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
|
|
|
+ LPBITMAPINFOHEADER 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;
|
|
|
+
|
|
|
+ // fill in BITMAP structure, return NULL if it didn't work
|
|
|
+
|
|
|
+ if (!GetObject(hBitmap, sizeof(bm), (LPSTR)&bm))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ // if no palette is specified, use default palette
|
|
|
+
|
|
|
+ if (hPal == NULL)
|
|
|
+ hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
|
|
|
+
|
|
|
+ // calculate bits per pixel
|
|
|
+
|
|
|
+ biBits = bm.bmPlanes * bm.bmBitsPixel;
|
|
|
+
|
|
|
+ // make sure bits per pixel is valid
|
|
|
+
|
|
|
+ if (biBits <= 1)
|
|
|
+ biBits = 1;
|
|
|
+ else if (biBits <= 4)
|
|
|
+ biBits = 4;
|
|
|
+ else if (biBits <= 8)
|
|
|
+ biBits = 8;
|
|
|
+ else // if greater than 8-bit, force to 24-bit
|
|
|
+ biBits = 24;
|
|
|
+
|
|
|
+ // initialize BITMAPINFOHEADER
|
|
|
+
|
|
|
+ bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
+ bi.biWidth = bm.bmWidth;
|
|
|
+ bi.biHeight = bm.bmHeight;
|
|
|
+ bi.biPlanes = 1;
|
|
|
+ bi.biBitCount = biBits;
|
|
|
+ bi.biCompression = BI_RGB;
|
|
|
+ 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 = (LPBITMAPINFOHEADER)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, (UINT)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 = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
|
|
|
+
|
|
|
+ // call GetDIBits with a NON-NULL lpBits param, and actualy get the
|
|
|
+ // bits this time
|
|
|
+
|
|
|
+ if (GetDIBits(hDC, hBitmap, 0, (UINT)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 colors on this device.
|
|
|
+
|
|
|
+ nColors = (1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)));
|
|
|
+
|
|
|
+ assert(nColors);
|
|
|
+ return nColors;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+ *
|
|
|
+ * GetSystemPalette()
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ *
|
|
|
+ * None
|
|
|
+ *
|
|
|
+ * Return Value:
|
|
|
+ *
|
|
|
+ * HPALETTE - handle to a copy of the current system palette
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ *
|
|
|
+ * This function returns a handle to a palette which represents the system
|
|
|
+ * palette. The system RGB values are copied into our logical palette using
|
|
|
+ * the GetSystemPaletteEntries function.
|
|
|
+ *
|
|
|
+ ************************************************************************/
|
|
|
+
|
|
|
+HPALETTE GetSystemPalette(void)
|
|
|
+{
|
|
|
+ HDC hDC; // handle to a DC
|
|
|
+ static HPALETTE hPal = NULL; // handle to a palette
|
|
|
+ HANDLE hLogPal; // handle to a logical palette
|
|
|
+ LPLOGPALETTE lpLogPal; // pointer to a logical palette
|
|
|
+ int nColors; // number of colors
|
|
|
+
|
|
|
+ // Find out how many palette entries we want.
|
|
|
+
|
|
|
+ hDC = GetDC(NULL);
|
|
|
+
|
|
|
+ if (!hDC)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ nColors = PalEntriesOnDevice(hDC); // Number of palette entries
|
|
|
+
|
|
|
+ // 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;
|
|
|
+
|
|
|
+ // Copy the current system palette into our logical palette
|
|
|
+
|
|
|
+ GetSystemPaletteEntries(hDC, 0, nColors,
|
|
|
+ (LPPALETTEENTRY)(lpLogPal->palPalEntry));
|
|
|
+
|
|
|
+ // 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);
|
|
|
+ ReleaseDC(NULL, hDC);
|
|
|
+
|
|
|
+ return hPal;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+ *
|
|
|
+ * AllocRoomForDIB()
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ *
|
|
|
+ * BITMAPINFOHEADER - bitmap info header stucture
|
|
|
+ *
|
|
|
+ * HBITMAP - handle to the bitmap
|
|
|
+ *
|
|
|
+ * Return Value:
|
|
|
+ *
|
|
|
+ * HDIB - handle to memory block
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ *
|
|
|
+ * This routine takes a BITMAPINOHEADER, and returns a handle to global
|
|
|
+ * memory which can contain a DIB with that header. It also initializes
|
|
|
+ * the header portion of the global memory. GetDIBits() is used to determine
|
|
|
+ * the amount of room for the DIB's bits. The total amount of memory
|
|
|
+ * needed = sizeof(BITMAPINFOHEADER) + size of color table + size of bits.
|
|
|
+ *
|
|
|
+ ************************************************************************/
|
|
|
+
|
|
|
+HANDLE AllocRoomForDIB(BITMAPINFOHEADER bi, HBITMAP hBitmap)
|
|
|
+{
|
|
|
+ DWORD dwLen;
|
|
|
+ HANDLE hDIB;
|
|
|
+ HDC hDC;
|
|
|
+ LPBITMAPINFOHEADER lpbi;
|
|
|
+ HANDLE hTemp;
|
|
|
+
|
|
|
+ // Figure out the size needed to hold the BITMAPINFO structure
|
|
|
+ // (which includes the BITMAPINFOHEADER and the color table).
|
|
|
+
|
|
|
+ dwLen = bi.biSize + PaletteSize((LPSTR) &bi);
|
|
|
+ hDIB = GlobalAlloc(GHND,dwLen);
|
|
|
+
|
|
|
+ // Check that DIB handle is valid
|
|
|
+
|
|
|
+ if (!hDIB)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ // Set up the BITMAPINFOHEADER in the newly allocated global memory,
|
|
|
+ // then call GetDIBits() with lpBits = NULL to have it fill in the
|
|
|
+ // biSizeImage field for us.
|
|
|
+
|
|
|
+ lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
|
|
|
+ *lpbi = bi;
|
|
|
+
|
|
|
+ hDC = GetDC(NULL);
|
|
|
+
|
|
|
+ GetDIBits(hDC, hBitmap, 0, (UINT) bi.biHeight, NULL, (LPBITMAPINFO)lpbi,
|
|
|
+ DIB_RGB_COLORS);
|
|
|
+ ReleaseDC(NULL, hDC);
|
|
|
+
|
|
|
+ // If the driver did not fill in the biSizeImage field,
|
|
|
+ // fill it in -- NOTE: this is a bug in the driver!
|
|
|
+
|
|
|
+ if (lpbi->biSizeImage == 0)
|
|
|
+ lpbi->biSizeImage = WIDTHBYTES((DWORD)lpbi->biWidth *
|
|
|
+ lpbi->biBitCount) * lpbi->biHeight;
|
|
|
+
|
|
|
+ // Get the size of the memory block we need
|
|
|
+
|
|
|
+ dwLen = lpbi->biSize + PaletteSize((LPSTR) &bi) + lpbi->biSizeImage;
|
|
|
+
|
|
|
+ // Unlock the memory block
|
|
|
+
|
|
|
+ GlobalUnlock(hDIB);
|
|
|
+
|
|
|
+ // ReAlloc the buffer big enough to hold all the bits
|
|
|
+
|
|
|
+ if (hTemp = GlobalReAlloc(hDIB,dwLen,0))
|
|
|
+ return hTemp;
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Else free memory block and return failure
|
|
|
+
|
|
|
+ GlobalFree(hDIB);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+ *
|
|
|
+ * ChangeDIBFormat()
|
|
|
+ *
|
|
|
+ * Parameter:
|
|
|
+ *
|
|
|
+ * HDIB - handle to packed-DIB in memory
|
|
|
+ *
|
|
|
+ * WORD - desired bits per pixel
|
|
|
+ *
|
|
|
+ * DWORD - desired compression format
|
|
|
+ *
|
|
|
+ * Return Value:
|
|
|
+ *
|
|
|
+ * HDIB - handle to the new DIB if successful, else NULL
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ *
|
|
|
+ * This function will convert the bits per pixel and/or the compression
|
|
|
+ * format of the specified DIB. Note: If the conversion was unsuccessful,
|
|
|
+ * we return NULL. The original DIB is left alone. Don't use code like the
|
|
|
+ * following:
|
|
|
+ *
|
|
|
+ * hMyDIB = ChangeDIBFormat(hMyDIB, 8, BI_RLE4);
|
|
|
+ *
|
|
|
+ * The conversion will fail, but hMyDIB will now be NULL and the original
|
|
|
+ * DIB will now hang around in memory. We could have returned the old
|
|
|
+ * DIB, but we wanted to allow the programmer to check whether this
|
|
|
+ * conversion succeeded or failed.
|
|
|
+ *
|
|
|
+ ************************************************************************/
|
|
|
+
|
|
|
+HDIB ChangeDIBFormat(HDIB hDIB, WORD wBitCount, DWORD dwCompression)
|
|
|
+{
|
|
|
+ HDC hDC; // Handle to DC
|
|
|
+ HBITMAP hBitmap; // Handle to bitmap
|
|
|
+ BITMAP Bitmap; // BITMAP data structure
|
|
|
+ BITMAPINFOHEADER bi; // Bitmap info header
|
|
|
+ LPBITMAPINFOHEADER lpbi; // Pointer to bitmap info
|
|
|
+ HDIB hNewDIB = NULL; // Handle to new DIB
|
|
|
+ HPALETTE hPal, hOldPal; // Handle to palette, prev pal
|
|
|
+ WORD DIBBPP, NewBPP; // DIB bits per pixel, new bpp
|
|
|
+ DWORD DIBComp, NewComp;// DIB compression, new compression
|
|
|
+
|
|
|
+ // Check for a valid DIB handle
|
|
|
+
|
|
|
+ if (!hDIB)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ // Get the old DIB's bits per pixel and compression format
|
|
|
+
|
|
|
+ lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
|
|
|
+ DIBBPP = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
|
|
|
+ DIBComp = ((LPBITMAPINFOHEADER)lpbi)->biCompression;
|
|
|
+ GlobalUnlock(hDIB);
|
|
|
+
|
|
|
+ // Validate wBitCount and dwCompression
|
|
|
+ // They must match correctly (i.e., BI_RLE4 and 4 BPP or
|
|
|
+ // BI_RLE8 and 8BPP, etc.) or we return failure
|
|
|
+ if (wBitCount == 0)
|
|
|
+ {
|
|
|
+ NewBPP = DIBBPP;
|
|
|
+ if ((dwCompression == BI_RLE4 && NewBPP == 4) ||
|
|
|
+ (dwCompression == BI_RLE8 && NewBPP == 8) ||
|
|
|
+ (dwCompression == BI_RGB))
|
|
|
+ NewComp = dwCompression;
|
|
|
+ else
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ else if (wBitCount == 1 && dwCompression == BI_RGB)
|
|
|
+ {
|
|
|
+ NewBPP = wBitCount;
|
|
|
+ NewComp = BI_RGB;
|
|
|
+ }
|
|
|
+ else if (wBitCount == 4)
|
|
|
+ {
|
|
|
+ NewBPP = wBitCount;
|
|
|
+ if (dwCompression == BI_RGB || dwCompression == BI_RLE4)
|
|
|
+ NewComp = dwCompression;
|
|
|
+ else
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ else if (wBitCount == 8)
|
|
|
+ {
|
|
|
+ NewBPP = wBitCount;
|
|
|
+ if (dwCompression == BI_RGB || dwCompression == BI_RLE8)
|
|
|
+ NewComp = dwCompression;
|
|
|
+ else
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ else if (wBitCount == 24 && dwCompression == BI_RGB)
|
|
|
+ {
|
|
|
+ NewBPP = wBitCount;
|
|
|
+ NewComp = BI_RGB;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ // Save the old DIB's palette
|
|
|
+
|
|
|
+ hPal = CreateDIBPalette(hDIB);
|
|
|
+ if (!hPal)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ // Convert old DIB to a bitmap
|
|
|
+
|
|
|
+ hBitmap = DIBToBitmap(hDIB, hPal);
|
|
|
+ if (!hBitmap)
|
|
|
+ {
|
|
|
+ DeleteObject(hPal);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get info about the bitmap
|
|
|
+ GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
|
|
|
+
|
|
|
+ // Fill in the BITMAPINFOHEADER appropriately
|
|
|
+
|
|
|
+ bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
+ bi.biWidth = Bitmap.bmWidth;
|
|
|
+ bi.biHeight = Bitmap.bmHeight;
|
|
|
+ bi.biPlanes = 1;
|
|
|
+ bi.biBitCount = NewBPP;
|
|
|
+ bi.biCompression = NewComp;
|
|
|
+ bi.biSizeImage = 0;
|
|
|
+ bi.biXPelsPerMeter = 0;
|
|
|
+ bi.biYPelsPerMeter = 0;
|
|
|
+ bi.biClrUsed = 0;
|
|
|
+ bi.biClrImportant = 0;
|
|
|
+
|
|
|
+ // Go allocate room for the new DIB
|
|
|
+
|
|
|
+ hNewDIB = AllocRoomForDIB(bi, hBitmap);
|
|
|
+ if (!hNewDIB)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ // Get a pointer to the new DIB
|
|
|
+
|
|
|
+ lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);
|
|
|
+
|
|
|
+ // Get a DC and select/realize our palette in it
|
|
|
+
|
|
|
+ hDC = GetDC(NULL);
|
|
|
+ hOldPal = SelectPalette(hDC, hPal, FALSE);
|
|
|
+ RealizePalette(hDC);
|
|
|
+
|
|
|
+ // Call GetDIBits and get the new DIB bits
|
|
|
+
|
|
|
+ if (!GetDIBits(hDC, hBitmap, 0, (UINT) lpbi->biHeight,
|
|
|
+ (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),
|
|
|
+ (LPBITMAPINFO)lpbi, DIB_RGB_COLORS))
|
|
|
+ {
|
|
|
+ GlobalUnlock(hNewDIB);
|
|
|
+ GlobalFree(hNewDIB);
|
|
|
+ hNewDIB = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Clean up and return
|
|
|
+
|
|
|
+ SelectPalette(hDC, hOldPal, TRUE);
|
|
|
+ RealizePalette(hDC);
|
|
|
+ ReleaseDC(NULL, hDC);
|
|
|
+
|
|
|
+ // Unlock the new DIB's memory block
|
|
|
+ if (hNewDIB)
|
|
|
+ GlobalUnlock(hNewDIB);
|
|
|
+
|
|
|
+ DeleteObject(hBitmap);
|
|
|
+ DeleteObject(hPal);
|
|
|
+
|
|
|
+ return hNewDIB;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+ *
|
|
|
+ * ChangeBitmapFormat()
|
|
|
+ *
|
|
|
+ * Parameter:
|
|
|
+ *
|
|
|
+ * HBITMAP - handle to a bitmap
|
|
|
+ *
|
|
|
+ * WORD - desired bits per pixel
|
|
|
+ *
|
|
|
+ * DWORD - desired compression format
|
|
|
+ *
|
|
|
+ * HPALETTE - handle to palette
|
|
|
+ *
|
|
|
+ * Return Value:
|
|
|
+ *
|
|
|
+ * HDIB - handle to the new DIB if successful, else NULL
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ *
|
|
|
+ * This function will convert a bitmap to the specified bits per pixel
|
|
|
+ * and compression format. The bitmap and it's palette will remain
|
|
|
+ * after calling this function.
|
|
|
+ *
|
|
|
+ ************************************************************************/
|
|
|
+
|
|
|
+HDIB ChangeBitmapFormat(HBITMAP hBitmap, WORD wBitCount, DWORD dwCompression,
|
|
|
+ HPALETTE hPal)
|
|
|
+{
|
|
|
+ HDC hDC; // Screen DC
|
|
|
+ HDIB hNewDIB=NULL; // Handle to new DIB
|
|
|
+ BITMAP Bitmap; // BITMAP data structure
|
|
|
+ BITMAPINFOHEADER bi; // Bitmap info. header
|
|
|
+ LPBITMAPINFOHEADER lpbi; // Pointer to bitmap header
|
|
|
+ HPALETTE hOldPal=NULL; // Handle to palette
|
|
|
+ WORD NewBPP; // New bits per pixel
|
|
|
+ DWORD NewComp; // New compression format
|
|
|
+
|
|
|
+ // Check for a valid bitmap handle
|
|
|
+
|
|
|
+ if (!hBitmap)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ // Validate wBitCount and dwCompression
|
|
|
+ // They must match correctly (i.e., BI_RLE4 and 4 BPP or
|
|
|
+ // BI_RLE8 and 8BPP, etc.) or we return failure
|
|
|
+
|
|
|
+ if (wBitCount == 0)
|
|
|
+ {
|
|
|
+ NewComp = dwCompression;
|
|
|
+ if (NewComp == BI_RLE4)
|
|
|
+ NewBPP = 4;
|
|
|
+ else if (NewComp == BI_RLE8)
|
|
|
+ NewBPP = 8;
|
|
|
+ else // Not enough info */
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ else if (wBitCount == 1 && dwCompression == BI_RGB)
|
|
|
+ {
|
|
|
+ NewBPP = wBitCount;
|
|
|
+ NewComp = BI_RGB;
|
|
|
+ }
|
|
|
+ else if (wBitCount == 4)
|
|
|
+ {
|
|
|
+ NewBPP = wBitCount;
|
|
|
+ if (dwCompression == BI_RGB || dwCompression == BI_RLE4)
|
|
|
+ NewComp = dwCompression;
|
|
|
+ else
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ else if (wBitCount == 8)
|
|
|
+ {
|
|
|
+ NewBPP = wBitCount;
|
|
|
+ if (dwCompression == BI_RGB || dwCompression == BI_RLE8)
|
|
|
+ NewComp = dwCompression;
|
|
|
+ else
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ else if (wBitCount == 24 && dwCompression == BI_RGB)
|
|
|
+ {
|
|
|
+ NewBPP = wBitCount;
|
|
|
+ NewComp = BI_RGB;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ // Get info about the bitmap
|
|
|
+
|
|
|
+ GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
|
|
|
+
|
|
|
+ // Fill in the BITMAPINFOHEADER appropriately
|
|
|
+
|
|
|
+ bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
+ bi.biWidth = Bitmap.bmWidth;
|
|
|
+ bi.biHeight = Bitmap.bmHeight;
|
|
|
+ bi.biPlanes = 1;
|
|
|
+ bi.biBitCount = NewBPP;
|
|
|
+ bi.biCompression = NewComp;
|
|
|
+ bi.biSizeImage = 0;
|
|
|
+ bi.biXPelsPerMeter = 0;
|
|
|
+ bi.biYPelsPerMeter = 0;
|
|
|
+ bi.biClrUsed = 0;
|
|
|
+ bi.biClrImportant = 0;
|
|
|
+
|
|
|
+ // Go allocate room for the new DIB
|
|
|
+
|
|
|
+ hNewDIB = AllocRoomForDIB(bi, hBitmap);
|
|
|
+ if (!hNewDIB)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ // Get a pointer to the new DIB
|
|
|
+
|
|
|
+ lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);
|
|
|
+
|
|
|
+ // If we have a palette, get a DC and select/realize it
|
|
|
+
|
|
|
+ if (hPal)
|
|
|
+ {
|
|
|
+ hDC = GetDC(NULL);
|
|
|
+ hOldPal = SelectPalette(hDC, hPal, FALSE);
|
|
|
+ RealizePalette(hDC);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Call GetDIBits and get the new DIB bits
|
|
|
+
|
|
|
+ if (!GetDIBits(hDC, hBitmap, 0, (UINT) lpbi->biHeight, (LPSTR)lpbi +
|
|
|
+ (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,
|
|
|
+ DIB_RGB_COLORS))
|
|
|
+ {
|
|
|
+ GlobalUnlock(hNewDIB);
|
|
|
+ GlobalFree(hNewDIB);
|
|
|
+ hNewDIB = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Clean up and return
|
|
|
+
|
|
|
+ if (hOldPal)
|
|
|
+ {
|
|
|
+ SelectPalette(hDC, hOldPal, TRUE);
|
|
|
+ RealizePalette(hDC);
|
|
|
+ ReleaseDC(NULL, hDC);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Unlock the new DIB's memory block
|
|
|
+
|
|
|
+ if (hNewDIB)
|
|
|
+ GlobalUnlock(hNewDIB);
|
|
|
+
|
|
|
+ return hNewDIB;
|
|
|
+}
|