root/trunk/src/win/readdib.c

Revision 918, 8.4 kB (checked in by takkaria, 6 months ago)

Use consistent newlines everywhere, and also set the svn:eol-style property to native on all text files.

  • Property svn:eol-style set to native
Line 
1 /* File: readdib.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.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  */
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  */
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  */
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  */
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         /* offset to the bits from start of DIB header */
290         offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);
291
292         if (bf.bfOffBits != 0L)
293         {
294                 _llseek(fh,bf.bfOffBits,SEEK_SET);
295         }
296
297         /* Use local version of '_lread()' above */
298         if (lpbi->biSizeImage == lread(fh, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
299         {
300                 GlobalUnlock(pInfo->hDIB);
301
302                 hDC = GetDC(hWnd);
303                 if (!MakeBitmapAndPalette(hDC, pInfo->hDIB, &(pInfo->hPalette),
304                                           &(pInfo->hBitmap)))
305                 {
306                         ReleaseDC(hWnd,hDC);
307                         goto ErrExit2;
308                 }
309                 else
310                 {
311                         ReleaseDC(hWnd,hDC);
312                         result = TRUE;
313                 }
314         }
315         else
316         {
317 ErrExit:
318                 GlobalUnlock(pInfo->hDIB);
319 ErrExit2:
320                 GlobalFree(pInfo->hDIB);
321         }
322
323         _lclose(fh);
324         return (result);
325 }
326
327
328 /* Free a DIB */
329 void FreeDIB(DIBINIT *dib)
330 {
331         /* Free the bitmap stuff */
332         if (dib->hPalette) DeleteObject(dib->hPalette);
333         if (dib->hBitmap) DeleteObject(dib->hBitmap);
334         if (dib->hDIB) GlobalFree(dib->hDIB);
335
336         dib->hPalette = NULL;
337         dib->hBitmap = NULL;
338         dib->hDIB = NULL;
339 }
340
341 #endif /* USE_WIN || WINDOWS || WIN32 */
Note: See TracBrowser for help on using the browser.