コード例 #1
0
ファイル: exif.c プロジェクト: jcupitt/libvips
/* And thumbnail. 
 */
static int
vips_exif_set_thumbnail( ExifData *ed, VipsImage *im )
{
	/* Delete any old thumbnail data. We should use the exif free func,
	 * but the memory allocator is not exposed by libexif! Hopefully they
	 * are just using free().
	 *
	 * exif.c makes this assumption too when it tries to update a
	 * thumbnail. 
	 */
	if( ed->data ) {
		free( ed->data );
		ed->data = NULL;
	}
	ed->size = 0;

	/* Update EXIF thumbnail from metadata, if any. 
	 */
	if( vips_image_get_typeof( im, "jpeg-thumbnail-data" ) ) { 
		void *data;
		size_t length;

		if( vips_image_get_blob( im, "jpeg-thumbnail-data", 
			&data, &length ) ) 
			return( -1 );

		/* Again, we should use the exif allocator attached to this
		 * entry, but it is not exposed!
		 */
		if( length > 0 && 
			data ) { 
			ed->data = malloc( length );
			memcpy( ed->data, data, length );
			ed->size = length;
		}
	}

	return( 0 );
}
コード例 #2
0
ファイル: exif.c プロジェクト: jcupitt/libvips
/* Scan the exif block on the image, if any, and make a set of vips metadata 
 * tags for what we find.
 */
int
vips__exif_parse( VipsImage *image )
{
	void *data;
	size_t length;
	ExifData *ed;
	VipsExifParams params;
	const char *str;

	if( !vips_image_get_typeof( image, VIPS_META_EXIF_NAME ) )
		return( 0 );
	if( vips_image_get_blob( image, VIPS_META_EXIF_NAME, &data, &length ) )
		return( -1 ); 
	if( !(ed = vips_exif_load_data_without_fix( data, length )) )
		return( -1 );

#ifdef DEBUG_VERBOSE
	show_tags( ed );
	show_values( ed );
#endif /*DEBUG_VERBOSE*/

	/* Look for resolution fields and use them to set the VIPS xres/yres 
	 * fields.
	 *
	 * If the fields are missing, set them from the image, which will have
	 * previously had them set from something like JFIF. 
	 */
	if( vips_image_resolution_from_exif( image, ed ) &&
		vips_exif_resolution_from_image( ed, image ) ) {
		exif_data_free( ed );
		return( -1 ); 
	}

	/* Make sure all required fields are there before we attach the vips
	 * metadata.
	 */
	exif_data_fix( ed );

	/* Attach informational fields for what we find.
	 */
	params.image = image;
	params.ed = ed;
	exif_data_foreach_content( ed, 
		(ExifDataForeachContentFunc) vips_exif_get_content, &params );

	vips_exif_get_thumbnail( image, ed );
	exif_data_free( ed );

	/* Orientation handling. ifd0 has the Orientation tag for the main
	 * image. 
	 */
	if( vips_image_get_typeof( image, "exif-ifd0-Orientation" ) != 0 &&
		!vips_image_get_string( image, 
			"exif-ifd0-Orientation", &str ) ) {
		int orientation;

		orientation = atoi( str );
		orientation = VIPS_CLIP( 1, orientation, 8 );
		vips_image_set_int( image, VIPS_META_ORIENTATION, orientation );
	}

	return( 0 );
}
コード例 #3
0
ファイル: exif.c プロジェクト: jcupitt/libvips
/* Examine the metadata tags on the image and update the EXIF block.
 */
int
vips__exif_update( VipsImage *image )
{
	unsigned char *data;
	size_t length;
	unsigned int idl;
	ExifData *ed;

	/* Either parse from the embedded EXIF, or if there's none, make
	 * some fresh EXIF we can write the resolution to.
	 */
	if( vips_image_get_typeof( image, VIPS_META_EXIF_NAME ) ) {
		if( vips_image_get_blob( image, VIPS_META_EXIF_NAME, 
			(void *) &data, &length ) )
			return( -1 );

		if( !(ed = exif_data_new_from_data( data, length )) )
			return( -1 );
	}
	else  {
		ed = exif_data_new();

		exif_data_set_option( ed, 
			EXIF_DATA_OPTION_FOLLOW_SPECIFICATION );
		exif_data_set_data_type( ed, EXIF_DATA_TYPE_COMPRESSED );
		exif_data_set_byte_order( ed, EXIF_BYTE_ORDER_INTEL );
	
		/* Create the mandatory EXIF fields with default data.
		 */
		exif_data_fix( ed );
	}

	/* Update EXIF tags from the image metadata.
	 */
	vips_exif_update( ed, image );

	/* Update EXIF resolution from the vips image header.
	 */
	if( vips_exif_resolution_from_image( ed, image ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Update EXIF image dimensions from the vips image header.
	 */
	if( vips_exif_set_dimensions( ed, image ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Update EXIF orientation from the vips image header.
	 */
	if( vips_exif_set_orientation( ed, image ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Update the thumbnail.
	 */
	if( vips_exif_set_thumbnail( ed, image ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Reserialise and write. exif_data_save_data() returns an int for some
	 * reason.
	 */
	exif_data_save_data( ed, &data, &idl );
	if( !idl ) {
		vips_error( "exif", "%s", _( "error saving EXIF" ) );
		exif_data_free( ed );
		return( -1 );
	}
	length = idl;

#ifdef DEBUG
	printf( "vips__exif_update: generated %zd bytes of EXIF\n", length  );
#endif /*DEBUG*/

	vips_image_set_blob( image, VIPS_META_EXIF_NAME, 
		(VipsCallbackFn) vips_free, data, length );

	exif_data_free( ed );

	return( 0 );
}
コード例 #4
0
ファイル: vipspng.c プロジェクト: ChiaraCaiazza/collageMaker
/* Write a VIPS image to PNG.
 */
static int
write_vips( Write *write, 
	int compress, int interlace, const char *profile,
	VipsForeignPngFilter filter, gboolean strip )
{
	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 );
	}

	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 );
	}

	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 );
}
コード例 #5
0
ファイル: vipspng.c プロジェクト: binarytemple/debian-vips
/* Write a VIPS image to PNG.
 */
static int
write_vips( Write *write, int compress, int interlace )
{
	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( 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 );

	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:
		g_assert( 0 );

		/* Keep -Wall happy.
		 */
		return( 0 );
	}

	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. libpnbg 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( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) {
		void *profile;
		size_t profile_length;

		if( vips_image_get_blob( in, VIPS_META_ICC_NAME, 
			&profile, &profile_length ) ) 
			return( -1 ); 

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

		png_set_iCCP( write->pPng, write->pInfo, "icc", 
			PNG_COMPRESSION_TYPE_BASE, profile, profile_length );
	}

	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( write->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 );
}
コード例 #6
0
ファイル: vipspng.c プロジェクト: jcupitt/libvips
/* 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 );
}
コード例 #7
0
static int
write_exif( Write *write )
{
#ifdef HAVE_EXIF
	unsigned char *data;
	size_t data_length;
	unsigned int idl;
	ExifData *ed;

	/* Either parse from the embedded EXIF, or if there's none, make
	 * some fresh EXIF we can write the resolution to.
	 */
	if( vips_image_get_typeof( write->in, VIPS_META_EXIF_NAME ) ) {
		if( vips_image_get_blob( write->in, VIPS_META_EXIF_NAME, 
			(void *) &data, &data_length ) )
			return( -1 );

		if( !(ed = exif_data_new_from_data( data, data_length )) )
			return( -1 );
	}
	else  {
		ed = exif_data_new();

		exif_data_set_option( ed, 
			EXIF_DATA_OPTION_FOLLOW_SPECIFICATION );
		exif_data_set_data_type( ed, EXIF_DATA_TYPE_COMPRESSED );
		exif_data_set_byte_order( ed, EXIF_BYTE_ORDER_INTEL );
	
		/* Create the mandatory EXIF fields with default data.
		 */
		exif_data_fix( ed );
	}

	/* Update EXIF tags from the image metadata.
	 */
	vips_exif_update( ed, write->in );

	/* Update EXIF resolution from the vips image header.
	 */
	if( vips__set_exif_resolution( ed, write->in ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Update EXIF image dimensions from the vips image header.
	 */
	if( set_exif_dimensions( ed, write->in ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Update EXIF orientation from the vips image header.
	 */
	if( set_exif_orientation( ed, write->in ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Reserialise and write. exif_data_save_data() returns an int for some
	 * reason.
	 */
	exif_data_save_data( ed, &data, &idl );
	if( !idl ) {
		vips_error( "VipsJpeg", "%s", _( "error saving EXIF" ) );
		exif_data_free( ed );
		return( -1 );
	}
	data_length = idl;

#ifdef DEBUG
	printf( "write_exif: attaching %zd bytes of EXIF\n", data_length  );
#endif /*DEBUG*/

	exif_data_free( ed );
	jpeg_write_marker( &write->cinfo, JPEG_APP0 + 1, data, data_length );
	free( data );
#else /*!HAVE_EXIF*/
	/* No libexif ... just copy the embedded EXIF over.
	 */
	if( write_blob( write, VIPS_META_EXIF_NAME, JPEG_APP0 + 1 ) )
		return( -1 );
#endif /*!HAVE_EXIF*/

	return( 0 );
}