home *** CD-ROM | disk | FTP | other *** search
- /***
- **** QuBE --- Graphical image manipulation routines.
- ***/
-
- #include "qube.h"
- #include "image.h"
-
- /* This is how Quake stores its pictures. */
-
- static struct {
- char name[16];
- long width;
- long height;
- long scale1pos;
- long scale2pos;
- long scale4pos;
- long scale8pos;
- } picture;
-
- /* Again, this table should be dynamic or something */
-
- static long int picptrs[1024];
-
- /* Standard (ugh) Windows BMP file. Padded with the 2 chars at the top
- so that RISC architectures won't burp trying to use it. */
-
- static struct {
- char dummyspace[2];
- char id[2];
- long int filesize;
- short int reserved[2];
- long int headersize;
- long int infosize;
- long int width;
- long int height;
- short int planes;
- short int bits;
- long int compression;
- long int sizeimage;
- long int xpelspermeter;
- long int ypelspermeter;
- long int colorsused;
- long int colorsimportant;
- } bmpfile;
-
- /* Standard Quake palette. Can this thing change per Quake file? I haven't
- seen it done, but the possibility exists. */
-
- static unsigned char QuakePalette[] = {
- 0x00,0x00,0x00,0x0F,0x0F,0x0F,0x1F,0x1F,0x1F,0x2F,0x2F,0x2F,0x3F,0x3F,0x3F,0x4B,
- 0x4B,0x4B,0x5B,0x5B,0x5B,0x6B,0x6B,0x6B,0x7B,0x7B,0x7B,0x8B,0x8B,0x8B,0x9B,0x9B,
- 0x9B,0xAB,0xAB,0xAB,0xBB,0xBB,0xBB,0xCB,0xCB,0xCB,0xDB,0xDB,0xDB,0xEB,0xEB,0xEB,
- 0x0F,0x0B,0x07,0x17,0x0F,0x0B,0x1F,0x17,0x0B,0x27,0x1B,0x0F,0x2F,0x23,0x13,0x37,
- 0x2B,0x17,0x3F,0x2F,0x17,0x4B,0x37,0x1B,0x53,0x3B,0x1B,0x5B,0x43,0x1F,0x63,0x4B,
- 0x1F,0x6B,0x53,0x1F,0x73,0x57,0x1F,0x7B,0x5F,0x23,0x83,0x67,0x23,0x8F,0x6F,0x23,
- 0x0B,0x0B,0x0F,0x13,0x13,0x1B,0x1B,0x1B,0x27,0x27,0x27,0x33,0x2F,0x2F,0x3F,0x37,
- 0x37,0x4B,0x3F,0x3F,0x57,0x47,0x47,0x67,0x4F,0x4F,0x73,0x5B,0x5B,0x7F,0x63,0x63,
- 0x8B,0x6B,0x6B,0x97,0x73,0x73,0xA3,0x7B,0x7B,0xAF,0x83,0x83,0xBB,0x8B,0x8B,0xCB,
- 0x00,0x00,0x00,0x07,0x07,0x00,0x0B,0x0B,0x00,0x13,0x13,0x00,0x1B,0x1B,0x00,0x23,
- 0x23,0x00,0x2B,0x2B,0x07,0x2F,0x2F,0x07,0x37,0x37,0x07,0x3F,0x3F,0x07,0x47,0x47,
- 0x07,0x4B,0x4B,0x0B,0x53,0x53,0x0B,0x5B,0x5B,0x0B,0x63,0x63,0x0B,0x6B,0x6B,0x0F,
- 0x07,0x00,0x00,0x0F,0x00,0x00,0x17,0x00,0x00,0x1F,0x00,0x00,0x27,0x00,0x00,0x2F,
- 0x00,0x00,0x37,0x00,0x00,0x3F,0x00,0x00,0x47,0x00,0x00,0x4F,0x00,0x00,0x57,0x00,
- 0x00,0x5F,0x00,0x00,0x67,0x00,0x00,0x6F,0x00,0x00,0x77,0x00,0x00,0x7F,0x00,0x00,
- 0x13,0x13,0x00,0x1B,0x1B,0x00,0x23,0x23,0x00,0x2F,0x2B,0x00,0x37,0x2F,0x00,0x43,
- 0x37,0x00,0x4B,0x3B,0x07,0x57,0x43,0x07,0x5F,0x47,0x07,0x6B,0x4B,0x0B,0x77,0x53,
- 0x0F,0x83,0x57,0x13,0x8B,0x5B,0x13,0x97,0x5F,0x1B,0xA3,0x63,0x1F,0xAF,0x67,0x23,
- 0x23,0x13,0x07,0x2F,0x17,0x0B,0x3B,0x1F,0x0F,0x4B,0x23,0x13,0x57,0x2B,0x17,0x63,
- 0x2F,0x1F,0x73,0x37,0x23,0x7F,0x3B,0x2B,0x8F,0x43,0x33,0x9F,0x4F,0x33,0xAF,0x63,
- 0x2F,0xBF,0x77,0x2F,0xCF,0x8F,0x2B,0xDF,0xAB,0x27,0xEF,0xCB,0x1F,0xFF,0xF3,0x1B,
- 0x0B,0x07,0x00,0x1B,0x13,0x00,0x2B,0x23,0x0F,0x37,0x2B,0x13,0x47,0x33,0x1B,0x53,
- 0x37,0x23,0x63,0x3F,0x2B,0x6F,0x47,0x33,0x7F,0x53,0x3F,0x8B,0x5F,0x47,0x9B,0x6B,
- 0x53,0xA7,0x7B,0x5F,0xB7,0x87,0x6B,0xC3,0x93,0x7B,0xD3,0xA3,0x8B,0xE3,0xB3,0x97,
- 0xAB,0x8B,0xA3,0x9F,0x7F,0x97,0x93,0x73,0x87,0x8B,0x67,0x7B,0x7F,0x5B,0x6F,0x77,
- 0x53,0x63,0x6B,0x4B,0x57,0x5F,0x3F,0x4B,0x57,0x37,0x43,0x4B,0x2F,0x37,0x43,0x27,
- 0x2F,0x37,0x1F,0x23,0x2B,0x17,0x1B,0x23,0x13,0x13,0x17,0x0B,0x0B,0x0F,0x07,0x07,
- 0xBB,0x73,0x9F,0xAF,0x6B,0x8F,0xA3,0x5F,0x83,0x97,0x57,0x77,0x8B,0x4F,0x6B,0x7F,
- 0x4B,0x5F,0x73,0x43,0x53,0x6B,0x3B,0x4B,0x5F,0x33,0x3F,0x53,0x2B,0x37,0x47,0x23,
- 0x2B,0x3B,0x1F,0x23,0x2F,0x17,0x1B,0x23,0x13,0x13,0x17,0x0B,0x0B,0x0F,0x07,0x07,
- 0xDB,0xC3,0xBB,0xCB,0xB3,0xA7,0xBF,0xA3,0x9B,0xAF,0x97,0x8B,0xA3,0x87,0x7B,0x97,
- 0x7B,0x6F,0x87,0x6F,0x5F,0x7B,0x63,0x53,0x6B,0x57,0x47,0x5F,0x4B,0x3B,0x53,0x3F,
- 0x33,0x43,0x33,0x27,0x37,0x2B,0x1F,0x27,0x1F,0x17,0x1B,0x13,0x0F,0x0F,0x0B,0x07,
- 0x6F,0x83,0x7B,0x67,0x7B,0x6F,0x5F,0x73,0x67,0x57,0x6B,0x5F,0x4F,0x63,0x57,0x47,
- 0x5B,0x4F,0x3F,0x53,0x47,0x37,0x4B,0x3F,0x2F,0x43,0x37,0x2B,0x3B,0x2F,0x23,0x33,
- 0x27,0x1F,0x2B,0x1F,0x17,0x23,0x17,0x0F,0x1B,0x13,0x0B,0x13,0x0B,0x07,0x0B,0x07,
- 0xFF,0xF3,0x1B,0xEF,0xDF,0x17,0xDB,0xCB,0x13,0xCB,0xB7,0x0F,0xBB,0xA7,0x0F,0xAB,
- 0x97,0x0B,0x9B,0x83,0x07,0x8B,0x73,0x07,0x7B,0x63,0x07,0x6B,0x53,0x00,0x5B,0x47,
- 0x00,0x4B,0x37,0x00,0x3B,0x2B,0x00,0x2B,0x1F,0x00,0x1B,0x0F,0x00,0x0B,0x07,0x00,
- 0x00,0x00,0xFF,0x0B,0x0B,0xEF,0x13,0x13,0xDF,0x1B,0x1B,0xCF,0x23,0x23,0xBF,0x2B,
- 0x2B,0xAF,0x2F,0x2F,0x9F,0x2F,0x2F,0x8F,0x2F,0x2F,0x7F,0x2F,0x2F,0x6F,0x2F,0x2F,
- 0x5F,0x2B,0x2B,0x4F,0x23,0x23,0x3F,0x1B,0x1B,0x2F,0x13,0x13,0x1F,0x0B,0x0B,0x0F,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC7,0xC3,0x37,0xE7,0xE3,0x57,0x7F,0xBF,0xFF,0xAB,
- 0xE7,0xFF,0xD7,0xFF,0xFF,0x67,0x00,0x00,0x8B,0x00,0x00,0xB3,0x00,0x00,0xD7,0x00,
- 0x00,0xFF,0x00,0x00,0xFF,0xF3,0x93,0xFF,0xF7,0xC7,0xFF,0xFF,0xFF,0x9F,0x5B,0x53,
- };
-
- void PicList(void);
- void PicExtract(void);
-
- static void writebmp(FILE *out, long int width, long int height);
- static void extract(char *name, char *size);
-
- /*
- ** PicList. Dump the pictures.
- */
-
- void PicList(void)
- {
- long int i, j;
-
- if (header.id != 0x17)
- Error("Not a valid .BSP file");
-
- /* Go to the picture table */
-
- fseek(fi, header.pictures, SEEK_SET);
-
- /* Get the picture count */
-
- fread(&i, 4, 1, fi);
- printf("Pictures: %ld\n", i);
-
- /* Read in the pointers */
-
- for (j = 0; j < i; j++) {
- fread(picptrs+j, 4, 1, fi);
- picptrs[j] += header.pictures;
- }
-
- /* And dump their data */
-
- for (j = 0; j < i; j++) {
- fseek(fi, picptrs[j], SEEK_SET);
- fread(&picture, 40, 1, fi);
-
- printf("%3ld. %-16s ", j, picture.name);
-
- printf("\t%4ldx%-4ld ", picture.width, picture.height);
-
- printf("%08lX ", picture.scale1pos + picptrs[j]);
- printf("%08lX ", picture.scale2pos + picptrs[j]);
- printf("%08lX ", picture.scale4pos + picptrs[j]);
- printf("%08lX ", picture.scale8pos + picptrs[j]);
-
- printf("\n");
- }
- }
-
- /*
- ** PicXtract. Top-level function for extracting by wildcard filename.
- */
-
- void PicXtract(int argnum, char **argv)
- {
- if (header.id != 0x17)
- Error("Not a valid .BSP file");
-
- extract(argv[argnum+1], argv[argnum+2]);
- }
-
- /*
- ** PicXtract2. Top-level function for extracting all pictures.
- */
-
- void PicXtract2(void)
- {
- if (header.id != 0x17)
- Error("Not a valid .BSP file");
-
- extract("*", "*");
- }
-
- /*
- ** extract. Actual extraction function. Iterates down the list
- ** one by one and rips out those that match.
- */
-
- static void extract(char *name, char *size)
- {
- long int i, j, width, height;
- FILE *fp;
- long int cur, cur2, total;
- char filename[1024];
-
- fseek(fi, header.pictures, SEEK_SET);
-
- fread(&total, 4, 1, fi);
-
- for (j = 0; j < total; j++) {
- fread(picptrs+j, 4, 1, fi);
- picptrs[j] += header.pictures;
- }
-
- /* Start at the top and check all of 'em */
- for (cur = 0; cur < total; cur++) {
-
- fseek(fi, picptrs[cur], SEEK_SET);
- fread(&picture, 40, 1, fi);
-
- if (verbose) printf("Attempting to match picture #%ld: %s\n", cur, picture.name);
-
- /* If the filename matches the wildcards... */
- if (MatchName(name, picture.name)) {
-
- /* ...do its separate sub-files */
- for (cur2 = 1; cur2 <= 8; cur2 <<= 1) {
-
- /* Only extract those that match the size */
-
- sprintf(filename, "%ld", cur2);
-
- if (verbose) printf("Attempting to match size %s\n", filename);
-
- if (MatchName(size, filename)) {
-
- strcpy(filename, picture.name);
- strcat(filename, ".bm");
-
- printf("Extracting %s: normally %ldx%ld, this is ",
- picture.name, picture.width, picture.height);
-
- /* Select the picture's dimensions */
-
- switch (cur2) {
- case 1: printf("%ldx%ld", width = picture.width, height = picture.height);
- strcat(filename, "p");
- i = picture.scale1pos;
- break;
- case 2: printf("%ldx%ld", width = picture.width/2, height = picture.height/2);
- strcat(filename, "2");
- i = picture.scale2pos;
- break;
- case 4: printf("%ldx%ld", width = picture.width/4, height = picture.height/4);
- strcat(filename, "4");
- i = picture.scale4pos;
- break;
- case 8: printf("%ldx%ld", width = picture.width/8, height = picture.height/8);
- strcat(filename, "8");
- i = picture.scale8pos;
- break;
- default: printf("invalid");
- break;
- }
- printf("\n");
-
- fseek(fi, i + picptrs[cur], SEEK_SET);
-
- /* Clean up that nasty little asterisk before the animated ones */
-
- if (filename[0] == '*') filename[0] = '_';
-
- /* Write out a .BMP. Other file formats would be good additions */
-
- if (verbose) printf(" Creating file...\n");
-
- if ((fp = fopen(filename, "wb")) == NULL)
- Error("Unable to get permission to write files.");
- writebmp(fp, width, height);
-
- if (verbose) printf(" Closing file...\n");
-
- fclose(fp);
- }
- }
- }
- }
- }
-
- /*
- ** writebmp. This writes out a .BMP file, architecture-independent.
- ** Don't ask how the hell it works; look in a graphics manual.
- */
-
- static void writebmp(FILE *out, long int width, long int height)
- {
- long int i, j;
- long int size = width * height;
- unsigned char *temp;
- long int readsize;
- unsigned char **list;
-
- bmpfile.id[0] = 'B';
- bmpfile.id[1] = 'M';
- bmpfile.infosize = 0x28;
- bmpfile.width = width;
- bmpfile.height = height;
- bmpfile.planes = 1;
- bmpfile.compression = 0;
- bmpfile.bits = 8;
- bmpfile.xpelspermeter = 300;
- bmpfile.ypelspermeter = 300;
- bmpfile.colorsused = 256;
- bmpfile.colorsimportant = 256;
-
- bmpfile.filesize = size + sizeof(bmpfile) + 1022L;
- bmpfile.headersize = sizeof(bmpfile) + 1022L;
- bmpfile.sizeimage = size;
-
- if (verbose) printf(" Writing BMP file header...\n");
-
- fwrite(((char *)(&bmpfile))+2, sizeof(bmpfile)-2, 1L, out);
-
- if (verbose) printf(" Writing palette...\n");
-
- for (i = 0L; i < 256; i++) {
- fputc(QuakePalette[i*3 + 2], out);
- fputc(QuakePalette[i*3 + 1], out);
- fputc(QuakePalette[i*3 + 0], out);
- fputc(0, out);
- }
-
- if (verbose) printf(" Allocating memory...\n");
-
- list = Qmalloc(sizeof(char *) * height);
-
- if (verbose) printf(" Constructing image...\n");
-
- for (i = 0L; i < height; i++) {
- list[i] = Qmalloc(width);
- fread(list[i], 1, width, fi);
- }
-
- if (verbose) printf(" Writing image...\n");
-
- for (i = height - 1; i >= 0; i--) {
- fwrite(list[i], 1, width, out);
- Qfree(list[i]);
- }
-
- if (verbose) printf(" Releasing memory...\n");
-
- Qfree(list);
- }
-
-