--- /dev/null
+/* converts a QT RAW image file into the c structure that the
+ * kernel panic ui system expects.
+ *
+ * to build: cc -o genimage genimage.c
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+
+int EncodeImage(
+ unsigned char * data,
+ int pixels,
+ unsigned char * fileArr );
+int decode_rle(
+ unsigned char * dataPtr,
+ unsigned int * quantity,
+ unsigned int * depth,
+ unsigned char ** value );
+int findIndexNearMatch(
+ unsigned int color24 );
+unsigned char findIndexMatch(
+ unsigned int color24 );
+int convert24toGrey(
+ unsigned char * data,
+ unsigned int size );
+int convert8toGrey(
+ unsigned char * data,
+ unsigned int size );
+int convert8bitIndexto24(
+ unsigned char * data,
+ int height,
+ int width,
+ unsigned char ** dout );
+int convert8bitIndexto8(
+ unsigned char * data,
+ int height,
+ int width,
+ unsigned char ** dout );
+int convert24to8bitIndex(
+ unsigned char * data,
+ int height,
+ int width,
+ unsigned char ** dout );
+unsigned int * CreateCLUTarry(
+ unsigned char * raw_clut );
+unsigned int * ReplaceCLUT(
+ char * iname );
+void GenerateCLUT(
+ char * oname );
+void WriteQTRawFile(
+ FILE * ostream,
+ unsigned char * data,
+ int height,
+ int width,
+ int depth,
+ unsigned int size );
+void CreateRawQTFont(
+ void );
+void CreateRawQTCLUT(
+ int type );
+
+#define offsetof(type, field) ((size_t)(&((type *)0)->field))
+
+struct panicimage {
+ unsigned int pd_sum;
+ unsigned int pd_dataSize;
+ unsigned int pd_tag;
+ unsigned short pd_width;
+ unsigned short pd_height;
+ unsigned char pd_depth;
+ unsigned char pd_info_height;
+ unsigned char pd_info_color[2];
+ unsigned char data[];
+};
+
+
+
+
+void
+usage( int type ) {
+printf(
+"\n"
+"Usage:\n"
+"\tgenimage -i <.qtif> [operands ...]\n\n"
+"\tThe following operands are available\n\n"
+"\t-h\t\tDisplay full help information\n"
+"\t-i <file>\tUse file containing QuickTime uncompressed raw image as\n"
+"\t\t\tthe panic dialog (8 or 24 bit)\n"
+"\t-o <file>\tWrite the output as a compressed WHD RAW image suitable\n"
+"\t\t\tfor loading into the kernel\n"
+"\t-c <file>\tUse file containing 256 RGB values for 8-bit indexed \n"
+"\t\t\tlookups, overrides built-in appleClut8\n"
+"\t-fg <color>\tForeground color of font used for panic information in\n"
+"\t\t\t24-bits, default 0xFFFFFF (100%% white)\n"
+"\t-bg <color>\tBackground color of font used for panic information in\n"
+"\t\t\t24-bits, default 0x222222 (13%% white, dark gray)\n"
+"\t-n <lines>\tNumber of lines that have been reserved to display the\n"
+"\t\t\tpanic information, must be at least 20\n"
+"\n\tThese are useful options for testing\n"
+"\t-io <file>\tUse <file> to override the default C source filename\n"
+"\t-bw\t\tConvert the input image to shades of gray\n"
+"\t-n24\t\tConvert an image from 8 bit to 24 bit mode before\n"
+"\t\t\tprocessing\n"
+"\t-n8\t\tDon't convert an image from 24 bit to 8 bit mode before \n"
+"\t\t\tprocessing, default is to convert\n"
+"\t-qt <file>\t(requires -i) Write QuickTime uncompressed raw .gtif\n"
+"\t\t\tfile containing the input image in 8-bit format\n"
+"\t-r\t\tCreate a Quicktime uncompressed image of the 8-bit\n"
+"\t\t\tsystem CLUT named appleclut8.qtif <debugging>\n"
+"\t-f\t\tCreate a Quicktime uncompressed image of the 8x16\n"
+"\t\t\tbit panic info font named font.qtif <debugging>\n"
+"\n\n" );
+if ( type > 0 )
+printf(
+"\
+This utility is used to convert a panic dialog from .qtif format, into\n\
+one that is suitable for the kernel to display. The .qtif image file\n\
+can be in either 24 or 8 bit mode, but must be in an uncompressed raw\n\
+format. 8 bit mode is preferred, as it requires no conversion to the\n\
+colors that are contained in the CLUT. If a color cannot be found in\n\
+the CLUT, it will be converted to the nearest gray. The default CLUT\n\
+is the same as the system CLUT. If needed, this can be overridden by\n\
+providing a new CLUT with the -c option.\n\
+\n\
+However, if you override the default CLUT. The panic UI may not appear\n\
+as you intended, when the systme is in 8 bit mode. Colors that are not\n\
+present in the active CLUT, will be converted to the nearest gray.\n\
+\n\
+The panic dialog must have a number of lines reserved at the bottom for\n\
+displaying additional panic information. The minimum number of lines\n\
+is 20. The font use to display this information needs to have the\n\
+foreground and background colors defined. The defaults are full white\n\
+on dark gray. This can be changed by using the -fg and/or -bg options to\n\
+provide new 24 bit colors. These colors must be contained in the CLUT.\n\
+\n\
+There are two possible output results. The default is to create a C\n\
+source file named panic_image.c that contains the panic image in a 8 bit\n\
+modified RLE compressed format and the CLUT that was used to create the\n\
+image. The second possibility is to create a binary version of the same\n\
+information by using the -o option. This file can then be used to replace\n\
+the panic dialog that is currently active in the kernel by using\n\
+sysctl(KERN_PANIC_INFO).\n\
+\n\n");
+}
+
+
+#include "appleclut8.h"
+#include "../iso_font.c"
+
+struct QTHeader {
+ long idSize; /* total size of ImageDescription including extra data ( CLUTs and other per sequence data ) */
+ long cType; /* 'raw '; what kind of codec compressed this data */
+ long resvd1; /* reserved for Apple use */
+ short resvd2; /* reserved for Apple use */
+ short dataRefIndex; /* set to zero */
+ short version; /* which version is this data */
+ short revisionLevel; /* what version of that codec did this */
+ long vendor; /* whose codec compressed this data */
+ long temporalQuality; /* what was the temporal quality factor */
+ long spatialQuality; /* what was the spatial quality factor */
+ short width; /* how many pixels wide is this data */
+ short height; /* how many pixels high is this data */
+ long hRes; /* horizontal resolution */
+ long vRes; /* vertical resolution */
+ long dataSize; /* if known, the size of data for this image descriptor */
+ short frameCount; /* number of frames this description applies to */
+ char name[32]; /* name of codec ( in case not installed ) */
+ short depth; /* what depth is this data (1-32) or ( 33-40 grayscale ) */
+ short clutID; /* clut id or if 0 clut follows or -1 if no clut */
+} image_header;
+
+static unsigned int mismatchClut[256];
+static int nextmis = -1, neargrey = 0, cvt2grey = 0, exactmatch=0;
+static int grey = 0, debug = 0, testfont = 0, testclut = 0;
+static int convert = 8; // default is to convert image to 8 bit uncompressed .tgif
+static unsigned char fg, bg;
+unsigned int * panic_clut = NULL;
+static char * clutin = NULL;
+
+union colors {
+ unsigned int c24;
+ unsigned char rgb[4];
+ struct {
+ unsigned char dummy;
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ } clut;
+};
+
+int
+main( int argc, char *argv[] )
+{
+ char *file = NULL;
+ char *out = NULL;
+ char *kraw = NULL;
+ char *qtraw = NULL;
+ char *clutout = NULL;
+ char *whdname = NULL;
+ FILE * stream, *out_stream;
+ unsigned char * data;
+ unsigned short width = 0, height = 0;
+ unsigned char depth = 0, lines = 20;
+ unsigned int i, pixels, sum, encodedSize, fg24= 0xFFFFFF, bg24=0x222222;
+ unsigned char *fileArr;
+ int chars_this_line, next, runindex;
+
+
+ // pull apart the arguments
+ for( next = 1; next < argc; next++ )
+ {
+ if (strcmp(argv[next], "-i") == 0) // image file in raw QT uncompressed format (.qtif)
+ file = argv[++next];
+
+ else if (strcmp(argv[next], "-o") == 0) // output file for WHD image
+ kraw = argv[++next];
+ else if (strcmp(argv[next], "-io") == 0) // output file for image
+ out = argv[++next];
+
+ else if (strcmp(argv[next], "-n") == 0) // numbers of reserved lines
+ lines = atoi(argv[++next]);
+ else if (strcmp(argv[next], "-fg") == 0) // foreground color in 24 bits
+ sscanf(argv[++next], "%i", &fg24);
+ else if (strcmp(argv[next], "-bg") == 0) // background color in 24 bits
+ sscanf(argv[++next], "%i", &bg24);
+ else if (strcmp(argv[next], "-c") == 0) // input file for clut
+ clutin = argv[++next];
+ else if (strcmp(argv[next], "-h") == 0) // display more help
+ { usage(1); exit(1); }
+
+ // useful testing options
+ else if (strcmp(argv[next], "-co") == 0) // output file for generating appleClut8.h array included in this file
+ clutout = argv[++next];
+ else if (strcmp(argv[next], "-a8") == 0) // output file for testing system CLUT 8 in QT RAW (test)
+ testclut = 8;
+ else if (strcmp(argv[next], "-r") == 0) // output file for QT clut RAW (test)
+ testclut = 1;
+ else if (strcmp(argv[next], "-qt") == 0) // output file for QT RAW (test)
+ qtraw = argv[++next];
+ else if (strcmp(argv[next], "-bw") == 0) // use only shades of grey (test)
+ grey = 1;
+ else if (strcmp(argv[next], "-n8") == 0) // don't convert to 8 by default (test)
+ convert = 0;
+ else if (strcmp(argv[next], "-n24") == 0) // convert to 8 to 24 (test)
+ convert = 24;
+ else if (strcmp(argv[next], "-f") == 0) // test font (test)
+ testfont = 1;
+ else if (strcmp(argv[next], "-w") == 0) // read WHD raw file and output 8 bit tqif
+ whdname = argv[++next];
+
+ else if (strcmp(argv[next], "-debug") == 0) // verbose
+ debug++;
+ }
+
+ if (!(file || clutout || testfont || testclut || whdname) ) {
+ usage(0);
+ exit(1);
+ }
+
+ printf("\n");
+
+ panic_clut = appleClut8;
+
+ if ( clutin )
+ {
+ panic_clut = ReplaceCLUT( clutin );
+ printf("Built-in CLUT has been replaced with %s...\n", clutin);
+ } else
+ {
+ if ( whdname )
+ printf("Using CLUT from %s...\n", whdname);
+ else
+ printf("Using Built-in CLUT...\n");
+ }
+
+ if ( clutout )
+ {
+ GenerateCLUT( clutout );
+ printf("Created C source file of %s...\n", clutout);
+ }
+
+ fg = findIndexNearMatch(fg24);
+ bg = findIndexNearMatch(bg24);
+
+ if ( testclut )
+ CreateRawQTCLUT(testclut);
+
+ if ( testfont )
+ CreateRawQTFont();
+
+ // Begin to process the image
+
+ if( file == NULL)
+ {
+ if ( whdname == NULL )
+ {
+ if ( debug)
+ printf("No image file was processed...\n\n");
+ exit(0);
+ }
+ }
+
+
+ printf("Verifing image file...\n");
+ if ( file != NULL )
+ {
+ stream = fopen(file, "r");
+ if (!stream) {
+ fprintf(stderr, "Err: could not open .qtif image file.\n\n");
+ exit(1);
+ }
+
+ {
+ long hdr_off;
+ long hdr_type;
+
+ fread((void *) &hdr_off, sizeof(long), 1, stream);
+ fread((void *) &hdr_type, sizeof(long), 1, stream);
+
+ if ( hdr_type != 'idat' ) goto errQTimage;
+
+ fseek(stream, hdr_off, SEEK_SET);
+ fread((void *) &hdr_off, sizeof(long), 1, stream);
+ fread((void *) &hdr_type, sizeof(long), 1, stream);
+
+ if ( hdr_type != 'idsc' ) goto errQTimage;
+
+ fread((void *) &image_header, sizeof(image_header), 1, stream);
+ if ( image_header.cType != 'raw ' ) goto errQTimage;
+ if (( image_header.depth != 8 ) && ( image_header.depth != 24 )) goto errQTimage;
+
+ width = image_header.width;
+ height = image_header.height;
+ depth = image_header.depth;
+
+ printf("Image info: width: %d height: %d depth: %d...\n", width, height, depth);
+
+ if (!(width && height && depth)) {
+ fprintf(stderr,"Err: Invalid image file header (width, height, or depth is 0)\n");
+ exit(1);
+ }
+ }
+
+ if ( !(data = (char *)malloc(image_header.dataSize))) {
+ fprintf(stderr,"Err: Couldn't malloc file data (%ld bytes)... bailing.\n", image_header.dataSize);
+ exit(1);
+ }
+
+ // Read the image data
+ fseek(stream, 8, SEEK_SET);
+ fread((void *) data, image_header.dataSize, 1, stream);
+ fclose( stream );
+
+ if ( kraw && image_header.depth == 24 )
+ {
+ fprintf(stderr, "Err: The WHD raw file (%s) will not be created when input in is millions of colors\n", kraw);
+ kraw = NULL;
+ }
+
+ pixels = image_header.dataSize;
+
+ if ( image_header.depth == 24 )
+ {
+ if ( grey == 1 )
+ pixels = convert24toGrey( data, image_header.dataSize);
+
+ if ( convert == 8 )
+ {
+ printf("Converting image file to 8 bit...\n");
+ pixels = convert24to8bitIndex( data, height, width, &data );
+ image_header.dataSize = pixels;
+ depth = 1;
+ } else
+ depth = 3;
+ } else {
+ if ( grey == 1 )
+ pixels = convert8toGrey( data, image_header.dataSize );
+
+ if ( convert == 24 )
+ {
+ printf("Converting image file to 24 bit...\n");
+ pixels = convert8bitIndexto24( data, height, width, &data );
+ image_header.dataSize = pixels;
+ depth = 3;
+ } else
+ {
+ printf("Converting image file to 8 bit raw...\n");
+ pixels = convert8bitIndexto8( data, height, width, &data );
+ image_header.dataSize = pixels;
+ depth = 1;
+ }
+ }
+
+ printf("Converted %d pixels%s...\n", pixels/depth, ((grey==1)?" to grayscale":""));
+ if ( exactmatch > 0 )
+ printf("Found %d color mathces in CLUT...\n", exactmatch);
+ if ( cvt2grey > 0 )
+ printf("Converted %d colors to gray...\n", cvt2grey);
+ if ( neargrey > 0 )
+ printf("Adjusted %d grays to best match...\n", neargrey);
+ if ( nextmis > 0 )
+ printf("Total of %d seperate color mismatches...\n", nextmis);
+ }
+ else
+ {
+ unsigned int pixels_out;
+ struct panicimage image;
+
+ stream = fopen(whdname, "r");
+ if (!stream) {
+ fprintf(stderr, "Err: could not open WHD raw image file.\n\n");
+ exit(1);
+ }
+
+ fread(&image, sizeof(image), 1, stream);
+
+ if ( image.pd_tag != 'RNMp' )
+ goto errWHDimage;
+
+ if ( image.pd_depth != 1 )
+ goto errWHDimage;
+
+ width = image.pd_width;
+ height = image.pd_height;
+ depth = image.pd_depth;
+
+ printf("Image info: width: %d height: %d depth: %d...\n", image.pd_width, image.pd_height, image.pd_depth);
+
+ if (!(width && height && depth)) {
+ fprintf(stderr,"Err: Invalid image file header (width, height, or depth is 0)\n");
+ exit(1);
+ }
+
+ if ( !(fileArr = (char *)malloc(image.pd_dataSize))) {
+ fprintf(stderr,"Err: Couldn't malloc file data (%ld bytes)... bailing.\n", image.pd_dataSize);
+ exit(1);
+ }
+
+ /* read the data into a buffer */
+ fread(fileArr, image.pd_dataSize, 1, stream);
+ fclose(stream);
+
+ encodedSize = image.pd_dataSize - (256 * 3);
+
+ for(sum=0,i=0; i<encodedSize; i++)
+ {
+ sum += fileArr[i];
+ sum <<= sum&1;
+ }
+
+ if (debug) printf("WHD sum = %x\n", sum);
+
+ if ( sum != image.pd_sum )
+ goto errWHDimage;
+
+ for(pixels=0,i=0; i<encodedSize;)
+ {
+ unsigned int quantity, depth;
+ unsigned char * value;
+
+ i += decode_rle( &fileArr[i], &quantity, &depth, &value );
+ pixels += quantity * depth;
+ }
+
+ if ( debug) printf("pixels = %d sum = %x\n", pixels, sum);
+ if ( debug) printf("es = %d H*W = %d sum = %x\n", encodedSize, image.pd_height*image.pd_width, image.pd_sum);
+
+ if ( !(data = (char *)malloc(pixels))) {
+ fprintf(stderr,"Err: Couldn't malloc file data (%ld bytes)... bailing.\n", pixels);
+ exit(1);
+ }
+
+ {
+ unsigned int quantity, line, col, depth, sum;
+ unsigned char * dataIn, * value;
+
+ sum = 0;
+ pixels_out = 0;
+ dataIn = fileArr;
+ quantity = 0;
+ for (line=0; line < height; line++) {
+ for (col=0; col < width; col++) {
+
+ if ( quantity == 0 ) {
+ dataIn += decode_rle( dataIn, &quantity, &depth, &value );
+ i = 0;
+ sum += quantity * depth;
+ }
+ data[pixels_out++] = value[i++];
+
+ if ( i == depth )
+ {
+ i = 0;
+ quantity--;
+ }
+ }
+ }
+ if (debug) printf("total Q*D = %d\n", sum);
+ }
+
+ if( pixels_out != pixels )
+ {
+ printf("Err: miscalclulated pixels %d pixels_out %d\n", pixels, pixels_out);
+ exit(1);
+ }
+
+ panic_clut = CreateCLUTarry( &fileArr[image.pd_dataSize-(256*3)] );
+
+ qtraw = "panic_image.qtif";
+ }
+
+ if ( qtraw )
+ {
+ FILE * ostream;
+
+ if ( (ostream = fopen(qtraw, "wb")) == NULL ) {
+ fprintf(stderr,"Err: Could not open output file %s.\n\n", qtraw);
+ exit(1);
+ }
+
+ printf("Creating image %s in QuickTime No Compression %s %s format...\n", qtraw,
+ (depth==3)?"Millions of":"256", (grey==0)?"colors":"grays");
+
+ WriteQTRawFile( ostream, data, height, width, depth, pixels );
+ fclose(ostream);
+ }
+
+ if ( depth != 1 )
+ {
+ printf("Depth != 1 (8-bit), skipping writing output..\n");
+ goto leaveOK;
+ }
+
+ printf("Encoding image file...\n");
+
+ if (!(fileArr = (unsigned char *) malloc(pixels))) {
+ fprintf(stderr,"Err: Couldn't malloc fileArr (%d pixels)... bailing.\n", pixels);
+ exit(1);
+ }
+
+ encodedSize = EncodeImage( data, pixels, fileArr );
+ if ( encodedSize >= pixels )
+ {
+ printf("Skipping encoding...\n");
+ }
+
+ for (sum=0,i=0; i<encodedSize; i++)
+ {
+ sum += fileArr[i];
+ sum <<= sum&1;
+ }
+
+ // write raw image suitable for kernel panic dialog
+ if ( kraw )
+ {
+ FILE * ostream;
+ unsigned int tag;
+
+ if ( (ostream = fopen(kraw, "wb")) == NULL ) {
+ fprintf(stderr,"Err: Could not open output file %s.\n\n", kraw);
+ exit(1);
+ }
+
+ printf("Writing to binary panic dialog file %s, which is suitable for loading into kernel...\n", kraw);
+
+ tag = 'RNMp'; // Raw NMage for Panic dialog
+ depth = 1; // only CLUT is supported
+
+ fwrite(&sum, sizeof(sum), 1, ostream);
+ sum = encodedSize;
+ encodedSize += (256*3);
+ fwrite(&encodedSize, sizeof(encodedSize), 1, ostream);
+ encodedSize = sum;
+ fwrite(&tag, sizeof(tag), 1, ostream);
+ fwrite(&width, sizeof(width), 1, ostream);
+ fwrite(&height, sizeof(height), 1, ostream);
+ fwrite(&depth, sizeof(depth), 1, ostream);
+ fwrite(&lines, sizeof(lines), 1, ostream);
+ fwrite(&fg, sizeof(fg), 1, ostream);
+ fwrite(&bg, sizeof(bg), 1, ostream);
+ fwrite(fileArr, encodedSize, 1, ostream);
+
+ for ( i=0; i<256; i++)
+ {
+ union colors c;
+ unsigned char arr[3];
+
+ c.c24 = panic_clut[i];
+
+ arr[0] = c.clut.red;
+ arr[1] = c.clut.green;
+ arr[2] = c.clut.blue;
+ fwrite(arr, 3, 1, ostream);
+ }
+ fclose(ostream);
+ if ( out == NULL ) goto leaveOK;
+ }
+
+ // it's ok to generate the c file
+
+ if ( out == NULL ) out = "panic_image.c";
+ out_stream = fopen(out, "w");
+
+ if(out_stream == NULL) {
+ fprintf(stderr,"Err: Couldn't open out file %s.\n\n", out);
+ exit(1);
+ }
+
+ printf("Writing C source %s, suitable for including into kernel build...\n", out);
+
+ fprintf( out_stream, "/* autogenerated with genimage.c using %s as image input */\n", file);
+ {
+ char * s = "the built-in appleClut8";
+ if ( clutin )
+ s = clutin;
+ fprintf( out_stream, "/* and %s for the color look up table (CLUT) */\n\n", s);
+ }
+
+ fprintf( out_stream, "static const struct panicimage {\n");
+ fprintf( out_stream, "\tunsigned int\tpd_sum;\n");
+ fprintf( out_stream, "\tunsigned int\tpd_dataSize;\n");
+ fprintf( out_stream, "\tunsigned int\tpd_tag;\n");
+ fprintf( out_stream, "\tunsigned short\tpd_width;\n");
+ fprintf( out_stream, "\tunsigned short\tpd_height;\n");
+ fprintf( out_stream, "\tunsigned char\tpd_depth;\n");
+ fprintf( out_stream, "\tunsigned char\tpd_info_height;\n");
+ fprintf( out_stream, "\tunsigned char\tpd_info_color[2];\n");
+ fprintf( out_stream, "\tunsigned char\tdata[];\n");
+
+ fprintf( out_stream, "} panic_dialog_default = {\n\t");
+ fprintf( out_stream, "0x%08x, ", sum); /* panic dialog x */
+ fprintf( out_stream, "0x%08x, ", encodedSize+(256*3)); /* panic dialog x */
+ fprintf( out_stream, "0x%08x, ", 'RNMp'); /* panic dialog x */
+ fprintf( out_stream, "%d, ", width); /* panic dialog x */
+ fprintf( out_stream, "%d, ", height); /* panic dialog y */
+ fprintf( out_stream, "%d, ", depth); /* bytes per pixel */
+ fprintf( out_stream, "%d, ", lines); /* lines reserved for panic info */
+ fprintf( out_stream, "0x%02x, ", fg); /* font foreground color: indexed */
+ fprintf( out_stream, "0x%02x, ", bg); /* font background color: indexed */
+
+ fprintf( out_stream, "\n");
+
+ chars_this_line = 0;
+ fprintf( out_stream, "{\n");
+
+ for( i=0; i < encodedSize;)
+ {
+ chars_this_line += fprintf( out_stream, "0x%.2x,", fileArr[i++]);
+
+ if (i >= encodedSize) // this is the last element
+ break;
+
+ if(chars_this_line >= 80) {
+ fprintf( out_stream, "\n");
+ chars_this_line = 0;
+ }
+ }
+
+
+ if (debug)
+ {
+ printf("Encoded size = %d\n", encodedSize);
+ printf("Decoded size = %d\n", pixels);
+ }
+
+ fprintf(out_stream, "\n\n");
+ for ( i=0; i<256; i+=4)
+ {
+ union colors c;
+
+ if ( (i % 16) == 0 ) fprintf(out_stream, "// %02X\n", i);
+ c.c24 = panic_clut[i+0];
+ fprintf(out_stream, "\t0x%02X,0x%02X,0x%02X, ", c.clut.red, c.clut.green, c.clut.blue);
+ c.c24 = panic_clut[i+1];
+ fprintf(out_stream, "0x%02X,0x%02X,0x%02X, ", c.clut.red, c.clut.green, c.clut.blue);
+ c.c24 = panic_clut[i+2];
+ fprintf(out_stream, "0x%02X,0x%02X,0x%02X, ", c.clut.red, c.clut.green, c.clut.blue);
+ c.c24 = panic_clut[i+3];
+ fprintf(out_stream, "0x%02X,0x%02X,0x%02X%s\n", c.clut.red, c.clut.green, c.clut.blue, ((i!=(256-4))?",":""));
+ }
+
+ fprintf(out_stream, "}\n");
+ fprintf(out_stream, "};\n");
+
+ fclose( out_stream );
+
+leaveOK:
+ printf("\n");
+ return 0;
+
+errQTimage:
+ fprintf(stderr,"Err: Image must be in the QuickTime Raw Uncompressed Millions or 256 Colors format\n");
+ exit(1);
+errWHDimage:
+ fprintf(stderr,"Err: Image must be in the WHD Raw 256 Colors format\n");
+ exit(1);
+}
+
+
+
+#define RUN_MAX ((1<<20)-1)
+
+union RunData {
+ unsigned int i;
+ unsigned char c[4];
+};
+
+unsigned int encode_rle(
+ unsigned char * fileArr,
+ unsigned int filePos,
+ unsigned int quantity,
+ union RunData * value,
+ int depth);
+
+int
+compareruns( unsigned char * data, unsigned int * index, unsigned int max, union RunData * currP, int * depth )
+{
+ unsigned int i = *index;
+ union RunData * nextP;
+ static int retc = 0;
+
+ if ( currP == NULL || data == NULL )
+ {
+ retc = 0;
+ goto Leave;
+ }
+
+ if ( (*index+*depth) > max )
+ {
+ *depth = 1;
+ retc = 0;
+ goto Leave;
+ }
+
+ nextP = (union RunData *) &data[*index];
+
+ if ( retc == 1 )
+ {
+ // check current data against current depth
+ switch ( *depth )
+ {
+ case 1:
+ if ( nextP->c[0] == currP->c[0] )
+ goto Leave;
+ break;
+ case 2:
+ if ( nextP->c[0] == currP->c[0] &&
+ nextP->c[1] == currP->c[1] )
+ goto Leave;
+ break;
+ case 3:
+ if ( nextP->c[0] == currP->c[0] &&
+ nextP->c[1] == currP->c[1] &&
+ nextP->c[2] == currP->c[2] )
+ goto Leave;
+ break;
+ case 4:
+ if ( nextP->c[0] == currP->c[0] &&
+ nextP->c[1] == currP->c[1] &&
+ nextP->c[2] == currP->c[2] &&
+ nextP->c[3] == currP->c[3] )
+ goto Leave;
+ break;
+ }
+
+ retc = 0;
+ goto Leave;
+ }
+
+ // start of a new pattern match begine with depth = 1
+
+ if ( (*index+6) <= max )
+ {
+ // We have at least 8 bytes left in the buffer starting from currP
+#if 1
+ nextP = (union RunData *) &data[*index+3];
+ if ( nextP->c[0] == currP->c[0] &&
+ nextP->c[1] == currP->c[1] &&
+ nextP->c[2] == currP->c[2] &&
+ nextP->c[3] == currP->c[3] )
+ {
+ // check if they are all the same value
+ if ( currP->c[0] == currP->c[1] &&
+ currP->c[1] == currP->c[2] &&
+ currP->c[2] == currP->c[3] )
+ { // if so, leave at depth = 1
+ retc = 1;
+ *depth = 1;
+ goto Leave;
+ }
+
+ if (debug>2) printf("Found 4 at %x\n", *index);
+ retc = 1;
+ *depth = 4;
+ *index += 3;
+ goto Leave;
+ }
+
+ nextP = (union RunData *) &data[*index+2];
+ if ( nextP->c[0] == currP->c[0] &&
+ nextP->c[1] == currP->c[1] &&
+ nextP->c[2] == currP->c[2] )
+ {
+ // check if they are all the same value
+ if ( currP->c[0] == currP->c[1] &&
+ currP->c[1] == currP->c[2] )
+ { // if so, leave at depth = 1
+ retc = 1;
+ *depth = 1;
+ goto Leave;
+ }
+
+ if (debug>2) printf("Found 3 at %x\n", *index);
+ retc = 1;
+ *depth = 3;
+ *index += 2;
+ goto Leave;
+ }
+
+ nextP = (union RunData *) &data[*index+1];
+ if ( nextP->c[0] == currP->c[0] &&
+ nextP->c[1] == currP->c[1] )
+ {
+ // check if they are all the same value
+ if ( currP->c[0] == currP->c[1] )
+ { // if so, leave at depth = 1
+ retc = 1;
+ *depth = 1;
+ goto Leave;
+ }
+
+ if (debug>2) printf("Found 2 at %x\n", *index);
+ retc = 1;
+ *depth = 2;
+ *index += 1;
+ goto Leave;
+ }
+
+#endif
+ nextP = (union RunData *) &data[*index];
+
+ }
+
+ if ( nextP->c[0] == currP->c[0] )
+ retc = 1;
+ else
+ retc = 0;
+
+Leave:
+
+ if ( retc == 1 )
+ *index += *depth;
+
+ return retc;
+}
+
+int
+EncodeImage( unsigned char * data, int pixels, unsigned char * fileArr )
+{
+ union RunData * currP, * norunP ;
+ int i, match, depth;
+ unsigned int filePos, run, nomatchrun;
+
+ currP = NULL;
+ norunP = NULL;
+ nomatchrun = 0;
+ filePos = 0; // position in the file we're writing out
+ run = 1;
+ depth = 1;
+
+ currP = (union RunData *)&data[0]; // start a new run
+ for (i=1; i<pixels;)
+ {
+ if ( compareruns( data, &i, pixels, currP, &depth ) )
+ run++;
+ else
+ {
+ if ( (run*depth) > 2 )
+ {
+ unsigned char * p = (unsigned char *)norunP;
+
+ if( nomatchrun )
+ {
+ while (nomatchrun)
+ {
+ int cnt;
+
+ cnt = (nomatchrun > 127) ? 127 : nomatchrun;
+ fileArr[filePos++] = cnt;
+ nomatchrun -= cnt;
+
+ while ( cnt-- )
+ fileArr[filePos++] = *p++;
+ }
+ }
+
+ filePos += encode_rle(fileArr, filePos, run, currP, depth);
+
+ norunP = NULL;
+ }
+ else
+ {
+ nomatchrun+=run;
+ }
+
+ currP = (union RunData *)&data[i]; // start a new run
+
+ if( norunP == NULL )
+ {
+ nomatchrun = 0;
+ norunP = currP;
+ }
+
+ depth = 1; // switch back to a single byte depth
+ run = 1; // thee is always at least one entry
+ i++; // point to next byte
+ }
+ }
+
+ if( nomatchrun )
+ {
+ unsigned char * p = (unsigned char *)norunP;
+ while (nomatchrun)
+ {
+ int cnt;
+
+ cnt = (nomatchrun > 127) ? 127 : nomatchrun;
+ fileArr[filePos++] = cnt;
+ nomatchrun -= cnt;
+
+ while ( cnt-- )
+ fileArr[filePos++] = *p++;
+ }
+ }
+
+ // write out any run that was in progress
+ if (run > 0) {
+ filePos += encode_rle(fileArr, filePos, run, currP, depth);
+ }
+
+ return filePos;
+}
+
+/* encode_rle applies a "modified-RLE encoding to a given image. The encoding works as follows:
+
+ The quantity is described in the first byte. If the MSB is zero, then the next seven bits
+ are the quantity. If the MSB is set, bits 0-3 of the quantity are in the least significant bits.
+ If bit 5 is set, then the quantity is further described in the next byte, where an additional
+ 7 bits (4-10) worth of quantity will be found. If the MSB of this byte is set, then an additional
+ 7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of
+ a quantity byte is zero, thus ending the chain.
+
+ The value is described in the first byte. If the MSB is zero, then the value is in the next byte.
+ If the MSB is set, then bits 5/6 describe the number of value bytes following the quantity bytes.
+
+ encodings are: (q = quantity, v = value, c = quantity continues)
+
+ Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 Byte 7 Byte 8
+ case 1: [ 0 q6-q0 ] [ v7-v0 ]
+ case 2: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ]
+ case 3: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ]
+ case 4: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
+ case 5: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
+*/
+
+unsigned int
+encode_length(unsigned char * fileArr, unsigned int filePos, unsigned int quantity, unsigned int mask)
+{
+ unsigned char single_mask = 0x0F;
+ unsigned char double_mask = 0x7F;
+ unsigned int slots_used = 0;
+
+ fileArr[filePos] = mask | (quantity & single_mask); // low bits (plus mask)
+ slots_used++;
+
+ if (quantity >>= 4)
+ {
+ fileArr[filePos++] |= 0x10; // set length continuation bit
+ fileArr[filePos] = quantity & double_mask;
+ slots_used++;
+
+ while (quantity >>= 7)
+ {
+ fileArr[filePos++] |= 0x80; // set length continuation bit
+ fileArr[filePos] = quantity & double_mask;
+ slots_used++;
+ }
+ }
+
+ return slots_used;
+}
+
+
+unsigned int
+encode_rle(unsigned char * fileArr, unsigned int filePos, unsigned int quantity, union RunData * value, int depth)
+{
+ unsigned char single_mask = 0x0F;
+ unsigned char double_mask = 0x7F;
+ unsigned char slots_used = 0;
+
+
+ switch ( depth )
+ {
+ case 1:
+ slots_used += encode_length( fileArr, filePos, quantity, 0x80 );
+ fileArr[filePos+slots_used++] = value->c[0];
+ break;
+
+ case 2:
+ slots_used += encode_length( fileArr, filePos, quantity, 0xA0 );
+ fileArr[filePos+slots_used++] = value->c[0];
+ fileArr[filePos+slots_used++] = value->c[1];
+ break;
+
+ case 3:
+ slots_used += encode_length( fileArr, filePos, quantity, 0xC0 );
+ fileArr[filePos+slots_used++] = value->c[0];
+ fileArr[filePos+slots_used++] = value->c[1];
+ fileArr[filePos+slots_used++] = value->c[2];
+ break;
+
+ case 4:
+ slots_used += encode_length( fileArr, filePos, quantity, 0xE0 );
+ fileArr[filePos+slots_used++] = value->c[0];
+ fileArr[filePos+slots_used++] = value->c[1];
+ fileArr[filePos+slots_used++] = value->c[2];
+ fileArr[filePos+slots_used++] = value->c[3];
+ break;
+ }
+
+ return slots_used;
+}
+
+int
+decode_rle( unsigned char * dataPtr, unsigned int * quantity, unsigned int * depth, unsigned char ** value )
+{
+ unsigned int mask;
+ int i, runlen, runsize;
+
+ i = 0;
+ mask = dataPtr[i] & 0xF0;
+
+ if ( mask & 0x80 )
+ {
+ runsize = ((mask & 0x60) >> 5) + 1;
+ runlen = dataPtr[i++] & 0x0F;
+
+ if ( mask & 0x10 )
+ {
+ int shift = 4;
+
+ do
+ {
+ mask = dataPtr[i] & 0x80;
+ runlen |= ((dataPtr[i++] & 0x7F) << shift);
+ shift+=7;
+ } while (mask);
+ }
+ } else
+ {
+ runlen = 1;
+ runsize = dataPtr[i++];
+ }
+
+ *depth = runsize;
+ *quantity = runlen;
+ *value = &dataPtr[i];
+
+ return i+runsize;
+}
+
+int
+findIndexNearMatch( unsigned int color24 )
+{
+ union colors color8;
+ union colors clut8;
+ int isGrey = 0;
+
+ color8.c24 = color24;
+
+ if ( color8.clut.red == color8.clut.green && color8.clut.green == color8.clut.blue )
+ isGrey = 1;
+
+ if ( isGrey ) {
+ int i;
+ unsigned int bestIndex = 0, rel, bestMatch = -1;
+
+ for (i=0; i<256; i++)
+ {
+ clut8.c24 = panic_clut[i];
+
+ if ( clut8.clut.red != clut8.clut.green || clut8.clut.green != clut8.clut.blue )
+ continue;
+
+ if ( clut8.clut.red > color8.clut.red) continue;
+ rel = abs(color8.clut.red - clut8.clut.red);
+ if ( rel < bestMatch ) {
+ bestMatch = rel;
+ bestIndex = i;
+ }
+ }
+
+ return bestIndex;
+ }
+
+ // we must have a non-grey color
+ return -1;
+}
+
+unsigned int
+color24toGrey( unsigned int color24 )
+{
+ float R, G, B;
+ float Grey;
+ union colors c;
+ unsigned char grey8;
+ unsigned int grey24;
+
+ c.c24 = color24;
+
+ R = (c.clut.red & 0xFF) ;
+ G = (c.clut.green & 0xFF) ;
+ B = (c.clut.blue & 0xFF) ;
+
+ Grey = (R*.30) + (G*.59) + (B*.11);
+ grey8 = (unsigned char) ( Grey + .5);
+ grey24 = (grey8<<16) | (grey8<<8) | grey8;
+ return grey24;
+}
+
+int
+convert24toGrey( unsigned char * data, unsigned int size )
+{
+ float R, G, B;
+ float Grey;
+ unsigned int grey8;
+ int i24;
+
+
+ for ( i24=0; i24<size; i24+=3)
+ {
+ R = ((data[i24+0]) & 0xFF) ;
+ G = ((data[i24+1]) & 0xFF) ;
+ B = ((data[i24+2]) & 0xFF) ;
+
+ Grey = (R*.30) + (G*.59) + (B*.11);
+ grey8 = (unsigned int) ( Grey + .5);
+
+ data[i24+0] = grey8;
+ data[i24+1] = grey8;
+ data[i24+2] = grey8;
+ }
+
+ return size;
+}
+
+int
+convert8toGrey( unsigned char * data, unsigned int size )
+{
+ int i;
+ unsigned int c24;
+ union colors c;
+
+ for ( i=0; i<size; i++)
+ {
+ c.c24 = panic_clut[data[i]];
+ c24 = color24toGrey( c.c24 );
+ data[i] = findIndexMatch( c24 );
+ }
+
+ return size;
+}
+
+unsigned int
+findColor24NearMatch( unsigned int color24 )
+{
+ union colors c, i_color;
+ unsigned char d=0xff, d_red, d_green, d_blue, i, prim;
+ static unsigned int last_c = -1, last_co = -1, last_p = -1;
+
+ if ( last_c == color24 )
+ return last_co;
+
+ c.c24 = color24;
+
+ if ( c.rgb[1] > c.rgb[2] && c.rgb[1] > c.rgb[3] )
+ prim = 1;
+ else if ( c.rgb[2] > c.rgb[1] && c.rgb[2] > c.rgb[3] )
+ prim = 2;
+ else if ( c.rgb[3] > c.rgb[1] && c.rgb[3] > c.rgb[2] )
+ prim = 3;
+ else if ( c.rgb[1] == c.rgb[2] && c.rgb[1] == c.rgb[3] )
+ prim = 0; // gray
+ else if ( c.rgb[1] == c.rgb[2] )
+ prim = 0x12; // red green
+ else if ( c.rgb[1] == c.rgb[3] )
+ prim = 0x13; // red blue
+ else if ( c.rgb[2] == c.rgb[3] )
+ prim = 0x23; // green blue
+ else
+ printf("cannot tell color %06x\n", color24);
+
+ last_c = color24;
+ last_p = prim;
+
+ if ( prim == 0 || prim > 3 )
+ {
+ last_co = -1;
+ return last_co;
+ }
+
+#if 0
+ for (i=0; i<256; i++)
+ {
+
+ break;
+ }
+#endif
+
+ return -1;
+}
+
+
+unsigned char
+findIndexMatch( unsigned int color24 )
+{
+ int i;
+ unsigned char ri;
+ static unsigned char last = 0;
+
+retry:
+ if ( panic_clut[last] == color24 )
+ {
+ exactmatch++;
+ return last;
+ }
+
+ for (i=0; i<256; i++)
+ {
+ if ( panic_clut[i] == color24 ) {
+ last = i;
+ exactmatch++;
+ return last;
+ }
+ }
+
+ if ( nextmis == -1 ) {
+ for (i=0; i<256; i++) mismatchClut[i] = -1;
+ nextmis = 0;
+ }
+
+ i = findIndexNearMatch(color24);
+
+ if ( i == -1 ) // found a color that is not grey
+ {
+ unsigned int colormatch = findColor24NearMatch( color24 );
+
+ if ( colormatch == -1 ) // cannot convert color
+ {
+ cvt2grey++;
+ if (debug>1) printf("color %06X not matched at all\n", color24);
+ color24 = color24toGrey(color24);
+ if (debug>1) printf("now grey %06X\n", color24);
+ }
+ else
+ color24 = colormatch;
+
+ goto retry;
+ }
+
+ if (debug>1) printf("color %06X now matched at %x\n", color24, i);
+
+ ri = i;
+
+ neargrey++;
+
+ // keep track of missed repeats
+ for ( i=0; i<nextmis; i++)
+ if ( mismatchClut[i] == color24 )
+ return ri;
+
+ if ( debug) printf("closest match for %06X is at index %d %06X\n", color24, ri, panic_clut[ri]);
+ if ( nextmis < 256 )
+ mismatchClut[nextmis++] = color24;
+
+ if ( debug && (nextmis >= 256) )
+ {
+ fprintf(stderr,"Err: Too many color mismatches detected with this CLUT\n");
+ exit(1);
+ }
+
+ return ri;
+}
+
+/*
+ * Convert 24 bit mode to 8 bit. We do not do any alignment conversions
+ */
+
+int
+convert24to8bitIndex( unsigned char * data, int height, int width, unsigned char ** dout )
+{
+ unsigned int row, col, i, i24, i8, size;
+ unsigned char index;
+ unsigned char * ddata;
+ union colors color24;
+
+ size = height * width;
+
+ ddata = (unsigned char *) calloc( size, 1);
+
+ for (i24=0,i8=0,row=0; row<height; row++)
+ {
+ for (col=0; col<width; col++)
+ {
+ color24.clut.red = data[i24++];
+ color24.clut.green = data[i24++];
+ color24.clut.blue = data[i24++];
+
+ index = findIndexMatch( color24.c24 );
+ ddata[i8++] = index;
+ }
+ }
+
+ * dout = ddata;
+
+ return (i8);
+}
+
+/*
+ * Convert 8 bit mode to 8 bit, We have to strip off the alignment bytes
+ */
+
+int
+convert8bitIndexto8( unsigned char * data, int height, int width, unsigned char ** dout )
+{
+ unsigned int row, col, i, i8, size, adj;
+ unsigned char index;
+ unsigned char * ddata;
+ union colors color24;
+
+ adj=(4-(width%4))%4; // adjustment needed to strip off the word alignment padding
+ size = height * width;
+ ddata = (unsigned char *) calloc( size, 1);
+
+ for (i8=0,row=0; row<height; row++)
+ {
+ for (col=0; col<width; col++)
+ {
+ index = *data++;
+ color24.c24 = panic_clut[index];
+ index = findIndexMatch( color24.c24 );
+ ddata[i8++] = index;
+ }
+
+ for (i=0; i<adj; i++)
+ data++;
+ }
+
+ * dout = ddata;
+
+ return (i8);
+}
+/*
+ * Convert 8 bit mode to 24 bit, We have to strip off the alignment bytes
+ */
+
+int
+convert8bitIndexto24( unsigned char * data, int height, int width, unsigned char ** dout )
+{
+ unsigned int row, col, i, i24, i8, size, adj;
+ unsigned char index;
+ unsigned char * ddata;
+ union colors color24;
+
+ adj=(4-(width%4))%4; // adjustment needed to strip off the word alignment padding
+ size = height * width;
+ ddata = (unsigned char *) calloc( size, 3);
+
+ for (i24=0,i8=0,row=0; row<height; row++)
+ {
+ for (col=0; col<width; col++)
+ {
+ index = data[i8++];
+ color24.c24 = panic_clut[index];
+
+ ddata[i24++] = color24.clut.red;
+ ddata[i24++] = color24.clut.green;
+ ddata[i24++] = color24.clut.blue;
+ }
+
+ for (i=0; i<adj; i++)
+ i8++;
+ }
+
+ * dout = ddata;
+
+ return (i24);
+}
+
+
+unsigned int *
+CreateCLUTarry( unsigned char * raw_clut )
+{
+ unsigned int * new_clut, index, i;
+
+ new_clut = (unsigned int *) calloc(256, sizeof(unsigned int));
+ for ( index=0,i=0; i<256; index+=3,i++ )
+ new_clut[i] = (raw_clut[index] << 16) | (raw_clut[index+1] << 8) | raw_clut[index+2];
+
+ return new_clut;
+}
+
+
+unsigned int *
+ReplaceCLUT( char * iname )
+{
+ FILE * stream;
+ unsigned char * raw_clut;
+ unsigned int * new_clut, index, i;
+
+ if ( (stream = fopen(iname, "rb")) == NULL ) {
+ fprintf(stderr,"Err: Could not open input clut file %s.\n\n", iname);
+ exit(1);
+ }
+
+ raw_clut = (char *) calloc(256, 3);
+ fread(raw_clut, 256, 3, stream);
+ fclose(stream);
+
+ new_clut = CreateCLUTarry( raw_clut );
+
+ free(raw_clut);
+ return new_clut;
+}
+
+
+void
+GenerateCLUT( char * oname )
+{
+ FILE * ostream;
+ int i;
+
+
+ if ( (ostream = fopen(oname, "w")) == NULL ) {
+ fprintf(stderr,"Err: Could not open output clut file %s.\n\n", oname);
+ exit(1);
+ }
+
+ printf("Generating new CLUT array named %s\n", oname);
+ fprintf(ostream, "// This Clut was generated from %s\n", (clutin)?clutin:"built-in appleClut8");
+ fprintf(ostream, "unsigned int appleClut8[256] = {\n");
+ for ( i=0; i<256; i+=8)
+ {
+ if ( (i % 16) == 0 ) fprintf(ostream, "// %02X\n", i);
+ fprintf(ostream, "\t0x%06X, 0x%06X, 0x%06X, 0x%06X, 0x%06X, 0x%06X, 0x%06X, 0x%06X%s\n",
+ panic_clut[i+0], panic_clut[i+1], panic_clut[i+2], panic_clut[i+3],
+ panic_clut[i+4], panic_clut[i+5], panic_clut[i+6], panic_clut[i+7], ((i!=(256-8))?",":""));
+ }
+ fprintf(ostream, "};\n");
+ fclose(ostream);
+}
+
+void
+WriteQTRawFile( FILE * ostream, unsigned char * data, int height, int width, int depth, unsigned int size )
+{
+ unsigned int i, adj, csize, tmp, col, line;
+
+
+ if ( depth == 1)
+ adj=(4-(width%4))%4; // adjustment needed to add the word alignment padding
+ else
+ adj = 0;
+
+ csize = height*depth*(width+adj);
+
+ if( debug && csize != size )
+ printf("Adjusted Computed size (%d=H*W*D) to account to account for word alignment %d(%d)\n", size,csize,csize-size);
+
+ tmp = csize + ( 2 * sizeof(unsigned int) );
+ fwrite(&tmp, sizeof(unsigned int), 1, ostream);
+
+ tmp = 'idat';
+ fwrite(&tmp, sizeof(unsigned int), 1, ostream);
+
+ if ( depth == 1)
+ {
+ for (line=0; line<height; line++)
+ {
+ for (col=0; col<width; col++)
+ fwrite(data++, 1, 1, ostream);
+
+ for (i=0; i<adj; i++)
+ fwrite(&data[-1], 1, 1, ostream);
+ }
+ } else
+ fwrite(data, csize, 1, ostream);
+
+ tmp = 0x5e;
+ fwrite(&tmp, sizeof(unsigned int), 1, ostream);
+ tmp = 'idsc';
+ fwrite(&tmp, sizeof(unsigned int), 1, ostream);
+
+ image_header.idSize = sizeof(image_header) - 2;
+ image_header.cType = 'raw ';
+ image_header.dataRefIndex = 0;
+ image_header.version = 1;
+ image_header.revisionLevel = 1;
+ image_header.vendor = 'appl';
+ image_header.temporalQuality = 0;
+ image_header.spatialQuality = 1024-1;
+ image_header.width = width;
+ image_header.height = height;
+ image_header.hRes = 72 << 16;
+ image_header.vRes = 72 << 16;
+ image_header.dataSize = csize;
+ image_header.frameCount = 1;
+ strcpy(image_header.name, " None");
+ image_header.name[0] = 4;
+ image_header.depth = depth*8;
+ image_header.clutID = (depth==1) ? 8 : -1;
+
+ fwrite(&image_header, sizeof(image_header)-2, 1, ostream);
+}
+
+
+void
+CreateRawQTCLUT( int type )
+{
+ FILE * ostream;
+ char * name;
+ unsigned char * raw_clut, * p;
+ int row, i;
+ int H=32, W=32, D;
+
+ if ( type == 8 )
+ {
+ name = "appleclut8.qtif";
+ D = 1;
+ }
+ else
+ {
+ name = "unknownclut.qtif";
+ D = 3;
+ }
+
+ if ( (ostream = fopen(name, "wb")) == NULL ) {
+ fprintf(stderr,"Err: Could not open output index file %s.\n\n", name);
+ exit(1);
+ }
+
+ raw_clut = (unsigned char *) malloc(H*W*D*256);
+
+ for (p=raw_clut, row=0; row<H; row++)
+ {
+ for (i=0; i<256; i++)
+ {
+ int j;
+ union colors c;
+
+ if ( D == 3 )
+ c.c24 = panic_clut[i];
+
+ for (j=0; j<W; j++)
+ {
+ if ( D == 1 )
+ *p++ = i;
+ else
+ {
+ *p++ = c.clut.red;
+ *p++ = c.clut.green;
+ *p++ = c.clut.blue;
+ }
+ }
+ }
+ }
+ WriteQTRawFile( ostream, (unsigned char *) raw_clut, H, 256*W, D, H*256*W*D );
+
+ fclose(ostream);
+}
+
+
+void
+CreateRawQTFont( void )
+{
+ FILE * ostream;
+ unsigned char fonts[16][256][8];
+ int row, i;
+
+ if ( (ostream = fopen("font.qtif", "wb")) == NULL ) {
+ fprintf(stderr,"Err: Could not open output index file %s.\n\n", "font.qtif");
+ exit(1);
+ }
+
+ for (row=0; row<16; row++)
+ {
+ for (i=0; i<256; i++)
+ {
+ int j;
+ unsigned char * c;
+ unsigned char bits;
+
+ c = &iso_font[i*16];
+ bits = c[row];
+ for (j=7; j>=0; j--)
+ {
+ if ( bits & 0x80)
+ fonts[row][i][j] = fg;
+ else
+ fonts[row][i][j] = bg;
+ bits <<= 1;
+ }
+ }
+ }
+
+ WriteQTRawFile( ostream, (unsigned char *) fonts, 16, 256*8, 1, 16*256*8 );
+ fclose(ostream);
+}