]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/console/panic_ui/genimage.c
1 /* converts a QT RAW image file into the c structure that the
2 * kernel panic ui system expects.
4 * to build: cc -o genimage genimage.c
10 #include <sys/types.h>
17 unsigned char * fileArr
);
19 unsigned char * dataPtr
,
20 unsigned int * quantity
,
22 unsigned char ** value
);
23 int findIndexNearMatch(
24 unsigned int color24
);
25 unsigned char findIndexMatch(
26 unsigned int color24
);
33 int convert8bitIndexto24(
37 unsigned char ** dout
);
38 int convert8bitIndexto8(
42 unsigned char ** dout
);
43 int convert24to8bitIndex(
47 unsigned char ** dout
);
48 unsigned int * CreateCLUTarry(
49 unsigned char * raw_clut
);
50 unsigned int * ReplaceCLUT(
66 #define offsetof(type, field) ((size_t)(&((type *)0)->field))
70 unsigned int pd_dataSize
;
72 unsigned short pd_width
;
73 unsigned short pd_height
;
74 unsigned char pd_depth
;
75 unsigned char pd_info_height
;
76 unsigned char pd_info_color
[2];
88 "\tgenimage -i <.qtif> [operands ...]\n\n"
89 "\tThe following operands are available\n\n"
90 "\t-h\t\tDisplay full help information\n"
91 "\t-i <file>\tUse file containing QuickTime uncompressed raw image as\n"
92 "\t\t\tthe panic dialog (8 or 24 bit)\n"
93 "\t-o <file>\tWrite the output as a compressed WHD RAW image suitable\n"
94 "\t\t\tfor loading into the kernel\n"
95 "\t-c <file>\tUse file containing 256 RGB values for 8-bit indexed \n"
96 "\t\t\tlookups, overrides built-in appleClut8\n"
97 "\t-fg <color>\tForeground color of font used for panic information in\n"
98 "\t\t\t24-bits, default 0xFFFFFF (100%% white)\n"
99 "\t-bg <color>\tBackground color of font used for panic information in\n"
100 "\t\t\t24-bits, default 0x222222 (13%% white, dark gray)\n"
101 "\t-n <lines>\tNumber of lines that have been reserved to display the\n"
102 "\t\t\tpanic information, must be at least 20\n"
103 "\n\tThese are useful options for testing\n"
104 "\t-io <file>\tUse <file> to override the default C source filename\n"
105 "\t-bw\t\tConvert the input image to shades of gray\n"
106 "\t-n24\t\tConvert an image from 8 bit to 24 bit mode before\n"
108 "\t-n8\t\tDon't convert an image from 24 bit to 8 bit mode before \n"
109 "\t\t\tprocessing, default is to convert\n"
110 "\t-qt <file>\t(requires -i) Write QuickTime uncompressed raw .gtif\n"
111 "\t\t\tfile containing the input image in 8-bit format\n"
112 "\t-r\t\tCreate a Quicktime uncompressed image of the 8-bit\n"
113 "\t\t\tsystem CLUT named appleclut8.qtif <debugging>\n"
114 "\t-f\t\tCreate a Quicktime uncompressed image of the 8x16\n"
115 "\t\t\tbit panic info font named font.qtif <debugging>\n"
120 This utility is used to convert a panic dialog from .qtif format, into\n\
121 one that is suitable for the kernel to display. The .qtif image file\n\
122 can be in either 24 or 8 bit mode, but must be in an uncompressed raw\n\
123 format. 8 bit mode is preferred, as it requires no conversion to the\n\
124 colors that are contained in the CLUT. If a color cannot be found in\n\
125 the CLUT, it will be converted to the nearest gray. The default CLUT\n\
126 is the same as the system CLUT. If needed, this can be overridden by\n\
127 providing a new CLUT with the -c option.\n\
129 However, if you override the default CLUT. The panic UI may not appear\n\
130 as you intended, when the systme is in 8 bit mode. Colors that are not\n\
131 present in the active CLUT, will be converted to the nearest gray.\n\
133 The panic dialog must have a number of lines reserved at the bottom for\n\
134 displaying additional panic information. The minimum number of lines\n\
135 is 20. The font use to display this information needs to have the\n\
136 foreground and background colors defined. The defaults are full white\n\
137 on dark gray. This can be changed by using the -fg and/or -bg options to\n\
138 provide new 24 bit colors. These colors must be contained in the CLUT.\n\
140 There are two possible output results. The default is to create a C\n\
141 source file named panic_image.c that contains the panic image in a 8 bit\n\
142 modified RLE compressed format and the CLUT that was used to create the\n\
143 image. The second possibility is to create a binary version of the same\n\
144 information by using the -o option. This file can then be used to replace\n\
145 the panic dialog that is currently active in the kernel by using\n\
146 sysctl(KERN_PANIC_INFO).\n\
151 #include "appleclut8.h"
152 #include "../iso_font.c"
155 long idSize
; /* total size of ImageDescription including extra data ( CLUTs and other per sequence data ) */
156 long cType
; /* 'raw '; what kind of codec compressed this data */
157 long resvd1
; /* reserved for Apple use */
158 short resvd2
; /* reserved for Apple use */
159 short dataRefIndex
; /* set to zero */
160 short version
; /* which version is this data */
161 short revisionLevel
; /* what version of that codec did this */
162 long vendor
; /* whose codec compressed this data */
163 long temporalQuality
; /* what was the temporal quality factor */
164 long spatialQuality
; /* what was the spatial quality factor */
165 short width
; /* how many pixels wide is this data */
166 short height
; /* how many pixels high is this data */
167 long hRes
; /* horizontal resolution */
168 long vRes
; /* vertical resolution */
169 long dataSize
; /* if known, the size of data for this image descriptor */
170 short frameCount
; /* number of frames this description applies to */
171 char name
[32]; /* name of codec ( in case not installed ) */
172 short depth
; /* what depth is this data (1-32) or ( 33-40 grayscale ) */
173 short clutID
; /* clut id or if 0 clut follows or -1 if no clut */
176 static unsigned int mismatchClut
[256];
177 static int nextmis
= -1, neargrey
= 0, cvt2grey
= 0, exactmatch
=0;
178 static int grey
= 0, debug
= 0, testfont
= 0, testclut
= 0;
179 static int convert
= 8; // default is to convert image to 8 bit uncompressed .tgif
180 static unsigned char fg
, bg
;
181 unsigned int * panic_clut
= NULL
;
182 static char * clutin
= NULL
;
186 unsigned char rgb
[4];
196 main( int argc
, char *argv
[] )
202 char *clutout
= NULL
;
203 char *whdname
= NULL
;
204 FILE * stream
, *out_stream
;
205 unsigned char * data
;
206 unsigned short width
= 0, height
= 0;
207 unsigned char depth
= 0, lines
= 20;
208 unsigned int i
, pixels
, sum
, encodedSize
, fg24
= 0xFFFFFF, bg24
=0x222222;
209 unsigned char *fileArr
;
210 int chars_this_line
, next
, runindex
;
213 // pull apart the arguments
214 for( next
= 1; next
< argc
; next
++ )
216 if (strcmp(argv
[next
], "-i") == 0) // image file in raw QT uncompressed format (.qtif)
219 else if (strcmp(argv
[next
], "-o") == 0) // output file for WHD image
221 else if (strcmp(argv
[next
], "-io") == 0) // output file for image
224 else if (strcmp(argv
[next
], "-n") == 0) // numbers of reserved lines
225 lines
= atoi(argv
[++next
]);
226 else if (strcmp(argv
[next
], "-fg") == 0) // foreground color in 24 bits
227 sscanf(argv
[++next
], "%i", &fg24
);
228 else if (strcmp(argv
[next
], "-bg") == 0) // background color in 24 bits
229 sscanf(argv
[++next
], "%i", &bg24
);
230 else if (strcmp(argv
[next
], "-c") == 0) // input file for clut
231 clutin
= argv
[++next
];
232 else if (strcmp(argv
[next
], "-h") == 0) // display more help
233 { usage(1); exit(1); }
235 // useful testing options
236 else if (strcmp(argv
[next
], "-co") == 0) // output file for generating appleClut8.h array included in this file
237 clutout
= argv
[++next
];
238 else if (strcmp(argv
[next
], "-a8") == 0) // output file for testing system CLUT 8 in QT RAW (test)
240 else if (strcmp(argv
[next
], "-r") == 0) // output file for QT clut RAW (test)
242 else if (strcmp(argv
[next
], "-qt") == 0) // output file for QT RAW (test)
243 qtraw
= argv
[++next
];
244 else if (strcmp(argv
[next
], "-bw") == 0) // use only shades of grey (test)
246 else if (strcmp(argv
[next
], "-n8") == 0) // don't convert to 8 by default (test)
248 else if (strcmp(argv
[next
], "-n24") == 0) // convert to 8 to 24 (test)
250 else if (strcmp(argv
[next
], "-f") == 0) // test font (test)
252 else if (strcmp(argv
[next
], "-w") == 0) // read WHD raw file and output 8 bit tqif
253 whdname
= argv
[++next
];
255 else if (strcmp(argv
[next
], "-debug") == 0) // verbose
259 if (!(file
|| clutout
|| testfont
|| testclut
|| whdname
) ) {
266 panic_clut
= appleClut8
;
270 panic_clut
= ReplaceCLUT( clutin
);
271 printf("Built-in CLUT has been replaced with %s...\n", clutin
);
275 printf("Using CLUT from %s...\n", whdname
);
277 printf("Using Built-in CLUT...\n");
282 GenerateCLUT( clutout
);
283 printf("Created C source file of %s...\n", clutout
);
286 fg
= findIndexNearMatch(fg24
);
287 bg
= findIndexNearMatch(bg24
);
290 CreateRawQTCLUT(testclut
);
295 // Begin to process the image
299 if ( whdname
== NULL
)
302 printf("No image file was processed...\n\n");
308 printf("Verifing image file...\n");
311 stream
= fopen(file
, "r");
313 fprintf(stderr
, "Err: could not open .qtif image file.\n\n");
321 fread((void *) &hdr_off
, sizeof(long), 1, stream
);
322 fread((void *) &hdr_type
, sizeof(long), 1, stream
);
324 if ( hdr_type
!= 'idat' ) goto errQTimage
;
326 fseek(stream
, hdr_off
, SEEK_SET
);
327 fread((void *) &hdr_off
, sizeof(long), 1, stream
);
328 fread((void *) &hdr_type
, sizeof(long), 1, stream
);
330 if ( hdr_type
!= 'idsc' ) goto errQTimage
;
332 fread((void *) &image_header
, sizeof(image_header
), 1, stream
);
333 if ( image_header
.cType
!= 'raw ' ) goto errQTimage
;
334 if (( image_header
.depth
!= 8 ) && ( image_header
.depth
!= 24 )) goto errQTimage
;
336 width
= image_header
.width
;
337 height
= image_header
.height
;
338 depth
= image_header
.depth
;
340 printf("Image info: width: %d height: %d depth: %d...\n", width
, height
, depth
);
342 if (!(width
&& height
&& depth
)) {
343 fprintf(stderr
,"Err: Invalid image file header (width, height, or depth is 0)\n");
348 if ( !(data
= (char *)malloc(image_header
.dataSize
))) {
349 fprintf(stderr
,"Err: Couldn't malloc file data (%ld bytes)... bailing.\n", image_header
.dataSize
);
353 // Read the image data
354 fseek(stream
, 8, SEEK_SET
);
355 fread((void *) data
, image_header
.dataSize
, 1, stream
);
358 if ( kraw
&& image_header
.depth
== 24 )
360 fprintf(stderr
, "Err: The WHD raw file (%s) will not be created when input in is millions of colors\n", kraw
);
364 pixels
= image_header
.dataSize
;
366 if ( image_header
.depth
== 24 )
369 pixels
= convert24toGrey( data
, image_header
.dataSize
);
373 printf("Converting image file to 8 bit...\n");
374 pixels
= convert24to8bitIndex( data
, height
, width
, &data
);
375 image_header
.dataSize
= pixels
;
381 pixels
= convert8toGrey( data
, image_header
.dataSize
);
385 printf("Converting image file to 24 bit...\n");
386 pixels
= convert8bitIndexto24( data
, height
, width
, &data
);
387 image_header
.dataSize
= pixels
;
391 printf("Converting image file to 8 bit raw...\n");
392 pixels
= convert8bitIndexto8( data
, height
, width
, &data
);
393 image_header
.dataSize
= pixels
;
398 printf("Converted %d pixels%s...\n", pixels
/depth
, ((grey
==1)?" to grayscale":""));
399 if ( exactmatch
> 0 )
400 printf("Found %d color mathces in CLUT...\n", exactmatch
);
402 printf("Converted %d colors to gray...\n", cvt2grey
);
404 printf("Adjusted %d grays to best match...\n", neargrey
);
406 printf("Total of %d seperate color mismatches...\n", nextmis
);
410 unsigned int pixels_out
;
411 struct panicimage image
;
413 stream
= fopen(whdname
, "r");
415 fprintf(stderr
, "Err: could not open WHD raw image file.\n\n");
419 fread(&image
, sizeof(image
), 1, stream
);
421 if ( image
.pd_tag
!= 'RNMp' )
424 if ( image
.pd_depth
!= 1 )
427 width
= image
.pd_width
;
428 height
= image
.pd_height
;
429 depth
= image
.pd_depth
;
431 printf("Image info: width: %d height: %d depth: %d...\n", image
.pd_width
, image
.pd_height
, image
.pd_depth
);
433 if (!(width
&& height
&& depth
)) {
434 fprintf(stderr
,"Err: Invalid image file header (width, height, or depth is 0)\n");
438 if ( !(fileArr
= (char *)malloc(image
.pd_dataSize
))) {
439 fprintf(stderr
,"Err: Couldn't malloc file data (%ld bytes)... bailing.\n", image
.pd_dataSize
);
443 /* read the data into a buffer */
444 fread(fileArr
, image
.pd_dataSize
, 1, stream
);
447 encodedSize
= image
.pd_dataSize
- (256 * 3);
449 for(sum
=0,i
=0; i
<encodedSize
; i
++)
455 if (debug
) printf("WHD sum = %x\n", sum
);
457 if ( sum
!= image
.pd_sum
)
460 for(pixels
=0,i
=0; i
<encodedSize
;)
462 unsigned int quantity
, depth
;
463 unsigned char * value
;
465 i
+= decode_rle( &fileArr
[i
], &quantity
, &depth
, &value
);
466 pixels
+= quantity
* depth
;
469 if ( debug
) printf("pixels = %d sum = %x\n", pixels
, sum
);
470 if ( debug
) printf("es = %d H*W = %d sum = %x\n", encodedSize
, image
.pd_height
*image
.pd_width
, image
.pd_sum
);
472 if ( !(data
= (char *)malloc(pixels
))) {
473 fprintf(stderr
,"Err: Couldn't malloc file data (%ld bytes)... bailing.\n", pixels
);
478 unsigned int quantity
, line
, col
, depth
, sum
;
479 unsigned char * dataIn
, * value
;
485 for (line
=0; line
< height
; line
++) {
486 for (col
=0; col
< width
; col
++) {
488 if ( quantity
== 0 ) {
489 dataIn
+= decode_rle( dataIn
, &quantity
, &depth
, &value
);
491 sum
+= quantity
* depth
;
493 data
[pixels_out
++] = value
[i
++];
502 if (debug
) printf("total Q*D = %d\n", sum
);
505 if( pixels_out
!= pixels
)
507 printf("Err: miscalclulated pixels %d pixels_out %d\n", pixels
, pixels_out
);
511 panic_clut
= CreateCLUTarry( &fileArr
[image
.pd_dataSize
-(256*3)] );
513 qtraw
= "panic_image.qtif";
520 if ( (ostream
= fopen(qtraw
, "wb")) == NULL
) {
521 fprintf(stderr
,"Err: Could not open output file %s.\n\n", qtraw
);
525 printf("Creating image %s in QuickTime No Compression %s %s format...\n", qtraw
,
526 (depth
==3)?"Millions of":"256", (grey
==0)?"colors":"grays");
528 WriteQTRawFile( ostream
, data
, height
, width
, depth
, pixels
);
534 printf("Depth != 1 (8-bit), skipping writing output..\n");
538 printf("Encoding image file...\n");
540 if (!(fileArr
= (unsigned char *) malloc(pixels
))) {
541 fprintf(stderr
,"Err: Couldn't malloc fileArr (%d pixels)... bailing.\n", pixels
);
545 encodedSize
= EncodeImage( data
, pixels
, fileArr
);
546 if ( encodedSize
>= pixels
)
548 printf("Skipping encoding...\n");
551 for (sum
=0,i
=0; i
<encodedSize
; i
++)
557 // write raw image suitable for kernel panic dialog
563 if ( (ostream
= fopen(kraw
, "wb")) == NULL
) {
564 fprintf(stderr
,"Err: Could not open output file %s.\n\n", kraw
);
568 printf("Writing to binary panic dialog file %s, which is suitable for loading into kernel...\n", kraw
);
570 tag
= 'RNMp'; // Raw NMage for Panic dialog
571 depth
= 1; // only CLUT is supported
573 fwrite(&sum
, sizeof(sum
), 1, ostream
);
575 encodedSize
+= (256*3);
576 fwrite(&encodedSize
, sizeof(encodedSize
), 1, ostream
);
578 fwrite(&tag
, sizeof(tag
), 1, ostream
);
579 fwrite(&width
, sizeof(width
), 1, ostream
);
580 fwrite(&height
, sizeof(height
), 1, ostream
);
581 fwrite(&depth
, sizeof(depth
), 1, ostream
);
582 fwrite(&lines
, sizeof(lines
), 1, ostream
);
583 fwrite(&fg
, sizeof(fg
), 1, ostream
);
584 fwrite(&bg
, sizeof(bg
), 1, ostream
);
585 fwrite(fileArr
, encodedSize
, 1, ostream
);
587 for ( i
=0; i
<256; i
++)
590 unsigned char arr
[3];
592 c
.c24
= panic_clut
[i
];
595 arr
[1] = c
.clut
.green
;
596 arr
[2] = c
.clut
.blue
;
597 fwrite(arr
, 3, 1, ostream
);
600 if ( out
== NULL
) goto leaveOK
;
603 // it's ok to generate the c file
605 if ( out
== NULL
) out
= "panic_image.c";
606 out_stream
= fopen(out
, "w");
608 if(out_stream
== NULL
) {
609 fprintf(stderr
,"Err: Couldn't open out file %s.\n\n", out
);
613 printf("Writing C source %s, suitable for including into kernel build...\n", out
);
615 fprintf( out_stream
, "/* autogenerated with genimage.c using %s as image input */\n", file
);
617 char * s
= "the built-in appleClut8";
620 fprintf( out_stream
, "/* and %s for the color look up table (CLUT) */\n\n", s
);
623 fprintf( out_stream
, "static const struct panicimage {\n");
624 fprintf( out_stream
, "\tunsigned int\tpd_sum;\n");
625 fprintf( out_stream
, "\tunsigned int\tpd_dataSize;\n");
626 fprintf( out_stream
, "\tunsigned int\tpd_tag;\n");
627 fprintf( out_stream
, "\tunsigned short\tpd_width;\n");
628 fprintf( out_stream
, "\tunsigned short\tpd_height;\n");
629 fprintf( out_stream
, "\tunsigned char\tpd_depth;\n");
630 fprintf( out_stream
, "\tunsigned char\tpd_info_height;\n");
631 fprintf( out_stream
, "\tunsigned char\tpd_info_color[2];\n");
632 fprintf( out_stream
, "\tunsigned char\tdata[];\n");
634 fprintf( out_stream
, "} panic_dialog_default = {\n\t");
635 fprintf( out_stream
, "0x%08x, ", sum
); /* panic dialog x */
636 fprintf( out_stream
, "0x%08x, ", encodedSize
+(256*3)); /* panic dialog x */
637 fprintf( out_stream
, "0x%08x, ", 'RNMp'); /* panic dialog x */
638 fprintf( out_stream
, "%d, ", width
); /* panic dialog x */
639 fprintf( out_stream
, "%d, ", height
); /* panic dialog y */
640 fprintf( out_stream
, "%d, ", depth
); /* bytes per pixel */
641 fprintf( out_stream
, "%d, ", lines
); /* lines reserved for panic info */
642 fprintf( out_stream
, "0x%02x, ", fg
); /* font foreground color: indexed */
643 fprintf( out_stream
, "0x%02x, ", bg
); /* font background color: indexed */
645 fprintf( out_stream
, "\n");
648 fprintf( out_stream
, "{\n");
650 for( i
=0; i
< encodedSize
;)
652 chars_this_line
+= fprintf( out_stream
, "0x%.2x,", fileArr
[i
++]);
654 if (i
>= encodedSize
) // this is the last element
657 if(chars_this_line
>= 80) {
658 fprintf( out_stream
, "\n");
666 printf("Encoded size = %d\n", encodedSize
);
667 printf("Decoded size = %d\n", pixels
);
670 fprintf(out_stream
, "\n\n");
671 for ( i
=0; i
<256; i
+=4)
675 if ( (i
% 16) == 0 ) fprintf(out_stream
, "// %02X\n", i
);
676 c
.c24
= panic_clut
[i
+0];
677 fprintf(out_stream
, "\t0x%02X,0x%02X,0x%02X, ", c
.clut
.red
, c
.clut
.green
, c
.clut
.blue
);
678 c
.c24
= panic_clut
[i
+1];
679 fprintf(out_stream
, "0x%02X,0x%02X,0x%02X, ", c
.clut
.red
, c
.clut
.green
, c
.clut
.blue
);
680 c
.c24
= panic_clut
[i
+2];
681 fprintf(out_stream
, "0x%02X,0x%02X,0x%02X, ", c
.clut
.red
, c
.clut
.green
, c
.clut
.blue
);
682 c
.c24
= panic_clut
[i
+3];
683 fprintf(out_stream
, "0x%02X,0x%02X,0x%02X%s\n", c
.clut
.red
, c
.clut
.green
, c
.clut
.blue
, ((i
!=(256-4))?",":""));
686 fprintf(out_stream
, "}\n");
687 fprintf(out_stream
, "};\n");
689 fclose( out_stream
);
696 fprintf(stderr
,"Err: Image must be in the QuickTime Raw Uncompressed Millions or 256 Colors format\n");
699 fprintf(stderr
,"Err: Image must be in the WHD Raw 256 Colors format\n");
705 #define RUN_MAX ((1<<20)-1)
712 unsigned int encode_rle(
713 unsigned char * fileArr
,
714 unsigned int filePos
,
715 unsigned int quantity
,
716 union RunData
* value
,
720 compareruns( unsigned char * data
, unsigned int * index
, unsigned int max
, union RunData
* currP
, int * depth
)
722 unsigned int i
= *index
;
723 union RunData
* nextP
;
726 if ( currP
== NULL
|| data
== NULL
)
732 if ( (*index
+*depth
) > max
)
739 nextP
= (union RunData
*) &data
[*index
];
743 // check current data against current depth
747 if ( nextP
->c
[0] == currP
->c
[0] )
751 if ( nextP
->c
[0] == currP
->c
[0] &&
752 nextP
->c
[1] == currP
->c
[1] )
756 if ( nextP
->c
[0] == currP
->c
[0] &&
757 nextP
->c
[1] == currP
->c
[1] &&
758 nextP
->c
[2] == currP
->c
[2] )
762 if ( nextP
->c
[0] == currP
->c
[0] &&
763 nextP
->c
[1] == currP
->c
[1] &&
764 nextP
->c
[2] == currP
->c
[2] &&
765 nextP
->c
[3] == currP
->c
[3] )
774 // start of a new pattern match begine with depth = 1
776 if ( (*index
+6) <= max
)
778 // We have at least 8 bytes left in the buffer starting from currP
780 nextP
= (union RunData
*) &data
[*index
+3];
781 if ( nextP
->c
[0] == currP
->c
[0] &&
782 nextP
->c
[1] == currP
->c
[1] &&
783 nextP
->c
[2] == currP
->c
[2] &&
784 nextP
->c
[3] == currP
->c
[3] )
786 // check if they are all the same value
787 if ( currP
->c
[0] == currP
->c
[1] &&
788 currP
->c
[1] == currP
->c
[2] &&
789 currP
->c
[2] == currP
->c
[3] )
790 { // if so, leave at depth = 1
796 if (debug
>2) printf("Found 4 at %x\n", *index
);
803 nextP
= (union RunData
*) &data
[*index
+2];
804 if ( nextP
->c
[0] == currP
->c
[0] &&
805 nextP
->c
[1] == currP
->c
[1] &&
806 nextP
->c
[2] == currP
->c
[2] )
808 // check if they are all the same value
809 if ( currP
->c
[0] == currP
->c
[1] &&
810 currP
->c
[1] == currP
->c
[2] )
811 { // if so, leave at depth = 1
817 if (debug
>2) printf("Found 3 at %x\n", *index
);
824 nextP
= (union RunData
*) &data
[*index
+1];
825 if ( nextP
->c
[0] == currP
->c
[0] &&
826 nextP
->c
[1] == currP
->c
[1] )
828 // check if they are all the same value
829 if ( currP
->c
[0] == currP
->c
[1] )
830 { // if so, leave at depth = 1
836 if (debug
>2) printf("Found 2 at %x\n", *index
);
844 nextP
= (union RunData
*) &data
[*index
];
848 if ( nextP
->c
[0] == currP
->c
[0] )
862 EncodeImage( unsigned char * data
, int pixels
, unsigned char * fileArr
)
864 union RunData
* currP
, * norunP
;
866 unsigned int filePos
, run
, nomatchrun
;
871 filePos
= 0; // position in the file we're writing out
875 currP
= (union RunData
*)&data
[0]; // start a new run
878 if ( compareruns( data
, &i
, pixels
, currP
, &depth
) )
882 if ( (run
*depth
) > 2 )
884 unsigned char * p
= (unsigned char *)norunP
;
892 cnt
= (nomatchrun
> 127) ? 127 : nomatchrun
;
893 fileArr
[filePos
++] = cnt
;
897 fileArr
[filePos
++] = *p
++;
901 filePos
+= encode_rle(fileArr
, filePos
, run
, currP
, depth
);
910 currP
= (union RunData
*)&data
[i
]; // start a new run
918 depth
= 1; // switch back to a single byte depth
919 run
= 1; // thee is always at least one entry
920 i
++; // point to next byte
926 unsigned char * p
= (unsigned char *)norunP
;
931 cnt
= (nomatchrun
> 127) ? 127 : nomatchrun
;
932 fileArr
[filePos
++] = cnt
;
936 fileArr
[filePos
++] = *p
++;
940 // write out any run that was in progress
942 filePos
+= encode_rle(fileArr
, filePos
, run
, currP
, depth
);
948 /* encode_rle applies a "modified-RLE encoding to a given image. The encoding works as follows:
950 The quantity is described in the first byte. If the MSB is zero, then the next seven bits
951 are the quantity. If the MSB is set, bits 0-3 of the quantity are in the least significant bits.
952 If bit 5 is set, then the quantity is further described in the next byte, where an additional
953 7 bits (4-10) worth of quantity will be found. If the MSB of this byte is set, then an additional
954 7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of
955 a quantity byte is zero, thus ending the chain.
957 The value is described in the first byte. If the MSB is zero, then the value is in the next byte.
958 If the MSB is set, then bits 5/6 describe the number of value bytes following the quantity bytes.
960 encodings are: (q = quantity, v = value, c = quantity continues)
962 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 Byte 7 Byte 8
963 case 1: [ 0 q6-q0 ] [ v7-v0 ]
964 case 2: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ]
965 case 3: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ]
966 case 4: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
967 case 5: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
971 encode_length(unsigned char * fileArr
, unsigned int filePos
, unsigned int quantity
, unsigned int mask
)
973 unsigned char single_mask
= 0x0F;
974 unsigned char double_mask
= 0x7F;
975 unsigned int slots_used
= 0;
977 fileArr
[filePos
] = mask
| (quantity
& single_mask
); // low bits (plus mask)
982 fileArr
[filePos
++] |= 0x10; // set length continuation bit
983 fileArr
[filePos
] = quantity
& double_mask
;
986 while (quantity
>>= 7)
988 fileArr
[filePos
++] |= 0x80; // set length continuation bit
989 fileArr
[filePos
] = quantity
& double_mask
;
999 encode_rle(unsigned char * fileArr
, unsigned int filePos
, unsigned int quantity
, union RunData
* value
, int depth
)
1001 unsigned char single_mask
= 0x0F;
1002 unsigned char double_mask
= 0x7F;
1003 unsigned char slots_used
= 0;
1009 slots_used
+= encode_length( fileArr
, filePos
, quantity
, 0x80 );
1010 fileArr
[filePos
+slots_used
++] = value
->c
[0];
1014 slots_used
+= encode_length( fileArr
, filePos
, quantity
, 0xA0 );
1015 fileArr
[filePos
+slots_used
++] = value
->c
[0];
1016 fileArr
[filePos
+slots_used
++] = value
->c
[1];
1020 slots_used
+= encode_length( fileArr
, filePos
, quantity
, 0xC0 );
1021 fileArr
[filePos
+slots_used
++] = value
->c
[0];
1022 fileArr
[filePos
+slots_used
++] = value
->c
[1];
1023 fileArr
[filePos
+slots_used
++] = value
->c
[2];
1027 slots_used
+= encode_length( fileArr
, filePos
, quantity
, 0xE0 );
1028 fileArr
[filePos
+slots_used
++] = value
->c
[0];
1029 fileArr
[filePos
+slots_used
++] = value
->c
[1];
1030 fileArr
[filePos
+slots_used
++] = value
->c
[2];
1031 fileArr
[filePos
+slots_used
++] = value
->c
[3];
1039 decode_rle( unsigned char * dataPtr
, unsigned int * quantity
, unsigned int * depth
, unsigned char ** value
)
1042 int i
, runlen
, runsize
;
1045 mask
= dataPtr
[i
] & 0xF0;
1049 runsize
= ((mask
& 0x60) >> 5) + 1;
1050 runlen
= dataPtr
[i
++] & 0x0F;
1058 mask
= dataPtr
[i
] & 0x80;
1059 runlen
|= ((dataPtr
[i
++] & 0x7F) << shift
);
1066 runsize
= dataPtr
[i
++];
1071 *value
= &dataPtr
[i
];
1077 findIndexNearMatch( unsigned int color24
)
1079 union colors color8
;
1083 color8
.c24
= color24
;
1085 if ( color8
.clut
.red
== color8
.clut
.green
&& color8
.clut
.green
== color8
.clut
.blue
)
1090 unsigned int bestIndex
= 0, rel
, bestMatch
= -1;
1092 for (i
=0; i
<256; i
++)
1094 clut8
.c24
= panic_clut
[i
];
1096 if ( clut8
.clut
.red
!= clut8
.clut
.green
|| clut8
.clut
.green
!= clut8
.clut
.blue
)
1099 if ( clut8
.clut
.red
> color8
.clut
.red
) continue;
1100 rel
= abs(color8
.clut
.red
- clut8
.clut
.red
);
1101 if ( rel
< bestMatch
) {
1110 // we must have a non-grey color
1115 color24toGrey( unsigned int color24
)
1120 unsigned char grey8
;
1121 unsigned int grey24
;
1125 R
= (c
.clut
.red
& 0xFF) ;
1126 G
= (c
.clut
.green
& 0xFF) ;
1127 B
= (c
.clut
.blue
& 0xFF) ;
1129 Grey
= (R
*.30) + (G
*.59) + (B
*.11);
1130 grey8
= (unsigned char) ( Grey
+ .5);
1131 grey24
= (grey8
<<16) | (grey8
<<8) | grey8
;
1136 convert24toGrey( unsigned char * data
, unsigned int size
)
1144 for ( i24
=0; i24
<size
; i24
+=3)
1146 R
= ((data
[i24
+0]) & 0xFF) ;
1147 G
= ((data
[i24
+1]) & 0xFF) ;
1148 B
= ((data
[i24
+2]) & 0xFF) ;
1150 Grey
= (R
*.30) + (G
*.59) + (B
*.11);
1151 grey8
= (unsigned int) ( Grey
+ .5);
1153 data
[i24
+0] = grey8
;
1154 data
[i24
+1] = grey8
;
1155 data
[i24
+2] = grey8
;
1162 convert8toGrey( unsigned char * data
, unsigned int size
)
1168 for ( i
=0; i
<size
; i
++)
1170 c
.c24
= panic_clut
[data
[i
]];
1171 c24
= color24toGrey( c
.c24
);
1172 data
[i
] = findIndexMatch( c24
);
1179 findColor24NearMatch( unsigned int color24
)
1181 union colors c
, i_color
;
1182 unsigned char d
=0xff, d_red
, d_green
, d_blue
, i
, prim
;
1183 static unsigned int last_c
= -1, last_co
= -1, last_p
= -1;
1185 if ( last_c
== color24
)
1190 if ( c
.rgb
[1] > c
.rgb
[2] && c
.rgb
[1] > c
.rgb
[3] )
1192 else if ( c
.rgb
[2] > c
.rgb
[1] && c
.rgb
[2] > c
.rgb
[3] )
1194 else if ( c
.rgb
[3] > c
.rgb
[1] && c
.rgb
[3] > c
.rgb
[2] )
1196 else if ( c
.rgb
[1] == c
.rgb
[2] && c
.rgb
[1] == c
.rgb
[3] )
1198 else if ( c
.rgb
[1] == c
.rgb
[2] )
1199 prim
= 0x12; // red green
1200 else if ( c
.rgb
[1] == c
.rgb
[3] )
1201 prim
= 0x13; // red blue
1202 else if ( c
.rgb
[2] == c
.rgb
[3] )
1203 prim
= 0x23; // green blue
1205 printf("cannot tell color %06x\n", color24
);
1210 if ( prim
== 0 || prim
> 3 )
1217 for (i
=0; i
<256; i
++)
1229 findIndexMatch( unsigned int color24
)
1233 static unsigned char last
= 0;
1236 if ( panic_clut
[last
] == color24
)
1242 for (i
=0; i
<256; i
++)
1244 if ( panic_clut
[i
] == color24
) {
1251 if ( nextmis
== -1 ) {
1252 for (i
=0; i
<256; i
++) mismatchClut
[i
] = -1;
1256 i
= findIndexNearMatch(color24
);
1258 if ( i
== -1 ) // found a color that is not grey
1260 unsigned int colormatch
= findColor24NearMatch( color24
);
1262 if ( colormatch
== -1 ) // cannot convert color
1265 if (debug
>1) printf("color %06X not matched at all\n", color24
);
1266 color24
= color24toGrey(color24
);
1267 if (debug
>1) printf("now grey %06X\n", color24
);
1270 color24
= colormatch
;
1275 if (debug
>1) printf("color %06X now matched at %x\n", color24
, i
);
1281 // keep track of missed repeats
1282 for ( i
=0; i
<nextmis
; i
++)
1283 if ( mismatchClut
[i
] == color24
)
1286 if ( debug
) printf("closest match for %06X is at index %d %06X\n", color24
, ri
, panic_clut
[ri
]);
1287 if ( nextmis
< 256 )
1288 mismatchClut
[nextmis
++] = color24
;
1290 if ( debug
&& (nextmis
>= 256) )
1292 fprintf(stderr
,"Err: Too many color mismatches detected with this CLUT\n");
1300 * Convert 24 bit mode to 8 bit. We do not do any alignment conversions
1304 convert24to8bitIndex( unsigned char * data
, int height
, int width
, unsigned char ** dout
)
1306 unsigned int row
, col
, i
, i24
, i8
, size
;
1307 unsigned char index
;
1308 unsigned char * ddata
;
1309 union colors color24
;
1311 size
= height
* width
;
1313 ddata
= (unsigned char *) calloc( size
, 1);
1315 for (i24
=0,i8
=0,row
=0; row
<height
; row
++)
1317 for (col
=0; col
<width
; col
++)
1319 color24
.clut
.red
= data
[i24
++];
1320 color24
.clut
.green
= data
[i24
++];
1321 color24
.clut
.blue
= data
[i24
++];
1323 index
= findIndexMatch( color24
.c24
);
1324 ddata
[i8
++] = index
;
1334 * Convert 8 bit mode to 8 bit, We have to strip off the alignment bytes
1338 convert8bitIndexto8( unsigned char * data
, int height
, int width
, unsigned char ** dout
)
1340 unsigned int row
, col
, i
, i8
, size
, adj
;
1341 unsigned char index
;
1342 unsigned char * ddata
;
1343 union colors color24
;
1345 adj
=(4-(width%4
))%4
; // adjustment needed to strip off the word alignment padding
1346 size
= height
* width
;
1347 ddata
= (unsigned char *) calloc( size
, 1);
1349 for (i8
=0,row
=0; row
<height
; row
++)
1351 for (col
=0; col
<width
; col
++)
1354 color24
.c24
= panic_clut
[index
];
1355 index
= findIndexMatch( color24
.c24
);
1356 ddata
[i8
++] = index
;
1359 for (i
=0; i
<adj
; i
++)
1368 * Convert 8 bit mode to 24 bit, We have to strip off the alignment bytes
1372 convert8bitIndexto24( unsigned char * data
, int height
, int width
, unsigned char ** dout
)
1374 unsigned int row
, col
, i
, i24
, i8
, size
, adj
;
1375 unsigned char index
;
1376 unsigned char * ddata
;
1377 union colors color24
;
1379 adj
=(4-(width%4
))%4
; // adjustment needed to strip off the word alignment padding
1380 size
= height
* width
;
1381 ddata
= (unsigned char *) calloc( size
, 3);
1383 for (i24
=0,i8
=0,row
=0; row
<height
; row
++)
1385 for (col
=0; col
<width
; col
++)
1388 color24
.c24
= panic_clut
[index
];
1390 ddata
[i24
++] = color24
.clut
.red
;
1391 ddata
[i24
++] = color24
.clut
.green
;
1392 ddata
[i24
++] = color24
.clut
.blue
;
1395 for (i
=0; i
<adj
; i
++)
1406 CreateCLUTarry( unsigned char * raw_clut
)
1408 unsigned int * new_clut
, index
, i
;
1410 new_clut
= (unsigned int *) calloc(256, sizeof(unsigned int));
1411 for ( index
=0,i
=0; i
<256; index
+=3,i
++ )
1412 new_clut
[i
] = (raw_clut
[index
] << 16) | (raw_clut
[index
+1] << 8) | raw_clut
[index
+2];
1419 ReplaceCLUT( char * iname
)
1422 unsigned char * raw_clut
;
1423 unsigned int * new_clut
, index
, i
;
1425 if ( (stream
= fopen(iname
, "rb")) == NULL
) {
1426 fprintf(stderr
,"Err: Could not open input clut file %s.\n\n", iname
);
1430 raw_clut
= (char *) calloc(256, 3);
1431 fread(raw_clut
, 256, 3, stream
);
1434 new_clut
= CreateCLUTarry( raw_clut
);
1442 GenerateCLUT( char * oname
)
1448 if ( (ostream
= fopen(oname
, "w")) == NULL
) {
1449 fprintf(stderr
,"Err: Could not open output clut file %s.\n\n", oname
);
1453 printf("Generating new CLUT array named %s\n", oname
);
1454 fprintf(ostream
, "// This Clut was generated from %s\n", (clutin
)?clutin
:"built-in appleClut8");
1455 fprintf(ostream
, "unsigned int appleClut8[256] = {\n");
1456 for ( i
=0; i
<256; i
+=8)
1458 if ( (i
% 16) == 0 ) fprintf(ostream
, "// %02X\n", i
);
1459 fprintf(ostream
, "\t0x%06X, 0x%06X, 0x%06X, 0x%06X, 0x%06X, 0x%06X, 0x%06X, 0x%06X%s\n",
1460 panic_clut
[i
+0], panic_clut
[i
+1], panic_clut
[i
+2], panic_clut
[i
+3],
1461 panic_clut
[i
+4], panic_clut
[i
+5], panic_clut
[i
+6], panic_clut
[i
+7], ((i
!=(256-8))?",":""));
1463 fprintf(ostream
, "};\n");
1468 WriteQTRawFile( FILE * ostream
, unsigned char * data
, int height
, int width
, int depth
, unsigned int size
)
1470 unsigned int i
, adj
, csize
, tmp
, col
, line
;
1474 adj
=(4-(width%4
))%4
; // adjustment needed to add the word alignment padding
1478 csize
= height
*depth
*(width
+adj
);
1480 if( debug
&& csize
!= size
)
1481 printf("Adjusted Computed size (%d=H*W*D) to account to account for word alignment %d(%d)\n", size
,csize
,csize
-size
);
1483 tmp
= csize
+ ( 2 * sizeof(unsigned int) );
1484 fwrite(&tmp
, sizeof(unsigned int), 1, ostream
);
1487 fwrite(&tmp
, sizeof(unsigned int), 1, ostream
);
1491 for (line
=0; line
<height
; line
++)
1493 for (col
=0; col
<width
; col
++)
1494 fwrite(data
++, 1, 1, ostream
);
1496 for (i
=0; i
<adj
; i
++)
1497 fwrite(&data
[-1], 1, 1, ostream
);
1500 fwrite(data
, csize
, 1, ostream
);
1503 fwrite(&tmp
, sizeof(unsigned int), 1, ostream
);
1505 fwrite(&tmp
, sizeof(unsigned int), 1, ostream
);
1507 image_header
.idSize
= sizeof(image_header
) - 2;
1508 image_header
.cType
= 'raw ';
1509 image_header
.dataRefIndex
= 0;
1510 image_header
.version
= 1;
1511 image_header
.revisionLevel
= 1;
1512 image_header
.vendor
= 'appl';
1513 image_header
.temporalQuality
= 0;
1514 image_header
.spatialQuality
= 1024-1;
1515 image_header
.width
= width
;
1516 image_header
.height
= height
;
1517 image_header
.hRes
= 72 << 16;
1518 image_header
.vRes
= 72 << 16;
1519 image_header
.dataSize
= csize
;
1520 image_header
.frameCount
= 1;
1521 strcpy(image_header
.name
, " None");
1522 image_header
.name
[0] = 4;
1523 image_header
.depth
= depth
*8;
1524 image_header
.clutID
= (depth
==1) ? 8 : -1;
1526 fwrite(&image_header
, sizeof(image_header
)-2, 1, ostream
);
1531 CreateRawQTCLUT( int type
)
1535 unsigned char * raw_clut
, * p
;
1541 name
= "appleclut8.qtif";
1546 name
= "unknownclut.qtif";
1550 if ( (ostream
= fopen(name
, "wb")) == NULL
) {
1551 fprintf(stderr
,"Err: Could not open output index file %s.\n\n", name
);
1555 raw_clut
= (unsigned char *) malloc(H
*W
*D
*256);
1557 for (p
=raw_clut
, row
=0; row
<H
; row
++)
1559 for (i
=0; i
<256; i
++)
1565 c
.c24
= panic_clut
[i
];
1574 *p
++ = c
.clut
.green
;
1580 WriteQTRawFile( ostream
, (unsigned char *) raw_clut
, H
, 256*W
, D
, H
*256*W
*D
);
1587 CreateRawQTFont( void )
1590 unsigned char fonts
[16][256][8];
1593 if ( (ostream
= fopen("font.qtif", "wb")) == NULL
) {
1594 fprintf(stderr
,"Err: Could not open output index file %s.\n\n", "font.qtif");
1598 for (row
=0; row
<16; row
++)
1600 for (i
=0; i
<256; i
++)
1606 c
= &iso_font
[i
*16];
1608 for (j
=7; j
>=0; j
--)
1611 fonts
[row
][i
][j
] = fg
;
1613 fonts
[row
][i
][j
] = bg
;
1619 WriteQTRawFile( ostream
, (unsigned char *) fonts
, 16, 256*8, 1, 16*256*8 );