libvips/libsrc/iofuncs/im_header.c

267 lines
6.5 KiB
C

/* im_header_int, im_header_double, im_header_string: output various fields
* from the VIPS header
*
* 9/7/02 JC
* - first version
* 7/6/05
* - now reads meta fields too
* - cleaned up
* - added im_header_exists(), im_header_map()
* 1/8/05
* - now im_header_get_type() and im_header_get() rather than
* im_header_exists()
* 4/1/07
* - removed Hist from standard fields ... now a separate function
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Name, offset pair.
*/
typedef struct _HeaderField {
const char *field;
glong offset;
} HeaderField;
/* Built in fields and struct offsets.
*/
static HeaderField int_field[] = {
{ "Xsize", G_STRUCT_OFFSET( IMAGE, Xsize ) },
{ "Ysize", G_STRUCT_OFFSET( IMAGE, Ysize ) },
{ "Bands", G_STRUCT_OFFSET( IMAGE, Bands ) },
{ "Bbits", G_STRUCT_OFFSET( IMAGE, Bbits ) },
{ "BandFmt", G_STRUCT_OFFSET( IMAGE, BandFmt ) },
{ "Coding", G_STRUCT_OFFSET( IMAGE, Coding ) },
{ "Type", G_STRUCT_OFFSET( IMAGE, Type ) },
{ "Xoffset", G_STRUCT_OFFSET( IMAGE, Xoffset ) },
{ "Yoffset", G_STRUCT_OFFSET( IMAGE, Yoffset ) }
};
/* These are actually floats :-( how annoying. We report them as doubles for
* consistency with the im_meta_*() functions.
*/
static HeaderField double_field[] = {
{ "Xres", G_STRUCT_OFFSET( IMAGE, Xres ) },
{ "Yres", G_STRUCT_OFFSET( IMAGE, Yres ) }
};
static HeaderField string_field[] = {
{ "filename", G_STRUCT_OFFSET( IMAGE, filename ) }
};
int
im_header_int( IMAGE *im, const char *field, int *out )
{
int i;
for( i = 0; i < IM_NUMBER( int_field ); i++ )
if( strcmp( field, int_field[i].field ) == 0 ) {
*out = G_STRUCT_MEMBER( int, im,
int_field[i].offset );
break;
}
if( i == IM_NUMBER( int_field ) &&
im_meta_get_int( im, field, out ) ) {
im_error( "im_header_int",
_( "no such int field \"%s\"" ), field );
return( -1 );
}
return( 0 );
}
int
im_header_double( IMAGE *im, const char *field, double *out )
{
int i;
for( i = 0; i < IM_NUMBER( double_field ); i++ )
if( strcmp( field, double_field[i].field ) == 0 ) {
*out = G_STRUCT_MEMBER( float, im,
double_field[i].offset );
break;
}
if( i == IM_NUMBER( double_field ) &&
im_meta_get_double( im, field, out ) ) {
im_error( "im_header_double",
_( "no such double field \"%s\"" ), field );
return( -1 );
}
return( 0 );
}
int
im_header_string( IMAGE *im, const char *field, char **out )
{
int i;
for( i = 0; i < IM_NUMBER( string_field ); i++ )
if( strcmp( field, string_field[i].field ) == 0 ) {
*out = G_STRUCT_MEMBER( char *, im,
string_field[i].offset );
break;
}
if( i == IM_NUMBER( string_field ) &&
im_meta_get_string( im, field, out ) ) {
im_error( "im_header_string",
_( "no such string field \"%s\"" ), field );
return( -1 );
}
return( 0 );
}
GType
im_header_get_type( IMAGE *im, const char *field )
{
int i;
GType type;
for( i = 0; i < IM_NUMBER( int_field ); i++ )
if( strcmp( field, int_field[i].field ) == 0 )
return( G_TYPE_INT );
for( i = 0; i < IM_NUMBER( double_field ); i++ )
if( strcmp( field, double_field[i].field ) == 0 )
return( G_TYPE_DOUBLE );
for( i = 0; i < IM_NUMBER( string_field ); i++ )
if( strcmp( field, string_field[i].field ) == 0 )
return( G_TYPE_STRING );
if( (type = im_meta_get_type( im, field )) )
return( type );
return( 0 );
}
/* Fill value_copy with a copy of the value, -1 on error. value_copy must be
* zeroed but uninitialised. User must g_value_unset( value ).
*/
int
im_header_get( IMAGE *im, const char *field, GValue *value_copy )
{
int i;
for( i = 0; i < IM_NUMBER( int_field ); i++ )
if( strcmp( field, int_field[i].field ) == 0 ) {
g_value_init( value_copy, G_TYPE_INT );
g_value_set_int( value_copy,
G_STRUCT_MEMBER( int, im,
int_field[i].offset ) );
return( 0 );
}
for( i = 0; i < IM_NUMBER( double_field ); i++ )
if( strcmp( field, double_field[i].field ) == 0 ) {
g_value_init( value_copy, G_TYPE_DOUBLE );
g_value_set_double( value_copy,
G_STRUCT_MEMBER( float, im,
double_field[i].offset ) );
return( 0 );
}
for( i = 0; i < IM_NUMBER( string_field ); i++ )
if( strcmp( field, string_field[i].field ) == 0 ) {
g_value_init( value_copy, G_TYPE_STRING );
g_value_set_static_string( value_copy,
G_STRUCT_MEMBER( char *, im,
string_field[i].offset ) );
return( 0 );
}
if( !im_meta_get( im, field, value_copy ) )
return( 0 );
return( -1 );
}
static void *
header_map_fn( Meta *meta, im_header_map_fn fn, void *a )
{
return( fn( meta->im, meta->field, &meta->value, a ) );
}
void *
im_header_map( IMAGE *im, im_header_map_fn fn, void *a )
{
int i;
GValue value = { 0 };
void *result;
for( i = 0; i < IM_NUMBER( int_field ); i++ ) {
im_header_get( im, int_field[i].field, &value );
result = fn( im, int_field[i].field, &value, a );
g_value_unset( &value );
if( result )
return( result );
}
for( i = 0; i < IM_NUMBER( double_field ); i++ ) {
im_header_get( im, double_field[i].field, &value );
result = fn( im, double_field[i].field, &value, a );
g_value_unset( &value );
if( result )
return( result );
}
for( i = 0; i < IM_NUMBER( string_field ); i++ ) {
im_header_get( im, string_field[i].field, &value );
result = fn( im, string_field[i].field, &value, a );
g_value_unset( &value );
if( result )
return( result );
}
if( im->Meta_traverse &&
(result = im_slist_map2( im->Meta_traverse,
(VSListMap2Fn) header_map_fn, fn, a )) )
return( result );
return( NULL );
}