static int iwopt_palette_is_valid_gray(struct iw_context *ctx, struct iw_opt_ctx *optctx, int bpp, int *pbinary_trns, unsigned int *ptrns_shade) { int factor; int i; int max_entries; iw_byte clr_used[256]; iw_byte key_clr=0; *pbinary_trns = 0; *ptrns_shade = 0; if(optctx->has_color) return 0; if(optctx->has_partial_transparency) return 0; if(optctx->has_transparency && !ctx->opt_binary_trns) return 0; if(optctx->has_transparency && !(ctx->output_profile&IW_PROFILE_BINARYTRNS)) return 0; switch(bpp) { case 1: factor=255; max_entries=2; break; case 2: factor=85; max_entries=4; break; case 4: factor=17; max_entries=16; break; case 8: factor=1; max_entries=256; break; default: return 0; } if(optctx->palette->num_entries > max_entries) return 0; // If there is a background color label, it must be one of the available gray shades. if(optctx->has_bkgdlabel && bpp<8) { // We already know the bkgd label is gray (because has_color is false), so we // only have to look at one of the components. if(optctx->bkgdlabel[0] % factor != 0) { return 0; } } iw_zeromem(clr_used,256); for(i=0;i<optctx->palette->num_entries;i++) { if(optctx->palette->entry[i].a>0) { // Look at all the nontransparent entries. if(optctx->palette->entry[i].r % factor) return 0; // Keep track of which shades were used. clr_used[optctx->palette->entry[i].r / factor] = 1; } } // In order for binary transparency to be usable, there must be at least // one unused gray shade. if(optctx->has_transparency) { if(!iwopt_find_unused(clr_used,max_entries,&key_clr)) return 0; *pbinary_trns = 1; *ptrns_shade = (unsigned int)key_clr; } return 1; }
static void iwopt_try_gray8_binary_trns(struct iw_context *ctx, struct iw_opt_ctx *optctx) { int i,j; const unsigned char *ptr; unsigned char *ptr2; unsigned char clr_used[256]; unsigned char key_clr; unsigned char *trns_mask = NULL; if(!(ctx->output_profile&IW_PROFILE_BINARYTRNS)) return; if(!ctx->opt_binary_trns) return; memset(&clr_used,0,256*sizeof(unsigned char)); trns_mask = iw_malloc_large(ctx, optctx->width, optctx->height); if(!trns_mask) goto done; for(j=0;j<optctx->height;j++) { for(i=0;i<optctx->width;i++) { ptr = &optctx->pixelsptr[j*optctx->bpr+i*2]; if(ptr[1]==0) { // Transparent pixel trns_mask[j*optctx->width+i] = 0; continue; } else { // Nontransparent pixel trns_mask[j*optctx->width+i] = 1; } clr_used[(int)ptr[0]] = 1; } } if(!iwopt_find_unused(clr_used,256,&key_clr)) { goto done; } // Strip the alpha channel: iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_GRAY,0,0,0); if(!optctx->tmp_pixels) goto done; // Change the color of all transparent pixels to the key color for(j=0;j<optctx->height;j++) { for(i=0;i<optctx->width;i++) { ptr2 = &optctx->tmp_pixels[j*optctx->bpr+i]; if(trns_mask[j*optctx->width+i]==0) { ptr2[0] = key_clr; } } } optctx->has_colorkey_trns = 1; optctx->colorkey_r = key_clr; optctx->colorkey_g = key_clr; optctx->colorkey_b = key_clr; done: if(trns_mask) iw_free(trns_mask); }
static int iwopt_palette_is_valid_gray(struct iw_context *ctx, struct iw_opt_ctx *optctx, int bpp, int *pbinary_trns, unsigned int *ptrns_shade) { int factor; int i; int max_entries; unsigned char clr_used[256]; unsigned char key_clr=0; *pbinary_trns = 0; *ptrns_shade = 0; if(optctx->has_color) return 0; if(optctx->has_partial_transparency) return 0; if(optctx->has_transparency && !ctx->opt_binary_trns) return 0; if(optctx->has_transparency && !(ctx->output_profile&IW_PROFILE_BINARYTRNS)) return 0; switch(bpp) { case 1: factor=255; max_entries=2; break; case 2: factor=85; max_entries=4; break; case 4: factor=17; max_entries=16; break; case 8: factor=1; max_entries=256; break; default: return 0; } if(optctx->palette->num_entries > max_entries) return 0; memset(&clr_used,0,256*sizeof(unsigned char)); for(i=0;i<optctx->palette->num_entries;i++) { if(optctx->palette->entry[i].a>0) { // Look at all the nontransparent entries. if(optctx->palette->entry[i].r % factor) return 0; // Keep track of which shades were used. clr_used[optctx->palette->entry[i].r / factor] = 1; } } // In order for binary transparency to be usable, there must be at least // one unused gray shade. if(optctx->has_transparency) { if(!iwopt_find_unused(clr_used,max_entries,&key_clr)) return 0; *pbinary_trns = 1; *ptrns_shade = (unsigned int)key_clr; } return 1; }
static void iwopt_try_rgb16_binary_trns(struct iw_context *ctx, struct iw_opt_ctx *optctx) { int i,j; const unsigned char *ptr; unsigned char *ptr2; unsigned char clr_used[256]; unsigned char key_clr; // low 8-bits of red component of the key color unsigned char *trns_mask = NULL; if(!(ctx->output_profile&IW_PROFILE_BINARYTRNS)) return; if(!ctx->opt_binary_trns) return; memset(&clr_used,0,256*sizeof(unsigned char)); trns_mask = iw_malloc_large(ctx, optctx->width, optctx->height); if(!trns_mask) goto done; for(j=0;j<optctx->height;j++) { for(i=0;i<optctx->width;i++) { ptr = &optctx->pixelsptr[j*optctx->bpr+(i*2)*4]; if(ptr[6]==0 && ptr[7]==0) { // Transparent pixel trns_mask[j*optctx->width+i] = 0; continue; } else { // Nontransparent pixel trns_mask[j*optctx->width+i] = 1; } // For the colors we look for, all bytes are 192 except possibly the low-red byte. if(ptr[0]!=192 || ptr[2]!=192 || ptr[3]!=192 || ptr[4]!=192 || ptr[5]!=192) continue; clr_used[(int)ptr[1]] = 1; } } if(!iwopt_find_unused(clr_used,256,&key_clr)) { goto done; } // Strip the alpha channel: iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_RGB,0,1,2); if(!optctx->tmp_pixels) goto done; // Change the color of all transparent pixels to the key color for(j=0;j<optctx->height;j++) { for(i=0;i<optctx->width;i++) { ptr2 = &optctx->tmp_pixels[j*optctx->bpr+(i*2)*3]; if(trns_mask[j*optctx->width+i]==0) { ptr2[0] = 192; ptr2[1] = key_clr; ptr2[2] = 192; ptr2[3] = 192; ptr2[4] = 192; ptr2[5] = 192; } } } optctx->has_colorkey_trns = 1; optctx->colorkey_r = 192*256+key_clr; optctx->colorkey_g = 192*256+192; optctx->colorkey_b = 192*256+192; done: if(trns_mask) iw_free(trns_mask); }
// Try to convert from RGBA to RGB+binary trns. // Assumes we already know there is transparency, but no partial transparency. static void iwopt_try_rgb8_binary_trns(struct iw_context *ctx, struct iw_opt_ctx *optctx) { int i,j; const unsigned char *ptr; unsigned char *ptr2; unsigned char clr_used[256]; unsigned char key_clr; // Red component of the key color unsigned char *trns_mask = NULL; if(!(ctx->output_profile&IW_PROFILE_BINARYTRNS)) return; if(!ctx->opt_binary_trns) return; // Try to find a color that's not used in the image. // Looking for all 2^24 possible colors is too much work. // We will just look for 256 predefined colors: R={0-255},G=192,B=192 memset(&clr_used,0,256*sizeof(unsigned char)); // Hard to decide how to do this. I don't want the optimization phase // to modify img2.pixels, though that would be the easiest method. // Another option would be to make a version of iw_opt_copychannels_8() // that sets the transparent pixels to a certain value, but that would // get messy. // Instead, I'll make a transparency mask, then strip the alpha // channel, then use the mask to patch up the new image. trns_mask = iw_malloc_large(ctx, optctx->width, optctx->height); if(!trns_mask) goto done; for(j=0;j<optctx->height;j++) { for(i=0;i<optctx->width;i++) { ptr = &optctx->pixelsptr[j*optctx->bpr+i*4]; if(ptr[3]==0) { // transparent pixel trns_mask[j*optctx->width+i] = 0; // Remember which pixels are transparent. continue; } else { trns_mask[j*optctx->width+i] = 1; } if(ptr[1]!=192 || ptr[2]!=192) continue; clr_used[(int)ptr[0]] = 1; } } if(!iwopt_find_unused(clr_used,256,&key_clr)) { goto done; } // Strip the alpha channel: iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_RGB,0,1,2); if(!optctx->tmp_pixels) goto done; // Change the color of all transparent pixels to the key color for(j=0;j<optctx->height;j++) { for(i=0;i<optctx->width;i++) { ptr2 = &optctx->tmp_pixels[j*optctx->bpr+i*3]; if(trns_mask[j*optctx->width+i]==0) { ptr2[0] = key_clr; ptr2[1] = 192; ptr2[2] = 192; } } } optctx->has_colorkey_trns = 1; optctx->colorkey_r = key_clr; optctx->colorkey_g = 192; optctx->colorkey_b = 192; done: if(trns_mask) iw_free(trns_mask); }
static void iwopt_try_gray16_binary_trns(struct iw_context *ctx, struct iw_opt_ctx *optctx) { int i,j; const iw_byte *ptr; iw_byte *ptr2; iw_byte clr_used[256]; iw_byte key_clr=0; // low 8-bits of the key color iw_byte *trns_mask = NULL; if(!(ctx->output_profile&IW_PROFILE_BINARYTRNS)) return; if(!ctx->opt_binary_trns) return; iw_zeromem(clr_used,256); trns_mask = iw_malloc_large(ctx, optctx->width, optctx->height); if(!trns_mask) goto done; for(j=0;j<optctx->height;j++) { for(i=0;i<optctx->width;i++) { ptr = &optctx->pixelsptr[j*optctx->bpr+(i*2)*2]; if(ptr[2]==0 && ptr[3]==0) { // Transparent pixel trns_mask[j*optctx->width+i] = 0; continue; } else { // Nontransparent pixel trns_mask[j*optctx->width+i] = 1; } // For the colors we look for, the high byte is always 192. if(ptr[0]!=192) continue; clr_used[(int)ptr[1]] = 1; } } if(!iwopt_find_unused(clr_used,256,&key_clr)) { goto done; } // Strip the alpha channel: iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_GRAY,0,0,0); if(!optctx->tmp_pixels) goto done; // Change the color of all transparent pixels to the key color for(j=0;j<optctx->height;j++) { for(i=0;i<optctx->width;i++) { ptr2 = &optctx->tmp_pixels[j*optctx->bpr+(i*2)]; if(trns_mask[j*optctx->width+i]==0) { ptr2[0] = 192; ptr2[1] = key_clr; } } } optctx->has_colorkey_trns = 1; optctx->colorkey[IW_CHANNELTYPE_RED] = 192*256+key_clr; optctx->colorkey[IW_CHANNELTYPE_GREEN] = 192*256+key_clr; optctx->colorkey[IW_CHANNELTYPE_BLUE] = 192*256+key_clr; done: if(trns_mask) iw_free(ctx,trns_mask); }