int vips__ppm_save( VipsImage *in, const char *filename, gboolean ascii ) { Write *write; if( vips_check_uintorf( "vips2ppm", in ) || vips_check_bands_1or3( "vips2ppm", in ) || vips_check_uncoded( "vips2ppm", in ) || vips_image_pio_input( in ) ) return( -1 ); /* We can only write >8 bit binary images in float. */ if( vips_format_sizeof( in->BandFmt ) > 1 && !ascii && in->BandFmt != VIPS_FORMAT_FLOAT ) { vips_error( "vips2ppm", "%s", _( "binary >8 bit images must be float" ) ); return( -1 ); } if( !(write = write_new( in, filename )) ) return( -1 ); if( write_ppm( write, ascii ) ) { write_destroy( write ); return( -1 ); } write_destroy( write ); return( 0 ); }
/* Make a sequence value. */ static void * vips_shrinkh_start( VipsImage *out, void *a, void *b ) { VipsImage *in = (VipsImage *) a; VipsShrinkhSequence *seq; if( !(seq = VIPS_NEW( out, VipsShrinkhSequence )) ) return( NULL ); seq->ir = vips_region_new( in ); /* Big enough for the largest intermediate. */ seq->sum = VIPS_ARRAY( out, in->Bands * vips_format_sizeof( VIPS_FORMAT_DPCOMPLEX ), VipsPel ); return( (void *) seq ); }
/* Write a TIFF header. width and height are the size of the VipsImage we are * writing (it may have been shrunk). */ static int write_tiff_header( Write *write, Layer *layer ) { TIFF *tif = layer->tif; int format; int orientation; /* Output base header fields. */ TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, layer->width ); TIFFSetField( tif, TIFFTAG_IMAGELENGTH, layer->height ); TIFFSetField( tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG ); TIFFSetField( tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT ); TIFFSetField( tif, TIFFTAG_COMPRESSION, write->compression ); if( write->compression == COMPRESSION_JPEG ) TIFFSetField( tif, TIFFTAG_JPEGQUALITY, write->jpqual ); if( write->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE ) TIFFSetField( tif, TIFFTAG_PREDICTOR, write->predictor ); /* Don't write mad resolutions (eg. zero), it confuses some programs. */ TIFFSetField( tif, TIFFTAG_RESOLUTIONUNIT, write->resunit ); TIFFSetField( tif, TIFFTAG_XRESOLUTION, VIPS_FCLIP( 0.01, write->xres, 1000000 ) ); TIFFSetField( tif, TIFFTAG_YRESOLUTION, VIPS_FCLIP( 0.01, write->yres, 1000000 ) ); if( !write->strip ) if( write_embed_profile( write, tif ) || write_embed_xmp( write, tif ) || write_embed_ipct( write, tif ) || write_embed_photoshop( write, tif ) || write_embed_imagedescription( write, tif ) ) return( -1 ); if( vips_image_get_typeof( write->im, VIPS_META_ORIENTATION ) && !vips_image_get_int( write->im, VIPS_META_ORIENTATION, &orientation ) ) TIFFSetField( tif, TIFFTAG_ORIENTATION, orientation ); /* And colour fields. */ if( write->im->Coding == VIPS_CODING_LABQ ) { TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, 3 ); TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, 8 ); TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CIELAB ); } else if( write->onebit ) { TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, 1 ); TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, 1 ); TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, write->miniswhite ? PHOTOMETRIC_MINISWHITE : PHOTOMETRIC_MINISBLACK ); } else { int photometric; /* Number of bands that have colour in .. other bands are saved * as alpha. */ int colour_bands; int alpha_bands; TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, write->im->Bands ); TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, vips_format_sizeof( write->im->BandFmt ) << 3 ); if( write->im->Bands < 3 ) { /* Mono or mono + alpha. */ photometric = write->miniswhite ? PHOTOMETRIC_MINISWHITE : PHOTOMETRIC_MINISBLACK; colour_bands = 1; } else { /* Could be: RGB, CMYK, LAB, perhaps with extra alpha. */ if( write->im->Type == VIPS_INTERPRETATION_LAB || write->im->Type == VIPS_INTERPRETATION_LABS ) { photometric = PHOTOMETRIC_CIELAB; colour_bands = 3; } else if( write->im->Type == VIPS_INTERPRETATION_CMYK && write->im->Bands >= 4 ) { photometric = PHOTOMETRIC_SEPARATED; TIFFSetField( tif, TIFFTAG_INKSET, INKSET_CMYK ); colour_bands = 4; } else if( write->compression == COMPRESSION_JPEG && write->im->Bands == 3 && write->im->BandFmt == VIPS_FORMAT_UCHAR && (!write->rgbjpeg && write->jpqual < 90) ) { /* This signals to libjpeg that it can do * YCbCr chrominance subsampling from RGB, not * that we will supply the image as YCbCr. */ photometric = PHOTOMETRIC_YCBCR; TIFFSetField( tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB ); colour_bands = 3; } else { /* Some kind of generic multi-band image .. * save the first three bands as RGB, the rest * as alpha. */ photometric = PHOTOMETRIC_RGB; colour_bands = 3; } } alpha_bands = VIPS_CLIP( 0, write->im->Bands - colour_bands, MAX_ALPHA ); if( alpha_bands > 0 ) { uint16 v[MAX_ALPHA]; int i; /* EXTRASAMPLE_UNASSALPHA means generic extra * alpha-like channels. ASSOCALPHA means pre-multipled * alpha only. */ for( i = 0; i < alpha_bands; i++ ) v[i] = EXTRASAMPLE_UNASSALPHA; TIFFSetField( tif, TIFFTAG_EXTRASAMPLES, alpha_bands, v ); } TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, photometric ); } /* Layout. */ if( write->tile ) { TIFFSetField( tif, TIFFTAG_TILEWIDTH, write->tilew ); TIFFSetField( tif, TIFFTAG_TILELENGTH, write->tileh ); } else TIFFSetField( tif, TIFFTAG_ROWSPERSTRIP, write->tileh ); if( layer->above ) /* Pyramid layer. */ TIFFSetField( tif, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE ); /* Sample format. */ format = SAMPLEFORMAT_UINT; if( vips_band_format_isuint( write->im->BandFmt ) ) format = SAMPLEFORMAT_UINT; else if( vips_band_format_isint( write->im->BandFmt ) ) format = SAMPLEFORMAT_INT; else if( vips_band_format_isfloat( write->im->BandFmt ) ) format = SAMPLEFORMAT_IEEEFP; else if( vips_band_format_iscomplex( write->im->BandFmt ) ) format = SAMPLEFORMAT_COMPLEXIEEEFP; TIFFSetField( tif, TIFFTAG_SAMPLEFORMAT, format ); return( 0 ); }