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 strlcpy(image_header.name, " None", sizeof(image_header.name)); 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} 1622