home *** CD-ROM | disk | FTP | other *** search
/ PDA Software Library / pdasoftwarelib.iso / PILOT / PC / RC2BMP / PRC2BMP.CPP next >
Encoding:
C/C++ Source or Header  |  1996-08-26  |  6.2 KB  |  257 lines

  1. // PRC2BMP
  2. //
  3. // Takes a Pilot resource database (PRC) file extracts the icon and
  4. // saves it as a .bmp file.
  5. //
  6. // Written by Scott Ludwig (scottlu@eskimo.com).
  7. // .PRC reading pulled from PRC2BIN by Darrin Massena (darrin@massena.com)
  8. // 8 Aug 96
  9.  
  10. #include <Windows.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. // My favorite lower case types
  16.  
  17. typedef unsigned char byte;            // b
  18. typedef unsigned short ushort;        // us
  19. typedef unsigned long ulong;        // ul
  20. #pragma warning(disable : 4237)        // disable bool keyword warning
  21. typedef BOOL bool;                    // f
  22.  
  23. #define SWAPPER
  24. #include "swapper.h"
  25.  
  26. typedef ulong FourCC;
  27.  
  28. const ulong kcbHeader = 0x4e;
  29. byte gabHeader[kcbHeader];
  30.  
  31. #pragma pack(2)
  32. struct ResourceMapEntry {
  33.     ulong fcType;
  34.     ushort id;
  35.     ulong ulOffset;
  36. };
  37. #pragma pack()
  38.  
  39. ResourceMapEntry garme[2000];        // should be enough
  40. byte gabResData[65536];                // should be plenty
  41.  
  42. void tAIBToBmpSave(const char *pszOutName);
  43.  
  44. /////////////////////////////////////////////////////////////////////////////
  45.  
  46. void main(int cpszArgs, char *apszArgs[])
  47. {
  48.     if (cpszArgs < 2 || strcmp(apszArgs[1], "-?") == 0) {
  49.         printf("prc2bmp 1.0 -- Extracts icon from .prc and saves as .bmp\n"
  50.                 "by Scott Ludwig (scottlu@eskimo.com)\n\n"
  51.                 "Usage: prc2bmp <PRC file or wildcard such as *.prc>\n");
  52.         exit(1);
  53.     }
  54.  
  55.     char *pszFilename = apszArgs[1];
  56.  
  57.     WIN32_FIND_DATA fd;
  58.     HANDLE h = FindFirstFile(pszFilename, &fd);
  59.     if (h == INVALID_HANDLE_VALUE) {
  60.         printf("Error: Can't open input file \"%s\"\n", pszFilename);
  61.         exit(1);
  62.     }
  63.  
  64.     // Split the path from the original
  65.  
  66.     char szDrive[_MAX_PATH];
  67.     char szDir[_MAX_PATH];
  68.     _splitpath(pszFilename, szDrive, szDir, NULL, NULL);
  69.  
  70.  
  71.     char szFullPath[_MAX_PATH];
  72.     do {
  73.         // Create full path to file
  74.  
  75.         strcpy(szFullPath, szDrive);
  76.         strcat(szFullPath, szDir);
  77.         strcat(szFullPath, fd.cFileName);
  78.  
  79.         // Open the file
  80.  
  81.            FILE *pfil = fopen(szFullPath, "rb");
  82.         if (pfil == NULL || pfil == (FILE *)-1) {
  83.             printf("Error: Can't open input file \"%s\"\n", szFullPath);
  84.             exit(1);
  85.         }
  86.  
  87.         // Read the PRC header.
  88.  
  89.         if (fread(gabHeader, sizeof(gabHeader), 1, pfil) != 1) {
  90.             printf("Error: Can't read %s's PRC header\n", szFullPath);
  91.             exit(1);
  92.         }
  93.  
  94.         //
  95.         // Loop through all the resources, suck 'em in and spit 'em out.
  96.         //
  97.  
  98.         ulong cres = ReverseLong(*(ulong *)(gabHeader + kcbHeader - 4));
  99.  
  100.         // Read the resource map.
  101.  
  102.         ResourceMapEntry *prme = garme;
  103.         for (ulong i = 0; i < cres; i++, prme++) {
  104.             
  105.             if (fread(prme, sizeof(ResourceMapEntry), 1, pfil) != 1) {
  106.                 printf("Error: Can't read the resource map\n");
  107.                 exit(1);
  108.             }
  109.             prme->id = SwapBytes(prme->id);
  110.             prme->ulOffset = ReverseLong(prme->ulOffset);
  111.         }
  112.  
  113.  
  114.         char szOutName[_MAX_PATH];
  115.         _splitpath(szFullPath, NULL, NULL, szOutName, NULL);
  116.         strcat(szOutName, ".bmp");
  117.  
  118.         // Read each resource and write it out as a new file.
  119.  
  120.         char szType[5];
  121.         szType[4] = 0;
  122.         prme = garme;
  123.         for (i = 0; i < cres; i++, prme++) {
  124.             *(ulong *)szType = prme->fcType;
  125.  
  126.             ulong cbres;
  127.             if (i + 1 < cres)
  128.                 cbres = garme[i + 1].ulOffset - prme->ulOffset;
  129.             else
  130.                 cbres = 65536;
  131.             
  132.             fseek(pfil, prme->ulOffset, SEEK_SET);
  133.             cbres = fread(gabResData, 1, cbres, pfil);
  134.             if (cbres == 0) {
  135.                 printf("Error: Can't read the resource %s\n", szOutName);
  136.                 exit(1);
  137.             }
  138.  
  139.             // If not the icon, continue    
  140.  
  141.             if (strcmp(szType, "tAIB") != 0)
  142.                 continue;
  143.  
  144.             // Convert pilot icon bits into windows bitmap
  145.  
  146.             tAIBToBmpSave(szOutName);
  147.             printf("Bitmap %s written.\n", szOutName);
  148.             break;
  149.         }
  150.  
  151.         fclose(pfil);
  152.  
  153.     } while (FindNextFile(h, &fd));
  154.  
  155.     FindClose(h);
  156.     printf("Done.\n");
  157. }
  158.  
  159. // Pilot bitmap format (also format of icon)
  160.  
  161. typedef struct _Bitmap { // bm
  162.         ushort cx;
  163.         ushort cy;
  164.         ushort cbRow;
  165.         ushort ff;
  166.         ushort ausUnk[4];
  167.         byte abBits[1]; // word aligned bits
  168. } Bitmap;
  169.  
  170. // Test bit in a 1bpp bitmap
  171.  
  172. BOOL TestBit(int cx, int cy, byte *pb, int x, int y, int cBitsAlign)
  173. {
  174.     int cbRow = (cx + (cBitsAlign - 1)) & ~(cBitsAlign - 1);
  175.     pb += (cbRow >> 3) * y + (x >> 3);
  176.     return (*pb & (1 << (7 - (x & 7))));
  177. }
  178.  
  179. // Set bit in a 1bpp bitmap
  180.  
  181. void SetBit(int cx, int cy, byte *pb, int x, int y, int cBitsAlign)
  182. {
  183.     int cbRow = (cx + (cBitsAlign - 1)) & ~(cBitsAlign - 1);
  184.     pb += (cbRow >> 3) * y + (x >> 3);
  185.     *pb |= (1 << (7 - (x & 7)));
  186. }
  187.  
  188. void tAIBToBmpSave(const char *pszOutName)
  189. {
  190.     // Only first 32 cx, 22 cy pixels shown in app dialog
  191. #define kcxIcon 32
  192. #define kcyIcon 22
  193. #define kcbBmpBits (kcxIcon / 8 * kcyIcon)
  194.  
  195.     BITMAPFILEHEADER bfh;
  196.     memset(&bfh, 0, sizeof(bfh));
  197.     bfh.bfType = 'B' | ((unsigned short)'M' << 8);
  198.     bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
  199.             2 * sizeof(RGBQUAD) + kcbBmpBits;
  200.     bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 
  201.             2 * sizeof(RGBQUAD);
  202.  
  203.     BITMAPINFO bmi;
  204.     memset(&bmi, 0, sizeof(bmi));
  205.     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
  206.     bmi.bmiHeader.biWidth = kcxIcon;
  207.     bmi.bmiHeader.biHeight = kcyIcon;
  208.     bmi.bmiHeader.biPlanes = 1;
  209.     bmi.bmiHeader.biBitCount = 1;
  210.     bmi.bmiHeader.biSizeImage = kcbBmpBits;
  211.     bmi.bmiHeader.biCompression = BI_RGB;
  212.     bmi.bmiHeader.biClrUsed = 2;
  213.     bmi.bmiHeader.biClrImportant = 2;
  214.  
  215.     // Convert bits. Fill bits off first, then turn on where pilot bits
  216.     // are off
  217.  
  218.     byte *pbNew = &gabResData[8192];
  219.     memset(pbNew, 0, kcbBmpBits);
  220.  
  221.     Bitmap *pbm = (Bitmap *)gabResData;
  222.     pbm->cx = SwapBytes(pbm->cx);
  223.     pbm->cy = SwapBytes(pbm->cy);
  224.  
  225.     for (int y = 0; y < kcyIcon; y++) {
  226.         for (int x = 0; x < kcxIcon; x++) {
  227.             if (!TestBit(pbm->cx, pbm->cy, pbm->abBits, x, y, 16))
  228.                 SetBit(kcxIcon, kcyIcon, pbNew, x, kcyIcon - y - 1, 32);
  229.         }
  230.     }
  231.  
  232.     // Write it out!
  233.  
  234.     FILE *pfilOut = fopen(pszOutName, "wb");
  235.     if (pfilOut == NULL || pfilOut == (FILE *)-1) {
  236.         printf("Error: Can't open the output file %s\n", pszOutName);
  237.         exit(1);
  238.     }
  239.  
  240.     // Write header and bitmapinfo
  241.  
  242.     fwrite(&bfh, sizeof(bfh), 1, pfilOut);
  243.     fwrite(&bmi, sizeof(bmi) - sizeof(RGBQUAD), 1, pfilOut);
  244.  
  245.     // Write color table
  246.  
  247.     ulong ul = 0;
  248.     fwrite(&ul, sizeof(ul), 1, pfilOut);
  249.     ul = 0x00FFFFFF;
  250.     fwrite(&ul, sizeof(ul), 1, pfilOut);
  251.  
  252.     // Write bits
  253.  
  254.     fwrite(pbNew, kcbBmpBits, 1, pfilOut);
  255.     fclose(pfilOut);
  256. }
  257.