]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/console/panic_ui/genimage.c
xnu-792.tar.gz
[apple/xnu.git] / osfmk / console / panic_ui / genimage.c
diff --git a/osfmk/console/panic_ui/genimage.c b/osfmk/console/panic_ui/genimage.c
new file mode 100644 (file)
index 0000000..2c1ecd1
--- /dev/null
@@ -0,0 +1,1621 @@
+/* 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);
+}