| 1 | 
 | 
|---|
| 2 | /***********************************************************************
 | 
|---|
| 3 | 
 | 
|---|
| 4 |   $Id: loadbmp.c 1438 2009-06-28 20:47:00Z gyoung $
 | 
|---|
| 5 | 
 | 
|---|
| 6 |   Load bitmaps
 | 
|---|
| 7 | 
 | 
|---|
| 8 |   Copyright (c) 1993-98 M. Kimes
 | 
|---|
| 9 |   Copyright (c) 2006, 2008 Steven H. Levine
 | 
|---|
| 10 | 
 | 
|---|
| 11 |   22 Jul 06 SHL Check more run time errors
 | 
|---|
| 12 |   16 Jan 07 SHL Check more run time errors
 | 
|---|
| 13 |   16 Jan 07 SHL Sync variable names for sanity
 | 
|---|
| 14 |   16 Jan 07 SHL Open bitmap file binary - no wonder the code does not work
 | 
|---|
| 15 |   16 Jan 07 SHL Beautify with indent -i2
 | 
|---|
| 16 |   18 Apr 08 SHL LoadBitmapFromFile ensure pf initialized if no hPS
 | 
|---|
| 17 |   19 Jul 08 GKY Replace save_dir2(dir) with pFM2SaveDirectory
 | 
|---|
| 18 | 
 | 
|---|
| 19 | ***********************************************************************/
 | 
|---|
| 20 | 
 | 
|---|
| 21 | #include <stdlib.h>
 | 
|---|
| 22 | #include <stdio.h>
 | 
|---|
| 23 | #include <string.h>
 | 
|---|
| 24 | #include <share.h>
 | 
|---|
| 25 | 
 | 
|---|
| 26 | #define INCL_DOS
 | 
|---|
| 27 | #define INCL_WIN
 | 
|---|
| 28 | #define INCL_GPI
 | 
|---|
| 29 | #define INCL_LONGLONG                   // dircnrs.h
 | 
|---|
| 30 | 
 | 
|---|
| 31 | #include "fm3dll.h"
 | 
|---|
| 32 | #include "init.h"                       // Data declaration(s)
 | 
|---|
| 33 | #include "errutil.h"                    // Dos_Error...
 | 
|---|
| 34 | #include "loadbmp.h"
 | 
|---|
| 35 | #include "wrappers.h"                   // xfree
 | 
|---|
| 36 | #include "dirs.h"                       // save_dir2
 | 
|---|
| 37 | 
 | 
|---|
| 38 | static PSZ pszSrcFile = __FILE__;
 | 
|---|
| 39 | 
 | 
|---|
| 40 | static HBITMAP LoadBitmapFromFile(CHAR * pszFileName);
 | 
|---|
| 41 | 
 | 
|---|
| 42 | HBITMAP LoadBitmapFromFileNum(USHORT id)
 | 
|---|
| 43 | {
 | 
|---|
| 44 |   char s[CCHMAXPATH];
 | 
|---|
| 45 | 
 | 
|---|
| 46 |   strcpy(s, pFM2SaveDirectory);
 | 
|---|
| 47 |   sprintf(s + strlen(s), "%s%u.BMP", PCSZ_BACKSLASH, id);
 | 
|---|
| 48 |   return LoadBitmapFromFile(s);
 | 
|---|
| 49 | }
 | 
|---|
| 50 | 
 | 
|---|
| 51 | HBITMAP LoadBitmapFromFile(CHAR * pszFileName)
 | 
|---|
| 52 | {
 | 
|---|
| 53 |   HBITMAP hBmp = (HBITMAP) 0;
 | 
|---|
| 54 |   FILE *pf;
 | 
|---|
| 55 |   ULONG rc;
 | 
|---|
| 56 |   USHORT usType;
 | 
|---|
| 57 |   PBITMAPARRAYFILEHEADER2 pbmafh2 = NULL;       // Must init for xfree
 | 
|---|
| 58 |   PBITMAPFILEHEADER2 pbmfh2;    // No color table
 | 
|---|
| 59 |   PBITMAPINFOHEADER2 pbmih2;    // No color table
 | 
|---|
| 60 |   PBITMAPINFO2 pbmi2;           // Includes color table
 | 
|---|
| 61 |   BOOL is2x;                    // Format 1.x or 2.x
 | 
|---|
| 62 |   ULONG ulColors;
 | 
|---|
| 63 |   ULONG ulRGBOffset;
 | 
|---|
| 64 |   PBYTE pData = NULL;           // Must init for xfree
 | 
|---|
| 65 |   ULONG ulDataSize;
 | 
|---|
| 66 |   SIZEL sizel;
 | 
|---|
| 67 |   HPS hPS = WinGetPS(HWND_DESKTOP);
 | 
|---|
| 68 | 
 | 
|---|
| 69 |   if (!hPS) {
 | 
|---|
| 70 |     Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__, "WinGetPS");
 | 
|---|
| 71 |     pf = NULL;
 | 
|---|
| 72 |     goto ExitLoadBMP;
 | 
|---|
| 73 |   }
 | 
|---|
| 74 | 
 | 
|---|
| 75 |   pf = _fsopen(pszFileName, "rb", SH_DENYWR);
 | 
|---|
| 76 |   if (!pf) {
 | 
|---|
| 77 |     // OK for file to not exist - enable following for debug as needed
 | 
|---|
| 78 |     // Runtime_Error(pszSrcFile, __LINE__, "_fsopen %s", pszFileName);
 | 
|---|
| 79 |     goto ExitLoadBMP;
 | 
|---|
| 80 |   }
 | 
|---|
| 81 | 
 | 
|---|
| 82 |   // Read image type
 | 
|---|
| 83 |   // fixme to just read type2 header - this is silly and wastes time
 | 
|---|
| 84 |   rc = fread(&usType, 1, sizeof(usType), pf);
 | 
|---|
| 85 |   if (rc != sizeof(usType)) {
 | 
|---|
| 86 |     Runtime_Error(pszSrcFile, __LINE__, "fread");
 | 
|---|
| 87 |     goto ExitLoadBMP;
 | 
|---|
| 88 |   }
 | 
|---|
| 89 | 
 | 
|---|
| 90 |   /* Read bitmap info header
 | 
|---|
| 91 |      Allocate enough to hold a complete 2.x bitmap array file header
 | 
|---|
| 92 |      fixme to support > 256 colors?
 | 
|---|
| 93 |    */
 | 
|---|
| 94 |   pbmafh2 =
 | 
|---|
| 95 |     xmalloc(sizeof(*pbmafh2) + 256 * sizeof(RGB2), pszSrcFile, __LINE__);
 | 
|---|
| 96 |   if (!pbmafh2)
 | 
|---|
| 97 |     goto ExitLoadBMP;
 | 
|---|
| 98 |   /* Assign pointers to the file header and bitmap info header etc.
 | 
|---|
| 99 |      Both the 1.x and 2.x structures are assigned to simplify code
 | 
|---|
| 100 |      fixme to clean this up - aliased pointers are evil
 | 
|---|
| 101 |    */
 | 
|---|
| 102 |   pbmfh2 = &pbmafh2->bfh2;
 | 
|---|
| 103 |   pbmih2 = &pbmfh2->bmp2;
 | 
|---|
| 104 |   pbmi2 = (PBITMAPINFO2) pbmih2;
 | 
|---|
| 105 | 
 | 
|---|
| 106 |   switch (usType) {
 | 
|---|
| 107 |   case BFT_BMAP:
 | 
|---|
| 108 |   case BFT_ICON:
 | 
|---|
| 109 |   case BFT_POINTER:
 | 
|---|
| 110 |   case BFT_COLORICON:
 | 
|---|
| 111 |   case BFT_COLORPOINTER:
 | 
|---|
| 112 |     {
 | 
|---|
| 113 |       /* Assume image is a 2.0 image and read as a 2.x header
 | 
|---|
| 114 |          OK for 1.x file - read will not fail unless file is corrupted
 | 
|---|
| 115 |        */
 | 
|---|
| 116 |       rc = fseek(pf, 0, SEEK_SET);
 | 
|---|
| 117 |       if (rc) {
 | 
|---|
| 118 |         Runtime_Error(pszSrcFile, __LINE__, "fseek 0");
 | 
|---|
| 119 |         goto ExitLoadBMP;
 | 
|---|
| 120 |       }
 | 
|---|
| 121 | 
 | 
|---|
| 122 |       rc = fread(pbmfh2, 1, sizeof(*pbmfh2), pf);
 | 
|---|
| 123 |       if (rc != sizeof(*pbmfh2)) {
 | 
|---|
| 124 |         Runtime_Error(pszSrcFile, __LINE__, "fread");
 | 
|---|
| 125 |         goto ExitLoadBMP;
 | 
|---|
| 126 |       }
 | 
|---|
| 127 | 
 | 
|---|
| 128 |       is2x = pbmih2->cbFix > sizeof(BITMAPINFOHEADER);  // 1.x or 2.x bitmap
 | 
|---|
| 129 |       /* We will read the color table later
 | 
|---|
| 130 |          Color table follows header but
 | 
|---|
| 131 |          location depends on the type of the bitmap (old vs new)
 | 
|---|
| 132 |          1.x header is fixed size
 | 
|---|
| 133 |          2.x header is variable sized, so offset must be calculated
 | 
|---|
| 134 |          cbFix contains actual size of BITMAPINFOHEADER2 in file
 | 
|---|
| 135 |        */
 | 
|---|
| 136 |       ulRGBOffset = is2x ? sizeof(*pbmfh2) - sizeof(*pbmih2) + pbmih2->cbFix :
 | 
|---|
| 137 |         sizeof(BITMAPFILEHEADER);
 | 
|---|
| 138 |     }
 | 
|---|
| 139 |     break;
 | 
|---|
| 140 | 
 | 
|---|
| 141 |   case BFT_BITMAPARRAY:
 | 
|---|
| 142 |     {
 | 
|---|
| 143 |       /* Now we are dealing with a bitmap array which is a collection of bitmaps
 | 
|---|
| 144 |          Each bitmap has its own file header
 | 
|---|
| 145 |        */
 | 
|---|
| 146 | 
 | 
|---|
| 147 |       ULONG ulCurOffset;
 | 
|---|
| 148 |       ULONG clScreenWidth;
 | 
|---|
| 149 |       ULONG clScreenHeight;
 | 
|---|
| 150 |       ULONG ulDeviceColors;
 | 
|---|
| 151 |       ULONG ulSizeDiff;
 | 
|---|
| 152 |       ULONG ulOffsetPicked = 0;
 | 
|---|
| 153 |       ULONG ulColorsPicked;
 | 
|---|
| 154 |       ULONG ulSizeDiffPicked;
 | 
|---|
| 155 |       HDC hdc;
 | 
|---|
| 156 | 
 | 
|---|
| 157 |       /* Scan the array and chose the bitmap best suited
 | 
|---|
| 158 |          for the current display size and color capacities
 | 
|---|
| 159 |        */
 | 
|---|
| 160 |       hdc = GpiQueryDevice(hPS);
 | 
|---|
| 161 |       if (!hdc) {
 | 
|---|
| 162 |         Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
 | 
|---|
| 163 |                   "GpiQueryDevice");
 | 
|---|
| 164 |         goto ExitLoadBMP;
 | 
|---|
| 165 |       }
 | 
|---|
| 166 |       DevQueryCaps(hdc, CAPS_COLORS, 1, (PLONG) & ulDeviceColors);
 | 
|---|
| 167 |       DevQueryCaps(hdc, CAPS_WIDTH, 1, (PLONG) & clScreenWidth);
 | 
|---|
| 168 |       DevQueryCaps(hdc, CAPS_HEIGHT, 1, (PLONG) & clScreenHeight);
 | 
|---|
| 169 |       pbmafh2->offNext = 0;
 | 
|---|
| 170 |       do {
 | 
|---|
| 171 |         ulCurOffset = pbmafh2->offNext;
 | 
|---|
| 172 |         rc = fseek(pf, pbmafh2->offNext, SEEK_SET);
 | 
|---|
| 173 |         if (rc) {
 | 
|---|
| 174 |           Runtime_Error(pszSrcFile, __LINE__, "fseek %ld", pbmafh2->offNext);
 | 
|---|
| 175 |           goto ExitLoadBMP;
 | 
|---|
| 176 |         }
 | 
|---|
| 177 |         rc = fread(pbmafh2, 1, sizeof(*pbmafh2), pf);
 | 
|---|
| 178 |         if (rc != sizeof(*pbmafh2)) {
 | 
|---|
| 179 |           Runtime_Error(pszSrcFile, __LINE__, "fread");
 | 
|---|
| 180 |           goto ExitLoadBMP;
 | 
|---|
| 181 |         }
 | 
|---|
| 182 |         is2x = pbmih2->cbFix > sizeof(BITMAPINFOHEADER);
 | 
|---|
| 183 |         if (is2x) {
 | 
|---|
| 184 |           ulColors = 1 << (pbmafh2->bfh2.bmp2.cBitCount *
 | 
|---|
| 185 |                            pbmafh2->bfh2.bmp2.cPlanes);
 | 
|---|
| 186 |         }
 | 
|---|
| 187 |         else {
 | 
|---|
| 188 |           ulColors =
 | 
|---|
| 189 |             1 << (((PBITMAPARRAYFILEHEADER) pbmafh2)->bfh.bmp.cBitCount *
 | 
|---|
| 190 |                   ((PBITMAPARRAYFILEHEADER) pbmafh2)->bfh.bmp.cPlanes);
 | 
|---|
| 191 |         }
 | 
|---|
| 192 |         if (pbmafh2->cxDisplay == 0 && pbmafh2->cyDisplay == 0) {
 | 
|---|
| 193 |           // This is a device independant bitmap - process it as a VGA
 | 
|---|
| 194 |           pbmafh2->cxDisplay = 640;
 | 
|---|
| 195 |           pbmafh2->cyDisplay = 480;
 | 
|---|
| 196 |         }
 | 
|---|
| 197 |         ulSizeDiff = abs(pbmafh2->cxDisplay - clScreenWidth) +
 | 
|---|
| 198 |           abs(pbmafh2->cyDisplay - clScreenHeight);
 | 
|---|
| 199 |         if (ulDeviceColors == ulColors && ulSizeDiff == 0) {
 | 
|---|
| 200 |           // We found the perfect match
 | 
|---|
| 201 |           ulOffsetPicked = ulCurOffset;
 | 
|---|
| 202 |           break;                        // Stop scan
 | 
|---|
| 203 |         }
 | 
|---|
| 204 |         if (ulOffsetPicked == 0 ||      // First time thru
 | 
|---|
| 205 |             ulSizeDiff < ulSizeDiffPicked ||    // Better fit than any previous
 | 
|---|
| 206 |             (ulColors > ulColorsPicked && ulColors < ulDeviceColors) || // More colors than prev & less than device
 | 
|---|
| 207 |             (ulColors < ulColorsPicked && ulColors > ulDeviceColors)) {
 | 
|---|
| 208 |           ulOffsetPicked = ulCurOffset; // Make this our current pick
 | 
|---|
| 209 |           ulColorsPicked = ulColors;
 | 
|---|
| 210 |           ulSizeDiffPicked = ulSizeDiff;
 | 
|---|
| 211 |         }
 | 
|---|
| 212 |       } while (pbmafh2->offNext != 0);
 | 
|---|
| 213 | 
 | 
|---|
| 214 |       // Retrieve the selected bitmap
 | 
|---|
| 215 |       rc = fseek(pf, ulOffsetPicked, SEEK_SET);
 | 
|---|
| 216 |       if (rc) {
 | 
|---|
| 217 |         Runtime_Error(pszSrcFile, __LINE__, "fseek %ld", ulOffsetPicked);
 | 
|---|
| 218 |         goto ExitLoadBMP;
 | 
|---|
| 219 |       }
 | 
|---|
| 220 |       rc = fread(pbmafh2, 1, sizeof(*pbmafh2), pf);
 | 
|---|
| 221 |       if (rc != sizeof(*pbmafh2)) {
 | 
|---|
| 222 |         Runtime_Error(pszSrcFile, __LINE__, "fread");
 | 
|---|
| 223 |         goto ExitLoadBMP;
 | 
|---|
| 224 |       }
 | 
|---|
| 225 | 
 | 
|---|
| 226 |       is2x = pbmih2->cbFix > sizeof(BITMAPINFOHEADER);
 | 
|---|
| 227 |       /* As before, we calculate offset in file stream to color table
 | 
|---|
| 228 |          This code must match single bitmap logic
 | 
|---|
| 229 |        */
 | 
|---|
| 230 |       ulRGBOffset = ulOffsetPicked;
 | 
|---|
| 231 |       ulRGBOffset +=
 | 
|---|
| 232 |         is2x ? sizeof(*pbmafh2) - sizeof(*pbmih2) +
 | 
|---|
| 233 |         pbmih2->cbFix : sizeof(BITMAPARRAYFILEHEADER);
 | 
|---|
| 234 |     }
 | 
|---|
| 235 |     break;
 | 
|---|
| 236 | 
 | 
|---|
| 237 |   default:
 | 
|---|
| 238 |     Runtime_Error(pszSrcFile, __LINE__, "Bad type %u", usType);
 | 
|---|
| 239 |     goto ExitLoadBMP;
 | 
|---|
| 240 |   }                                     // endswitch
 | 
|---|
| 241 | 
 | 
|---|
| 242 |   // Position to color table
 | 
|---|
| 243 |   rc = fseek(pf, ulRGBOffset, SEEK_SET);
 | 
|---|
| 244 |   if (rc) {
 | 
|---|
| 245 |     Runtime_Error(pszSrcFile, __LINE__, "fseek %ld", ulRGBOffset);
 | 
|---|
| 246 |     goto ExitLoadBMP;
 | 
|---|
| 247 |   }
 | 
|---|
| 248 | 
 | 
|---|
| 249 |   // Read color table
 | 
|---|
| 250 |   if (is2x) {
 | 
|---|
| 251 |     /* For a 2.0 bitmap, read the color table as is
 | 
|---|
| 252 |        The bitmap info structure is header + color table
 | 
|---|
| 253 |        If we have 24 bits per pel, there is usually no color table, unless
 | 
|---|
| 254 |        pbmih2->cclrUsed or pbmih2->cclrImportant are non zero
 | 
|---|
| 255 |        fixme to test this
 | 
|---|
| 256 |      */
 | 
|---|
| 257 |     if (pbmih2->cBitCount < 24) {
 | 
|---|
| 258 |       ULONG ulRGBBytes;
 | 
|---|
| 259 | 
 | 
|---|
| 260 |       ulColors = 1L << pbmih2->cBitCount;
 | 
|---|
| 261 | 
 | 
|---|
| 262 |       if (ulColors > 256) {
 | 
|---|
| 263 |         Runtime_Error(pszSrcFile, __LINE__, "RGB exceeds 256 colors: %lu",
 | 
|---|
| 264 |                       ulColors);
 | 
|---|
| 265 |         goto ExitLoadBMP;
 | 
|---|
| 266 |       }
 | 
|---|
| 267 |       ulRGBBytes = ulColors * sizeof(RGB2);
 | 
|---|
| 268 |       rc = fread(&pbmi2->argbColor[0], 1, ulRGBBytes, pf);
 | 
|---|
| 269 |       if (rc != ulRGBBytes) {
 | 
|---|
| 270 |         Runtime_Error(pszSrcFile, __LINE__, "fread");
 | 
|---|
| 271 |         goto ExitLoadBMP;
 | 
|---|
| 272 |       }
 | 
|---|
| 273 |     }                                   // endif
 | 
|---|
| 274 |     // Get pointer to bitmap info (header and color table)
 | 
|---|
| 275 |     pbmi2 = (PBITMAPINFO2) pbmih2;
 | 
|---|
| 276 |   }
 | 
|---|
| 277 |   else {
 | 
|---|
| 278 |     /* This is a 1.x format bitmap
 | 
|---|
| 279 |        Since the current standard format is the 2.0
 | 
|---|
| 280 |        convert the header and color table to 2.x format
 | 
|---|
| 281 |      */
 | 
|---|
| 282 |     ULONG ul;
 | 
|---|
| 283 |     RGB rgb;
 | 
|---|
| 284 |     PBITMAPINFOHEADER pbmih = &((PBITMAPARRAYFILEHEADER) pbmafh2)->bfh.bmp;
 | 
|---|
| 285 | 
 | 
|---|
| 286 |     if (pbmih->cBitCount < 24) {
 | 
|---|
| 287 |       ulColors = 1 << pbmih->cBitCount;
 | 
|---|
| 288 |       if (ulColors > 256) {
 | 
|---|
| 289 |         Runtime_Error(pszSrcFile, __LINE__, "RGB exceeds 256 colors: %lu",
 | 
|---|
| 290 |                       ulColors);
 | 
|---|
| 291 |         goto ExitLoadBMP;
 | 
|---|
| 292 |       }
 | 
|---|
| 293 |       // Read in 1.x color table and reformat for 2.x
 | 
|---|
| 294 |       for (ul = 0; ul < ulColors; ul++) {
 | 
|---|
| 295 |         fread(&rgb, 1, sizeof(rgb), pf);
 | 
|---|
| 296 |         pbmi2->argbColor[ul].bRed = rgb.bRed;
 | 
|---|
| 297 |         pbmi2->argbColor[ul].bGreen = rgb.bGreen;
 | 
|---|
| 298 |         pbmi2->argbColor[ul].bBlue = rgb.bBlue;
 | 
|---|
| 299 |         pbmi2->argbColor[ul].fcOptions = 0;     // initialize 2.x extra byte to 0
 | 
|---|
| 300 |       }                                 // for
 | 
|---|
| 301 |     }
 | 
|---|
| 302 | 
 | 
|---|
| 303 |     // Convert the old style to the new header format
 | 
|---|
| 304 |     pbmi2->cbFix = sizeof(BITMAPINFOHEADER2);
 | 
|---|
| 305 |     pbmi2->cBitCount = pbmih->cBitCount;
 | 
|---|
| 306 |     pbmi2->cPlanes = pbmih->cPlanes;
 | 
|---|
| 307 |     pbmi2->cy = pbmih->cy;
 | 
|---|
| 308 |     pbmi2->cx = pbmih->cx;
 | 
|---|
| 309 |     // set rest to zero
 | 
|---|
| 310 |     memset((PCHAR) pbmi2 + 16, 0, sizeof(BITMAPINFOHEADER2) - 16);
 | 
|---|
| 311 |   }                                     // if 1.x
 | 
|---|
| 312 | 
 | 
|---|
| 313 |   /* The 2.0 bitmap info structure set up
 | 
|---|
| 314 |      Position to start of the bitmap data
 | 
|---|
| 315 |    */
 | 
|---|
| 316 |   rc = fseek(pf, pbmfh2->offBits, SEEK_SET);
 | 
|---|
| 317 |   if (rc) {
 | 
|---|
| 318 |     Runtime_Error(pszSrcFile, __LINE__, "fseek %ld", pbmfh2->offBits);
 | 
|---|
| 319 |     goto ExitLoadBMP;
 | 
|---|
| 320 |   }
 | 
|---|
| 321 | 
 | 
|---|
| 322 |   /* Read the bitmap data
 | 
|---|
| 323 |      The read size is derived using the magic formula
 | 
|---|
| 324 |      Each bitmap scan line is aligned on a doubleword boundary
 | 
|---|
| 325 |      The size of the scan line is the number of pels times the bpp
 | 
|---|
| 326 |      After aligning it, we divide by 4 to get the number of bytes, and
 | 
|---|
| 327 |      multiply by the number of scan lines and the number of pel planes
 | 
|---|
| 328 |    */
 | 
|---|
| 329 |   if (pbmi2->ulCompression)
 | 
|---|
| 330 |     ulDataSize = pbmi2->cbImage;
 | 
|---|
| 331 |   else
 | 
|---|
| 332 |     ulDataSize = (((pbmi2->cBitCount * pbmi2->cx) + 31) / 32) * 4 *
 | 
|---|
| 333 |       pbmi2->cy * pbmi2->cPlanes;
 | 
|---|
| 334 |   pData = xmalloc(ulDataSize, pszSrcFile, __LINE__);
 | 
|---|
| 335 |   if (!pData)
 | 
|---|
| 336 |     goto ExitLoadBMP;
 | 
|---|
| 337 |   rc = fread(pData, 1, ulDataSize, pf);
 | 
|---|
| 338 |   if (rc != ulDataSize) {
 | 
|---|
| 339 |     Runtime_Error(pszSrcFile, __LINE__, "fread");
 | 
|---|
| 340 |     goto ExitLoadBMP;
 | 
|---|
| 341 |   }
 | 
|---|
| 342 | 
 | 
|---|
| 343 |   // Create the GPI bitmap image
 | 
|---|
| 344 |   sizel.cx = pbmi2->cx;
 | 
|---|
| 345 |   sizel.cy = pbmi2->cy;
 | 
|---|
| 346 | 
 | 
|---|
| 347 |   hBmp = GpiCreateBitmap(hPS, (PBITMAPINFOHEADER2) pbmi2, CBM_INIT,
 | 
|---|
| 348 |                          pData, pbmi2);
 | 
|---|
| 349 |   if (!hBmp)
 | 
|---|
| 350 |     Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
 | 
|---|
| 351 |               "GpiCreateBitmap");
 | 
|---|
| 352 | 
 | 
|---|
| 353 | ExitLoadBMP:
 | 
|---|
| 354 | 
 | 
|---|
| 355 |   xfree(pData, pszSrcFile, __LINE__);
 | 
|---|
| 356 |   xfree(pbmafh2, pszSrcFile, __LINE__);
 | 
|---|
| 357 |   if (pf)
 | 
|---|
| 358 |     fclose(pf);
 | 
|---|
| 359 |   if (hPS)
 | 
|---|
| 360 |     WinReleasePS(hPS);
 | 
|---|
| 361 |   return hBmp;
 | 
|---|
| 362 | }
 | 
|---|
| 363 | 
 | 
|---|
| 364 | #pragma alloc_text(LOADBITMAP,LoadBitmapFromFile,LoadBitmapFromFileNum)
 | 
|---|