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
|
- remove VipsPool, vips_object_local_array() is much better
|
||||||
- cache.c now drops if you have too many open files
|
- cache.c now drops if you have too many open files
|
||||||
- CLI args to change max files
|
- CLI args to change max files
|
||||||
|
- new format for handling exif tags
|
||||||
|
|
||||||
12/10/11 started 7.26.6
|
12/10/11 started 7.26.6
|
||||||
- NOCACHE was not being set correctly on OS X causing performance
|
- 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)
|
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
|
strings
|
||||||
|
|
||||||
|
|
||||||
|
@ -254,36 +254,128 @@ show_values( ExifData *data )
|
|||||||
#endif /*HAVE_EXIF*/
|
#endif /*HAVE_EXIF*/
|
||||||
|
|
||||||
#ifdef 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];
|
ExifByteOrder bo = exif_data_get_byte_order( ed );
|
||||||
VipsBuf name;
|
size_t sizeof_component = entry->size / entry->components;
|
||||||
char value_text[256];
|
size_t offset = component * sizeof_component;
|
||||||
VipsBuf value;
|
|
||||||
char exif_value[256];
|
|
||||||
|
|
||||||
vips_buf_init_static( &name, name_text, 256 );
|
if( entry->format == EXIF_FORMAT_SHORT )
|
||||||
vips_buf_init_static( &value, value_text, 256 );
|
*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 ) );
|
return( 0 );
|
||||||
vips_buf_appendf( &value, "%s (%s, %lu components, %d bytes)",
|
}
|
||||||
exif_entry_get_value( entry, exif_value, 256 ),
|
|
||||||
|
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 ),
|
exif_format_get_name( entry->format ),
|
||||||
entry->components,
|
entry->components,
|
||||||
entry->size );
|
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.
|
/* 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 ) );
|
vips_buf_all( &name ), vips_buf_all( &value ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
attach_exif_content( ExifContent *content, IMAGE *im )
|
attach_exif_content( ExifContent *content, VipsExif *ve )
|
||||||
{
|
{
|
||||||
exif_content_foreach_entry( content,
|
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?)
|
/* 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 )
|
get_entry_rational( ExifData *ed, ExifTag tag, double *out )
|
||||||
{
|
{
|
||||||
ExifEntry *entry;
|
ExifEntry *entry;
|
||||||
ExifRational rational;
|
|
||||||
|
|
||||||
if( !(entry = find_entry( ed, tag )) ||
|
if( !(entry = find_entry( ed, tag )) ||
|
||||||
entry->format != EXIF_FORMAT_RATIONAL ||
|
entry->format != EXIF_FORMAT_RATIONAL ||
|
||||||
entry->components != 1 )
|
entry->components != 1 )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
rational = exif_get_rational( entry->data,
|
return( vips_exif_get_double( ed, entry, 0, out ) );
|
||||||
exif_data_get_byte_order( ed ) );
|
|
||||||
|
|
||||||
*out = (double) rational.numerator / rational.denominator;
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -332,10 +418,7 @@ get_entry_short( ExifData *ed, ExifTag tag, int *out )
|
|||||||
entry->components != 1 )
|
entry->components != 1 )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
*out = exif_get_short( entry->data,
|
return( vips_exif_get_int( ed, entry, 0, out ) );
|
||||||
exif_data_get_byte_order( ed ) );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -434,6 +517,8 @@ read_exif( IMAGE *im, void *data, int data_length )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( ed->size > 0 ) {
|
if( ed->size > 0 ) {
|
||||||
|
VipsExif ve;
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
#ifdef DEBUG_VERBOSE
|
||||||
show_tags( ed );
|
show_tags( ed );
|
||||||
show_values( ed );
|
show_values( ed );
|
||||||
@ -448,8 +533,10 @@ read_exif( IMAGE *im, void *data, int data_length )
|
|||||||
layer?
|
layer?
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
ve.image = im;
|
||||||
|
ve.ed = ed;
|
||||||
exif_data_foreach_content( 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
|
/* Look for resolution fields and use them to set the VIPS
|
||||||
* xres/yres fields.
|
* xres/yres fields.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user