home *** CD-ROM | disk | FTP | other *** search
- //-----------------------------------------------------------------------------
- // DIB.C
- //
- // This is a collection of useful DIB manipulation/information gathering
- // functions. Many functions are supplied simply to take the burden
- // of taking into account whether a DIB is a Win30 style or OS/2 style
- // DIB away from the application.
- //
- // The functions in this module assume that the DIB pointers or handles
- // passed to them point to a block of memory in one of two formats:
- //
- // a) BITMAPINFOHEADER + color table + DIB bits (3.0 style DIB)
- // b) BITMAPCOREHEADER + color table + DIB bits (OS/2 PM style)
- //
- // The SDK Reference, Volume 2 describes these data structures.
- //
- // A number of functions in this module were lifted from SHOWDIB,
- // and modified to handle OS/2 DIBs.
- //
- // The functions in this module could be streamlined (made faster and
- // smaller) by removing the OS/2 DIB specific code, and assuming all
- // DIBs passed to it are Win30 style DIBs. The DIB file reading code
- // would need to be modified to always convert DIBs to Win30 style
- // DIBs. The only reason this isn't done in DIBView is because DIBView
- // was written to test display and printer drivers (which are supposed
- // to support OS/2 DIBs wherever they support Win30 style DIBs). SHOWDIB
- // is a great example of how to go about doing this.
- //-----------------------------------------------------------------------------
-
- #include <windows.h>
- #include <memory.h>
- #include "errors.h"
- #include "dib.h"
-
- //---------------------------------------------------------------------
- //
- // Function: FindDIBBits
- //
- // Purpose: Given a pointer to a DIB, returns a pointer to the
- // DIB's bitmap bits.
- //
- // Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER
- // or BITMAPCOREHEADER)
- //
- // History: Date Reason
- // 6/01/91 Created
- //
- //---------------------------------------------------------------------
-
- LPSTR FAR PASCAL FindDIBBits (LPSTR lpbi)
- {
- return (lpbi + *(LPDWORD)lpbi + PaletteSize (lpbi));
- }
-
- //---------------------------------------------------------------------
- //
- // Function: DIBNumColors
- //
- // Purpose: Given a pointer to a DIB, returns a number of colors in
- // the DIB's color table.
- //
- // Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER
- // or BITMAPCOREHEADER)
- //
- // History: Date Reason
- // 6/01/91 Created
- //
- //---------------------------------------------------------------------
-
- WORD FAR PASCAL DIBNumColors (LPSTR lpbi)
- {
- WORD wBitCount;
-
-
- // 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;
-
- switch (wBitCount)
- {
- case 1:
- return 2;
-
- case 4:
- return 16;
-
- case 8:
- return 256;
-
- default:
- return 0;
- }
- }
-
- //---------------------------------------------------------------------
- //
- // Function: PaletteSize
- //
- // Purpose: Given a pointer to a DIB, returns number of bytes
- // in the DIB's color table.
- //
- // Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER
- // or BITMAPCOREHEADER)
- //
- // History: Date Reason
- // 6/01/91 Created
- //
- //---------------------------------------------------------------------
-
- WORD FAR PASCAL PaletteSize (LPSTR lpbi)
- {
- if (IS_WIN30_DIB (lpbi))
- return (DIBNumColors (lpbi) * sizeof (RGBQUAD));
- else
- return (DIBNumColors (lpbi) * sizeof (RGBTRIPLE));
- }
-
- //---------------------------------------------------------------------
- //
- // Function: CreateDIBPalette
- //
- // Purpose: Given a handle to a DIB, constructs a logical palette,
- // and returns a handle to this palette.
- //
- // Stolen almost verbatim from ShowDIB.
- //
- // Parms: hDIB == HANDLE to global memory with a DIB header
- // (either BITMAPINFOHEADER or BITMAPCOREHEADER)
- //
- // History: Date Reason
- // 6/01/91 Created
- //
- //---------------------------------------------------------------------
-
- HPALETTE FAR PASCAL CreateDIBPalette (HANDLE hDIB)
- {
- LPLOGPALETTE lpPal;
- HANDLE hLogPal;
- HPALETTE hPal = NULL;
- int i, wNumColors;
- LPSTR lpbi;
- LPBITMAPINFO lpbmi;
- LPBITMAPCOREINFO lpbmc;
- BOOL bWinStyleDIB;
-
- if (!hDIB)
- return NULL;
-
- lpbi = GlobalLock (hDIB);
- lpbmi = (LPBITMAPINFO) lpbi;
- lpbmc = (LPBITMAPCOREINFO) lpbi;
- wNumColors = DIBNumColors (lpbi);
- bWinStyleDIB = IS_WIN30_DIB (lpbi);
-
- if (wNumColors)
- {
- hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) +
- sizeof (PALETTEENTRY) * wNumColors);
-
- if (!hLogPal)
- {
- DIBError (ERR_CREATEPAL);
- GlobalUnlock (hDIB);
- return NULL;
- }
-
- lpPal = (LPLOGPALETTE) GlobalLock (hLogPal);
-
- lpPal->palVersion = PALVERSION;
- lpPal->palNumEntries = wNumColors;
-
- 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;
- }
- }
-
- hPal = CreatePalette (lpPal);
-
- if (!hPal)
- DIBError (ERR_CREATEPAL);
-
- GlobalUnlock (hLogPal);
- GlobalFree (hLogPal);
- }
-
- GlobalUnlock (hDIB);
-
- return hPal;
- }
-
- //---------------------------------------------------------------------
- //
- // Function: DIBHeight
- //
- // Purpose: Given a pointer to a DIB, returns its height. Note
- // that it returns a DWORD (since a Win30 DIB can have
- // a DWORD in its height field), but under Win30, the
- // high order word isn't used!
- //
- // Parms: lpDIB == pointer to DIB header (either BITMAPINFOHEADER
- // or BITMAPCOREHEADER)
- //
- // History: Date Reason
- // 6/01/91 Created
- //
- //---------------------------------------------------------------------
-
- DWORD FAR PASCAL DIBHeight (LPSTR lpDIB)
- {
- LPBITMAPINFOHEADER lpbmi;
- LPBITMAPCOREHEADER lpbmc;
-
- lpbmi = (LPBITMAPINFOHEADER) lpDIB;
- lpbmc = (LPBITMAPCOREHEADER) lpDIB;
-
- if (lpbmi->biSize == sizeof (BITMAPINFOHEADER))
- return lpbmi->biHeight;
- else
- return (DWORD) lpbmc->bcHeight;
- }
-
- //---------------------------------------------------------------------
- //
- // Function: DIBWidth
- //
- // Purpose: Given a pointer to a DIB, returns its width. Note
- // that it returns a DWORD (since a Win30 DIB can have
- // a DWORD in its width field), but under Win30, the
- // high order word isn't used!
- //
- // Parms: lpDIB == pointer to DIB header (either BITMAPINFOHEADER
- // or BITMAPCOREHEADER)
- //
- // History: Date Reason
- // 6/01/91 Created
- //
- //---------------------------------------------------------------------
-
- DWORD FAR PASCAL DIBWidth (LPSTR lpDIB)
- {
- LPBITMAPINFOHEADER lpbmi;
- LPBITMAPCOREHEADER lpbmc;
-
- lpbmi = (LPBITMAPINFOHEADER) lpDIB;
- lpbmc = (LPBITMAPCOREHEADER) lpDIB;
-
- if (lpbmi->biSize == sizeof (BITMAPINFOHEADER))
- return lpbmi->biWidth;
- else
- return (DWORD) lpbmc->bcWidth;
- }
-
- //---------------------------------------------------------------------
- //
- // Function: DIBLoad
- //
- // Purpose: Given a pointer to a DIB filename, will open that file
- // and read the DIB data into a globally allocated memory
- // block.
- //
- // Parms: lpszDIBName == pointer to a string containing the name
- // (any valid DOS filename) of the DIB file
- //
- // Returns: Will return a handle to the global memory block if
- // successful. Will return NULL otherwise.
- //
- // History: Date Reason
- // 3/10/92 Created
- //
- //---------------------------------------------------------------------
-
- HANDLE FAR PASCAL DIBLoad (LPSTR lpszDIBName)
- {
- unsigned fh;
- LPBITMAPINFOHEADER lpbi;
- OFSTRUCT of;
- BITMAPFILEHEADER bf;
- WORD nNumColors;
- WORD offBits;
- HANDLE hDIBInfo = NULL;
- char * szMsg;
- HANDLE result = NULL; /* assume failure */
-
- /* Open the file and get a handle to it's BITMAPINFO */
-
- hDIBInfo = GlobalAlloc(GMEM_MOVEABLE,
- (DWORD)(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)));
- if (hDIBInfo == NULL) {
- wsprintf((LPSTR) szMsg, "Not enough memory to load '%s'", lpszDIBName);
- MessageBox((HWND) NULL, (LPSTR) szMsg, "Error", MB_ICONSTOP | MB_OK);
- return (NULL);
- }
-
- lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIBInfo);
-
- fh = OpenFile (lpszDIBName, &of, OF_READ);
- if (fh == -1) {
- wsprintf((LPSTR) szMsg, "Can't open file '%s'", lpszDIBName);
- MessageBox((HWND) NULL, (LPSTR) szMsg, "Error", MB_ICONSTOP | MB_OK);
- return (NULL);
- }
-
- /* read the BITMAPFILEHEADER */
- if (sizeof (bf) != _lread (fh, (LPSTR)&bf, sizeof (bf)))
- goto ErrExit;
-
- if (bf.bfType != 0x4d42) /* 'BM' */
- goto ErrExit;
-
- if (sizeof(BITMAPINFOHEADER) != _lread (fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))
- goto ErrExit;
-
- /* don't even deal with OS/2 bitmaps */
- if (!IS_WIN30_DIB(lpbi)) {
- wsprintf((LPSTR) szMsg, "OS/2 bitmaps (%s) not supported!", lpszDIBName);
- MessageBox((HWND) NULL, (LPSTR) szMsg, "Error", MB_ICONSTOP | MB_OK);
- goto ErrExit;
- }
-
- if (!(nNumColors = (WORD)lpbi->biClrUsed))
- {
- /* no color table for 24-bit, default size otherwise */
- if (lpbi->biBitCount != 24)
- nNumColors = 1 << lpbi->biBitCount; /* standard size table */
- }
-
- /* fill in some default values if they are zero */
- if (lpbi->biClrUsed == 0)
- lpbi->biClrUsed = (DWORD)nNumColors;
-
- if (lpbi->biSizeImage == 0)
- {
- lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3)
- * lpbi->biHeight;
- }
-
- /* get a proper-sized buffer for header, color table and bits */
- GlobalUnlock(hDIBInfo);
- hDIBInfo = GlobalReAlloc(hDIBInfo, lpbi->biSize +
- nNumColors * sizeof(RGBQUAD) +
- lpbi->biSizeImage, 0);
- if (!hDIBInfo) { /* can't resize buffer for loading */
- wsprintf((LPSTR) szMsg, "Not enough memory to load '%s'", lpszDIBName);
- MessageBox((HWND) NULL, (LPSTR) szMsg, "Error", MB_ICONSTOP | MB_OK);
- goto ErrExit;
- }
-
- lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIBInfo);
-
- /* read the color table */
- _lread (fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));
-
- /* offset to the bits from start of DIB header */
- offBits = (WORD)lpbi->biSize + nNumColors * sizeof(RGBQUAD);
-
- if (bf.bfOffBits != 0L)
- {
- _llseek(fh,bf.bfOffBits, SEEK_SET);
- }
- if (lpbi->biSizeImage == lread(fh, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
- result = hDIBInfo;
-
- ErrExit:
- _lclose(fh);
- GlobalUnlock(hDIBInfo);
- return(result);
- }
-
- /**************** PRIVATE ROUTINE TO READ MORE THAN 64K *********************/
- /****************************************************************************
- * *
- * FUNCTION : lread(int fh, VOID FAR *pv, DWORD ul) *
- * *
- * PURPOSE : Reads data in steps of 32k till all the data has been read.*
- * *
- * RETURNS : 0 - If read did not proceed correctly. *
- * number of bytes read otherwise. *
- * *
- ****************************************************************************/
- DWORD PASCAL lread (int fh, VOID far *pv, DWORD ul)
- {
- DWORD ulT = ul;
- BYTE huge *hp = pv;
-
- while (ul > (DWORD)MAXREAD) {
- if (_lread(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
- return 0;
- ul -= MAXREAD;
- hp += MAXREAD;
- }
- if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
- return 0;
- return ulT;
- }
-