home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / quake / programs / qube / image.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-07  |  10.9 KB  |  338 lines

  1. /***
  2. ****  QuBE --- Graphical image manipulation routines.
  3. ***/
  4.  
  5. #include "qube.h"
  6. #include "image.h"
  7.  
  8. /* This is how Quake stores its pictures. */
  9.  
  10. static struct {
  11.     char name[16];
  12.     long width;
  13.     long height;
  14.     long scale1pos;
  15.     long scale2pos;
  16.     long scale4pos;
  17.     long scale8pos;
  18. } picture;
  19.  
  20. /* Again, this table should be dynamic or something */
  21.  
  22. static long int picptrs[1024];
  23.  
  24. /* Standard (ugh) Windows BMP file.  Padded with the 2 chars at the top
  25.    so that RISC architectures won't burp trying to use it. */
  26.  
  27. static struct {
  28.     char dummyspace[2];
  29.     char id[2];
  30.     long int filesize;
  31.     short int reserved[2];
  32.     long int headersize;
  33.     long int infosize;
  34.     long int width;
  35.     long int height;
  36.     short int planes;
  37.     short int bits;
  38.     long int compression;
  39.     long int sizeimage;
  40.     long int xpelspermeter;
  41.     long int ypelspermeter;
  42.     long int colorsused;
  43.     long int colorsimportant;
  44. } bmpfile;
  45.  
  46. /* Standard Quake palette.  Can this thing change per Quake file?  I haven't
  47.    seen it done, but the possibility exists. */
  48.  
  49. static unsigned char QuakePalette[] = {
  50.     0x00,0x00,0x00,0x0F,0x0F,0x0F,0x1F,0x1F,0x1F,0x2F,0x2F,0x2F,0x3F,0x3F,0x3F,0x4B,
  51.     0x4B,0x4B,0x5B,0x5B,0x5B,0x6B,0x6B,0x6B,0x7B,0x7B,0x7B,0x8B,0x8B,0x8B,0x9B,0x9B,
  52.     0x9B,0xAB,0xAB,0xAB,0xBB,0xBB,0xBB,0xCB,0xCB,0xCB,0xDB,0xDB,0xDB,0xEB,0xEB,0xEB,
  53.     0x0F,0x0B,0x07,0x17,0x0F,0x0B,0x1F,0x17,0x0B,0x27,0x1B,0x0F,0x2F,0x23,0x13,0x37,
  54.     0x2B,0x17,0x3F,0x2F,0x17,0x4B,0x37,0x1B,0x53,0x3B,0x1B,0x5B,0x43,0x1F,0x63,0x4B,
  55.     0x1F,0x6B,0x53,0x1F,0x73,0x57,0x1F,0x7B,0x5F,0x23,0x83,0x67,0x23,0x8F,0x6F,0x23,
  56.     0x0B,0x0B,0x0F,0x13,0x13,0x1B,0x1B,0x1B,0x27,0x27,0x27,0x33,0x2F,0x2F,0x3F,0x37,
  57.     0x37,0x4B,0x3F,0x3F,0x57,0x47,0x47,0x67,0x4F,0x4F,0x73,0x5B,0x5B,0x7F,0x63,0x63,
  58.     0x8B,0x6B,0x6B,0x97,0x73,0x73,0xA3,0x7B,0x7B,0xAF,0x83,0x83,0xBB,0x8B,0x8B,0xCB,
  59.     0x00,0x00,0x00,0x07,0x07,0x00,0x0B,0x0B,0x00,0x13,0x13,0x00,0x1B,0x1B,0x00,0x23,
  60.     0x23,0x00,0x2B,0x2B,0x07,0x2F,0x2F,0x07,0x37,0x37,0x07,0x3F,0x3F,0x07,0x47,0x47,
  61.     0x07,0x4B,0x4B,0x0B,0x53,0x53,0x0B,0x5B,0x5B,0x0B,0x63,0x63,0x0B,0x6B,0x6B,0x0F,
  62.     0x07,0x00,0x00,0x0F,0x00,0x00,0x17,0x00,0x00,0x1F,0x00,0x00,0x27,0x00,0x00,0x2F,
  63.     0x00,0x00,0x37,0x00,0x00,0x3F,0x00,0x00,0x47,0x00,0x00,0x4F,0x00,0x00,0x57,0x00,
  64.     0x00,0x5F,0x00,0x00,0x67,0x00,0x00,0x6F,0x00,0x00,0x77,0x00,0x00,0x7F,0x00,0x00,
  65.     0x13,0x13,0x00,0x1B,0x1B,0x00,0x23,0x23,0x00,0x2F,0x2B,0x00,0x37,0x2F,0x00,0x43,
  66.     0x37,0x00,0x4B,0x3B,0x07,0x57,0x43,0x07,0x5F,0x47,0x07,0x6B,0x4B,0x0B,0x77,0x53,
  67.     0x0F,0x83,0x57,0x13,0x8B,0x5B,0x13,0x97,0x5F,0x1B,0xA3,0x63,0x1F,0xAF,0x67,0x23,
  68.     0x23,0x13,0x07,0x2F,0x17,0x0B,0x3B,0x1F,0x0F,0x4B,0x23,0x13,0x57,0x2B,0x17,0x63,
  69.     0x2F,0x1F,0x73,0x37,0x23,0x7F,0x3B,0x2B,0x8F,0x43,0x33,0x9F,0x4F,0x33,0xAF,0x63,
  70.     0x2F,0xBF,0x77,0x2F,0xCF,0x8F,0x2B,0xDF,0xAB,0x27,0xEF,0xCB,0x1F,0xFF,0xF3,0x1B,
  71.     0x0B,0x07,0x00,0x1B,0x13,0x00,0x2B,0x23,0x0F,0x37,0x2B,0x13,0x47,0x33,0x1B,0x53,
  72.     0x37,0x23,0x63,0x3F,0x2B,0x6F,0x47,0x33,0x7F,0x53,0x3F,0x8B,0x5F,0x47,0x9B,0x6B,
  73.     0x53,0xA7,0x7B,0x5F,0xB7,0x87,0x6B,0xC3,0x93,0x7B,0xD3,0xA3,0x8B,0xE3,0xB3,0x97,
  74.     0xAB,0x8B,0xA3,0x9F,0x7F,0x97,0x93,0x73,0x87,0x8B,0x67,0x7B,0x7F,0x5B,0x6F,0x77,
  75.     0x53,0x63,0x6B,0x4B,0x57,0x5F,0x3F,0x4B,0x57,0x37,0x43,0x4B,0x2F,0x37,0x43,0x27,
  76.     0x2F,0x37,0x1F,0x23,0x2B,0x17,0x1B,0x23,0x13,0x13,0x17,0x0B,0x0B,0x0F,0x07,0x07,
  77.     0xBB,0x73,0x9F,0xAF,0x6B,0x8F,0xA3,0x5F,0x83,0x97,0x57,0x77,0x8B,0x4F,0x6B,0x7F,
  78.     0x4B,0x5F,0x73,0x43,0x53,0x6B,0x3B,0x4B,0x5F,0x33,0x3F,0x53,0x2B,0x37,0x47,0x23,
  79.     0x2B,0x3B,0x1F,0x23,0x2F,0x17,0x1B,0x23,0x13,0x13,0x17,0x0B,0x0B,0x0F,0x07,0x07,
  80.     0xDB,0xC3,0xBB,0xCB,0xB3,0xA7,0xBF,0xA3,0x9B,0xAF,0x97,0x8B,0xA3,0x87,0x7B,0x97,
  81.     0x7B,0x6F,0x87,0x6F,0x5F,0x7B,0x63,0x53,0x6B,0x57,0x47,0x5F,0x4B,0x3B,0x53,0x3F,
  82.     0x33,0x43,0x33,0x27,0x37,0x2B,0x1F,0x27,0x1F,0x17,0x1B,0x13,0x0F,0x0F,0x0B,0x07,
  83.     0x6F,0x83,0x7B,0x67,0x7B,0x6F,0x5F,0x73,0x67,0x57,0x6B,0x5F,0x4F,0x63,0x57,0x47,
  84.     0x5B,0x4F,0x3F,0x53,0x47,0x37,0x4B,0x3F,0x2F,0x43,0x37,0x2B,0x3B,0x2F,0x23,0x33,
  85.     0x27,0x1F,0x2B,0x1F,0x17,0x23,0x17,0x0F,0x1B,0x13,0x0B,0x13,0x0B,0x07,0x0B,0x07,
  86.     0xFF,0xF3,0x1B,0xEF,0xDF,0x17,0xDB,0xCB,0x13,0xCB,0xB7,0x0F,0xBB,0xA7,0x0F,0xAB,
  87.     0x97,0x0B,0x9B,0x83,0x07,0x8B,0x73,0x07,0x7B,0x63,0x07,0x6B,0x53,0x00,0x5B,0x47,
  88.     0x00,0x4B,0x37,0x00,0x3B,0x2B,0x00,0x2B,0x1F,0x00,0x1B,0x0F,0x00,0x0B,0x07,0x00,
  89.     0x00,0x00,0xFF,0x0B,0x0B,0xEF,0x13,0x13,0xDF,0x1B,0x1B,0xCF,0x23,0x23,0xBF,0x2B,
  90.     0x2B,0xAF,0x2F,0x2F,0x9F,0x2F,0x2F,0x8F,0x2F,0x2F,0x7F,0x2F,0x2F,0x6F,0x2F,0x2F,
  91.     0x5F,0x2B,0x2B,0x4F,0x23,0x23,0x3F,0x1B,0x1B,0x2F,0x13,0x13,0x1F,0x0B,0x0B,0x0F,
  92.     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  93.     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  94.     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  95.     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC7,0xC3,0x37,0xE7,0xE3,0x57,0x7F,0xBF,0xFF,0xAB,
  96.     0xE7,0xFF,0xD7,0xFF,0xFF,0x67,0x00,0x00,0x8B,0x00,0x00,0xB3,0x00,0x00,0xD7,0x00,
  97.     0x00,0xFF,0x00,0x00,0xFF,0xF3,0x93,0xFF,0xF7,0xC7,0xFF,0xFF,0xFF,0x9F,0x5B,0x53,
  98. };
  99.  
  100. void PicList(void);
  101. void PicExtract(void);
  102.  
  103. static void writebmp(FILE *out, long int width, long int height);
  104. static void extract(char *name, char *size);
  105.  
  106. /*
  107. **  PicList.  Dump the pictures.
  108. */
  109.  
  110. void PicList(void)
  111. {
  112.     long int i, j;
  113.  
  114.     if (header.id != 0x17)
  115.         Error("Not a valid .BSP file");
  116.  
  117.     /* Go to the picture table */
  118.  
  119.         fseek(fi, header.pictures, SEEK_SET);
  120.  
  121.     /* Get the picture count */
  122.  
  123.     fread(&i, 4, 1, fi);
  124.     printf("Pictures: %ld\n", i);
  125.  
  126.     /* Read in the pointers */
  127.  
  128.         for (j = 0; j < i; j++) {
  129.         fread(picptrs+j, 4, 1, fi);
  130.         picptrs[j] += header.pictures;
  131.     }
  132.  
  133.     /* And dump their data */
  134.  
  135.     for (j = 0; j < i; j++) {
  136.         fseek(fi, picptrs[j], SEEK_SET);
  137.         fread(&picture, 40, 1, fi);
  138.  
  139.                 printf("%3ld. %-16s ", j, picture.name);
  140.  
  141.                 printf("\t%4ldx%-4ld ", picture.width, picture.height);
  142.  
  143.         printf("%08lX ", picture.scale1pos + picptrs[j]);
  144.         printf("%08lX ", picture.scale2pos + picptrs[j]);
  145.         printf("%08lX ", picture.scale4pos + picptrs[j]);
  146.         printf("%08lX ", picture.scale8pos + picptrs[j]);
  147.  
  148.                 printf("\n");
  149.         }
  150. }
  151.  
  152. /*
  153. **  PicXtract.    Top-level function for extracting by wildcard filename.
  154. */
  155.  
  156. void PicXtract(int argnum, char **argv)
  157. {
  158.     if (header.id != 0x17)
  159.         Error("Not a valid .BSP file");
  160.  
  161.         extract(argv[argnum+1], argv[argnum+2]);
  162. }
  163.  
  164. /*
  165. **  PicXtract2.  Top-level function for extracting all pictures.
  166. */
  167.  
  168. void PicXtract2(void)
  169. {
  170.     if (header.id != 0x17)
  171.         Error("Not a valid .BSP file");
  172.  
  173.         extract("*", "*");
  174. }
  175.  
  176. /*
  177. **  extract.  Actual extraction function.  Iterates down the list
  178. **    one by one and rips out those that match.
  179. */
  180.  
  181. static void extract(char *name, char *size)
  182. {
  183.     long int i, j, width, height;
  184.     FILE *fp;
  185.     long int cur, cur2, total;
  186.         char filename[1024];
  187.  
  188.         fseek(fi, header.pictures, SEEK_SET);
  189.  
  190.     fread(&total, 4, 1, fi);
  191.  
  192.     for (j = 0; j < total; j++) {
  193.         fread(picptrs+j, 4, 1, fi);
  194.         picptrs[j] += header.pictures;
  195.     }
  196.  
  197.     /* Start at the top and check all of 'em */
  198.     for (cur = 0; cur < total; cur++) {
  199.  
  200.                 fseek(fi, picptrs[cur], SEEK_SET);
  201.         fread(&picture, 40, 1, fi);
  202.  
  203.         if (verbose) printf("Attempting to match picture #%ld: %s\n", cur, picture.name);
  204.  
  205.                 /* If the filename matches the wildcards... */
  206.                 if (MatchName(name, picture.name)) {
  207.  
  208.                         /* ...do its separate sub-files */
  209.                         for (cur2 = 1; cur2 <= 8; cur2 <<= 1) {
  210.  
  211.                 /* Only extract those that match the size */
  212.  
  213.                                 sprintf(filename, "%ld", cur2);
  214.  
  215.                 if (verbose) printf("Attempting to match size %s\n", filename);
  216.  
  217.                                 if (MatchName(size, filename)) {
  218.  
  219.                     strcpy(filename, picture.name);
  220.                     strcat(filename, ".bm");
  221.  
  222.                     printf("Extracting %s: normally %ldx%ld, this is ",
  223.                         picture.name, picture.width, picture.height);
  224.  
  225.                     /* Select the picture's dimensions */
  226.  
  227.                                         switch (cur2) {
  228.                     case 1: printf("%ldx%ld", width = picture.width, height = picture.height);
  229.                         strcat(filename, "p");
  230.                         i = picture.scale1pos;
  231.                         break;
  232.                     case 2: printf("%ldx%ld", width = picture.width/2, height = picture.height/2);
  233.                         strcat(filename, "2");
  234.                         i = picture.scale2pos;
  235.                         break;
  236.                     case 4: printf("%ldx%ld", width = picture.width/4, height = picture.height/4);
  237.                         strcat(filename, "4");
  238.                         i = picture.scale4pos;
  239.                         break;
  240.                     case 8: printf("%ldx%ld", width = picture.width/8, height = picture.height/8);
  241.                         strcat(filename, "8");
  242.                         i = picture.scale8pos;
  243.                         break;
  244.                     default: printf("invalid");
  245.                         break;
  246.                     }
  247.                     printf("\n");
  248.  
  249.                     fseek(fi, i + picptrs[cur], SEEK_SET);
  250.  
  251.                     /* Clean up that nasty little asterisk before the animated ones */
  252.  
  253.                     if (filename[0] == '*') filename[0] = '_';
  254.  
  255.                     /* Write out a .BMP.  Other file formats would be good additions */
  256.  
  257.                     if (verbose) printf("  Creating file...\n");
  258.  
  259.                     if ((fp = fopen(filename, "wb")) == NULL)
  260.                         Error("Unable to get permission to write files.");
  261.                                         writebmp(fp, width, height);
  262.  
  263.                     if (verbose) printf("  Closing file...\n");
  264.  
  265.                                         fclose(fp);
  266.                 }
  267.                         }
  268.                 }
  269.         }
  270. }
  271.  
  272. /*
  273. **  writebmp.  This writes out a .BMP file, architecture-independent.
  274. **    Don't ask how the hell it works; look in a graphics manual.
  275. */
  276.  
  277. static void writebmp(FILE *out, long int width, long int height)
  278. {
  279.     long int i, j;
  280.     long int size = width * height;
  281.     unsigned char *temp;
  282.     long int readsize;
  283.     unsigned char **list;
  284.  
  285.         bmpfile.id[0] = 'B';
  286.     bmpfile.id[1] = 'M';
  287.     bmpfile.infosize = 0x28;
  288.     bmpfile.width = width;
  289.     bmpfile.height = height;
  290.     bmpfile.planes = 1;
  291.     bmpfile.compression = 0;
  292.     bmpfile.bits = 8;
  293.     bmpfile.xpelspermeter = 300;
  294.     bmpfile.ypelspermeter = 300;
  295.     bmpfile.colorsused = 256;
  296.     bmpfile.colorsimportant = 256;
  297.  
  298.     bmpfile.filesize = size + sizeof(bmpfile) + 1022L;
  299.     bmpfile.headersize = sizeof(bmpfile) + 1022L;
  300.     bmpfile.sizeimage = size;
  301.  
  302.     if (verbose) printf("  Writing BMP file header...\n");
  303.  
  304.         fwrite(((char *)(&bmpfile))+2, sizeof(bmpfile)-2, 1L, out);
  305.  
  306.     if (verbose) printf("  Writing palette...\n");
  307.  
  308.     for (i = 0L; i < 256; i++) {
  309.         fputc(QuakePalette[i*3 + 2], out);
  310.         fputc(QuakePalette[i*3 + 1], out);
  311.         fputc(QuakePalette[i*3 + 0], out);
  312.         fputc(0, out);
  313.         }
  314.  
  315.     if (verbose) printf("  Allocating memory...\n");
  316.  
  317.     list = Qmalloc(sizeof(char *) * height);
  318.  
  319.     if (verbose) printf("  Constructing image...\n");
  320.  
  321.     for (i = 0L; i < height; i++) {
  322.         list[i] = Qmalloc(width);
  323.         fread(list[i], 1, width, fi);
  324.     }
  325.  
  326.     if (verbose) printf("  Writing image...\n");
  327.  
  328.     for (i = height - 1; i >= 0; i--) {
  329.         fwrite(list[i], 1, width, out);
  330.         Qfree(list[i]);
  331.         }
  332.  
  333.     if (verbose) printf("  Releasing memory...\n");
  334.  
  335.     Qfree(list);
  336. }
  337.  
  338.