OSDN Git Service

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