static void callback_common(unsigned num,rgba *pixels) { if( flatspec.transmap_filename ) { if( flatspec.partial_transparency_mode == ALLOW_PARTIAL_TRANSPARENCY ) { unsigned i ; if( transfile == NULL ) start_writing(&transfile,5); for( i=0; i < num; i++ ) putc( ALPHA(pixels[i]), transfile ); } else { if( transfile == NULL ) { start_writing(&transfile,4); } /* Partial transparency should have been caught in the flattener, * so just extract a single byte. */ put_pbm_row(transfile,num,pixels,(rgba)1 << ALPHA_SHIFT); } } else if( ALPHA(flatspec.default_pixel) < 128 ) { unsigned i ; for( i=0; i < num; i++ ) if( !FULLALPHA(pixels[i]) ) FatalGeneric(100,_("Transparency found, but -a option not given")); } xcffree(pixels) ; }
static enum out_color_mode guessIndexed(struct FlattenSpec *spec,rgba *allPixels[]) { if( allPixels == NULL ) { if (spec->gimpish_indexed && colormapLength ) { unsigned i ; init_palette_hash(); for( i=0; i<colormapLength; i++ ) lookup_or_intern(NEWALPHA(colormap[i],255)); if( lookup_or_intern( FULLALPHA(spec->default_pixel) ? spec->default_pixel : 0 ) >= 0 ) return COLOR_INDEXED ; } } else { init_palette_hash() ; if( palettify_rows(allPixels,spec->dim.width,spec->dim.height) ) { /* Might grayscale sometimes be preferred? No, that is what * -g is for! */ return COLOR_INDEXED ; } } return COLOR_BY_CONTENTS ; }
int main(int argc,char **argv) { int option ; const char *unzipper = NULL ; const char *infile = NULL ; setlocale(LC_ALL,""); progname = argv[0] ; nls_init(); if( argc <= 1 ) gpl_blurb() ; init_flatspec(&flatspec) ; while( (option=getopt_long(argc,argv,"-"OPTSTRING,longopts,NULL)) >= 0 ) switch(option) { #define OPTION(char,long,desc,man) case char: #include "options.i" case 1: if( infile ) add_layer_request(&flatspec,optarg); else infile = optarg ; break ; case '?': usage(stderr); default: FatalUnexpected("Getopt(_long) unexpectedly returned '%c'",option); } if( infile == NULL ) { usage(stderr); } read_or_mmap_xcf(infile,unzipper); getBasicXcfInfo() ; initColormap(); complete_flatspec(&flatspec,guessIndexed); if( flatspec.process_in_memory ) { rgba **allPixels = flattenAll(&flatspec); analyse_colormode(&flatspec,allPixels,guessIndexed); /* See if we can do alpha compaction. */ if( flatspec.partial_transparency_mode != ALLOW_PARTIAL_TRANSPARENCY && !FULLALPHA(flatspec.default_pixel) && flatspec.out_color_mode != COLOR_INDEXED ) { rgba unused = findUnusedColor(allPixels, flatspec.dim.width, flatspec.dim.height); if( unused && (flatspec.out_color_mode == COLOR_RGB || degrayPixel(unused) >= 0) ) { unsigned x,y ; unused = NEWALPHA(unused,0) ; for( y=0; y<flatspec.dim.height; y++) for( x=0; x<flatspec.dim.width; x++) if( allPixels[y][x] == 0 ) allPixels[y][x] = unused ; flatspec.default_pixel = unused ; } } shipoutWithCallback(&flatspec,allPixels,selectCallback()); } else { flattenIncrementally(&flatspec,selectCallback()); } if( libpng ) { png_write_end(libpng,libpng2); png_destroy_write_struct(&libpng,&libpng2); } if( outfile ) { closeout(outfile,flatspec.output_filename); } return 0 ; }
void analyse_colormode(struct FlattenSpec *spec,rgba **allPixels, guesser guess_callback) { unsigned x,y ; int status ; /* 8 - looking for any transparency * 4 - looking for partially transparent pixels * 2 - looking for pixels other than black and white * 1 - looking for colored pixels */ int known_absent = 0 ; int assume_present = 0 ; if( spec->out_color_mode == COLOR_BY_CONTENTS && guess_callback ) spec->out_color_mode = guess_callback(spec,allPixels) ; if( spec->out_color_mode == COLOR_RGB ) assume_present |= 3 ; if( spec->out_color_mode == COLOR_INDEXED ) assume_present |= 3 ; if( spec->out_color_mode == COLOR_GRAY ) assume_present |= 2 ; switch( color_by_layers(spec) ) { case COLOR_GRAY: known_absent |= 1 ; break ; case COLOR_MONO: known_absent |= 3 ; break ; default: break ; } if( spec->partial_transparency_mode == DISSOLVE_PARTIAL_TRANSPARENCY || spec->partial_transparency_mode == PARTIAL_TRANSPARENCY_IMPOSSIBLE ) known_absent |= 4 ; if( ALPHA(spec->default_pixel) >= 128 ) known_absent |= 12 ; else if( spec->default_pixel == FORCE_ALPHA_CHANNEL ) assume_present |= 8 ; status = 15 - (known_absent | assume_present) ; for( y=0; status && y<spec->dim.height; y++ ) { rgba *row = allPixels[y] ; if( (status & 3) != 0 ) { /* We're still interested in color */ for( x=0; status && x<spec->dim.width; x++ ) { if( NULLALPHA(row[x]) ) status &= ~8 ; else { rgba full = row[x] | (255 << ALPHA_SHIFT) ; if( !FULLALPHA(row[x]) ) status &= ~12 ; if( full == NEWALPHA(0,255) || full == NEWALPHA(-1,255) ) /* Black or white */ ; else if( degrayPixel(row[x]) != -1 ) status &= ~2 ; /* gray */ else status &= ~3 ; /* color */ } } } else { /* Not interested in color */ for( x=0; status && x<spec->dim.width; x++ ) { if( NULLALPHA(row[x]) ) status &= ~8 ; else if( !FULLALPHA(row[x]) ) status &= ~12 ; } } } status |= known_absent ; switch( spec->out_color_mode ) { case COLOR_INDEXED: /* The caller takes responsibility */ case COLOR_RGB: /* Everything is fine. */ break ; case COLOR_GRAY: if( (status & 1) == 0 ) FatalGeneric(103, _("Grayscale output selected, but colored pixel(s) found")); break ; case COLOR_MONO: if( (status & 2) == 0 ) FatalGeneric(103,_("Monochrome output selected, but not all pixels " "are black or white")); break ; case COLOR_BY_FILENAME: /* Should not happen ... */ case COLOR_BY_CONTENTS: if( (status & 1) == 0 ) spec->out_color_mode = COLOR_RGB ; else if( (status & 2) == 0 ) spec->out_color_mode = COLOR_GRAY ; else spec->out_color_mode = COLOR_MONO ; break ; } if( (status & 12) == 12 ) /* No transparency found */ spec->default_pixel = NEWALPHA(colormap[0],255); else if( (status & 12) == 4 ) spec->partial_transparency_mode = PARTIAL_TRANSPARENCY_IMPOSSIBLE ; }