1/* converts a QT RAW 8-bit image file into format the kernel panic ui expects. 2 * 3 * to build: cc -o qtif2kraw qtif2kraw.c 4*/ 5 6#include <stdio.h> 7#include <unistd.h> 8#include <stdlib.h> 9#include <sys/types.h> 10#include <fcntl.h> 11#include <string.h> 12 13int EncodeImage( unsigned char * data, int pixels, unsigned char * fileArr ); 14int findIndexNearMatch( unsigned int color24 ); 15unsigned int findColor24NearMatch( unsigned int color24 ); 16unsigned char findIndexMatch( unsigned int color24 ); 17int convert8toGrey( unsigned char * data, unsigned int size ); 18int convert8bitIndexto8( unsigned char * data, int height, int width, unsigned char ** dout ); 19unsigned int * CreateCLUTarry( unsigned char * raw_clut ); 20unsigned int * ReplaceCLUT( char * iname ); 21 22#define offsetof(type, field) ((size_t)(&((type *)0)->field)) 23 24struct panicimage { 25 unsigned int pd_sum; 26 unsigned int pd_dataSize; 27 unsigned int pd_tag; 28 unsigned short pd_width; 29 unsigned short pd_height; 30 unsigned char pd_depth; 31 unsigned char pd_info_height; 32 unsigned char pd_info_color[2]; 33 unsigned char data[]; 34}; 35 36 37void 38usage( int type ) { 39printf( 40"\n" 41"Usage:\n" 42"\tqtif2kraw -i <.qtif> -o <.kraw> [operands ...]\n\n" 43"\tThe following operands are available\n\n" 44"\t-h\t\tDisplay full help information\n" 45"\t-i <file>\tUse file containing QuickTime uncompressed raw image as\n" 46"\t\t\tthe panic dialog (8 bit only)\n" 47"\t-o <file>\tWrite the output as a compressed kernel RAW image suitable\n" 48"\t\t\tfor loading into the kernel\n" 49"\t-c <file>\tUse file containing 256 RGB values for 8-bit indexed \n" 50"\t\t\tlookups, overrides built-in appleClut8\n" 51"\t-fg <color>\tForeground color of font used for panic information in\n" 52"\t\t\t24-bits, default 0xFFFFFF (100%% white)\n" 53"\t-bg <color>\tBackground color of font used for panic information in\n" 54"\t\t\t24-bits, default 0x222222 (13%% white, dark gray)\n" 55"\t-n <lines>\tNumber of lines that have been reserved to display the\n" 56"\t\t\tpanic information, must be at least 20\n" 57"\n\n" ); 58} 59 60 61#include "appleclut8.h" 62#include "../iso_font.c" 63 64struct QTHeader { 65 long idSize; /* total size of ImageDescription including extra data ( CLUTs and other per sequence data ) */ 66 long cType; /* 'raw '; what kind of codec compressed this data */ 67 long resvd1; /* reserved for Apple use */ 68 short resvd2; /* reserved for Apple use */ 69 short dataRefIndex; /* set to zero */ 70 short version; /* which version is this data */ 71 short revisionLevel; /* what version of that codec did this */ 72 long vendor; /* whose codec compressed this data */ 73 long temporalQuality; /* what was the temporal quality factor */ 74 long spatialQuality; /* what was the spatial quality factor */ 75 short width; /* how many pixels wide is this data */ 76 short height; /* how many pixels high is this data */ 77 long hRes; /* horizontal resolution */ 78 long vRes; /* vertical resolution */ 79 long dataSize; /* if known, the size of data for this image descriptor */ 80 short frameCount; /* number of frames this description applies to */ 81 char name[32]; /* name of codec ( in case not installed ) */ 82 short depth; /* what depth is this data (1-32) or ( 33-40 grayscale ) */ 83 short clutID; /* clut id or if 0 clut follows or -1 if no clut */ 84} image_header; 85 86static unsigned int mismatchClut[256]; 87static int nextmis = -1, neargrey = 0, cvt2grey = 0, exactmatch=0; 88static int grey = 0, debug = 0; 89static unsigned char fg, bg; 90unsigned int * panic_clut = NULL; 91static char * clutin = NULL; 92 93union colors { 94 unsigned int c24; 95 unsigned char rgb[4]; 96 struct { 97 unsigned char dummy; 98 unsigned char red; 99 unsigned char green; 100 unsigned char blue; 101 } clut; 102}; 103 104int 105main( int argc, char *argv[] ) 106{ 107 char *file = NULL; 108 char *kraw = NULL; 109 FILE * stream; 110 unsigned char * data; 111 unsigned short width = 0, height = 0; 112 unsigned char depth = 0, lines = 20; 113 unsigned int i, pixels, sum, encodedSize, fg24= 0xFFFFFF, bg24=0x222222; 114 unsigned char *fileArr; 115 int next; 116 117 118 // pull apart the arguments 119 for( next = 1; next < argc; next++ ) 120 { 121 if (strcmp(argv[next], "-i") == 0) // image file in raw QT uncompressed format (.qtif) 122 file = argv[++next]; 123 124 else if (strcmp(argv[next], "-o") == 0) // output file for WHD image 125 kraw = argv[++next]; 126 127 else if (strcmp(argv[next], "-n") == 0) // numbers of reserved lines 128 lines = atoi(argv[++next]); 129 else if (strcmp(argv[next], "-fg") == 0) // foreground color in 24 bits 130 sscanf(argv[++next], "%i", &fg24); 131 else if (strcmp(argv[next], "-bg") == 0) // background color in 24 bits 132 sscanf(argv[++next], "%i", &bg24); 133 else if (strcmp(argv[next], "-c") == 0) // input file for clut 134 clutin = argv[++next]; 135 else if (strcmp(argv[next], "-h") == 0) // display more help 136 { usage(1); exit(1); } 137 138 else if (strcmp(argv[next], "-debug") == 0) // verbose 139 debug++; 140 } 141 142 if (!(file || kraw) ) { 143 usage(0); 144 exit(1); 145 } 146 147 printf("\n"); 148 149 panic_clut = appleClut8; 150 151 if ( clutin ) 152 { 153 panic_clut = ReplaceCLUT( clutin ); 154 printf("Built-in CLUT has been replaced with %s...\n", clutin); 155 } 156 157 fg = findIndexNearMatch(fg24); 158 bg = findIndexNearMatch(bg24); 159 160 // Begin to process the image 161 162 if( file == NULL) 163 { 164 printf("No image file was processed...\n\n"); 165 exit(0); 166 } 167 168 169 printf("Verifing image file...\n"); 170 if ( file != NULL ) 171 { 172 stream = fopen(file, "r"); 173 if (!stream) { 174 fprintf(stderr, "Err: could not open .qtif image file.\n\n"); 175 exit(1); 176 } 177 178 { 179 long hdr_off; 180 long hdr_type; 181 int rc; 182 183 if ( ! fread((void *) &hdr_off, sizeof(long), 1, stream) ) goto errQTimage; 184 if ( ! fread((void *) &hdr_type, sizeof(long), 1, stream) ) goto errQTimage; 185 186 if ( hdr_type != 'idat' ) goto errQTimage; 187 188 if ( fseek(stream, hdr_off, SEEK_SET) ) goto errQTimage; 189 if ( ! fread((void *) &hdr_off, sizeof(long), 1, stream) ) goto errQTimage; 190 if ( ! fread((void *) &hdr_type, sizeof(long), 1, stream) ) goto errQTimage; 191 192 if ( hdr_type != 'idsc' ) goto errQTimage; 193 194 rc = fread((void *) &image_header, sizeof(image_header), 1, stream); 195 if ( !rc && !feof(stream) ) goto errQTimage; 196 if ( image_header.cType != 'raw ' ) goto errQTimage; 197 if ( image_header.depth != 8 ) goto errQTimage; 198 199 200 width = image_header.width; 201 height = image_header.height; 202 depth = image_header.depth; 203 204 printf("Image info: width: %d height: %d depth: %d...\n", width, height, depth); 205 206 if (!(width && height && depth)) { 207 fprintf(stderr,"Err: Invalid image file header (width, height, or depth is 0)\n"); 208 exit(1); 209 } 210 } 211 212 if ( !(data = (char *)malloc(image_header.dataSize))) { 213 fprintf(stderr,"Err: Couldn't malloc file data (%ld bytes)... bailing.\n", image_header.dataSize); 214 exit(1); 215 } 216 217 // Read the image data 218 if ( fseek(stream, 8, SEEK_SET) ) goto errQTimage; 219 if ( ! fread((void *) data, image_header.dataSize, 1, stream) ) goto errQTimage; 220 fclose( stream ); 221 222 pixels = image_header.dataSize; 223 224 if ( grey == 1 ) 225 pixels = convert8toGrey( data, image_header.dataSize ); 226 227 printf("Converting image file to 8 bit raw...\n"); 228 pixels = convert8bitIndexto8( data, height, width, &data ); 229 image_header.dataSize = pixels; 230 depth = 1; 231 232 printf("Converted %d pixels%s...\n", pixels/depth, ((grey==1)?" to grayscale":"")); 233 if ( exactmatch > 0 ) 234 printf("Found %d color mathces in CLUT...\n", exactmatch); 235 if ( cvt2grey > 0 ) 236 printf("Converted %d colors to gray...\n", cvt2grey); 237 if ( neargrey > 0 ) 238 printf("Adjusted %d grays to best match...\n", neargrey); 239 if ( nextmis > 0 ) 240 printf("Total of %d seperate color mismatches...\n", nextmis); 241 } 242 243 printf("Encoding image file...\n"); 244 245 if (!(fileArr = (unsigned char *) malloc(pixels))) { 246 fprintf(stderr,"Err: Couldn't malloc fileArr (%d pixels)... bailing.\n", pixels); 247 exit(1); 248 } 249 250 encodedSize = EncodeImage( data, pixels, fileArr ); 251 252 if ( encodedSize >= pixels ) 253 { 254 printf("Skipping encoding...\n"); 255 } 256 257 for (sum=0,i=0; i<encodedSize; i++) 258 { 259 sum += fileArr[i]; 260 sum <<= sum&1; 261 } 262 263 // write raw image suitable for kernel panic dialog 264 if ( kraw ) 265 { 266 FILE * ostream; 267 unsigned int tag; 268 269 if ( (ostream = fopen(kraw, "wb")) == NULL ) { 270 fprintf(stderr,"Err: Could not open output file %s.\n\n", kraw); 271 exit(1); 272 } 273 274 printf("Writing to binary panic dialog file %s, which is suitable for loading into kernel...\n", kraw); 275 276 tag = 'RNMp'; // Raw NMage for Panic dialog 277 depth = 1; // only CLUT is supported 278 279 fwrite(&sum, sizeof(sum), 1, ostream); 280 sum = encodedSize; 281 encodedSize += (256*3); 282 fwrite(&encodedSize, sizeof(encodedSize), 1, ostream); 283 encodedSize = sum; 284 fwrite(&tag, sizeof(tag), 1, ostream); 285 fwrite(&width, sizeof(width), 1, ostream); 286 fwrite(&height, sizeof(height), 1, ostream); 287 fwrite(&depth, sizeof(depth), 1, ostream); 288 fwrite(&lines, sizeof(lines), 1, ostream); 289 fwrite(&fg, sizeof(fg), 1, ostream); 290 fwrite(&bg, sizeof(bg), 1, ostream); 291 fwrite(fileArr, encodedSize, 1, ostream); 292 293 for ( i=0; i<256; i++) 294 { 295 union colors c; 296 unsigned char arr[3]; 297 298 c.c24 = panic_clut[i]; 299 300 arr[0] = c.clut.red; 301 arr[1] = c.clut.green; 302 arr[2] = c.clut.blue; 303 fwrite(arr, 3, 1, ostream); 304 } 305 fclose(ostream); 306 } 307 308 return 0; 309 310errQTimage: 311 fprintf(stderr,"Err: Input image must be in the QuickTime Raw Uncompressed 256 Colors format\n"); 312 exit(1); 313} 314 315 316 317#define RUN_MAX ((1<<20)-1) 318 319union RunData { 320 unsigned int i; 321 unsigned char c[4]; 322}; 323 324unsigned int encode_rle( 325 unsigned char * fileArr, 326 unsigned int filePos, 327 unsigned int quantity, 328 union RunData * value, 329 int depth); 330 331int 332compareruns( unsigned char * data, unsigned int * index, unsigned int max, union RunData * currP, int * depth ) 333{ 334 union RunData * nextP; 335 static int retc = 0; 336 337 if ( currP == NULL || data == NULL ) 338 { 339 retc = 0; 340 goto Leave; 341 } 342 343 if ( (*index+*depth) > max ) 344 { 345 *depth = 1; 346 retc = 0; 347 goto Leave; 348 } 349 350 nextP = (union RunData *) &data[*index]; 351 352 if ( retc == 1 ) 353 { 354 // check current data against current depth 355 switch ( *depth ) 356 { 357 case 1: 358 if ( nextP->c[0] == currP->c[0] ) 359 goto Leave; 360 break; 361 case 2: 362 if ( nextP->c[0] == currP->c[0] && 363 nextP->c[1] == currP->c[1] ) 364 goto Leave; 365 break; 366 case 3: 367 if ( nextP->c[0] == currP->c[0] && 368 nextP->c[1] == currP->c[1] && 369 nextP->c[2] == currP->c[2] ) 370 goto Leave; 371 break; 372 case 4: 373 if ( nextP->c[0] == currP->c[0] && 374 nextP->c[1] == currP->c[1] && 375 nextP->c[2] == currP->c[2] && 376 nextP->c[3] == currP->c[3] ) 377 goto Leave; 378 break; 379 } 380 381 retc = 0; 382 goto Leave; 383 } 384 385 // start of a new pattern match begine with depth = 1 386 387 if ( (*index+6) <= max ) 388 { 389 // We have at least 8 bytes left in the buffer starting from currP 390#if 1 391 nextP = (union RunData *) &data[*index+3]; 392 if ( nextP->c[0] == currP->c[0] && 393 nextP->c[1] == currP->c[1] && 394 nextP->c[2] == currP->c[2] && 395 nextP->c[3] == currP->c[3] ) 396 { 397 // check if they are all the same value 398 if ( currP->c[0] == currP->c[1] && 399 currP->c[1] == currP->c[2] && 400 currP->c[2] == currP->c[3] ) 401 { // if so, leave at depth = 1 402 retc = 1; 403 *depth = 1; 404 goto Leave; 405 } 406 407 if (debug>2) printf("Found 4 at %x\n", *index); 408 retc = 1; 409 *depth = 4; 410 *index += 3; 411 goto Leave; 412 } 413 414 nextP = (union RunData *) &data[*index+2]; 415 if ( nextP->c[0] == currP->c[0] && 416 nextP->c[1] == currP->c[1] && 417 nextP->c[2] == currP->c[2] ) 418 { 419 // check if they are all the same value 420 if ( currP->c[0] == currP->c[1] && 421 currP->c[1] == currP->c[2] ) 422 { // if so, leave at depth = 1 423 retc = 1; 424 *depth = 1; 425 goto Leave; 426 } 427 428 if (debug>2) printf("Found 3 at %x\n", *index); 429 retc = 1; 430 *depth = 3; 431 *index += 2; 432 goto Leave; 433 } 434 435 nextP = (union RunData *) &data[*index+1]; 436 if ( nextP->c[0] == currP->c[0] && 437 nextP->c[1] == currP->c[1] ) 438 { 439 // check if they are all the same value 440 if ( currP->c[0] == currP->c[1] ) 441 { // if so, leave at depth = 1 442 retc = 1; 443 *depth = 1; 444 goto Leave; 445 } 446 447 if (debug>2) printf("Found 2 at %x\n", *index); 448 retc = 1; 449 *depth = 2; 450 *index += 1; 451 goto Leave; 452 } 453 454#endif 455 nextP = (union RunData *) &data[*index]; 456 457 } 458 459 if ( nextP->c[0] == currP->c[0] ) 460 retc = 1; 461 else 462 retc = 0; 463 464Leave: 465 466 if ( retc == 1 ) 467 *index += *depth; 468 469 return retc; 470} 471 472int 473EncodeImage( unsigned char * data, int pixels, unsigned char * fileArr ) 474{ 475 union RunData * currP, * norunP ; 476 int i, depth; 477 unsigned int filePos, run, nomatchrun; 478 479 currP = NULL; 480 norunP = NULL; 481 nomatchrun = 0; 482 filePos = 0; // position in the file we're writing out 483 run = 1; 484 depth = 1; 485 486 currP = (union RunData *)&data[0]; // start a new run 487 for (i=1; i<pixels;) { 488 if ( compareruns( data, &i, pixels, currP, &depth ) ) 489 run++; 490 else { 491 if ( (run*depth) > 2 ) { 492 unsigned char * p = (unsigned char *)norunP; 493 494 if( nomatchrun ) { 495 while (nomatchrun) { 496 int cnt; 497 498 cnt = (nomatchrun > 127) ? 127 : nomatchrun; 499 fileArr[filePos++] = cnt; 500 nomatchrun -= cnt; 501 502 while ( cnt-- ) 503 fileArr[filePos++] = *p++; 504 } 505 } 506 507 filePos += encode_rle(fileArr, filePos, run, currP, depth); 508 509 norunP = NULL; 510 } else { 511 nomatchrun+=run; 512 } 513 514 currP = (union RunData *)&data[i]; // start a new run 515 516 if( norunP == NULL ) { 517 nomatchrun = 0; 518 norunP = currP; 519 } 520 521 depth = 1; // switch back to a single byte depth 522 run = 1; // thee is always at least one entry 523 i++; // point to next byte 524 } 525 } 526 527 if( nomatchrun ) { 528 unsigned char * p = (unsigned char *)norunP; 529 while (nomatchrun) { 530 int cnt; 531 532 cnt = (nomatchrun > 127) ? 127 : nomatchrun; 533 fileArr[filePos++] = cnt; 534 nomatchrun -= cnt; 535 536 while ( cnt-- ) 537 fileArr[filePos++] = *p++; 538 } 539 } 540 541 // write out any run that was in progress 542 if (run > 0) { 543 filePos += encode_rle(fileArr, filePos, run, currP, depth); 544 } 545 546 return filePos; 547} 548 549/* encode_rle applies a "modified-RLE encoding to a given image. The encoding works as follows: 550 551 The quantity is described in the first byte. If the MSB is zero, then the next seven bits 552 are the quantity. If the MSB is set, bits 0-3 of the quantity are in the least significant bits. 553 If bit 5 is set, then the quantity is further described in the next byte, where an additional 554 7 bits (4-10) worth of quantity will be found. If the MSB of this byte is set, then an additional 555 7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of 556 a quantity byte is zero, thus ending the chain. 557 558 The value is described in the first byte. If the MSB is zero, then the value is in the next byte. 559 If the MSB is set, then bits 5/6 describe the number of value bytes following the quantity bytes. 560 561 encodings are: (q = quantity, v = value, c = quantity continues) 562 563 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 Byte 7 Byte 8 564 case 1: [ 0 q6-q0 ] [ v7-v0 ] 565 case 2: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] 566 case 3: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] 567 case 4: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] 568 case 5: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] 569*/ 570 571unsigned int 572encode_length(unsigned char * fileArr, unsigned int filePos, unsigned int quantity, unsigned int mask) 573{ 574 unsigned char single_mask = 0x0F; 575 unsigned char double_mask = 0x7F; 576 unsigned int slots_used = 0; 577 578 fileArr[filePos] = mask | (quantity & single_mask); // low bits (plus mask) 579 slots_used++; 580 581 if (quantity >>= 4) { 582 fileArr[filePos++] |= 0x10; // set length continuation bit 583 fileArr[filePos] = quantity & double_mask; 584 slots_used++; 585 586 while (quantity >>= 7) { 587 fileArr[filePos++] |= 0x80; // set length continuation bit 588 fileArr[filePos] = quantity & double_mask; 589 slots_used++; 590 } 591 } 592 593 return slots_used; 594} 595 596 597unsigned int 598encode_rle(unsigned char * fileArr, unsigned int filePos, unsigned int quantity, union RunData * value, int depth) 599{ 600 unsigned char slots_used = 0; 601 602 603 switch ( depth ) { 604 case 1: 605 slots_used += encode_length( fileArr, filePos, quantity, 0x80 ); 606 fileArr[filePos+slots_used++] = value->c[0]; 607 break; 608 609 case 2: 610 slots_used += encode_length( fileArr, filePos, quantity, 0xA0 ); 611 fileArr[filePos+slots_used++] = value->c[0]; 612 fileArr[filePos+slots_used++] = value->c[1]; 613 break; 614 615 case 3: 616 slots_used += encode_length( fileArr, filePos, quantity, 0xC0 ); 617 fileArr[filePos+slots_used++] = value->c[0]; 618 fileArr[filePos+slots_used++] = value->c[1]; 619 fileArr[filePos+slots_used++] = value->c[2]; 620 break; 621 622 case 4: 623 slots_used += encode_length( fileArr, filePos, quantity, 0xE0 ); 624 fileArr[filePos+slots_used++] = value->c[0]; 625 fileArr[filePos+slots_used++] = value->c[1]; 626 fileArr[filePos+slots_used++] = value->c[2]; 627 fileArr[filePos+slots_used++] = value->c[3]; 628 break; 629 } 630 631 return slots_used; 632} 633 634 635int 636findIndexNearMatch( unsigned int color24 ) 637{ 638 union colors color8; 639 union colors clut8; 640 int isGrey = 0; 641 642 color8.c24 = color24; 643 644 if ( color8.clut.red == color8.clut.green && color8.clut.green == color8.clut.blue ) 645 isGrey = 1; 646 647 if ( isGrey ) { 648 int i; 649 unsigned int bestIndex = 0, rel, bestMatch = -1; 650 651 for (i=0; i<256; i++) { 652 clut8.c24 = panic_clut[i]; 653 654 if ( clut8.clut.red != clut8.clut.green || clut8.clut.green != clut8.clut.blue ) 655 continue; 656 657 if ( clut8.clut.red > color8.clut.red) continue; 658 rel = abs(color8.clut.red - clut8.clut.red); 659 if ( rel < bestMatch ) { 660 bestMatch = rel; 661 bestIndex = i; 662 } 663 } 664 665 return bestIndex; 666 } 667 668 // we must have a non-grey color 669 return -1; 670} 671 672unsigned int 673color24toGrey( unsigned int color24 ) 674{ 675 float R, G, B; 676 float Grey; 677 union colors c; 678 unsigned char grey8; 679 unsigned int grey24; 680 681 c.c24 = color24; 682 683 R = (c.clut.red & 0xFF) ; 684 G = (c.clut.green & 0xFF) ; 685 B = (c.clut.blue & 0xFF) ; 686 687 Grey = (R*.30) + (G*.59) + (B*.11); 688 grey8 = (unsigned char) ( Grey + .5); 689 grey24 = (grey8<<16) | (grey8<<8) | grey8; 690 return grey24; 691} 692 693 694int 695convert8toGrey( unsigned char * data, unsigned int size ) 696{ 697 int i; 698 unsigned int c24; 699 union colors c; 700 701 for ( i=0; i<size; i++) { 702 c.c24 = panic_clut[data[i]]; 703 c24 = color24toGrey( c.c24 ); 704 data[i] = findIndexMatch( c24 ); 705 } 706 707 return size; 708} 709 710unsigned int 711findColor24NearMatch( unsigned int color24 ) 712{ 713 union colors c; 714 unsigned char prim; 715 static unsigned int last_c = -1, last_co = -1, last_p = -1; 716 717 if ( last_c == color24 ) 718 return last_co; 719 720 c.c24 = color24; 721 722 if ( c.rgb[1] > c.rgb[2] && c.rgb[1] > c.rgb[3] ) 723 prim = 1; 724 else if ( c.rgb[2] > c.rgb[1] && c.rgb[2] > c.rgb[3] ) 725 prim = 2; 726 else if ( c.rgb[3] > c.rgb[1] && c.rgb[3] > c.rgb[2] ) 727 prim = 3; 728 else if ( c.rgb[1] == c.rgb[2] && c.rgb[1] == c.rgb[3] ) 729 prim = 0; // gray 730 else if ( c.rgb[1] == c.rgb[2] ) 731 prim = 0x12; // red green 732 else if ( c.rgb[1] == c.rgb[3] ) 733 prim = 0x13; // red blue 734 else if ( c.rgb[2] == c.rgb[3] ) 735 prim = 0x23; // green blue 736 else 737 printf("cannot tell color %06x\n", color24); 738 739 last_c = color24; 740 last_p = prim; 741 742 if ( prim == 0 || prim > 3 ) 743 { 744 last_co = -1; 745 return last_co; 746 } 747 748 return -1; 749} 750 751 752unsigned char 753findIndexMatch( unsigned int color24 ) 754{ 755 int i; 756 unsigned char ri; 757 static unsigned char last = 0; 758 759retry: 760 if ( panic_clut[last] == color24 ) 761 { 762 exactmatch++; 763 return last; 764 } 765 766 for (i=0; i<256; i++) 767 { 768 if ( panic_clut[i] == color24 ) { 769 last = i; 770 exactmatch++; 771 return last; 772 } 773 } 774 775 if ( nextmis == -1 ) { 776 for (i=0; i<256; i++) mismatchClut[i] = -1; 777 nextmis = 0; 778 } 779 780 i = findIndexNearMatch(color24); 781 782 if ( i == -1 ) // found a color that is not grey 783 { 784 unsigned int colormatch = findColor24NearMatch( color24 ); 785 786 if ( colormatch == -1 ) // cannot convert color 787 { 788 cvt2grey++; 789 if (debug>1) printf("color %06X not matched at all\n", color24); 790 color24 = color24toGrey(color24); 791 if (debug>1) printf("now grey %06X\n", color24); 792 } 793 else 794 color24 = colormatch; 795 796 goto retry; 797 } 798 799 if (debug>1) printf("color %06X now matched at %x\n", color24, i); 800 801 ri = i; 802 803 neargrey++; 804 805 // keep track of missed repeats 806 for ( i=0; i<nextmis; i++) 807 if ( mismatchClut[i] == color24 ) 808 return ri; 809 810 if ( debug) printf("closest match for %06X is at index %d %06X\n", color24, ri, panic_clut[ri]); 811 if ( nextmis < 256 ) 812 mismatchClut[nextmis++] = color24; 813 814 if ( debug && (nextmis >= 256) ) 815 { 816 fprintf(stderr,"Err: Too many color mismatches detected with this CLUT\n"); 817 exit(1); 818 } 819 820 return ri; 821} 822 823/* 824 * Convert 8 bit mode to 8 bit, We have to strip off the alignment bytes 825 */ 826 827int 828convert8bitIndexto8( unsigned char * data, int height, int width, unsigned char ** dout ) 829{ 830 unsigned int row, col, i, i8, size, adj; 831 unsigned char index; 832 unsigned char * ddata; 833 union colors color24; 834 835 adj=(4-(width%4))%4; // adjustment needed to strip off the word alignment padding 836 size = height * width; 837 ddata = (unsigned char *) calloc( size, 1); 838 839 for (i8=0,row=0; row<height; row++) 840 { 841 for (col=0; col<width; col++) 842 { 843 index = *data++; 844 color24.c24 = panic_clut[index]; 845 index = findIndexMatch( color24.c24 ); 846 ddata[i8++] = index; 847 } 848 849 for (i=0; i<adj; i++) 850 data++; 851 } 852 853 * dout = ddata; 854 855 return (i8); 856} 857 858 859unsigned int * 860CreateCLUTarry( unsigned char * raw_clut ) 861{ 862 unsigned int * new_clut, index, i; 863 864 new_clut = (unsigned int *) calloc(256, sizeof(unsigned int)); 865 for ( index=0,i=0; i<256; index+=3,i++ ) 866 new_clut[i] = (raw_clut[index] << 16) | (raw_clut[index+1] << 8) | raw_clut[index+2]; 867 868 return new_clut; 869} 870 871 872unsigned int * 873ReplaceCLUT( char * iname ) 874{ 875 FILE * stream; 876 unsigned char * raw_clut; 877 unsigned int * new_clut; 878 879 if ( (stream = fopen(iname, "rb")) == NULL ) { 880 fprintf(stderr,"Err: Could not open input clut file %s.\n\n", iname); 881 exit(1); 882 } 883 884 raw_clut = (char *) calloc(256, 3); 885 fread(raw_clut, 256, 3, stream); 886 fclose(stream); 887 888 new_clut = CreateCLUTarry( raw_clut ); 889 890 free(raw_clut); 891 return new_clut; 892} 893