Example #1
0
/* And orientation. 
 */
static int
vips_exif_set_orientation( ExifData *ed, VipsImage *im )
{
	int orientation;

	/* We set the tag, even if it's been deleted, since it's a required
	 * field.
	 */
	if( !vips_image_get_typeof( im, VIPS_META_ORIENTATION ) ||
		vips_image_get_int( im, VIPS_META_ORIENTATION, &orientation ) ) 
		orientation = 1;

	VIPS_DEBUG_MSG( "set_exif_orientation: %d\n", orientation );

	vips_exif_set_tag( ed, 0, EXIF_TAG_ORIENTATION, 
		vips_exif_set_int, (void *) &orientation );

	return( 0 );
}
Example #2
0
/* 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 );
}