1 /**
2 * \file readdib.c
3 *
4 * This package provides a routine to read a DIB file and set up the
5 * device dependent version of the image.
6 *
7 * This file has been modified for use with "Angband 2.9.2"
8 *
9 * COPYRIGHT:
10 *
11 * (C) Copyright Microsoft Corp. 1993. All rights reserved.
12 *
13 * You have a royalty-free right to use, modify, reproduce and
14 * distribute the Sample Files (and/or any modified version) in
15 * any way you find useful, provided that you agree that
16 * Microsoft has no warranty obligations or liability for any
17 * Sample Application Files which are modified.
18 */
19
20 #if defined(USE_WIN) || defined(WINDOWS) || defined(WIN32)
21
22 #include <windows.h>
23
24 #include "readdib.h"
25
26
27 /**
28 * Needed for lcc-win32
29 */
30 #ifndef SEEK_SET
31 #define SEEK_SET 0
32 #endif
33
34
35 /**
36 * Number of bytes to be read during each read operation
37 */
38 #define MAXREAD 32768
39
40 /**
41 * Private routine to read more than 64K at a time
42 *
43 * Reads data in steps of 32k till all the data has been read.
44 *
45 * Returns number of bytes requested, or zero if something went wrong.
46 */
lread(HFILE fh,VOID FAR * pv,DWORD ul)47 static DWORD PASCAL lread(HFILE fh, VOID FAR *pv, DWORD ul)
48 {
49 DWORD ulT = ul;
50 BYTE *hp = pv;
51
52 while (ul > (DWORD)MAXREAD)
53 {
54 if (_lread(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
55 return 0;
56 ul -= MAXREAD;
57 hp += MAXREAD;
58 }
59 if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
60 return 0;
61 return ulT;
62 }
63
64
65 /**
66 * Given a BITMAPINFOHEADER, create a palette based on the color table.
67 *
68 * Returns the handle of a palette, or zero if something went wrong.
69 */
MakeDIBPalette(LPBITMAPINFOHEADER lpInfo)70 static HPALETTE PASCAL NEAR MakeDIBPalette(LPBITMAPINFOHEADER lpInfo)
71 {
72 PLOGPALETTE npPal;
73 RGBQUAD FAR *lpRGB;
74 HPALETTE hLogPal;
75 DWORD i;
76
77 /*
78 * since biClrUsed field was filled during the loading of the DIB,
79 * we know it contains the number of colors in the color table.
80 */
81 if (lpInfo->biClrUsed)
82 {
83 npPal = (PLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +
84 (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY));
85 if (!npPal)
86 return (false);
87
88 npPal->palVersion = 0x300;
89 npPal->palNumEntries = (WORD)lpInfo->biClrUsed;
90
91 /* get pointer to the color table */
92 lpRGB = (RGBQUAD FAR *)((LPSTR)lpInfo + lpInfo->biSize);
93
94 /* copy colors from the color table to the LogPalette structure */
95 for (i = 0; i < lpInfo->biClrUsed; i++, lpRGB++)
96 {
97 npPal->palPalEntry[i].peRed = lpRGB->rgbRed;
98 npPal->palPalEntry[i].peGreen = lpRGB->rgbGreen;
99 npPal->palPalEntry[i].peBlue = lpRGB->rgbBlue;
100 npPal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
101 }
102
103 hLogPal = CreatePalette((LPLOGPALETTE)npPal);
104 LocalFree((HANDLE)npPal);
105 return (hLogPal);
106 }
107
108 /*
109 * 24-bit DIB with no color table. return default palette. Another
110 * option would be to create a 256 color "rainbow" palette to provide
111 * some good color choices.
112 */
113 else
114 {
115 return (GetStockObject(DEFAULT_PALETTE));
116 }
117 }
118
119
120 /**
121 * Given a DIB, create a bitmap and corresponding palette to be used for a
122 * device-dependent representation of the image.
123 *
124 * Returns true on success (phPal and phBitmap are filled with appropriate
125 * handles. Caller is responsible for freeing objects) and false on failure
126 * (unable to create objects, both pointer are invalid).
127 */
MakeBitmapAndPalette(HDC hDC,HANDLE hDIB,HPALETTE * phPal,HBITMAP * phBitmap)128 static bool NEAR PASCAL MakeBitmapAndPalette(HDC hDC, HANDLE hDIB,
129 HPALETTE * phPal, HBITMAP * phBitmap)
130 {
131 LPBITMAPINFOHEADER lpInfo;
132 bool result = false;
133 HBITMAP hBitmap;
134 HPALETTE hPalette, hOldPal;
135 LPSTR lpBits;
136
137 lpInfo = (LPBITMAPINFOHEADER) GlobalLock(hDIB);
138 if ((hPalette = MakeDIBPalette(lpInfo)) != 0)
139 {
140 /* Need to realize palette for converting DIB to bitmap. */
141 hOldPal = SelectPalette(hDC, hPalette, true);
142 RealizePalette(hDC);
143
144 lpBits = ((LPSTR)lpInfo + (WORD)lpInfo->biSize +
145 (WORD)lpInfo->biClrUsed * sizeof(RGBQUAD));
146 hBitmap = CreateDIBitmap(hDC, lpInfo, CBM_INIT, lpBits,
147 (LPBITMAPINFO)lpInfo, DIB_RGB_COLORS);
148
149 SelectPalette(hDC, hOldPal, true);
150 RealizePalette(hDC);
151
152 if (!hBitmap)
153 {
154 DeleteObject(hPalette);
155 }
156 else
157 {
158 *phBitmap = hBitmap;
159 *phPal = hPalette;
160 result = true;
161 }
162 }
163 return (result);
164 }
165
166
167
168 /**
169 * Reads a DIB from a file, obtains a handle to its BITMAPINFO struct, and
170 * loads the DIB. Once the DIB is loaded, the function also creates a bitmap
171 * and palette out of the DIB for a device-dependent form.
172 *
173 * Returns true if the DIB is loaded and the bitmap/palette created, in which
174 * case, the DIBINIT structure pointed to by pInfo is filled with the appropriate
175 * handles, and false if something went wrong.
176 */
ReadDIB(HWND hWnd,LPSTR lpFileName,DIBINIT * pInfo)177 bool ReadDIB(HWND hWnd, LPSTR lpFileName, DIBINIT *pInfo)
178 {
179 HFILE fh;
180 LPBITMAPINFOHEADER lpbi;
181 OFSTRUCT of;
182 BITMAPFILEHEADER bf;
183 WORD nNumColors;
184 bool result = false;
185 DWORD offBits;
186 HDC hDC;
187 bool bCoreHead = false;
188
189 /* Open the file and get a handle to it's BITMAPINFO */
190 fh = OpenFile(lpFileName, &of, OF_READ);
191 if (fh == -1)
192 return (false);
193
194 pInfo->hDIB = GlobalAlloc(GHND, (DWORD)(sizeof(BITMAPINFOHEADER) +
195 256 * sizeof(RGBQUAD)));
196
197 if (!pInfo->hDIB)
198 return (false);
199
200 lpbi = (LPBITMAPINFOHEADER)GlobalLock(pInfo->hDIB);
201
202 /* read the BITMAPFILEHEADER */
203 if (sizeof (bf) != _lread(fh, (LPSTR)&bf, sizeof(bf)))
204 goto ErrExit;
205
206 /* 'BM' */
207 if (bf.bfType != 0x4d42)
208 goto ErrExit;
209
210 if (sizeof(BITMAPCOREHEADER) != _lread(fh, (LPSTR)lpbi, sizeof(BITMAPCOREHEADER)))
211 goto ErrExit;
212
213 if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
214 {
215 lpbi->biSize = sizeof(BITMAPINFOHEADER);
216 lpbi->biBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
217 lpbi->biPlanes = ((LPBITMAPCOREHEADER)lpbi)->bcPlanes;
218 lpbi->biHeight = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
219 lpbi->biWidth = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
220 bCoreHead = true;
221 }
222 else
223 {
224 /* get to the start of the header and read INFOHEADER */
225 _llseek(fh, sizeof(BITMAPFILEHEADER), SEEK_SET);
226 if (sizeof(BITMAPINFOHEADER) != _lread(fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))
227 goto ErrExit;
228 }
229
230 if ((nNumColors = (WORD)lpbi->biClrUsed) == 0)
231 {
232 /* no color table for 24-bit, default size otherwise */
233 if (lpbi->biBitCount != 24)
234 nNumColors = 1 << lpbi->biBitCount;
235 }
236
237 /* fill in some default values if they are zero */
238 if (lpbi->biClrUsed == 0)
239 lpbi->biClrUsed = nNumColors;
240
241 if (lpbi->biSizeImage == 0)
242 {
243 lpbi->biSizeImage = (((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3)
244 * lpbi->biHeight);
245 }
246
247 /* otherwise wouldn't work with 16 color bitmaps -- S.K. */
248 else if ((nNumColors == 16) && (lpbi->biSizeImage > bf.bfSize))
249 {
250 lpbi->biSizeImage /= 2;
251 }
252
253 /* get a proper-sized buffer for header, color table and bits */
254 GlobalUnlock(pInfo->hDIB);
255 pInfo->hDIB = GlobalReAlloc(pInfo->hDIB, lpbi->biSize +
256 nNumColors * sizeof(RGBQUAD) +
257 lpbi->biSizeImage, 0);
258
259 /* can't resize buffer for loading */
260 if (!pInfo->hDIB)
261 goto ErrExit2;
262
263 lpbi = (LPBITMAPINFOHEADER)GlobalLock(pInfo->hDIB);
264
265 /* read the color table */
266 if (!bCoreHead)
267 {
268 _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));
269 }
270 else
271 {
272 signed int i;
273 RGBQUAD FAR *pQuad;
274 RGBTRIPLE FAR *pTriple;
275
276 _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBTRIPLE));
277
278 pQuad = (RGBQUAD FAR *)((LPSTR)lpbi + lpbi->biSize);
279 pTriple = (RGBTRIPLE FAR *) pQuad;
280 for (i = nNumColors - 1; i >= 0; i--)
281 {
282 pQuad[i].rgbRed = pTriple[i].rgbtRed;
283 pQuad[i].rgbBlue = pTriple[i].rgbtBlue;
284 pQuad[i].rgbGreen = pTriple[i].rgbtGreen;
285 pQuad[i].rgbReserved = 0;
286 }
287 }
288
289 pInfo->ImageWidth = lpbi->biWidth;
290 pInfo->ImageHeight = lpbi->biHeight;
291
292 /* offset to the bits from start of DIB header */
293 offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);
294
295 if (bf.bfOffBits != 0L)
296 {
297 _llseek(fh,bf.bfOffBits,SEEK_SET);
298 }
299
300 /* Use local version of '_lread()' above */
301 if (lpbi->biSizeImage == lread(fh, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
302 {
303 GlobalUnlock(pInfo->hDIB);
304
305 hDC = GetDC(hWnd);
306 if (!MakeBitmapAndPalette(hDC, pInfo->hDIB, &(pInfo->hPalette),
307 &(pInfo->hBitmap)))
308 {
309 ReleaseDC(hWnd,hDC);
310 goto ErrExit2;
311 }
312 else
313 {
314 ReleaseDC(hWnd,hDC);
315 result = true;
316 }
317 }
318 else
319 {
320 ErrExit:
321 GlobalUnlock(pInfo->hDIB);
322 ErrExit2:
323 GlobalFree(pInfo->hDIB);
324 }
325
326 _lclose(fh);
327 return (result);
328 }
329
330
331 /* Free a DIB */
FreeDIB(DIBINIT * dib)332 void FreeDIB(DIBINIT *dib)
333 {
334 /* Free the bitmap stuff */
335 if (dib->hPalette) DeleteObject(dib->hPalette);
336 if (dib->hBitmap) DeleteObject(dib->hBitmap);
337 if (dib->hDIB) GlobalFree(dib->hDIB);
338
339 dib->hPalette = NULL;
340 dib->hBitmap = NULL;
341 dib->hDIB = NULL;
342 dib->ImageWidth = 0;
343 dib->ImageHeight = 0;
344 }
345
346 #endif /* USE_WIN || WINDOWS || WIN32 */
347