new exif tag format
jpeg2vips now attaches exif in a way that can be modified by client programs
This commit is contained in:
parent
52c8678b23
commit
86fa10d474
@ -31,6 +31,7 @@
|
||||
- remove VipsPool, vips_object_local_array() is much better
|
||||
- cache.c now drops if you have too many open files
|
||||
- CLI args to change max files
|
||||
- new format for handling exif tags
|
||||
|
||||
12/10/11 started 7.26.6
|
||||
- NOCACHE was not being set correctly on OS X causing performance
|
||||
|
2
TODO
2
TODO
@ -103,7 +103,7 @@
|
||||
|
||||
exif-Orientation: 1 (Top-left, Short, 1 component, 2 bytes)
|
||||
|
||||
so we can restore the value from the "1" without needding to look up i18n
|
||||
so we can restore the value from the "1" without needing to look up i18n
|
||||
strings
|
||||
|
||||
|
||||
|
@ -254,36 +254,128 @@ show_values( ExifData *data )
|
||||
#endif /*HAVE_EXIF*/
|
||||
|
||||
#ifdef HAVE_EXIF
|
||||
static void
|
||||
attach_exif_entry( ExifEntry *entry, IMAGE *im )
|
||||
|
||||
static int
|
||||
vips_exif_get_int( ExifData *ed,
|
||||
ExifEntry *entry, unsigned long component, int *out )
|
||||
{
|
||||
char name_text[256];
|
||||
VipsBuf name;
|
||||
char value_text[256];
|
||||
VipsBuf value;
|
||||
char exif_value[256];
|
||||
ExifByteOrder bo = exif_data_get_byte_order( ed );
|
||||
size_t sizeof_component = entry->size / entry->components;
|
||||
size_t offset = component * sizeof_component;
|
||||
|
||||
vips_buf_init_static( &name, name_text, 256 );
|
||||
vips_buf_init_static( &value, value_text, 256 );
|
||||
if( entry->format == EXIF_FORMAT_SHORT )
|
||||
*out = exif_get_short( entry->data + offset, bo );
|
||||
else if( entry->format == EXIF_FORMAT_SSHORT )
|
||||
*out = exif_get_sshort( entry->data + offset, bo );
|
||||
else if( entry->format == EXIF_FORMAT_LONG )
|
||||
/* This won't work for huge values, but who cares.
|
||||
*/
|
||||
*out = (int) exif_get_long( entry->data + offset, bo );
|
||||
else if( entry->format == EXIF_FORMAT_SLONG )
|
||||
*out = exif_get_slong( entry->data + offset, bo );
|
||||
else
|
||||
return( -1 );
|
||||
|
||||
vips_buf_appendf( &name, "exif-%s", exif_tag_get_title( entry->tag ) );
|
||||
vips_buf_appendf( &value, "%s (%s, %lu components, %d bytes)",
|
||||
exif_entry_get_value( entry, exif_value, 256 ),
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_exif_get_double( ExifData *ed,
|
||||
ExifEntry *entry, unsigned long component, double *out )
|
||||
{
|
||||
ExifByteOrder bo = exif_data_get_byte_order( ed );
|
||||
size_t sizeof_component = entry->size / entry->components;
|
||||
size_t offset = component * sizeof_component;
|
||||
|
||||
if( entry->format == EXIF_FORMAT_RATIONAL ) {
|
||||
ExifRational value;
|
||||
|
||||
value = exif_get_rational( entry->data + offset, bo );
|
||||
*out = (double) value.numerator / value.denominator;
|
||||
}
|
||||
else if( entry->format == EXIF_FORMAT_SRATIONAL ) {
|
||||
ExifSRational value;
|
||||
|
||||
value = exif_get_srational( entry->data + offset, bo );
|
||||
*out = (double) value.numerator / value.denominator;
|
||||
}
|
||||
else
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Save an exif value to a string in a way that we can restore. We only bother
|
||||
* for the simple formats (that a client might try to change) though.
|
||||
*
|
||||
* Keep in sync with vips_exif_from_s() in vips2jpeg.
|
||||
*/
|
||||
static void
|
||||
vips_exif_to_s( ExifData *ed, ExifEntry *entry, VipsBuf *buf )
|
||||
{
|
||||
unsigned long i;
|
||||
int iv;
|
||||
double dv;
|
||||
char txt[256];
|
||||
|
||||
if( entry->format == EXIF_FORMAT_ASCII )
|
||||
vips_buf_appendf( buf, "%s ", entry->data );
|
||||
|
||||
else if( entry->components < 10 &&
|
||||
!vips_exif_get_int( ed, entry, 0, &iv ) ) {
|
||||
for( i = 0; i < entry->components; i++ ) {
|
||||
vips_exif_get_int( ed, entry, i, &iv );
|
||||
vips_buf_appendf( buf, "%d ", iv );
|
||||
}
|
||||
}
|
||||
else if( entry->components < 10 &&
|
||||
!vips_exif_get_double( ed, entry, 0, &dv ) ) {
|
||||
for( i = 0; i < entry->components; i++ ) {
|
||||
vips_exif_get_double( ed, entry, i, &dv );
|
||||
/* Need to be locale independent.
|
||||
*/
|
||||
g_ascii_dtostr( txt, 256, dv );
|
||||
vips_buf_appendf( buf, "%s ", txt );
|
||||
}
|
||||
}
|
||||
else
|
||||
vips_buf_appendf( buf, "%s ",
|
||||
exif_entry_get_value( entry, txt, 256 ) );
|
||||
|
||||
vips_buf_appendf( buf, "(%s, %s, %lu components, %d bytes)",
|
||||
exif_entry_get_value( entry, txt, 256 ),
|
||||
exif_format_get_name( entry->format ),
|
||||
entry->components,
|
||||
entry->size );
|
||||
}
|
||||
|
||||
typedef struct _VipsExif {
|
||||
VipsImage *image;
|
||||
ExifData *ed;
|
||||
} VipsExif;
|
||||
|
||||
static void
|
||||
attach_exif_entry( ExifEntry *entry, VipsExif *ve )
|
||||
{
|
||||
char name_txt[256];
|
||||
VipsBuf name = VIPS_BUF_STATIC( name_txt );
|
||||
char value_txt[256];
|
||||
VipsBuf value = VIPS_BUF_STATIC( value_txt );
|
||||
|
||||
vips_buf_appendf( &name, "exif-%s", exif_tag_get_title( entry->tag ) );
|
||||
vips_exif_to_s( ve->ed, entry, &value );
|
||||
|
||||
/* Can't do anything sensible with the error return.
|
||||
*/
|
||||
(void) im_meta_set_string( im,
|
||||
(void) im_meta_set_string( ve->image,
|
||||
vips_buf_all( &name ), vips_buf_all( &value ) );
|
||||
}
|
||||
|
||||
static void
|
||||
attach_exif_content( ExifContent *content, IMAGE *im )
|
||||
attach_exif_content( ExifContent *content, VipsExif *ve )
|
||||
{
|
||||
exif_content_foreach_entry( content,
|
||||
(ExifContentForeachEntryFunc) attach_exif_entry, im );
|
||||
(ExifContentForeachEntryFunc) attach_exif_entry, ve );
|
||||
}
|
||||
|
||||
/* Just find the first occurence of the tag (is this correct?)
|
||||
@ -307,19 +399,13 @@ static int
|
||||
get_entry_rational( ExifData *ed, ExifTag tag, double *out )
|
||||
{
|
||||
ExifEntry *entry;
|
||||
ExifRational rational;
|
||||
|
||||
if( !(entry = find_entry( ed, tag )) ||
|
||||
entry->format != EXIF_FORMAT_RATIONAL ||
|
||||
entry->components != 1 )
|
||||
return( -1 );
|
||||
|
||||
rational = exif_get_rational( entry->data,
|
||||
exif_data_get_byte_order( ed ) );
|
||||
|
||||
*out = (double) rational.numerator / rational.denominator;
|
||||
|
||||
return( 0 );
|
||||
return( vips_exif_get_double( ed, entry, 0, out ) );
|
||||
}
|
||||
|
||||
static int
|
||||
@ -332,10 +418,7 @@ get_entry_short( ExifData *ed, ExifTag tag, int *out )
|
||||
entry->components != 1 )
|
||||
return( -1 );
|
||||
|
||||
*out = exif_get_short( entry->data,
|
||||
exif_data_get_byte_order( ed ) );
|
||||
|
||||
return( 0 );
|
||||
return( vips_exif_get_int( ed, entry, 0, out ) );
|
||||
}
|
||||
|
||||
static void
|
||||
@ -434,6 +517,8 @@ read_exif( IMAGE *im, void *data, int data_length )
|
||||
return( -1 );
|
||||
|
||||
if( ed->size > 0 ) {
|
||||
VipsExif ve;
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
show_tags( ed );
|
||||
show_values( ed );
|
||||
@ -448,8 +533,10 @@ read_exif( IMAGE *im, void *data, int data_length )
|
||||
layer?
|
||||
|
||||
*/
|
||||
ve.image = im;
|
||||
ve.ed = ed;
|
||||
exif_data_foreach_content( ed,
|
||||
(ExifDataForeachContentFunc) attach_exif_content, im );
|
||||
(ExifDataForeachContentFunc) attach_exif_content, &ve );
|
||||
|
||||
/* Look for resolution fields and use them to set the VIPS
|
||||
* xres/yres fields.
|
||||
|
Loading…
x
Reference in New Issue
Block a user