Esempio n. 1
0
static void
vips_exif_update( ExifData *ed, VipsImage *image )
{
	VipsExifRemove ve;

	VIPS_DEBUG_MSG( "vips_exif_update: \n" );

	/* If this exif came from the image (rather than being an exif block we
	 * have made afresh), then any fields which are in the block but not on
	 * the image must have been deliberately removed. Remove them from the
	 * block as well.
	 *
	 * If there are any string-valued fields (eg. comment etc.) which
	 * exist as libvips metadata tags, we must also remove those from the
	 * exif block.
	 *
	 * libexif does not allow you to change string lengths, you must make
	 * new tags, so we have to remove ready to re-add.
	 */
	if( vips_image_get_typeof( image, VIPS_META_EXIF_NAME ) ) {
		ve.image = image;
		ve.ed = ed;
		exif_data_foreach_content( ed, 
			(ExifDataForeachContentFunc) vips_exif_exif_content, 
			&ve );
	}

	/* Walk the image and add any exif- that's set in image metadata.
	 */
	vips_image_map( image, vips_exif_image_field, ed );
}
Esempio n. 2
0
/* Print header, or parts of header.
 */
static int
print_header( IMAGE *im, gboolean many )
{
	if( !main_option_field ) {
		printf( "%s: ", im->filename );

		vips_object_print_summary( VIPS_OBJECT( im ) );

		if( main_option_all )
			(void) vips_image_map( im, print_field_fn, &many );
	}
	else if( strcmp( main_option_field, "getext" ) == 0 ) {
		if( im__has_extension_block( im ) ) {
			void *buf;
			int size;

			if( !(buf = im__read_extension_block( im, &size )) )
				return( -1 );
			printf( "%s", (char *) buf );
			im_free( buf );
		}
	}
	else if( strcmp( main_option_field, "Hist" ) == 0 ) 
		printf( "%s", im_history_get( im ) );
	else {
		GValue value = { 0 };
		GType type;

		if( im_header_get( im, main_option_field, &value ) )
			return( -1 );

		/* Display the save form, if there is one. This way we display
		 * something useful for ICC profiles, xml fields, etc.
		 */
		type = G_VALUE_TYPE( &value );
		if( g_value_type_transformable( type, IM_TYPE_SAVE_STRING ) ) {
			GValue save_value = { 0 };

			g_value_init( &save_value, IM_TYPE_SAVE_STRING );
			if( !g_value_transform( &value, &save_value ) ) 
				return( -1 );
			printf( "%s\n", im_save_string_get( &save_value ) );
			g_value_unset( &save_value );
		}
		else {
			char *str_value;

			str_value = g_strdup_value_contents( &value );
			printf( "%s\n", str_value );
			g_free( str_value );
		}

		g_value_unset( &value );
	}

	return( 0 );
}
Esempio n. 3
0
static int
vips_fits_set_header( VipsFits *fits, VipsImage *in )
{
	int status;
	int bitpix;
	int i;

	status = 0;

	fits->naxis = 3;
	fits->naxes[0] = in->Xsize;
	fits->naxes[1] = in->Ysize;
	fits->naxes[2] = in->Bands;

	for( i = 0; i < VIPS_NUMBER( fits2vips_formats ); i++ )
		if( fits2vips_formats[i][1] == in->BandFmt )
			break;
	if( i == VIPS_NUMBER( fits2vips_formats ) ) {
		vips_error( "fits", 
			_( "unsupported BandFmt %d\n" ), in->BandFmt );
		return( -1 );
	}
	bitpix = fits2vips_formats[i][0];
	fits->datatype = fits2vips_formats[i][2];

#ifdef VIPS_DEBUG
	VIPS_DEBUG_MSG( "naxis = %d\n", fits->naxis );
	for( i = 0; i < fits->naxis; i++ )
		VIPS_DEBUG_MSG( "%d) %lld\n", i, fits->naxes[i] );
	VIPS_DEBUG_MSG( "bitpix = %d\n", bitpix );
#endif /*VIPS_DEBUG*/

	if( fits_create_imgll( fits->fptr, bitpix, fits->naxis, 
		fits->naxes, &status ) ) {
		vips_fits_error( status );
		return( -1 );
	}

	if( vips_image_map( in,
		(VipsImageMapFn) vips_fits_write_meta, fits ) )
		return( -1 );

	return( 0 );
}
Esempio n. 4
0
static void
vips_exif_update( ExifData *ed, VipsImage *image )
{
	VipsExif ve;

	VIPS_DEBUG_MSG( "vips_exif_update: \n" );

	/* Walk the image and update any stuff that's been changed in image
	 * metadata.
	 */
	vips_image_map( image, vips_exif_image_field, ed );

	/* Walk the exif and look for any fields which are NOT in image
	 * metadata. They must have been removed ... remove them from exif as
	 * well.
	 */
	ve.image = image;
	ve.ed = ed;
	exif_data_foreach_content( ed, 
		(ExifDataForeachContentFunc) vips_exif_exif_content, &ve );
}
Esempio n. 5
0
/* Write a VIPS image to PNG.
 */
static int
write_vips( Write *write, 
	int compress, int interlace, const char *profile,
	VipsForeignPngFilter filter, gboolean strip,
	gboolean palette, int colours, int Q, double dither )
{
	VipsImage *in = write->in;

	int bit_depth;
	int color_type;
	int interlace_type;
	int i, nb_passes;

        g_assert( in->BandFmt == VIPS_FORMAT_UCHAR || 
		in->BandFmt == VIPS_FORMAT_USHORT );
	g_assert( in->Coding == VIPS_CODING_NONE );
        g_assert( in->Bands > 0 && in->Bands < 5 );

	/* Catch PNG errors.
	 */
	if( setjmp( png_jmpbuf( write->pPng ) ) ) 
		return( -1 );

	/* Check input image. If we are writing interlaced, we need to make 7
	 * passes over the image. We advertise ourselves as seq, so to ensure
	 * we only suck once from upstream, switch to WIO. 
	 */
	if( interlace ) {
		if( !(write->memory = vips_image_copy_memory( in )) )
			return( -1 );
		in = write->memory;
	}
	else {
		if( vips_image_pio_input( in ) )
			return( -1 );
	}
	if( compress < 0 || compress > 9 ) {
		vips_error( "vips2png", 
			"%s", _( "compress should be in [0,9]" ) );
		return( -1 );
	}

	/* Set compression parameters.
	 */
	png_set_compression_level( write->pPng, compress );

	/* Set row filter.
	 */
	png_set_filter( write->pPng, 0, filter );

	bit_depth = in->BandFmt == VIPS_FORMAT_UCHAR ? 8 : 16;

	switch( in->Bands ) {
	case 1: color_type = PNG_COLOR_TYPE_GRAY; break;
	case 2: color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
	case 3: color_type = PNG_COLOR_TYPE_RGB; break;
	case 4: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break;

	default:
		vips_error( "vips2png", 
			_( "can't save %d band image as png" ), in->Bands );
		return( -1 );
	}

#ifdef HAVE_IMAGEQUANT
	/* Enable image quantisation to paletted 8bpp PNG if colours is set.
	 */
	if( palette ) {
		g_assert( colours >= 2 && 
			colours <= 256 );
		bit_depth = 8;
		color_type = PNG_COLOR_TYPE_PALETTE;
	}
#else
	if( palette )
		g_warning( "%s",
			_( "ignoring palette (no quantisation support)" ) );
#endif /*HAVE_IMAGEQUANT*/

	interlace_type = interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE;

	png_set_IHDR( write->pPng, write->pInfo, 
		in->Xsize, in->Ysize, bit_depth, color_type, interlace_type, 
		PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );

	/* Set resolution. libpng uses pixels per meter.
	 */
	png_set_pHYs( write->pPng, write->pInfo, 
		VIPS_RINT( in->Xres * 1000 ), VIPS_RINT( in->Yres * 1000 ), 
		PNG_RESOLUTION_METER );

	/* Set ICC Profile.
	 */
	if( profile && 
		!strip ) {
		if( strcmp( profile, "none" ) != 0 ) { 
			void *data;
			size_t length;

			if( !(data = vips__file_read_name( profile, 
				vips__icc_dir(), &length )) ) 
				return( -1 );

#ifdef DEBUG
			printf( "write_vips: "
				"attaching %zd bytes of ICC profile\n",
				length );
#endif /*DEBUG*/

			png_set_iCCP( write->pPng, write->pInfo, "icc", 
				PNG_COMPRESSION_TYPE_BASE, data, length );
		}
	}
	else if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) &&
		!strip ) {
		void *data;
		size_t length;

		if( vips_image_get_blob( in, VIPS_META_ICC_NAME, 
			&data, &length ) ) 
			return( -1 ); 

#ifdef DEBUG
		printf( "write_vips: attaching %zd bytes of ICC profile\n",
			length );
#endif /*DEBUG*/

		png_set_iCCP( write->pPng, write->pInfo, "icc", 
			PNG_COMPRESSION_TYPE_BASE, data, length );
	}

	if( vips_image_get_typeof( in, VIPS_META_XMP_NAME ) ) {
		const char *str;

		if( vips_image_get_string( in, VIPS_META_XMP_NAME, &str ) )
			return( -1 );

		vips__png_set_text( write->pPng, write->pInfo, 
			"XML:com.adobe.xmp", str );
	}

	/* Set any "png-comment-xx-yyy" metadata items.
	 */
	if( vips_image_map( in, 
		write_png_comment, write ) )
		return( -1 );

#ifdef HAVE_IMAGEQUANT
	if( palette ) {
		VipsImage *im_index;
		VipsImage *im_palette;
		int palette_count;
		png_color *png_palette;
		png_byte *png_trans;
		int trans_count;

		if( vips__quantise_image( in, &im_index, &im_palette, 
			colours, Q, dither ) ) 
			return( -1 );

		palette_count = im_palette->Xsize;

		g_assert( palette_count <= PNG_MAX_PALETTE_LENGTH );

		png_palette = (png_color *) png_malloc( write->pPng,
			palette_count * sizeof( png_color ) );
		png_trans = (png_byte *) png_malloc( write->pPng,
			palette_count * sizeof( png_byte ) );
		trans_count = 0;
		for( i = 0; i < palette_count; i++ ) {
			VipsPel *p = (VipsPel *) 
				VIPS_IMAGE_ADDR( im_palette, i, 0 );
			png_color *col = &png_palette[i];

			col->red = p[0];
			col->green = p[1];
			col->blue = p[2];
			png_trans[i] = p[3];
			if( p[3] != 255 )
				trans_count = i + 1;
#ifdef DEBUG
			printf( "write_vips: palette[%d] %d %d %d %d\n",
				i + 1, p[0], p[1], p[2], p[3] );
#endif /*DEBUG*/
		}

#ifdef DEBUG
		printf( "write_vips: attaching %d color palette\n",
			palette_count );
#endif /*DEBUG*/
		png_set_PLTE( write->pPng, write->pInfo, png_palette,
			palette_count );
		if( trans_count ) {
#ifdef DEBUG
			printf( "write_vips: attaching %d alpha values\n",
				trans_count );
#endif /*DEBUG*/
			png_set_tRNS( write->pPng, write->pInfo, png_trans,
				trans_count, NULL );
		}

		png_free( write->pPng, (void *) png_palette );
		png_free( write->pPng, (void *) png_trans );

		VIPS_UNREF( im_palette );

		VIPS_UNREF( write->memory );
		write->memory = im_index;
		in = write->memory;
	}
#endif /*HAVE_IMAGEQUANT*/

	png_write_info( write->pPng, write->pInfo );

	/* If we're an intel byte order CPU and this is a 16bit image, we need
	 * to swap bytes.
	 */
	if( bit_depth > 8 && 
		!vips_amiMSBfirst() ) 
		png_set_swap( write->pPng ); 

	if( interlace )	
		nb_passes = png_set_interlace_handling( write->pPng );
	else
		nb_passes = 1;

	/* Write data.
	 */
	for( i = 0; i < nb_passes; i++ ) 
		if( vips_sink_disc( in, write_png_block, write ) )
			return( -1 );

	/* The setjmp() was held by our background writer: reset it.
	 */
	if( setjmp( png_jmpbuf( write->pPng ) ) ) 
		return( -1 );

	png_write_end( write->pPng, write->pInfo );

	return( 0 );
}