diff options
Diffstat (limited to 'src/readdib.c')
-rw-r--r-- | src/readdib.c | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/src/readdib.c b/src/readdib.c new file mode 100644 index 00000000..294c2702 --- /dev/null +++ b/src/readdib.c @@ -0,0 +1,342 @@ +/* File: readbits.c */ + +/* + * This package provides a routine to read a DIB file and set up the + * device dependent version of the image. + * + * This file has been modified for use with "Angband 2.8.2" + * + * COPYRIGHT: + * + * (C) Copyright Microsoft Corp. 1993. All rights reserved. + * + * You have a royalty-free right to use, modify, reproduce and + * distribute the Sample Files (and/or any modified version) in + * any way you find useful, provided that you agree that + * Microsoft has no warranty obligations or liability for any + * Sample Application Files which are modified. + */ + +#ifdef WINDOWS + +#include <windows.h> + +#include "readdib.h" + + +/* + * Extract the "WIN32" flag from the compiler + */ +#if defined(__WIN32__) || defined(__WINNT__) || defined(__NT__) +# ifndef WIN32 +# define WIN32 +# endif +#endif + +/* + * Make sure "huge" is legal XXX XXX XXX + */ +#undef huge +#ifdef WIN32 +# define huge /* oops */ +#endif + + +/* + * Number of bytes to be read during each read operation + */ +#define MAXREAD 32768 + +/* + * Private routine to read more than 64K at a time + * + * Reads data in steps of 32k till all the data has been read. + * + * Returns number of bytes requested, or zero if something went wrong. + */ +static 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; +} + + +/* + * Given a BITMAPINFOHEADER, create a palette based on the color table. + * + * Returns the handle of a palette, or zero if something went wrong. + */ +static HPALETTE PASCAL NEAR MakeDIBPalette(LPBITMAPINFOHEADER lpInfo) +{ + NPLOGPALETTE npPal; + RGBQUAD far *lpRGB; + HPALETTE hLogPal; + WORD i; + + /* + * since biClrUsed field was filled during the loading of the DIB, + * we know it contains the number of colors in the color table. + */ + if (lpInfo->biClrUsed) + { + npPal = (NPLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) + + (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY)); + if (!npPal) + return (FALSE); + + npPal->palVersion = 0x300; + npPal->palNumEntries = (WORD)lpInfo->biClrUsed; + + /* get pointer to the color table */ + lpRGB = (RGBQUAD FAR *)((LPSTR)lpInfo + lpInfo->biSize); + + /* copy colors from the color table to the LogPalette structure */ + for (i = 0; i < lpInfo->biClrUsed; i++, lpRGB++) + { + npPal->palPalEntry[i].peRed = lpRGB->rgbRed; + npPal->palPalEntry[i].peGreen = lpRGB->rgbGreen; + npPal->palPalEntry[i].peBlue = lpRGB->rgbBlue; + npPal->palPalEntry[i].peFlags = PC_NOCOLLAPSE; + } + + hLogPal = CreatePalette((LPLOGPALETTE)npPal); + LocalFree((HANDLE)npPal); + return (hLogPal); + } + + /* + * 24-bit DIB with no color table. return default palette. Another + * option would be to create a 256 color "rainbow" palette to provide + * some good color choices. + */ + else + { + return (GetStockObject(DEFAULT_PALETTE)); + } +} + + +/* + * Given a DIB, create a bitmap and corresponding palette to be used for a + * device-dependent representation of the image. + * + * Returns TRUE on success (phPal and phBitmap are filled with appropriate + * handles. Caller is responsible for freeing objects) and FALSE on failure + * (unable to create objects, both pointer are invalid). + */ +static BOOL NEAR PASCAL MakeBitmapAndPalette(HDC hDC, HANDLE hDIB, + HPALETTE * phPal, HBITMAP * phBitmap) +{ + LPBITMAPINFOHEADER lpInfo; + BOOL result = FALSE; + HBITMAP hBitmap; + HPALETTE hPalette, hOldPal; + LPSTR lpBits; + + lpInfo = (LPBITMAPINFOHEADER) GlobalLock(hDIB); + if ((hPalette = MakeDIBPalette(lpInfo)) != 0) + { + /* Need to realize palette for converting DIB to bitmap. */ + hOldPal = SelectPalette(hDC, hPalette, TRUE); + RealizePalette(hDC); + + lpBits = ((LPSTR)lpInfo + (WORD)lpInfo->biSize + + (WORD)lpInfo->biClrUsed * sizeof(RGBQUAD)); + hBitmap = CreateDIBitmap(hDC, lpInfo, CBM_INIT, lpBits, + (LPBITMAPINFO)lpInfo, DIB_RGB_COLORS); + + SelectPalette(hDC, hOldPal, TRUE); + RealizePalette(hDC); + + if (!hBitmap) + { + DeleteObject(hPalette); + } + else + { + *phBitmap = hBitmap; + *phPal = hPalette; + result = TRUE; + } + } + return (result); +} + + + +/* + * Reads a DIB from a file, obtains a handle to its BITMAPINFO struct, and + * loads the DIB. Once the DIB is loaded, the function also creates a bitmap + * and palette out of the DIB for a device-dependent form. + * + * Returns TRUE if the DIB is loaded and the bitmap/palette created, in which + * case, the DIBINIT structure pointed to by pInfo is filled with the appropriate + * handles, and FALSE if something went wrong. + */ +BOOL ReadDIB(HWND hWnd, LPSTR lpFileName, DIBINIT *pInfo) +{ + unsigned fh; + LPBITMAPINFOHEADER lpbi; + OFSTRUCT of; + BITMAPFILEHEADER bf; + WORD nNumColors; + BOOL result = FALSE; + char str[128]; + WORD offBits; + HDC hDC; + BOOL bCoreHead = FALSE; + + /* Open the file and get a handle to it's BITMAPINFO */ + fh = OpenFile(lpFileName, &of, OF_READ); + if (fh == -1) + { + wsprintf(str, "Can't open file '%ls'", (LPSTR)lpFileName); + MessageBox(NULL, str, "Error", MB_ICONSTOP | MB_OK); + return (FALSE); + } + + pInfo->hDIB = GlobalAlloc(GHND, (DWORD)(sizeof(BITMAPINFOHEADER) + + 256 * sizeof(RGBQUAD))); + + if (!pInfo->hDIB) + return (FALSE); + + lpbi = (LPBITMAPINFOHEADER)GlobalLock(pInfo->hDIB); + + /* read the BITMAPFILEHEADER */ + if (sizeof (bf) != _lread(fh, (LPSTR)&bf, sizeof(bf))) + goto ErrExit; + + /* 'BM' */ + if (bf.bfType != 0x4d42) + goto ErrExit; + + if (sizeof(BITMAPCOREHEADER) != _lread(fh, (LPSTR)lpbi, sizeof(BITMAPCOREHEADER))) + goto ErrExit; + + if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) + { + lpbi->biSize = sizeof(BITMAPINFOHEADER); + lpbi->biBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; + lpbi->biPlanes = ((LPBITMAPCOREHEADER)lpbi)->bcPlanes; + lpbi->biHeight = ((LPBITMAPCOREHEADER)lpbi)->bcHeight; + lpbi->biWidth = ((LPBITMAPCOREHEADER)lpbi)->bcWidth; + bCoreHead = TRUE; + } + else + { + /* get to the start of the header and read INFOHEADER */ + _llseek(fh, sizeof(BITMAPFILEHEADER), SEEK_SET); + if (sizeof(BITMAPINFOHEADER) != _lread(fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER))) + goto ErrExit; + } + + if (!(nNumColors = (WORD)lpbi->biClrUsed)) + { + /* no color table for 24-bit, default size otherwise */ + if (lpbi->biBitCount != 24) + nNumColors = 1 << lpbi->biBitCount; + } + + /* fill in some default values if they are zero */ + if (lpbi->biClrUsed == 0) + lpbi->biClrUsed = nNumColors; + + if (lpbi->biSizeImage == 0) + { + lpbi->biSizeImage = (((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) + * lpbi->biHeight); + } + + /* otherwise wouldn't work with 16 color bitmaps -- S.K. */ + else if ((nNumColors == 16) && (lpbi->biSizeImage > bf.bfSize)) + { + lpbi->biSizeImage /= 2; + } + + /* get a proper-sized buffer for header, color table and bits */ + GlobalUnlock(pInfo->hDIB); + pInfo->hDIB = GlobalReAlloc(pInfo->hDIB, lpbi->biSize + + nNumColors * sizeof(RGBQUAD) + + lpbi->biSizeImage, 0); + + /* can't resize buffer for loading */ + if (!pInfo->hDIB) + goto ErrExit2; + + lpbi = (LPBITMAPINFOHEADER)GlobalLock(pInfo->hDIB); + + /* read the color table */ + if (!bCoreHead) + { + _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD)); + } + else + { + signed int i; + RGBQUAD FAR *pQuad; + RGBTRIPLE FAR *pTriple; + + _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBTRIPLE)); + + pQuad = (RGBQUAD FAR *)((LPSTR)lpbi + lpbi->biSize); + pTriple = (RGBTRIPLE FAR *) pQuad; + for (i = nNumColors - 1; i >= 0; i--) + { + pQuad[i].rgbRed = pTriple[i].rgbtRed; + pQuad[i].rgbBlue = pTriple[i].rgbtBlue; + pQuad[i].rgbGreen = pTriple[i].rgbtGreen; + pQuad[i].rgbReserved = 0; + } + } + + /* 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); + } + + /* Use local version of '_lread()' above */ + if (lpbi->biSizeImage == lread(fh, (LPSTR)lpbi + offBits, lpbi->biSizeImage)) + { + GlobalUnlock(pInfo->hDIB); + + hDC = GetDC(hWnd); + if (!MakeBitmapAndPalette(hDC, pInfo->hDIB, &(pInfo->hPalette), + &(pInfo->hBitmap))) + { + ReleaseDC(hWnd, hDC); + goto ErrExit2; + } + else + { + ReleaseDC(hWnd, hDC); + result = TRUE; + } + } + else + { +ErrExit: + GlobalUnlock(pInfo->hDIB); +ErrExit2: + GlobalFree(pInfo->hDIB); + } + + _lclose(fh); + return (result); +} + +#endif |