/* setupdialog : converts a RAW image file into the c structure that the * kernel panic ui system expects. * * to build: cc -o setupdialog setupdialog.c */ #include #include #include #define RUN_MAX 32767 void create_numbers_file( FILE *stream, char *outfile ); unsigned int encode_rle(unsigned char * fileArr, unsigned int filePos, unsigned int quantity, unsigned char value); void usage(void) { printf("\nusage: setupdialog -i -oi -n -on \n"); printf("\nYou can supply a panic image file, a numbers file, or both. Input files\n"); printf("must be in RAW format where each pixel is represented by an index into the\n"); printf("MacOS X system CLUT. The first %d bytes must be the width, height, and depth\n", 3 * sizeof(short)); printf("(in that order, %d bytes each).\n", sizeof(short)); printf("\nThe output files are generated C structures in the format the panic ui code\n"); printf("expects (default output files are panic_image.c and rendered_numbers.c).\n\n"); } int main( int argc, char *argv[] ) { int next; char *file = NULL, *ptr, *out = NULL, *numsfile = NULL, *numsout = NULL; FILE * stream, *out_stream; int * data; short width = 0, height = 0, depth = 0; char word[2]; char byte; unsigned int i, pixels, filePos; int err; unsigned char *fileArr; unsigned char nextP; unsigned int count; int currP; int fd; int pairs_this_line; // pull apart the arguments for( next = 1; next < argc; next++ ) { if (strcmp(argv[next], "-i") == 0) // image file (RAW/PICT?) file = argv[++next]; else if (strcmp(argv[next], "-n") == 0) // numbers/chars image file (RAW) numsfile = argv[++next]; else if (strcmp(argv[next], "-oi") == 0) // output file for image out = argv[++next]; else if (strcmp(argv[next], "-on") == 0) // output file for numbers numsout = argv[++next]; /* perhaps we should just let the user specify the W/H rather than require the header */ /* else if (strcmp(argv[next], "-w") == 0) // image width (pixels) width = strtoul(argv[++next], &ptr, 0); else if (strcmp(argv[next], "-h") == 0) // image height (pixels) width = strtoul(argv[++next], &ptr, 0); */ } if (!(numsfile || file)) { usage(); exit(1); } if (!numsfile) { printf("\nNo numbers file to process\n"); } else { stream = fopen(numsfile, "r"); if (!stream) { printf("bad nums infile.. bailing.\n"); exit(1); } create_numbers_file( stream, numsout ); fclose(stream); } if( file == NULL) { printf("\nNo image file to process\n"); exit(1); } stream = fopen(file, "r"); if (!stream) { printf("bad infile.. bailing.\n"); exit(1); } printf("\nReading image file...\n"); fread((void *) &width, sizeof(short), 1, stream); printf("got width: %d\n", width); fread((void *) &height, sizeof(short), 1, stream); printf("got height: %d\n", height); fread((void *) &depth, sizeof(short), 1, stream); printf("got depth: %d\n", depth); if (!(width && height && depth)) { printf("Invalid image file header (width, height, or depth is 0)\n"); exit(1); } pixels = width * height; if (!(fileArr = (unsigned char *) malloc(pixels))) { printf("couldn't malloc fileArr (%d pixels)... bailing.\n", pixels); exit(1); } currP = -1; count = 0; filePos = 0; // position in the file we're writing out for (i=0; i < pixels; i++) { nextP = fgetc(stream); count++; if (nextP == currP) { if (count >= RUN_MAX) { filePos += encode_rle(fileArr, filePos, count, (unsigned char) currP); count = 0; currP = -1; } } else { if (currP != -1) { filePos += encode_rle(fileArr, filePos, count-1, (unsigned char) currP); } currP = nextP; // start a new run count = 1; } } // write out any run that was in progress if (count > 0) { filePos += encode_rle(fileArr, filePos, count, (unsigned char) currP); } fclose( stream ); // now, generate the c file if ( out == NULL) out = "panic_image.c"; out_stream = fopen(out, "w"); if(out_stream == NULL) { printf("couldn't open out file.. bailing\n"); exit(1); } pairs_this_line = 0; fprintf( out_stream, "/* generated c file */\n\n"); fprintf( out_stream, "static const struct {\n"); fprintf( out_stream, " unsigned int pd_width;\n"); fprintf( out_stream, " unsigned int pd_height;\n"); fprintf( out_stream, " unsigned int bytes_per_pixel; /* 1: CLUT, 3:RGB, 4:RGBA */\n"); fprintf( out_stream, " unsigned char image_pixel_data[%#4.2x];\n", (filePos)); fprintf( out_stream, "} panic_dialog = {\n"); fprintf( out_stream, "\t%d, ", width); /* panic dialog x */ fprintf( out_stream, "%d, ", height); /* panic dialog y */ fprintf( out_stream, "1,\n"); /* bytes per pixel */ for( i=0; i < filePos;) { fprintf( out_stream, "0x%.2x,0x%.2x", fileArr[i], fileArr[i+1]); i+=2; pairs_this_line++; // if the first byte had a leading 1, this is a 3-byte encoding if ((fileArr[i-2] >> 7) == 1) { fprintf( out_stream, ",0x%.2x", fileArr[i++]); pairs_this_line++; } if (i >= filePos) // this is the last element fprintf( out_stream, "\n};"); else fprintf( out_stream, ", "); if(pairs_this_line > 8) { fprintf( out_stream, "\n"); pairs_this_line = 0; } } fclose( out_stream ); return 0; } /* Each number/char (0-f) has its own row in the pixmap array. When done, these rows each contain an RLE character. The image file is read row by row, so the individual characters must be constructed in the same way. The numPos array tracks the current position in each character's RLE array. */ void create_numbers_file( FILE *stream, char *outfile ) { int err; short height, depth, totalwidth; int numbers = 17; int width[17] = {9,7,8,6,9,7,8,7,8,7,10,7,9,10,7,6,4}; int numPos[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int **pixmap; int row, col, item, line=0, currWidth; int nextP, currP; int count, currNum; FILE *out_stream; printf("\nReading numbers file...\n"); fread((void *) &totalwidth, sizeof(short), 1, stream); printf("got width: %d\n", totalwidth); fread((void *) &height, sizeof(short), 1, stream); printf("got height: %d\n", height); fread((void *) &depth, sizeof(short), 1, stream); printf("got depth: %d\n", depth); if (!(width && height && depth)) { printf("Invalid numbers file header (width, height, or depth is 0)\n"); return; } // allocate array to hold each number's RLE encoding (20 = 2xwidest width[i] value, 17 = num chars) pixmap = (int **) malloc( 17 * sizeof(int *) ); for( item=0; item<17; item++) pixmap[item] = (int *) malloc( 2*width[item]*height*sizeof(int) ); currP = -1; count = 0; currWidth = 0; currNum = 0; for( row=0; row < height; row++) { for( item=0; item < numbers; item++) { count = 0; currP = -1; // start each character fresh for( col=0; col < width[item]; col++) { nextP = fgetc( stream ); if( nextP == currP) { if( count == 127) { // probably never executed given the small widths pixmap[item][numPos[item]] = count; pixmap[item][numPos[item]+1] = currP; numPos[item]+=2; count = 0; currP = -1; } else count++; // add one to the current run } else { if( currP != -1) { pixmap[item][numPos[item]] = count; // currP was the end of the run pixmap[item][numPos[item]+1] = currP; numPos[item]+=2; } currP = nextP; // start a new run count = 1; } } // write out any run that was in progress if( count > 0) { pixmap[item][numPos[item]] = count; pixmap[item][numPos[item]+1] = currP; numPos[item]+=2; } } } // now, generate the c file if ( outfile == NULL) outfile = "rendered_numbers.c"; out_stream = fopen(outfile, "w"); if(out_stream == NULL) { printf("couldn't open numbers outfile.. bailing\n"); exit(1); } fprintf( out_stream, " /* generated c file */\n\n"); // iterate through all the numbers/chars for( item=0; item= width[item]) { fprintf( out_stream, "\n"); line = 0; } col+=2; } } fclose( out_stream ); } /* encode_rle applies a "modified-RLE encoding to a given image. The encoding works as follows: The quantity and value will be described by either two or three bytes. If the most significant bit of the first byte is a 0, then the next seven bits are the quantity (run-length) and the following 8 bits are the value (index into a clut, in this case). If the msb of the first byte is a 1, then the next 15 bits are the quantity and the following 8 are the value. Visually, the two possible encodings are: (q = quantity, v = value) Byte 1 Byte 2 Byte 3 case 1: [ 0 q6 q5 q4 q3 q2 q1 q0 ] [ v7 v6 v5 v4 v3 v2 v1 v0 ] [ ] case 2: [ 1 q14 q13 q12 a11 q10 q9 q8 ] [ q7 q6 q5 q4 q3 q2 q1 q0 ] [ v7 v6 v5 v4 v3 v2 v1 v0 ] */ unsigned int encode_rle(unsigned char * fileArr, unsigned int filePos, unsigned int quantity, unsigned char value) { unsigned char single_mask = 0x00; unsigned char double_mask = 0x80; unsigned char slots_used = 0; if (quantity < 128) { fileArr[filePos] = single_mask | quantity; slots_used = 1; } else { fileArr[filePos] = double_mask | (quantity >> 8); // high 7 bits (plus mask) fileArr[filePos+1] = (unsigned char) quantity; // low 8 bits slots_used = 2; } fileArr[filePos+slots_used] = value; slots_used++; return slots_used; }