]> git.saurik.com Git - apple/xnu.git/blame - osfmk/console/panic_ui/genimage.c
xnu-792.tar.gz
[apple/xnu.git] / osfmk / console / panic_ui / genimage.c
CommitLineData
91447636
A
1/* converts a QT RAW image file into the c structure that the
2 * kernel panic ui system expects.
3 *
4 * to build: cc -o genimage genimage.c
5*/
6
7#include <stdio.h>
8#include <unistd.h>
9#include <stdlib.h>
10#include <sys/types.h>
11#include <fcntl.h>
12#include <string.h>
13
14int EncodeImage(
15 unsigned char * data,
16 int pixels,
17 unsigned char * fileArr );
18int decode_rle(
19 unsigned char * dataPtr,
20 unsigned int * quantity,
21 unsigned int * depth,
22 unsigned char ** value );
23int findIndexNearMatch(
24 unsigned int color24 );
25unsigned char findIndexMatch(
26 unsigned int color24 );
27int convert24toGrey(
28 unsigned char * data,
29 unsigned int size );
30int convert8toGrey(
31 unsigned char * data,
32 unsigned int size );
33int convert8bitIndexto24(
34 unsigned char * data,
35 int height,
36 int width,
37 unsigned char ** dout );
38int convert8bitIndexto8(
39 unsigned char * data,
40 int height,
41 int width,
42 unsigned char ** dout );
43int convert24to8bitIndex(
44 unsigned char * data,
45 int height,
46 int width,
47 unsigned char ** dout );
48unsigned int * CreateCLUTarry(
49 unsigned char * raw_clut );
50unsigned int * ReplaceCLUT(
51 char * iname );
52void GenerateCLUT(
53 char * oname );
54void WriteQTRawFile(
55 FILE * ostream,
56 unsigned char * data,
57 int height,
58 int width,
59 int depth,
60 unsigned int size );
61void CreateRawQTFont(
62 void );
63void CreateRawQTCLUT(
64 int type );
65
66#define offsetof(type, field) ((size_t)(&((type *)0)->field))
67
68struct panicimage {
69 unsigned int pd_sum;
70 unsigned int pd_dataSize;
71 unsigned int pd_tag;
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];
77 unsigned char data[];
78};
79
80
81
82
83void
84usage( int type ) {
85printf(
86"\n"
87"Usage:\n"
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"
107"\t\t\tprocessing\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"
116"\n\n" );
117if ( type > 0 )
118printf(
119"\
120This utility is used to convert a panic dialog from .qtif format, into\n\
121one that is suitable for the kernel to display. The .qtif image file\n\
122can be in either 24 or 8 bit mode, but must be in an uncompressed raw\n\
123format. 8 bit mode is preferred, as it requires no conversion to the\n\
124colors that are contained in the CLUT. If a color cannot be found in\n\
125the CLUT, it will be converted to the nearest gray. The default CLUT\n\
126is the same as the system CLUT. If needed, this can be overridden by\n\
127providing a new CLUT with the -c option.\n\
128\n\
129However, if you override the default CLUT. The panic UI may not appear\n\
130as you intended, when the systme is in 8 bit mode. Colors that are not\n\
131present in the active CLUT, will be converted to the nearest gray.\n\
132\n\
133The panic dialog must have a number of lines reserved at the bottom for\n\
134displaying additional panic information. The minimum number of lines\n\
135is 20. The font use to display this information needs to have the\n\
136foreground and background colors defined. The defaults are full white\n\
137on dark gray. This can be changed by using the -fg and/or -bg options to\n\
138provide new 24 bit colors. These colors must be contained in the CLUT.\n\
139\n\
140There are two possible output results. The default is to create a C\n\
141source file named panic_image.c that contains the panic image in a 8 bit\n\
142modified RLE compressed format and the CLUT that was used to create the\n\
143image. The second possibility is to create a binary version of the same\n\
144information by using the -o option. This file can then be used to replace\n\
145the panic dialog that is currently active in the kernel by using\n\
146sysctl(KERN_PANIC_INFO).\n\
147\n\n");
148}
149
150
151#include "appleclut8.h"
152#include "../iso_font.c"
153
154struct QTHeader {
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 */
174} image_header;
175
176static unsigned int mismatchClut[256];
177static int nextmis = -1, neargrey = 0, cvt2grey = 0, exactmatch=0;
178static int grey = 0, debug = 0, testfont = 0, testclut = 0;
179static int convert = 8; // default is to convert image to 8 bit uncompressed .tgif
180static unsigned char fg, bg;
181unsigned int * panic_clut = NULL;
182static char * clutin = NULL;
183
184union colors {
185 unsigned int c24;
186 unsigned char rgb[4];
187 struct {
188 unsigned char dummy;
189 unsigned char red;
190 unsigned char green;
191 unsigned char blue;
192 } clut;
193};
194
195int
196main( int argc, char *argv[] )
197{
198 char *file = NULL;
199 char *out = NULL;
200 char *kraw = NULL;
201 char *qtraw = NULL;
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;
211
212
213 // pull apart the arguments
214 for( next = 1; next < argc; next++ )
215 {
216 if (strcmp(argv[next], "-i") == 0) // image file in raw QT uncompressed format (.qtif)
217 file = argv[++next];
218
219 else if (strcmp(argv[next], "-o") == 0) // output file for WHD image
220 kraw = argv[++next];
221 else if (strcmp(argv[next], "-io") == 0) // output file for image
222 out = argv[++next];
223
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); }
234
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)
239 testclut = 8;
240 else if (strcmp(argv[next], "-r") == 0) // output file for QT clut RAW (test)
241 testclut = 1;
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)
245 grey = 1;
246 else if (strcmp(argv[next], "-n8") == 0) // don't convert to 8 by default (test)
247 convert = 0;
248 else if (strcmp(argv[next], "-n24") == 0) // convert to 8 to 24 (test)
249 convert = 24;
250 else if (strcmp(argv[next], "-f") == 0) // test font (test)
251 testfont = 1;
252 else if (strcmp(argv[next], "-w") == 0) // read WHD raw file and output 8 bit tqif
253 whdname = argv[++next];
254
255 else if (strcmp(argv[next], "-debug") == 0) // verbose
256 debug++;
257 }
258
259 if (!(file || clutout || testfont || testclut || whdname) ) {
260 usage(0);
261 exit(1);
262 }
263
264 printf("\n");
265
266 panic_clut = appleClut8;
267
268 if ( clutin )
269 {
270 panic_clut = ReplaceCLUT( clutin );
271 printf("Built-in CLUT has been replaced with %s...\n", clutin);
272 } else
273 {
274 if ( whdname )
275 printf("Using CLUT from %s...\n", whdname);
276 else
277 printf("Using Built-in CLUT...\n");
278 }
279
280 if ( clutout )
281 {
282 GenerateCLUT( clutout );
283 printf("Created C source file of %s...\n", clutout);
284 }
285
286 fg = findIndexNearMatch(fg24);
287 bg = findIndexNearMatch(bg24);
288
289 if ( testclut )
290 CreateRawQTCLUT(testclut);
291
292 if ( testfont )
293 CreateRawQTFont();
294
295 // Begin to process the image
296
297 if( file == NULL)
298 {
299 if ( whdname == NULL )
300 {
301 if ( debug)
302 printf("No image file was processed...\n\n");
303 exit(0);
304 }
305 }
306
307
308 printf("Verifing image file...\n");
309 if ( file != NULL )
310 {
311 stream = fopen(file, "r");
312 if (!stream) {
313 fprintf(stderr, "Err: could not open .qtif image file.\n\n");
314 exit(1);
315 }
316
317 {
318 long hdr_off;
319 long hdr_type;
320
321 fread((void *) &hdr_off, sizeof(long), 1, stream);
322 fread((void *) &hdr_type, sizeof(long), 1, stream);
323
324 if ( hdr_type != 'idat' ) goto errQTimage;
325
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);
329
330 if ( hdr_type != 'idsc' ) goto errQTimage;
331
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;
335
336 width = image_header.width;
337 height = image_header.height;
338 depth = image_header.depth;
339
340 printf("Image info: width: %d height: %d depth: %d...\n", width, height, depth);
341
342 if (!(width && height && depth)) {
343 fprintf(stderr,"Err: Invalid image file header (width, height, or depth is 0)\n");
344 exit(1);
345 }
346 }
347
348 if ( !(data = (char *)malloc(image_header.dataSize))) {
349 fprintf(stderr,"Err: Couldn't malloc file data (%ld bytes)... bailing.\n", image_header.dataSize);
350 exit(1);
351 }
352
353 // Read the image data
354 fseek(stream, 8, SEEK_SET);
355 fread((void *) data, image_header.dataSize, 1, stream);
356 fclose( stream );
357
358 if ( kraw && image_header.depth == 24 )
359 {
360 fprintf(stderr, "Err: The WHD raw file (%s) will not be created when input in is millions of colors\n", kraw);
361 kraw = NULL;
362 }
363
364 pixels = image_header.dataSize;
365
366 if ( image_header.depth == 24 )
367 {
368 if ( grey == 1 )
369 pixels = convert24toGrey( data, image_header.dataSize);
370
371 if ( convert == 8 )
372 {
373 printf("Converting image file to 8 bit...\n");
374 pixels = convert24to8bitIndex( data, height, width, &data );
375 image_header.dataSize = pixels;
376 depth = 1;
377 } else
378 depth = 3;
379 } else {
380 if ( grey == 1 )
381 pixels = convert8toGrey( data, image_header.dataSize );
382
383 if ( convert == 24 )
384 {
385 printf("Converting image file to 24 bit...\n");
386 pixels = convert8bitIndexto24( data, height, width, &data );
387 image_header.dataSize = pixels;
388 depth = 3;
389 } else
390 {
391 printf("Converting image file to 8 bit raw...\n");
392 pixels = convert8bitIndexto8( data, height, width, &data );
393 image_header.dataSize = pixels;
394 depth = 1;
395 }
396 }
397
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);
401 if ( cvt2grey > 0 )
402 printf("Converted %d colors to gray...\n", cvt2grey);
403 if ( neargrey > 0 )
404 printf("Adjusted %d grays to best match...\n", neargrey);
405 if ( nextmis > 0 )
406 printf("Total of %d seperate color mismatches...\n", nextmis);
407 }
408 else
409 {
410 unsigned int pixels_out;
411 struct panicimage image;
412
413 stream = fopen(whdname, "r");
414 if (!stream) {
415 fprintf(stderr, "Err: could not open WHD raw image file.\n\n");
416 exit(1);
417 }
418
419 fread(&image, sizeof(image), 1, stream);
420
421 if ( image.pd_tag != 'RNMp' )
422 goto errWHDimage;
423
424 if ( image.pd_depth != 1 )
425 goto errWHDimage;
426
427 width = image.pd_width;
428 height = image.pd_height;
429 depth = image.pd_depth;
430
431 printf("Image info: width: %d height: %d depth: %d...\n", image.pd_width, image.pd_height, image.pd_depth);
432
433 if (!(width && height && depth)) {
434 fprintf(stderr,"Err: Invalid image file header (width, height, or depth is 0)\n");
435 exit(1);
436 }
437
438 if ( !(fileArr = (char *)malloc(image.pd_dataSize))) {
439 fprintf(stderr,"Err: Couldn't malloc file data (%ld bytes)... bailing.\n", image.pd_dataSize);
440 exit(1);
441 }
442
443 /* read the data into a buffer */
444 fread(fileArr, image.pd_dataSize, 1, stream);
445 fclose(stream);
446
447 encodedSize = image.pd_dataSize - (256 * 3);
448
449 for(sum=0,i=0; i<encodedSize; i++)
450 {
451 sum += fileArr[i];
452 sum <<= sum&1;
453 }
454
455 if (debug) printf("WHD sum = %x\n", sum);
456
457 if ( sum != image.pd_sum )
458 goto errWHDimage;
459
460 for(pixels=0,i=0; i<encodedSize;)
461 {
462 unsigned int quantity, depth;
463 unsigned char * value;
464
465 i += decode_rle( &fileArr[i], &quantity, &depth, &value );
466 pixels += quantity * depth;
467 }
468
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);
471
472 if ( !(data = (char *)malloc(pixels))) {
473 fprintf(stderr,"Err: Couldn't malloc file data (%ld bytes)... bailing.\n", pixels);
474 exit(1);
475 }
476
477 {
478 unsigned int quantity, line, col, depth, sum;
479 unsigned char * dataIn, * value;
480
481 sum = 0;
482 pixels_out = 0;
483 dataIn = fileArr;
484 quantity = 0;
485 for (line=0; line < height; line++) {
486 for (col=0; col < width; col++) {
487
488 if ( quantity == 0 ) {
489 dataIn += decode_rle( dataIn, &quantity, &depth, &value );
490 i = 0;
491 sum += quantity * depth;
492 }
493 data[pixels_out++] = value[i++];
494
495 if ( i == depth )
496 {
497 i = 0;
498 quantity--;
499 }
500 }
501 }
502 if (debug) printf("total Q*D = %d\n", sum);
503 }
504
505 if( pixels_out != pixels )
506 {
507 printf("Err: miscalclulated pixels %d pixels_out %d\n", pixels, pixels_out);
508 exit(1);
509 }
510
511 panic_clut = CreateCLUTarry( &fileArr[image.pd_dataSize-(256*3)] );
512
513 qtraw = "panic_image.qtif";
514 }
515
516 if ( qtraw )
517 {
518 FILE * ostream;
519
520 if ( (ostream = fopen(qtraw, "wb")) == NULL ) {
521 fprintf(stderr,"Err: Could not open output file %s.\n\n", qtraw);
522 exit(1);
523 }
524
525 printf("Creating image %s in QuickTime No Compression %s %s format...\n", qtraw,
526 (depth==3)?"Millions of":"256", (grey==0)?"colors":"grays");
527
528 WriteQTRawFile( ostream, data, height, width, depth, pixels );
529 fclose(ostream);
530 }
531
532 if ( depth != 1 )
533 {
534 printf("Depth != 1 (8-bit), skipping writing output..\n");
535 goto leaveOK;
536 }
537
538 printf("Encoding image file...\n");
539
540 if (!(fileArr = (unsigned char *) malloc(pixels))) {
541 fprintf(stderr,"Err: Couldn't malloc fileArr (%d pixels)... bailing.\n", pixels);
542 exit(1);
543 }
544
545 encodedSize = EncodeImage( data, pixels, fileArr );
546 if ( encodedSize >= pixels )
547 {
548 printf("Skipping encoding...\n");
549 }
550
551 for (sum=0,i=0; i<encodedSize; i++)
552 {
553 sum += fileArr[i];
554 sum <<= sum&1;
555 }
556
557 // write raw image suitable for kernel panic dialog
558 if ( kraw )
559 {
560 FILE * ostream;
561 unsigned int tag;
562
563 if ( (ostream = fopen(kraw, "wb")) == NULL ) {
564 fprintf(stderr,"Err: Could not open output file %s.\n\n", kraw);
565 exit(1);
566 }
567
568 printf("Writing to binary panic dialog file %s, which is suitable for loading into kernel...\n", kraw);
569
570 tag = 'RNMp'; // Raw NMage for Panic dialog
571 depth = 1; // only CLUT is supported
572
573 fwrite(&sum, sizeof(sum), 1, ostream);
574 sum = encodedSize;
575 encodedSize += (256*3);
576 fwrite(&encodedSize, sizeof(encodedSize), 1, ostream);
577 encodedSize = sum;
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);
586
587 for ( i=0; i<256; i++)
588 {
589 union colors c;
590 unsigned char arr[3];
591
592 c.c24 = panic_clut[i];
593
594 arr[0] = c.clut.red;
595 arr[1] = c.clut.green;
596 arr[2] = c.clut.blue;
597 fwrite(arr, 3, 1, ostream);
598 }
599 fclose(ostream);
600 if ( out == NULL ) goto leaveOK;
601 }
602
603 // it's ok to generate the c file
604
605 if ( out == NULL ) out = "panic_image.c";
606 out_stream = fopen(out, "w");
607
608 if(out_stream == NULL) {
609 fprintf(stderr,"Err: Couldn't open out file %s.\n\n", out);
610 exit(1);
611 }
612
613 printf("Writing C source %s, suitable for including into kernel build...\n", out);
614
615 fprintf( out_stream, "/* autogenerated with genimage.c using %s as image input */\n", file);
616 {
617 char * s = "the built-in appleClut8";
618 if ( clutin )
619 s = clutin;
620 fprintf( out_stream, "/* and %s for the color look up table (CLUT) */\n\n", s);
621 }
622
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");
633
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 */
644
645 fprintf( out_stream, "\n");
646
647 chars_this_line = 0;
648 fprintf( out_stream, "{\n");
649
650 for( i=0; i < encodedSize;)
651 {
652 chars_this_line += fprintf( out_stream, "0x%.2x,", fileArr[i++]);
653
654 if (i >= encodedSize) // this is the last element
655 break;
656
657 if(chars_this_line >= 80) {
658 fprintf( out_stream, "\n");
659 chars_this_line = 0;
660 }
661 }
662
663
664 if (debug)
665 {
666 printf("Encoded size = %d\n", encodedSize);
667 printf("Decoded size = %d\n", pixels);
668 }
669
670 fprintf(out_stream, "\n\n");
671 for ( i=0; i<256; i+=4)
672 {
673 union colors c;
674
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))?",":""));
684 }
685
686 fprintf(out_stream, "}\n");
687 fprintf(out_stream, "};\n");
688
689 fclose( out_stream );
690
691leaveOK:
692 printf("\n");
693 return 0;
694
695errQTimage:
696 fprintf(stderr,"Err: Image must be in the QuickTime Raw Uncompressed Millions or 256 Colors format\n");
697 exit(1);
698errWHDimage:
699 fprintf(stderr,"Err: Image must be in the WHD Raw 256 Colors format\n");
700 exit(1);
701}
702
703
704
705#define RUN_MAX ((1<<20)-1)
706
707union RunData {
708 unsigned int i;
709 unsigned char c[4];
710};
711
712unsigned int encode_rle(
713 unsigned char * fileArr,
714 unsigned int filePos,
715 unsigned int quantity,
716 union RunData * value,
717 int depth);
718
719int
720compareruns( unsigned char * data, unsigned int * index, unsigned int max, union RunData * currP, int * depth )
721{
722 unsigned int i = *index;
723 union RunData * nextP;
724 static int retc = 0;
725
726 if ( currP == NULL || data == NULL )
727 {
728 retc = 0;
729 goto Leave;
730 }
731
732 if ( (*index+*depth) > max )
733 {
734 *depth = 1;
735 retc = 0;
736 goto Leave;
737 }
738
739 nextP = (union RunData *) &data[*index];
740
741 if ( retc == 1 )
742 {
743 // check current data against current depth
744 switch ( *depth )
745 {
746 case 1:
747 if ( nextP->c[0] == currP->c[0] )
748 goto Leave;
749 break;
750 case 2:
751 if ( nextP->c[0] == currP->c[0] &&
752 nextP->c[1] == currP->c[1] )
753 goto Leave;
754 break;
755 case 3:
756 if ( nextP->c[0] == currP->c[0] &&
757 nextP->c[1] == currP->c[1] &&
758 nextP->c[2] == currP->c[2] )
759 goto Leave;
760 break;
761 case 4:
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] )
766 goto Leave;
767 break;
768 }
769
770 retc = 0;
771 goto Leave;
772 }
773
774 // start of a new pattern match begine with depth = 1
775
776 if ( (*index+6) <= max )
777 {
778 // We have at least 8 bytes left in the buffer starting from currP
779#if 1
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] )
785 {
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
791 retc = 1;
792 *depth = 1;
793 goto Leave;
794 }
795
796 if (debug>2) printf("Found 4 at %x\n", *index);
797 retc = 1;
798 *depth = 4;
799 *index += 3;
800 goto Leave;
801 }
802
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] )
807 {
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
812 retc = 1;
813 *depth = 1;
814 goto Leave;
815 }
816
817 if (debug>2) printf("Found 3 at %x\n", *index);
818 retc = 1;
819 *depth = 3;
820 *index += 2;
821 goto Leave;
822 }
823
824 nextP = (union RunData *) &data[*index+1];
825 if ( nextP->c[0] == currP->c[0] &&
826 nextP->c[1] == currP->c[1] )
827 {
828 // check if they are all the same value
829 if ( currP->c[0] == currP->c[1] )
830 { // if so, leave at depth = 1
831 retc = 1;
832 *depth = 1;
833 goto Leave;
834 }
835
836 if (debug>2) printf("Found 2 at %x\n", *index);
837 retc = 1;
838 *depth = 2;
839 *index += 1;
840 goto Leave;
841 }
842
843#endif
844 nextP = (union RunData *) &data[*index];
845
846 }
847
848 if ( nextP->c[0] == currP->c[0] )
849 retc = 1;
850 else
851 retc = 0;
852
853Leave:
854
855 if ( retc == 1 )
856 *index += *depth;
857
858 return retc;
859}
860
861int
862EncodeImage( unsigned char * data, int pixels, unsigned char * fileArr )
863{
864 union RunData * currP, * norunP ;
865 int i, match, depth;
866 unsigned int filePos, run, nomatchrun;
867
868 currP = NULL;
869 norunP = NULL;
870 nomatchrun = 0;
871 filePos = 0; // position in the file we're writing out
872 run = 1;
873 depth = 1;
874
875 currP = (union RunData *)&data[0]; // start a new run
876 for (i=1; i<pixels;)
877 {
878 if ( compareruns( data, &i, pixels, currP, &depth ) )
879 run++;
880 else
881 {
882 if ( (run*depth) > 2 )
883 {
884 unsigned char * p = (unsigned char *)norunP;
885
886 if( nomatchrun )
887 {
888 while (nomatchrun)
889 {
890 int cnt;
891
892 cnt = (nomatchrun > 127) ? 127 : nomatchrun;
893 fileArr[filePos++] = cnt;
894 nomatchrun -= cnt;
895
896 while ( cnt-- )
897 fileArr[filePos++] = *p++;
898 }
899 }
900
901 filePos += encode_rle(fileArr, filePos, run, currP, depth);
902
903 norunP = NULL;
904 }
905 else
906 {
907 nomatchrun+=run;
908 }
909
910 currP = (union RunData *)&data[i]; // start a new run
911
912 if( norunP == NULL )
913 {
914 nomatchrun = 0;
915 norunP = currP;
916 }
917
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
921 }
922 }
923
924 if( nomatchrun )
925 {
926 unsigned char * p = (unsigned char *)norunP;
927 while (nomatchrun)
928 {
929 int cnt;
930
931 cnt = (nomatchrun > 127) ? 127 : nomatchrun;
932 fileArr[filePos++] = cnt;
933 nomatchrun -= cnt;
934
935 while ( cnt-- )
936 fileArr[filePos++] = *p++;
937 }
938 }
939
940 // write out any run that was in progress
941 if (run > 0) {
942 filePos += encode_rle(fileArr, filePos, run, currP, depth);
943 }
944
945 return filePos;
946}
947
948/* encode_rle applies a "modified-RLE encoding to a given image. The encoding works as follows:
949
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.
956
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.
959
960 encodings are: (q = quantity, v = value, c = quantity continues)
961
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 ]
968*/
969
970unsigned int
971encode_length(unsigned char * fileArr, unsigned int filePos, unsigned int quantity, unsigned int mask)
972{
973 unsigned char single_mask = 0x0F;
974 unsigned char double_mask = 0x7F;
975 unsigned int slots_used = 0;
976
977 fileArr[filePos] = mask | (quantity & single_mask); // low bits (plus mask)
978 slots_used++;
979
980 if (quantity >>= 4)
981 {
982 fileArr[filePos++] |= 0x10; // set length continuation bit
983 fileArr[filePos] = quantity & double_mask;
984 slots_used++;
985
986 while (quantity >>= 7)
987 {
988 fileArr[filePos++] |= 0x80; // set length continuation bit
989 fileArr[filePos] = quantity & double_mask;
990 slots_used++;
991 }
992 }
993
994 return slots_used;
995}
996
997
998unsigned int
999encode_rle(unsigned char * fileArr, unsigned int filePos, unsigned int quantity, union RunData * value, int depth)
1000{
1001 unsigned char single_mask = 0x0F;
1002 unsigned char double_mask = 0x7F;
1003 unsigned char slots_used = 0;
1004
1005
1006 switch ( depth )
1007 {
1008 case 1:
1009 slots_used += encode_length( fileArr, filePos, quantity, 0x80 );
1010 fileArr[filePos+slots_used++] = value->c[0];
1011 break;
1012
1013 case 2:
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];
1017 break;
1018
1019 case 3:
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];
1024 break;
1025
1026 case 4:
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];
1032 break;
1033 }
1034
1035 return slots_used;
1036}
1037
1038int
1039decode_rle( unsigned char * dataPtr, unsigned int * quantity, unsigned int * depth, unsigned char ** value )
1040{
1041 unsigned int mask;
1042 int i, runlen, runsize;
1043
1044 i = 0;
1045 mask = dataPtr[i] & 0xF0;
1046
1047 if ( mask & 0x80 )
1048 {
1049 runsize = ((mask & 0x60) >> 5) + 1;
1050 runlen = dataPtr[i++] & 0x0F;
1051
1052 if ( mask & 0x10 )
1053 {
1054 int shift = 4;
1055
1056 do
1057 {
1058 mask = dataPtr[i] & 0x80;
1059 runlen |= ((dataPtr[i++] & 0x7F) << shift);
1060 shift+=7;
1061 } while (mask);
1062 }
1063 } else
1064 {
1065 runlen = 1;
1066 runsize = dataPtr[i++];
1067 }
1068
1069 *depth = runsize;
1070 *quantity = runlen;
1071 *value = &dataPtr[i];
1072
1073 return i+runsize;
1074}
1075
1076int
1077findIndexNearMatch( unsigned int color24 )
1078{
1079 union colors color8;
1080 union colors clut8;
1081 int isGrey = 0;
1082
1083 color8.c24 = color24;
1084
1085 if ( color8.clut.red == color8.clut.green && color8.clut.green == color8.clut.blue )
1086 isGrey = 1;
1087
1088 if ( isGrey ) {
1089 int i;
1090 unsigned int bestIndex = 0, rel, bestMatch = -1;
1091
1092 for (i=0; i<256; i++)
1093 {
1094 clut8.c24 = panic_clut[i];
1095
1096 if ( clut8.clut.red != clut8.clut.green || clut8.clut.green != clut8.clut.blue )
1097 continue;
1098
1099 if ( clut8.clut.red > color8.clut.red) continue;
1100 rel = abs(color8.clut.red - clut8.clut.red);
1101 if ( rel < bestMatch ) {
1102 bestMatch = rel;
1103 bestIndex = i;
1104 }
1105 }
1106
1107 return bestIndex;
1108 }
1109
1110 // we must have a non-grey color
1111 return -1;
1112}
1113
1114unsigned int
1115color24toGrey( unsigned int color24 )
1116{
1117 float R, G, B;
1118 float Grey;
1119 union colors c;
1120 unsigned char grey8;
1121 unsigned int grey24;
1122
1123 c.c24 = color24;
1124
1125 R = (c.clut.red & 0xFF) ;
1126 G = (c.clut.green & 0xFF) ;
1127 B = (c.clut.blue & 0xFF) ;
1128
1129 Grey = (R*.30) + (G*.59) + (B*.11);
1130 grey8 = (unsigned char) ( Grey + .5);
1131 grey24 = (grey8<<16) | (grey8<<8) | grey8;
1132 return grey24;
1133}
1134
1135int
1136convert24toGrey( unsigned char * data, unsigned int size )
1137{
1138 float R, G, B;
1139 float Grey;
1140 unsigned int grey8;
1141 int i24;
1142
1143
1144 for ( i24=0; i24<size; i24+=3)
1145 {
1146 R = ((data[i24+0]) & 0xFF) ;
1147 G = ((data[i24+1]) & 0xFF) ;
1148 B = ((data[i24+2]) & 0xFF) ;
1149
1150 Grey = (R*.30) + (G*.59) + (B*.11);
1151 grey8 = (unsigned int) ( Grey + .5);
1152
1153 data[i24+0] = grey8;
1154 data[i24+1] = grey8;
1155 data[i24+2] = grey8;
1156 }
1157
1158 return size;
1159}
1160
1161int
1162convert8toGrey( unsigned char * data, unsigned int size )
1163{
1164 int i;
1165 unsigned int c24;
1166 union colors c;
1167
1168 for ( i=0; i<size; i++)
1169 {
1170 c.c24 = panic_clut[data[i]];
1171 c24 = color24toGrey( c.c24 );
1172 data[i] = findIndexMatch( c24 );
1173 }
1174
1175 return size;
1176}
1177
1178unsigned int
1179findColor24NearMatch( unsigned int color24 )
1180{
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;
1184
1185 if ( last_c == color24 )
1186 return last_co;
1187
1188 c.c24 = color24;
1189
1190 if ( c.rgb[1] > c.rgb[2] && c.rgb[1] > c.rgb[3] )
1191 prim = 1;
1192 else if ( c.rgb[2] > c.rgb[1] && c.rgb[2] > c.rgb[3] )
1193 prim = 2;
1194 else if ( c.rgb[3] > c.rgb[1] && c.rgb[3] > c.rgb[2] )
1195 prim = 3;
1196 else if ( c.rgb[1] == c.rgb[2] && c.rgb[1] == c.rgb[3] )
1197 prim = 0; // gray
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
1204 else
1205 printf("cannot tell color %06x\n", color24);
1206
1207 last_c = color24;
1208 last_p = prim;
1209
1210 if ( prim == 0 || prim > 3 )
1211 {
1212 last_co = -1;
1213 return last_co;
1214 }
1215
1216#if 0
1217 for (i=0; i<256; i++)
1218 {
1219
1220 break;
1221 }
1222#endif
1223
1224 return -1;
1225}
1226
1227
1228unsigned char
1229findIndexMatch( unsigned int color24 )
1230{
1231 int i;
1232 unsigned char ri;
1233 static unsigned char last = 0;
1234
1235retry:
1236 if ( panic_clut[last] == color24 )
1237 {
1238 exactmatch++;
1239 return last;
1240 }
1241
1242 for (i=0; i<256; i++)
1243 {
1244 if ( panic_clut[i] == color24 ) {
1245 last = i;
1246 exactmatch++;
1247 return last;
1248 }
1249 }
1250
1251 if ( nextmis == -1 ) {
1252 for (i=0; i<256; i++) mismatchClut[i] = -1;
1253 nextmis = 0;
1254 }
1255
1256 i = findIndexNearMatch(color24);
1257
1258 if ( i == -1 ) // found a color that is not grey
1259 {
1260 unsigned int colormatch = findColor24NearMatch( color24 );
1261
1262 if ( colormatch == -1 ) // cannot convert color
1263 {
1264 cvt2grey++;
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);
1268 }
1269 else
1270 color24 = colormatch;
1271
1272 goto retry;
1273 }
1274
1275 if (debug>1) printf("color %06X now matched at %x\n", color24, i);
1276
1277 ri = i;
1278
1279 neargrey++;
1280
1281 // keep track of missed repeats
1282 for ( i=0; i<nextmis; i++)
1283 if ( mismatchClut[i] == color24 )
1284 return ri;
1285
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;
1289
1290 if ( debug && (nextmis >= 256) )
1291 {
1292 fprintf(stderr,"Err: Too many color mismatches detected with this CLUT\n");
1293 exit(1);
1294 }
1295
1296 return ri;
1297}
1298
1299/*
1300 * Convert 24 bit mode to 8 bit. We do not do any alignment conversions
1301 */
1302
1303int
1304convert24to8bitIndex( unsigned char * data, int height, int width, unsigned char ** dout )
1305{
1306 unsigned int row, col, i, i24, i8, size;
1307 unsigned char index;
1308 unsigned char * ddata;
1309 union colors color24;
1310
1311 size = height * width;
1312
1313 ddata = (unsigned char *) calloc( size, 1);
1314
1315 for (i24=0,i8=0,row=0; row<height; row++)
1316 {
1317 for (col=0; col<width; col++)
1318 {
1319 color24.clut.red = data[i24++];
1320 color24.clut.green = data[i24++];
1321 color24.clut.blue = data[i24++];
1322
1323 index = findIndexMatch( color24.c24 );
1324 ddata[i8++] = index;
1325 }
1326 }
1327
1328 * dout = ddata;
1329
1330 return (i8);
1331}
1332
1333/*
1334 * Convert 8 bit mode to 8 bit, We have to strip off the alignment bytes
1335 */
1336
1337int
1338convert8bitIndexto8( unsigned char * data, int height, int width, unsigned char ** dout )
1339{
1340 unsigned int row, col, i, i8, size, adj;
1341 unsigned char index;
1342 unsigned char * ddata;
1343 union colors color24;
1344
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);
1348
1349 for (i8=0,row=0; row<height; row++)
1350 {
1351 for (col=0; col<width; col++)
1352 {
1353 index = *data++;
1354 color24.c24 = panic_clut[index];
1355 index = findIndexMatch( color24.c24 );
1356 ddata[i8++] = index;
1357 }
1358
1359 for (i=0; i<adj; i++)
1360 data++;
1361 }
1362
1363 * dout = ddata;
1364
1365 return (i8);
1366}
1367/*
1368 * Convert 8 bit mode to 24 bit, We have to strip off the alignment bytes
1369 */
1370
1371int
1372convert8bitIndexto24( unsigned char * data, int height, int width, unsigned char ** dout )
1373{
1374 unsigned int row, col, i, i24, i8, size, adj;
1375 unsigned char index;
1376 unsigned char * ddata;
1377 union colors color24;
1378
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);
1382
1383 for (i24=0,i8=0,row=0; row<height; row++)
1384 {
1385 for (col=0; col<width; col++)
1386 {
1387 index = data[i8++];
1388 color24.c24 = panic_clut[index];
1389
1390 ddata[i24++] = color24.clut.red;
1391 ddata[i24++] = color24.clut.green;
1392 ddata[i24++] = color24.clut.blue;
1393 }
1394
1395 for (i=0; i<adj; i++)
1396 i8++;
1397 }
1398
1399 * dout = ddata;
1400
1401 return (i24);
1402}
1403
1404
1405unsigned int *
1406CreateCLUTarry( unsigned char * raw_clut )
1407{
1408 unsigned int * new_clut, index, i;
1409
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];
1413
1414 return new_clut;
1415}
1416
1417
1418unsigned int *
1419ReplaceCLUT( char * iname )
1420{
1421 FILE * stream;
1422 unsigned char * raw_clut;
1423 unsigned int * new_clut, index, i;
1424
1425 if ( (stream = fopen(iname, "rb")) == NULL ) {
1426 fprintf(stderr,"Err: Could not open input clut file %s.\n\n", iname);
1427 exit(1);
1428 }
1429
1430 raw_clut = (char *) calloc(256, 3);
1431 fread(raw_clut, 256, 3, stream);
1432 fclose(stream);
1433
1434 new_clut = CreateCLUTarry( raw_clut );
1435
1436 free(raw_clut);
1437 return new_clut;
1438}
1439
1440
1441void
1442GenerateCLUT( char * oname )
1443{
1444 FILE * ostream;
1445 int i;
1446
1447
1448 if ( (ostream = fopen(oname, "w")) == NULL ) {
1449 fprintf(stderr,"Err: Could not open output clut file %s.\n\n", oname);
1450 exit(1);
1451 }
1452
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)
1457 {
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))?",":""));
1462 }
1463 fprintf(ostream, "};\n");
1464 fclose(ostream);
1465}
1466
1467void
1468WriteQTRawFile( FILE * ostream, unsigned char * data, int height, int width, int depth, unsigned int size )
1469{
1470 unsigned int i, adj, csize, tmp, col, line;
1471
1472
1473 if ( depth == 1)
1474 adj=(4-(width%4))%4; // adjustment needed to add the word alignment padding
1475 else
1476 adj = 0;
1477
1478 csize = height*depth*(width+adj);
1479
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);
1482
1483 tmp = csize + ( 2 * sizeof(unsigned int) );
1484 fwrite(&tmp, sizeof(unsigned int), 1, ostream);
1485
1486 tmp = 'idat';
1487 fwrite(&tmp, sizeof(unsigned int), 1, ostream);
1488
1489 if ( depth == 1)
1490 {
1491 for (line=0; line<height; line++)
1492 {
1493 for (col=0; col<width; col++)
1494 fwrite(data++, 1, 1, ostream);
1495
1496 for (i=0; i<adj; i++)
1497 fwrite(&data[-1], 1, 1, ostream);
1498 }
1499 } else
1500 fwrite(data, csize, 1, ostream);
1501
1502 tmp = 0x5e;
1503 fwrite(&tmp, sizeof(unsigned int), 1, ostream);
1504 tmp = 'idsc';
1505 fwrite(&tmp, sizeof(unsigned int), 1, ostream);
1506
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;
1525
1526 fwrite(&image_header, sizeof(image_header)-2, 1, ostream);
1527}
1528
1529
1530void
1531CreateRawQTCLUT( int type )
1532{
1533 FILE * ostream;
1534 char * name;
1535 unsigned char * raw_clut, * p;
1536 int row, i;
1537 int H=32, W=32, D;
1538
1539 if ( type == 8 )
1540 {
1541 name = "appleclut8.qtif";
1542 D = 1;
1543 }
1544 else
1545 {
1546 name = "unknownclut.qtif";
1547 D = 3;
1548 }
1549
1550 if ( (ostream = fopen(name, "wb")) == NULL ) {
1551 fprintf(stderr,"Err: Could not open output index file %s.\n\n", name);
1552 exit(1);
1553 }
1554
1555 raw_clut = (unsigned char *) malloc(H*W*D*256);
1556
1557 for (p=raw_clut, row=0; row<H; row++)
1558 {
1559 for (i=0; i<256; i++)
1560 {
1561 int j;
1562 union colors c;
1563
1564 if ( D == 3 )
1565 c.c24 = panic_clut[i];
1566
1567 for (j=0; j<W; j++)
1568 {
1569 if ( D == 1 )
1570 *p++ = i;
1571 else
1572 {
1573 *p++ = c.clut.red;
1574 *p++ = c.clut.green;
1575 *p++ = c.clut.blue;
1576 }
1577 }
1578 }
1579 }
1580 WriteQTRawFile( ostream, (unsigned char *) raw_clut, H, 256*W, D, H*256*W*D );
1581
1582 fclose(ostream);
1583}
1584
1585
1586void
1587CreateRawQTFont( void )
1588{
1589 FILE * ostream;
1590 unsigned char fonts[16][256][8];
1591 int row, i;
1592
1593 if ( (ostream = fopen("font.qtif", "wb")) == NULL ) {
1594 fprintf(stderr,"Err: Could not open output index file %s.\n\n", "font.qtif");
1595 exit(1);
1596 }
1597
1598 for (row=0; row<16; row++)
1599 {
1600 for (i=0; i<256; i++)
1601 {
1602 int j;
1603 unsigned char * c;
1604 unsigned char bits;
1605
1606 c = &iso_font[i*16];
1607 bits = c[row];
1608 for (j=7; j>=0; j--)
1609 {
1610 if ( bits & 0x80)
1611 fonts[row][i][j] = fg;
1612 else
1613 fonts[row][i][j] = bg;
1614 bits <<= 1;
1615 }
1616 }
1617 }
1618
1619 WriteQTRawFile( ostream, (unsigned char *) fonts, 16, 256*8, 1, 16*256*8 );
1620 fclose(ostream);
1621}