/*************************************************************** ** ** Broadcom Corp. Confidential ** Copyright 2002 Broadcom Corp. All Rights Reserved. ** ** THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED ** SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM. ** YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT ** SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. ** ** Description: convert simple clut 8 pngs to raw clut images ** ** Created: 8/22/2002 by Jeffrey P. Fisher ** ** ** ****************************************************************/ #include /* for gettimeofday() */ #include /* for fprintf() */ #include /* for rand() */ #include /* for sleep() */ #include /* for memset() */ #include #include /* Broadcom includes */ /* structure holding all necessary decode info */ typedef struct ptw_t { FILE *log_fp; png_structp png_ptr; png_infop info_ptr; png_infop end_info; png_uint_32 width; png_uint_32 height; int bit_depth; int color_type; int interlace_method; int compression_method; int filter_method; png_byte channels; png_uint_32 rowbytes; png_colorp palette; int num_palette; png_bytep trans; int num_trans; png_color_16p trans_values; png_bytepp row_pointers; }ptw_t; typedef struct bcm_raw_8_t { unsigned long version; /* version number of raw file - for future use */ unsigned long type; /* type of raw file - for future use */ unsigned long pitch; /* number of bytes per row */ unsigned short width; /* number of pixel per row */ unsigned short height; /* number of rows */ unsigned char color_key; /* color key/transparency color value */ unsigned short clut_size; /* number of entries in the ARGB8888 CLUT */ }bcm_raw_8_t; #define DBG_FPRINTF(x) fprintf x #define RAW_TYPE 0x52415720 #define RAW_VERSION 0x00000001 /**************************************************************** * validate_png_header * * INPUTS: ptw_p * OUTPUTS: none * RETURNS: non-zero if supported * FUNCTION: Function to inspect header and validate it is a compatible * image * ****************************************************************/ int validate_png_header(ptw_t *ptw_p) { int supported = 0; int format_changed = 0; png_get_IHDR(ptw_p->png_ptr, ptw_p->info_ptr, &ptw_p->width, &ptw_p->height, &ptw_p->bit_depth, &ptw_p->color_type, &ptw_p->interlace_method, &ptw_p->compression_method, &ptw_p->filter_method); ptw_p->channels = png_get_channels(ptw_p->png_ptr, ptw_p->info_ptr); ptw_p->rowbytes = png_get_rowbytes(ptw_p->png_ptr, ptw_p->info_ptr); DBG_FPRINTF((ptw_p->log_fp,"width = %d\n",ptw_p->width)); DBG_FPRINTF((ptw_p->log_fp,"height = %d\n",ptw_p->height)); DBG_FPRINTF((ptw_p->log_fp,"bit_depth = %d\n",ptw_p->bit_depth)); DBG_FPRINTF((ptw_p->log_fp,"color_type = 0x%08x(0x%08x,0x%08x,0x%08x)\n",ptw_p->color_type, ptw_p->color_type & PNG_COLOR_MASK_PALETTE, ptw_p->color_type & PNG_COLOR_MASK_COLOR, ptw_p->color_type & PNG_COLOR_MASK_ALPHA)); DBG_FPRINTF((ptw_p->log_fp,"channels = %d\n",ptw_p->channels)); DBG_FPRINTF((ptw_p->log_fp,"rowbytes = %d\n",ptw_p->rowbytes)); DBG_FPRINTF((ptw_p->log_fp,"interlace_type = %d\n",ptw_p->interlace_method)); DBG_FPRINTF((ptw_p->log_fp,"compression_type = %d\n",ptw_p->compression_method)); DBG_FPRINTF((ptw_p->log_fp,"filter_method = %d\n",ptw_p->filter_method)); supported = (((ptw_p->bit_depth == 8) || (ptw_p->bit_depth == 4)) && (ptw_p->color_type & PNG_COLOR_MASK_PALETTE) && ((ptw_p->channels == 3) || (ptw_p->channels == 4) || (ptw_p->channels == 1))); if (ptw_p->bit_depth == 4) { #if 0 png_color_8p sig_bit; if (png_get_sBIT(ptw_p->png_ptr, ptw_p->info_ptr, &sig_bit)) png_set_shift(ptw_p->png_ptr, sig_bit); #endif } if (!supported) { /* Check for ARGB 8888 */ supported = ((ptw_p->bit_depth == 8) && (ptw_p->color_type & PNG_COLOR_MASK_COLOR)); if (!(ptw_p->color_type & PNG_COLOR_MASK_ALPHA) || (ptw_p->channels != 4)) { png_set_add_alpha(ptw_p->png_ptr,0xff,PNG_FILLER_AFTER); format_changed = 1; } #if 0 if (ptw_p->color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_swap_alpha(ptw_p->png_ptr); #endif if (ptw_p->color_type == PNG_COLOR_TYPE_RGB || ptw_p->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { png_set_bgr(ptw_p->png_ptr); format_changed = 1; } if (format_changed) { png_read_update_info(ptw_p->png_ptr, ptw_p->info_ptr); png_get_IHDR(ptw_p->png_ptr, ptw_p->info_ptr, &ptw_p->width, &ptw_p->height, &ptw_p->bit_depth, &ptw_p->color_type, &ptw_p->interlace_method, &ptw_p->compression_method, &ptw_p->filter_method); ptw_p->channels = png_get_channels(ptw_p->png_ptr, ptw_p->info_ptr); ptw_p->rowbytes = png_get_rowbytes(ptw_p->png_ptr, ptw_p->info_ptr); } } DBG_FPRINTF((ptw_p->log_fp,"PNG type %s\n" ,supported ? "Supported":"Not Supported")); return supported; } /**************************************************************** * read_row_callback * * INPUTS: * OUTPUTS: none * RETURNS: none * FUNCTION: * ****************************************************************/ void read_row_callback(png_structp ptr, png_uint_32 row, int pass) { #ifdef PTR_DEBUG printf("read_row_callback(%d,%d)\n",row,pass); #endif } /**************************************************************** * read_chunk_callback * * INPUTS: * OUTPUTS: none * RETURNS: none * FUNCTION: * ****************************************************************/ int read_chunk_callback(png_structp ptr, png_unknown_chunkp chunk) { /* put your code here. Return one of the following: */ #ifdef PTR_DEBUG printf("read_chunk_callback(0x%02%02%02%02%02,%d,%p)\n", chunk->name[0],chunk->name[1],chunk->name[2], chunk->name[3],chunk->name[4],chunk->size,chunk->data); #endif //return(-n); /* chunk had an error */ //return(0); /* did not recognize */ return (chunk->size); /* success */ } /**************************************************************** * inspect_palette * * INPUTS: ptw_p * OUTPUTS: none * RETURNS: none * FUNCTION: Output the palette and transparency info * ****************************************************************/ void inspect_palette(ptw_t *ptw_p) { int i,cnt; png_get_PLTE(ptw_p->png_ptr, ptw_p->info_ptr, &ptw_p->palette, &ptw_p->num_palette); png_get_tRNS(ptw_p->png_ptr, ptw_p->info_ptr, &ptw_p->trans, &ptw_p->num_trans, &ptw_p->trans_values); DBG_FPRINTF((ptw_p->log_fp,"\nRGB Palette[%d]:\n",ptw_p->num_palette)); for (i = 0; i < ptw_p->num_palette; ++i) { DBG_FPRINTF((ptw_p->log_fp,"RGB[0x%02x]=0x%02x 0x%02x 0x%02x\n",i,ptw_p->palette[i].red, ptw_p->palette[i].green, ptw_p->palette[i].blue)); } DBG_FPRINTF((ptw_p->log_fp,"\nTransparency[%d]:\n",ptw_p->num_trans)); for (i = 0; i < ptw_p->num_trans; ++i) { DBG_FPRINTF((ptw_p->log_fp,"TRN[0x%02x]=0x%02x\n",i,ptw_p->trans[i])); } cnt = 0; DBG_FPRINTF((ptw_p->log_fp,"\nARGB Palette[%d]:\n",ptw_p->num_palette)); for (i = 0; i < ptw_p->num_palette; ++i) { DBG_FPRINTF((ptw_p->log_fp,"0x%02x%02x%02x%02x,",(i < ptw_p->num_trans) ? ptw_p->trans[i] : 0xFF , ptw_p->palette[i].red, ptw_p->palette[i].green, ptw_p->palette[i].blue)); if (cnt++ >= 0x7) { cnt = 0; DBG_FPRINTF((ptw_p->log_fp,"\n")); } } DBG_FPRINTF((ptw_p->log_fp,"\n")); } /**************************************************************** * get_color_key * * INPUTS: ptw_p * OUTPUTS: none * RETURNS: value or -1 if no value is found * FUNCTION: Get the first transparent value * ****************************************************************/ unsigned char get_color_key(ptw_t *ptw_p) { int i; //printf("get_color_key %d\n", ptw_p->num_palette); for (i = 0; i < ptw_p->num_trans; ++i) { if (ptw_p->trans[i] == 0) { if (i >= ptw_p->num_palette) return (ptw_p->num_palette - 1); return i; } } return ptw_p->num_palette - 1; } /**************************************************************** * Output a row (bit_depth = 4 only) * ****************************************************************/ void print_row(unsigned char* p_row,int width, int pitch, int rowbytes) { #if 0 int i; for (i = 0; i < width; ++i) { if (i & 1) { printf("0x%1x,", p_row[i / 2] & 0x0F); } else { printf("0x%1x,", (p_row[i / 2] >> 4) & 0x0F); } } printf("\n"); for (i = 0; i < width; ++i) { printf("0x%02x,", p_row[i]); } printf("\n"); #endif } /**************************************************************** * ****************************************************************/ void hex_output(FILE* f,unsigned char* ptr,int len) { int i; for (i = 0; i < len; i++) { if (i % 8 == 0) { fprintf(f,"\n\t"); } fprintf(f,"0x%02x, ",ptr[i]); } } /**************************************************************** * main * * INPUTS: arc - argument count * argv - array of arguments * OUTPUTS: none * RETURNS: none * FUNCTION: main entry point * DESCRIPTION: Convert PNGs to raw clut 8 images. * ****************************************************************/ int main(int argc, char *argv[]) { FILE *fp = NULL; FILE *out_fp = NULL; int result = -1; char header[8]; int is_png,row,i,palette_only,yuv,cfile; ptw_t ptw; bcm_raw_8_t raw; unsigned long clut[0xFF]; FILE* logfile = NULL; palette_only = 0; cfile = 0; memset(clut,0,sizeof(unsigned long) * 0xFF); memset(&ptw,0,sizeof(ptw_t)); yuv = 1; if (argc < 3) { printf("USAGE: pngtoraw [-p -v -r -c]\n"); printf("\t-p Output a raw palette only\n"); printf("\t-r Output RGB palette (default is YUV)\n"); printf("\t-v Verbose mode\n"); printf("\t-c Output raw image as C structure\n"); goto done; } for (i = 3; i < argc; ++i) { if ((strcmp(argv[i],"-v") == 0) || (strcmp(argv[i],"-V") == 0)) { ptw.log_fp = stdout; } else if ((strcmp(argv[i],"-p") == 0) || (strcmp(argv[i],"-P") == 0)) { printf("Output palette only\n"); palette_only = 1; } else if ((strcmp(argv[i],"-r") == 0) || (strcmp(argv[i],"-R") == 0)) { printf("Output RGB palette\n"); yuv = 0; } else if ((strcmp(argv[i],"-c") == 0) || (strcmp(argv[i],"-C") == 0)) { printf("Output raw image as C structure.\n"); cfile = 1; } } if (!ptw.log_fp) { logfile = ptw.log_fp = fopen("pngtoraw.log", "w"); } fp = fopen(argv[1], "rb"); if (!fp) { printf("Error opening file %s\n",argv[1]); goto done; } out_fp = fopen(argv[2], "wb"); if (!out_fp) { printf("Error opening file %s\n",argv[2]); goto done; } /* check the PNG header */ fread(header, 1, 8, fp); is_png = !png_sig_cmp(header, 0, 8); if (!is_png) { printf("%s not a PNG file\n",argv[1]); goto done; } /* Initialize the PNG library and structures */ ptw.png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if (!ptw.png_ptr) { printf("png_create_read_struct error\n"); goto done; } ptw.info_ptr = png_create_info_struct(ptw.png_ptr); if (!ptw.info_ptr) { printf("png_create_info_struct error\n"); goto done; } ptw.end_info = png_create_info_struct(ptw.png_ptr); if (!ptw.end_info) { printf("png_create_info_struct error\n"); goto done; } png_init_io(ptw.png_ptr, fp); png_set_sig_bytes(ptw.png_ptr,8); png_set_read_user_chunk_fn(ptw.png_ptr, &ptw, read_chunk_callback); png_set_read_status_fn(ptw.png_ptr, read_row_callback); png_read_info(ptw.png_ptr, ptw.info_ptr); if (!validate_png_header(&ptw)) goto done; if (ptw.color_type & PNG_COLOR_MASK_PALETTE) { inspect_palette(&ptw); } // png_read_png(ptw.png_ptr, ptw.info_ptr,PNG_TRANSFORM_IDENTITY , NULL); ptw.row_pointers = png_malloc(ptw.png_ptr, ptw.height * sizeof(ptw.row_pointers)); for (row = 0; row < ptw.height; row++) { ptw.row_pointers[row] = png_malloc(ptw.png_ptr, ptw.rowbytes); } png_read_image(ptw.png_ptr, ptw.row_pointers); png_read_end(ptw.png_ptr, ptw.end_info); /* pitch required for broadcom surface */ //raw.pitch = ((((ptw.width * 4) / 4/* pp4 bytes */) + 0xF) & ~0xF); if (ptw.color_type & PNG_COLOR_MASK_PALETTE) raw.pitch = (ptw.width * ptw.bit_depth) / 8; else raw.pitch = ptw.rowbytes; raw.width = ptw.width; raw.height = ptw.height; raw.clut_size = ptw.num_palette; raw.type = RAW_TYPE; raw.version = RAW_VERSION; DBG_FPRINTF((ptw.log_fp,"raw.pitch = %d\n",raw.pitch)); DBG_FPRINTF((ptw.log_fp,"raw.width = %d\n",raw.width)); DBG_FPRINTF((ptw.log_fp,"raw.height = %d\n",raw.height)); DBG_FPRINTF((ptw.log_fp,"raw.clut_size = %d\n",raw.clut_size)); if (!cfile) { fwrite((char*)&raw,1,sizeof(raw),out_fp); } else { char *dot_ptr; unsigned char *ptr; static char out_name[1024]; int len; fprintf(out_fp,"/* FILE: %s */\n",argv[2]); fprintf(out_fp,"/* pitch: %d */\n",raw.pitch); fprintf(out_fp,"/* width: %d */\n",raw.width); fprintf(out_fp,"/* height: %d */\n",raw.height); fprintf(out_fp,"/* clut_size: %d */\n",raw.clut_size); dot_ptr = strstr(argv[2],"."); if (!dot_ptr) { sprintf(out_name,"%s.c",argv[2]); } else { strcpy(out_name,argv[2]); dot_ptr[0] = 0; sprintf(out_name,"%s.c",argv[2]); } len = sizeof(raw) + (raw.pitch * raw.height) + (raw.clut_size * sizeof(unsigned int)); fprintf(out_fp,"\nunsigned int g_%s_size = %d;\n",argv[2],len); fprintf(out_fp,"const unsigned char g_%s[] = \n{\n\t",argv[2]); hex_output(out_fp,(unsigned char*)&raw,sizeof(raw)); } if (ptw.color_type & PNG_COLOR_MASK_PALETTE) { raw.color_key = get_color_key(&ptw); DBG_FPRINTF((ptw.log_fp,"raw.color_key = 0x%02x\n",raw.color_key)); for (i = 0; i < raw.clut_size; ++i) { unsigned long trans; if (i < ptw.num_trans) trans = ptw.trans[i]; else trans = 0xFF; if ((ptw.num_trans == 0) && (i == raw.color_key)) { trans = 0; } if (yuv) { unsigned int Y,U,V; unsigned int R,G,B; R = ((unsigned int)ptw.palette[i].red) & 0xFF; G = ((unsigned int)ptw.palette[i].green) & 0xFF; B = ((unsigned int)ptw.palette[i].blue) & 0xFF; Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16; V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128; U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128; clut[i] = (trans << 24) | ((Y & 0xFF) << 16) | ((U & 0xFF) << 8) | (V & 0xFF); } else { clut[i] = (trans << 24) | (((unsigned long)ptw.palette[i].red) << 16) | (((unsigned long)ptw.palette[i].green) << 8) | (unsigned long)ptw.palette[i].blue; } } /* ouput the file */ if (cfile) { hex_output(out_fp,(unsigned char*)clut,(sizeof(unsigned long) * raw.clut_size)); } else { fwrite((char*)&clut,1,(sizeof(unsigned long) * raw.clut_size),out_fp); } } if (palette_only) goto done; for (row = 0; row < raw.height; row++) { if (cfile) hex_output(out_fp,(unsigned char*)ptw.row_pointers[row],raw.pitch); else fwrite((char*)ptw.row_pointers[row],1,raw.pitch,out_fp); print_row((char*)ptw.row_pointers[row],raw.width, raw.pitch,ptw.rowbytes); if (ptw.rowbytes < raw.pitch) { if (cfile) hex_output(out_fp,(unsigned char*)ptw.row_pointers[row],raw.pitch - ptw.rowbytes); else fwrite((char*)ptw.row_pointers[row],1,raw.pitch - ptw.rowbytes,out_fp); } } if (cfile) fprintf(out_fp,"\n};\n"); done: if (ptw.png_ptr && !ptw.info_ptr && !ptw.end_info) png_destroy_read_struct(&ptw.png_ptr, (png_infopp)NULL, (png_infopp)NULL); if (ptw.png_ptr && ptw.info_ptr && !ptw.end_info) png_destroy_read_struct(&ptw.png_ptr, (png_infopp)&ptw.info_ptr, (png_infopp)NULL); if (ptw.png_ptr && ptw.info_ptr && ptw.end_info) png_destroy_read_struct(&ptw.png_ptr, (png_infopp)&ptw.info_ptr, (png_infopp)&ptw.end_info); if (fp) fclose(fp); if (out_fp) fclose(out_fp); if (logfile) fclose(logfile); return result; }