| 1 | #define INCL_DOS
 | 
|---|
| 2 | #define INCL_WIN
 | 
|---|
| 3 | #define INCL_GPI
 | 
|---|
| 4 | 
 | 
|---|
| 5 | #include <os2.h>
 | 
|---|
| 6 | #include <stdlib.h>
 | 
|---|
| 7 | #include <stdio.h>
 | 
|---|
| 8 | #include <string.h>
 | 
|---|
| 9 | #include <share.h>
 | 
|---|
| 10 | #include "fm3dll.h"
 | 
|---|
| 11 | 
 | 
|---|
| 12 | #pragma alloc_text(LOADBITMAP,LoadBitmapFromFile,LoadBitmapFromFileNum)
 | 
|---|
| 13 | 
 | 
|---|
| 14 | 
 | 
|---|
| 15 | HBITMAP LoadBitmapFromFileNum (USHORT id) {
 | 
|---|
| 16 | 
 | 
|---|
| 17 |   char s[CCHMAXPATH];
 | 
|---|
| 18 | 
 | 
|---|
| 19 |   save_dir2(s);
 | 
|---|
| 20 |   sprintf(s + strlen(s),"\\%u.BMP",id);
 | 
|---|
| 21 |   return LoadBitmapFromFile(s);
 | 
|---|
| 22 | }
 | 
|---|
| 23 | 
 | 
|---|
| 24 | 
 | 
|---|
| 25 | HBITMAP LoadBitmapFromFile (CHAR *pszFileName) {
 | 
|---|
| 26 | 
 | 
|---|
| 27 |   HBITMAP                 hBmp = (HBITMAP)0;
 | 
|---|
| 28 |   FILE                   *File;
 | 
|---|
| 29 |   ULONG                   rc;
 | 
|---|
| 30 |   USHORT                  usType = 0;           // #@!!! compiler warnings
 | 
|---|
| 31 |   PBITMAPARRAYFILEHEADER2 pbafh2 = NULL;        // (MAM) chng init values to NULL instead of ptr to 0
 | 
|---|
| 32 |   PBITMAPFILEHEADER2      pbfh2  = NULL;                       
 | 
|---|
| 33 |   PBITMAPINFOHEADER2      pbih2  = NULL;                       
 | 
|---|
| 34 |   PBITMAPINFO2            pbmi2  = NULL;                       
 | 
|---|
| 35 |   PBITMAPARRAYFILEHEADER  pbafh  = NULL;                       
 | 
|---|
| 36 |   PBITMAPFILEHEADER       pbfh   = NULL;                       
 | 
|---|
| 37 |   PBITMAPINFOHEADER       pbih   = NULL;                       
 | 
|---|
| 38 |   BOOL                    f2;        // format 1.x or 2.x
 | 
|---|
| 39 |   ULONG                   ulOffset;
 | 
|---|
| 40 |   PBYTE                   pData  = NULL;
 | 
|---|
| 41 |   ULONG                   ulDataSize;
 | 
|---|
| 42 |   SIZEL                   sizel;
 | 
|---|
| 43 |   HPS                     hPS = WinGetPS(HWND_DESKTOP);
 | 
|---|
| 44 | 
 | 
|---|
| 45 |   //--- open the file
 | 
|---|
| 46 |   File = _fsopen(pszFileName,"r",SH_DENYWR);
 | 
|---|
| 47 |   if(!File)
 | 
|---|
| 48 |     goto ExitLoadBMP;
 | 
|---|
| 49 | 
 | 
|---|
| 50 |   /* Read image type, and reset the stream...................................*/
 | 
|---|
| 51 |   /* The image type is a USHORT, so we only read that........................*/
 | 
|---|
| 52 |   rc = fread(&usType,1,sizeof(usType),File);
 | 
|---|
| 53 |   if(rc != sizeof(usType))
 | 
|---|
| 54 |     goto ExitLoadBMP;
 | 
|---|
| 55 | 
 | 
|---|
| 56 |   /* Next read the bitmap info header........................................*/
 | 
|---|
| 57 |   // we allocate enough to hold a complete bitmap array file header
 | 
|---|
| 58 |   pbafh2 = (PBITMAPARRAYFILEHEADER2)malloc(sizeof(*pbafh2) +
 | 
|---|
| 59 |                                              256 * sizeof(RGB2));
 | 
|---|
| 60 |   if(!pbafh2)
 | 
|---|
| 61 |     goto ExitLoadBMP;
 | 
|---|
| 62 |   /* Next we assign pointers to the file header and bitmap info header...*/
 | 
|---|
| 63 |   /* Both the 1.x and 2.x structures are assigned just in case...........*/
 | 
|---|
| 64 |   pbfh2 = &pbafh2->bfh2;
 | 
|---|
| 65 |   pbih2 = &pbfh2->bmp2;
 | 
|---|
| 66 |   pbmi2 = (PBITMAPINFO2)pbih2;
 | 
|---|
| 67 |   pbafh = (PBITMAPARRAYFILEHEADER)pbafh2;
 | 
|---|
| 68 |   pbfh  = &pbafh->bfh;
 | 
|---|
| 69 |   pbih  = &pbfh->bmp;
 | 
|---|
| 70 |   switch (usType) {
 | 
|---|
| 71 |     case BFT_BMAP:
 | 
|---|
| 72 |     case BFT_ICON:
 | 
|---|
| 73 |     case BFT_POINTER:
 | 
|---|
| 74 |     case BFT_COLORICON:
 | 
|---|
| 75 |     case BFT_COLORPOINTER:
 | 
|---|
| 76 |       {
 | 
|---|
| 77 |         /* Now we assume the image is a 2.0 image and so we read a bitmap-file-*/
 | 
|---|
| 78 |         /* Now we reset the stream, next we'll read the bitmap info header. To do .*/
 | 
|---|
| 79 |         /* this we need to reset the stream to 0...................................*/
 | 
|---|
| 80 |         fseek(File,0,SEEK_SET);
 | 
|---|
| 81 |         /*-header-2 structure..................................................*/
 | 
|---|
| 82 |         rc = fread(pbfh2,1,sizeof(*pbfh2),File);
 | 
|---|
| 83 |         if(rc != sizeof(*pbfh2))
 | 
|---|
| 84 |           goto ExitLoadBMP;
 | 
|---|
| 85 | 
 | 
|---|
| 86 |         f2 = pbih2->cbFix > sizeof(*pbih); // 1.x or 2.x bitmap
 | 
|---|
| 87 |         /* We will need to read the color table. Thus we position the stream...*/
 | 
|---|
| 88 |         /* so that the next read will read IT. This, of course, depends on the.*/
 | 
|---|
| 89 |         /* type of the bitmap (old vs new), note that in the NEW case, we can..*/
 | 
|---|
| 90 |         /* not be certain of the size of the bitmap header.....................*/
 | 
|---|
| 91 |         ulOffset = (f2) ? sizeof(*pbfh2) + pbih->cbFix - sizeof(*pbih2) :
 | 
|---|
| 92 |                           sizeof(*pbfh);
 | 
|---|
| 93 |       }
 | 
|---|
| 94 |       break;
 | 
|---|
| 95 | 
 | 
|---|
| 96 |     case BFT_BITMAPARRAY:
 | 
|---|
| 97 |       {
 | 
|---|
| 98 |         /* Now we are dealing with a bitmap array. This is a collection of ....*/
 | 
|---|
| 99 |         /* bitmap files and each has its own file header.......................*/
 | 
|---|
| 100 | 
 | 
|---|
| 101 |         BOOL   bBest = FALSE;
 | 
|---|
| 102 |         ULONG  ulCurOffset, ulOffsetTemp = 0;
 | 
|---|
| 103 |         LONG   lScreenWidth;
 | 
|---|
| 104 |         LONG   lScreenHeight;
 | 
|---|
| 105 |         LONG   lClrsDev, lClrsTemp = 0;
 | 
|---|
| 106 |         LONG   lClrs;
 | 
|---|
| 107 |         ULONG  ulSizeDiff, ulSizeDiffTemp = 0xffffffff;
 | 
|---|
| 108 |         HDC    hdc;
 | 
|---|
| 109 | 
 | 
|---|
| 110 |         // -- We will browse through the array and chose the bitmap best suited
 | 
|---|
| 111 |         // -- for the current display size and color capacities.
 | 
|---|
| 112 |         hdc = GpiQueryDevice( hPS );
 | 
|---|
| 113 |         DevQueryCaps(hdc,CAPS_COLORS,1,&lClrsDev);
 | 
|---|
| 114 |         DevQueryCaps(hdc,CAPS_WIDTH, 1,&lScreenWidth);
 | 
|---|
| 115 |         DevQueryCaps(hdc,CAPS_HEIGHT,1,&lScreenHeight);
 | 
|---|
| 116 |         pbafh2->offNext = 0;
 | 
|---|
| 117 |         do {
 | 
|---|
| 118 |            ulCurOffset = pbafh2->offNext;
 | 
|---|
| 119 |            rc = fseek(File,pbafh2->offNext,SEEK_SET);
 | 
|---|
| 120 |            if(rc)
 | 
|---|
| 121 |              goto ExitLoadBMP;
 | 
|---|
| 122 |            rc = fread(pbafh2,1,sizeof(*pbafh2),File);
 | 
|---|
| 123 |            if(rc != sizeof(*pbafh2))
 | 
|---|
| 124 |              goto ExitLoadBMP;
 | 
|---|
| 125 |            f2 = pbih2->cbFix > sizeof(*pbih);
 | 
|---|
| 126 |            if(f2)
 | 
|---|
| 127 |              lClrs = 1 << (pbafh2->bfh2.bmp2.cBitCount *
 | 
|---|
| 128 |                            pbafh2->bfh2.bmp2.cPlanes);
 | 
|---|
| 129 |            else
 | 
|---|
| 130 |              lClrs = 1 << (pbafh->bfh.bmp.cBitCount *
 | 
|---|
| 131 |                            pbafh->bfh.bmp.cPlanes);
 | 
|---|
| 132 |            if((pbafh2->cxDisplay == 0) && (pbafh2->cyDisplay == 0)) {
 | 
|---|
| 133 |              // This is a device independant bitmap
 | 
|---|
| 134 |              // Process it as a VGA
 | 
|---|
| 135 |              pbafh2->cxDisplay = 640;
 | 
|---|
| 136 |              pbafh2->cyDisplay = 480;
 | 
|---|
| 137 |            } // endif
 | 
|---|
| 138 |            ulSizeDiff = abs(pbafh2->cxDisplay - lScreenWidth) +
 | 
|---|
| 139 |                             abs(pbafh2->cyDisplay - lScreenHeight);
 | 
|---|
| 140 |            if((lClrsDev == lClrs) &&
 | 
|---|
| 141 |               (ulSizeDiff == 0)) {
 | 
|---|
| 142 |              // We found the perfect match
 | 
|---|
| 143 |              bBest = TRUE;
 | 
|---|
| 144 |              ulOffsetTemp = ulCurOffset;
 | 
|---|
| 145 |            }
 | 
|---|
| 146 |            else {
 | 
|---|
| 147 |              if((ulOffsetTemp == 0) ||           // First time thru
 | 
|---|
| 148 |                 (ulSizeDiff < ulSizeDiffTemp) || // Better fit than any previous
 | 
|---|
| 149 |                   ((lClrs > lClrsTemp) && (lClrs < lClrsDev)) || // More colors than prev & less than device
 | 
|---|
| 150 |                   ((lClrs < lClrsTemp) && (lClrs > lClrsDev))) {
 | 
|---|
| 151 |                ulOffsetTemp = ulCurOffset;       // Make this our current pick
 | 
|---|
| 152 |                lClrsTemp   = lClrs;
 | 
|---|
| 153 |                ulSizeDiffTemp = ulSizeDiff;
 | 
|---|
| 154 |              } // endif
 | 
|---|
| 155 |            } // endif
 | 
|---|
| 156 |         } while((pbafh2->offNext != 0) && !bBest); // enddo
 | 
|---|
| 157 | 
 | 
|---|
| 158 |         // Now retrieve the best bitmap
 | 
|---|
| 159 |         rc = fseek(File,ulOffsetTemp,SEEK_SET);
 | 
|---|
| 160 |         if(rc)
 | 
|---|
| 161 |           goto ExitLoadBMP;
 | 
|---|
| 162 |         rc = fread(pbafh2,1,sizeof(*pbafh2),File);
 | 
|---|
| 163 |         if(rc != sizeof(*pbafh2))
 | 
|---|
| 164 |           goto ExitLoadBMP;
 | 
|---|
| 165 | 
 | 
|---|
| 166 |         f2 = pbih2->cbFix > sizeof(*pbih);
 | 
|---|
| 167 |         /* as before, we calculate where to position the stream in order to ...*/
 | 
|---|
| 168 |         /* read the color table information....................................*/
 | 
|---|
| 169 |         ulOffset = ulOffsetTemp;
 | 
|---|
| 170 |         ulOffset += (f2) ? sizeof(*pbafh2) + pbih2->cbFix - sizeof(*pbih2):
 | 
|---|
| 171 |                            sizeof(*pbafh);
 | 
|---|
| 172 |       }
 | 
|---|
| 173 |       break;
 | 
|---|
| 174 | 
 | 
|---|
| 175 |     default:
 | 
|---|
| 176 |        goto ExitLoadBMP;
 | 
|---|
| 177 |   } /* endswitch */
 | 
|---|
| 178 | 
 | 
|---|
| 179 |   /* We now position the stream on the color table information...............*/
 | 
|---|
| 180 |   rc = fseek(File,ulOffset,SEEK_SET);
 | 
|---|
| 181 |   if(rc)
 | 
|---|
| 182 |     goto ExitLoadBMP;
 | 
|---|
| 183 | 
 | 
|---|
| 184 |   /* Read the color table....................................................*/
 | 
|---|
| 185 |   if(f2) {
 | 
|---|
| 186 |     /* For a 2.0 bitmap, all we need to do is read the color table...........*/
 | 
|---|
| 187 |     /* The bitmap info structure is just the header + color table............*/
 | 
|---|
| 188 |     // If we have 24 bits per pel, there is usually no color table, unless
 | 
|---|
| 189 |     // pbih2->cclrUsed or pbih2->cclrImportant are non zero, we should
 | 
|---|
| 190 |     // test that !
 | 
|---|
| 191 |     if(pbih2->cBitCount < 24) {
 | 
|---|
| 192 | 
 | 
|---|
| 193 |       ULONG ul = (1 << pbih2->cBitCount) * sizeof(RGB2);
 | 
|---|
| 194 | 
 | 
|---|
| 195 |       rc = fread(&pbmi2->argbColor[0],1,ul,File);
 | 
|---|
| 196 |       if(rc != ul)
 | 
|---|
| 197 |         goto ExitLoadBMP;
 | 
|---|
| 198 |     } // endif
 | 
|---|
| 199 |     /* remember the bitmap info we mentioned just above?.....................*/
 | 
|---|
| 200 |     pbmi2 = (PBITMAPINFO2)pbih2;
 | 
|---|
| 201 |   }
 | 
|---|
| 202 |   else {
 | 
|---|
| 203 |     /* This is an old format bitmap. Since the common format is the 2.0......*/
 | 
|---|
| 204 |     /* We have to convert all the RGB entries to RGB2........................*/
 | 
|---|
| 205 | 
 | 
|---|
| 206 |     ULONG ul, cColors;
 | 
|---|
| 207 |     RGB   rgb;
 | 
|---|
| 208 | 
 | 
|---|
| 209 |     if(pbih->cBitCount <24)
 | 
|---|
| 210 |       cColors = 1 << pbih->cBitCount;
 | 
|---|
| 211 |     else
 | 
|---|
| 212 |     // If there are 24 bits per pel, the 24 bits are assumed to be a RGB value
 | 
|---|
| 213 |       cColors = 0;
 | 
|---|
| 214 |     /* Loop over the original table and create the new table, the extra byte.*/
 | 
|---|
| 215 |     /* has to be 0...........................................................*/
 | 
|---|
| 216 |     for(ul = 0; ul < cColors; ul++) {
 | 
|---|
| 217 |       fread(&rgb,1,sizeof(rgb),File);
 | 
|---|
| 218 |       pbmi2->argbColor[ul].bRed      = rgb.bRed;
 | 
|---|
| 219 |       pbmi2->argbColor[ul].bGreen    = rgb.bGreen;
 | 
|---|
| 220 |       pbmi2->argbColor[ul].bBlue     = rgb.bBlue;
 | 
|---|
| 221 |       pbmi2->argbColor[ul].fcOptions = 0;
 | 
|---|
| 222 |     } /* endfor */
 | 
|---|
| 223 | 
 | 
|---|
| 224 |     // we have to convert the old to the new version header
 | 
|---|
| 225 |     pbmi2->cbFix = sizeof(*pbih2);
 | 
|---|
| 226 |     pbmi2->cBitCount = pbih->cBitCount;
 | 
|---|
| 227 |     pbmi2->cPlanes = pbih->cPlanes;
 | 
|---|
| 228 |     pbmi2->cy = pbih->cy;
 | 
|---|
| 229 |     pbmi2->cx = pbih->cx;
 | 
|---|
| 230 |     // set rest to zero
 | 
|---|
| 231 |     memset((PCHAR)pbmi2 + 16,0,sizeof(*pbih2) - 16);
 | 
|---|
| 232 |   } /* endif */
 | 
|---|
| 233 | 
 | 
|---|
| 234 |   /* We have the 2.0 bitmap info structure set...............................*/
 | 
|---|
| 235 |   /* move to the stream to the start of the bitmap data......................*/
 | 
|---|
| 236 |   rc = fseek(File,pbfh2->offBits,SEEK_SET);
 | 
|---|
| 237 |   if(rc)
 | 
|---|
| 238 |     goto ExitLoadBMP;
 | 
|---|
| 239 | 
 | 
|---|
| 240 |   /* Read the bitmap data, the read size is derived using the magic formula..*/
 | 
|---|
| 241 |   /* The bitmap scan line is aligned on a doubleword boundary................*/
 | 
|---|
| 242 |   /* The size of the scan line is the number of pels times the bpp...........*/
 | 
|---|
| 243 |   /* After aligning it, we divide by 4 to get the number of bytes, and.......*/
 | 
|---|
| 244 |   /* multiply by the number of scan lines and the number of pel planes.......*/
 | 
|---|
| 245 |   if(pbmi2->ulCompression)
 | 
|---|
| 246 |     ulDataSize = pbmi2->cbImage;
 | 
|---|
| 247 |   else
 | 
|---|
| 248 |     ulDataSize = (((pbmi2->cBitCount * pbmi2->cx) + 31) / 32) * 4 *
 | 
|---|
| 249 |                   pbmi2->cy * pbmi2->cPlanes;
 | 
|---|
| 250 |   pData = (PBYTE)malloc(ulDataSize);
 | 
|---|
| 251 |   if(!pData)
 | 
|---|
| 252 |     goto ExitLoadBMP;
 | 
|---|
| 253 |   rc = fread(pData, 1, ulDataSize, File);
 | 
|---|
| 254 |   if(rc != ulDataSize)
 | 
|---|
| 255 |     goto ExitLoadBMP;
 | 
|---|
| 256 | 
 | 
|---|
| 257 |   /* Now, we create the bitmap...............................................*/
 | 
|---|
| 258 |   sizel.cx = pbmi2->cx;
 | 
|---|
| 259 |   sizel.cy = pbmi2->cy;
 | 
|---|
| 260 | 
 | 
|---|
| 261 |   hBmp = GpiCreateBitmap(hPS,(PBITMAPINFOHEADER2)pbmi2,CBM_INIT,
 | 
|---|
| 262 |                          pData,pbmi2);
 | 
|---|
| 263 | 
 | 
|---|
| 264 | ExitLoadBMP:
 | 
|---|
| 265 |   if(pData)
 | 
|---|
| 266 |     free(pData);
 | 
|---|
| 267 |   if(pbafh2)
 | 
|---|
| 268 |     free(pbafh2);
 | 
|---|
| 269 |   fclose(File);
 | 
|---|
| 270 |   WinReleasePS(hPS);
 | 
|---|
| 271 |   return(hBmp);
 | 
|---|
| 272 | }
 | 
|---|
| 273 | 
 | 
|---|