This commit is contained in:
John Cupitt 2011-11-24 14:53:30 +00:00
parent 584e11e88d
commit 2c641c6644
12 changed files with 1080 additions and 420 deletions

7
TODO
View File

@ -1,9 +1,6 @@
- move all the haeder / lazy load / lazy save stuff from image.c into file.c
- file.c has lazy open stuff in, needs work though
can common up a lot of load/save from the *2vips.c etc. into FileLoad,
hopefully
format from name should retur a char*, a recommended load operation
how do we handle loaders that don't need to be lazy (eg. tiled tiff load)

View File

@ -1,6 +1,7 @@
noinst_LTLIBRARIES = libfile.la
libfile_la_SOURCES = \
jpegload.c \
file.c
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

View File

@ -220,7 +220,58 @@ G_DEFINE_TYPE( VipsFileTiff, vips_file_tiff, VIPS_TYPE_FILE );
*
*/
/* To iterate over supported files, we build a temp list of subclasses of
/* Abstract base class for image files.
*/
G_DEFINE_ABSTRACT_TYPE( VipsFile, vips_file, VIPS_TYPE_OPERATION );
static void
vips_file_print_class( VipsObjectClass *object_class, VipsBuf *buf )
{
VipsFileClass *class = VIPS_FILE_CLASS( object_class );
const char **p;
VIPS_OBJECT_CLASS( vips_file_parent_class )->
print_class( object_class, buf );
vips_buf_appends( buf, ", " );
if( class->suffs ) {
vips_buf_appends( buf, "(" );
for( p = class->suffs; *p; p++ ) {
vips_buf_appendf( buf, "%s", *p );
if( p[1] )
vips_buf_appends( buf, ", " );
}
vips_buf_appends( buf, ") " );
}
vips_buf_appendf( buf, "priority=%d ", class->priority );
}
static void
vips_file_class_init( VipsFileClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
object_class->nickname = "file";
object_class->description = _( "load and save image files" );
object_class->print_class = vips_file_print_class;
VIPS_ARG_STRING( class, "filename", 12,
_( "Filename" ),
_( "File filename" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsFile, filename ),
NULL );
}
static void
vips_file_init( VipsFile *object )
{
}
/* To iterate over supported files we build a temp list of subclasses of
* VipsFile, sort by priority, iterate, and free.
*/
@ -275,94 +326,171 @@ vips_file_map( const char *base, VipsSListMap2Fn fn, void *a, void *b )
return( result );
}
/* Abstract base class for image files.
*/
G_DEFINE_ABSTRACT_TYPE( VipsFile, vips_file, VIPS_TYPE_OPERATION );
static void
vips_file_print_class( VipsObjectClass *object_class, VipsBuf *buf )
{
VipsFileClass *class = VIPS_FILE_CLASS( object_class );
const char **p;
VIPS_OBJECT_CLASS( vips_file_parent_class )->
print_class( object_class, buf );
vips_buf_appends( buf, ", " );
if( class->suffs ) {
vips_buf_appends( buf, "(" );
for( p = class->suffs; *p; p++ ) {
vips_buf_appendf( buf, "%s", *p );
if( p[1] )
vips_buf_appends( buf, ", " );
}
vips_buf_appends( buf, ") " );
}
vips_buf_appends( buf, "priority=%d ", class->priority );
if( class->is_a )
vips_buf_appends( buf, "is_a " );
}
static void
vips_file_class_init( VipsFileClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
object_class->nickname = "file";
object_class->description = _( "file file support" );
object_class->print_class = vips_file_print_class;
VIPS_ARG_STRING( class, "filename", 12,
_( "Filename" ),
_( "File filename" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsFile, filename ),
NULL );
}
static void
vips_file_init( VipsFile *object )
{
}
/* Abstract base class for image load.
*/
G_DEFINE_ABSTRACT_TYPE( VipsFileLoad, vips_files_load, VIPS_TYPE_FILE );
G_DEFINE_ABSTRACT_TYPE( VipsFileLoad, vips_file_load, VIPS_TYPE_FILE );
static void
vips_file_load_print_class( VipsObjectClass *object_class, VipsBuf *buf )
{
VipsFileLoadClass *class = VIPS_FILE_LOAD_CLASS( object_class );
const char **p;
VIPS_OBJECT_CLASS( vips_file_load_parent_class )->
print_class( object_class, buf );
vips_buf_appends( buf, ", " );
if( class->is_a )
vips_buf_appends( buf, "is_a " );
/*
if( class->header )
vips_buf_appends( buf, "header " );
if( class->load )
vips_buf_appends( buf, "load " );
*/
if( class->get_flags )
vips_buf_appends( buf, "get_flags " );
}
static size_t
disc_threshold( void )
{
static gboolean done = FALSE;
static size_t threshold;
if( !done ) {
const char *env;
done = TRUE;
/* 100mb default.
*/
threshold = 100 * 1024 * 1024;
if( (env = g_getenv( "IM_DISC_THRESHOLD" )) )
threshold = vips__parse_size( env );
if( vips__disc_threshold )
threshold = vips__parse_size( vips__disc_threshold );
VIPS_DEBUG_MSG( "disc_threshold: %zd bytes\n", threshold );
}
return( threshold );
}
/* Make the real underlying image: either a direct disc file, or a temp file
* somewhere.
*/
static int
vips_file_load_new_real( VipsFileLoad *load )
{
/* We open via disc if:
* - 'disc' is set
* - disc_threshold() has not been set to zero
* - the format does not support lazy read
* - the uncompressed image will be larger than disc_threshold()
*/
load->real = NULL;
if( lazy->disc &&
disc_threshold() &&
!(vips_format_get_flags( lazy->format, lazy->filename ) &
VIPS_FORMAT_PARTIAL) &&
VIPS_IMAGE_SIZEOF_IMAGE( lazy->image ) > disc_threshold() )
if( !(real = vips_image_new_disc_temp( "%s.v" )) )
return( NULL );
/* Otherwise, fall back to a "p".
*/
if( !real &&
!(real = vips_image_new()) )
return( NULL );
return( real );
}
/* Our start function ... do the lazy open, if necessary, and return a region
* on the new image.
*/
static void *
vips_file_load_start_cb( VipsImage *out, void *a, void *dummy )
{
VipsFileLoad *load = VIPS_FILE_LOAD( a );
VipsFileLoadClass *class = VIPS_FILE_LOAD_GET_CLASS( a );
if( !load->real ) {
if( vips_file_load_new_real( load ) ||
class->load( load ) ||
vips_image_pio_input( load->real ) ) {
VIPS_UNREF( load->real );
return( NULL );
}
}
return( vips_region_new( load->real ) );
}
/* Just pointer-copy.
*/
static int
vips_file_load_generate_cb( VipsRegion *or,
void *seq, void *a, void *b, gboolean *stop )
{
VipsRegion *ir = (VipsRegion *) seq;
VipsRect *r = &or->valid;
/* Ask for input we need.
*/
if( vips_region_prepare( ir, r ) )
return( -1 );
/* Attach output region to that.
*/
if( vips_region_region( or, ir, r, r->left, r->top ) )
return( -1 );
return( 0 );
}
static int
vips_file_load_build( VipsObject *object )
{
VipsFile *file = VIPS_FILE( object );
VipsFileLoad *load = VIPS_FILE_LOAD( object );
VipsFileLoadClass *class = VIPS_FILE_LOAD_GET_CLASS( object );
g_object_set( object, "out", vips_image_new(), NULL );
if( class->get_flags )
g_object_set( load,
"flags", class->get_flags( load ),
NULL );
if( VIPS_OBJECT_CLASS( vips_file_load_parent_class )->
build( object ) )
return( -1 );
/* Read header fields to init the return image. THINSTRIP since this is
* probably a disc file. We can't tell yet whether we will be opening
* to memory, sadly, so we can't suggest ANY.
*/
if( class->header &&
class->header( load ) )
return( -1 );
vips_demand_hint( load->out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
/* Then 'start' creates the real image and 'gen' paints 'out' with
* pixels from the real image on demand.
*/
if( vips_image_generate( load->out,
vips_file_load_start_cb,
vips_file_load_generate_cb,
vips_stop_one,
lazy, NULL ) )
return( -1 );
return( 0 );
}
@ -389,6 +517,13 @@ vips_file_load_class_init( VipsFileLoadClass *class )
VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsFileLoad, out ) );
VIPS_ARG_BOOL( class, "memory", 6,
_( "Memory" ),
_( "Open to memory" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsFileLoad, memory ),
FALSE );
}
static void
@ -402,32 +537,32 @@ static void *
vips_file_load_new_from_file_sub( VipsFileLoadClass *load_class,
const char *filename )
{
VipsFileClass *class = VIPS_FILE_CLASS( load_class );
if( load_class->is_a ) {
if( load_class->is_a( filename ) )
return( load_class );
}
else if( vips_filename_suffix_match( filename, load_class->suffs ) )
else if( vips_filename_suffix_match( filename, class->suffs ) )
return( load_class );
return( NULL );
}
/**
* vips_file_load_new_from_file:
* vips_file_find_load:
* @filename: file to find a file for
*
* Searches for a file you could use to load a file. Set some more options
* after this, then call _build() to actually load in the file.
* Searches for an operation you could use to load a file.
*
* See also: vips_file_read(), vips_file_for_name().
* See also: vips_file_read().
*
* Returns: a file on success, %NULL on error
* Returns: the nmae of an operation on success, %NULL on error
*/
VipsFileLoad *
vips_file_load_new_from_file( const char *filename )
const char *
vips_file_find_load( const char *filename )
{
VipsFileLoadClass *load_class;
VipsFileLoad *load;
if( !vips_existsf( "%s", filename ) ) {
vips_error( "VipsFileLoad",
@ -440,21 +575,11 @@ vips_file_load_new_from_file( const char *filename )
(VipsSListMap2Fn) vips_file_load_new_from_file_sub,
(void *) filename, NULL )) ) {
vips_error( "VipsFileLoad",
_( "file \"%s\" not a known file" ), name );
_( "file \"%s\" not a known file" ), filename );
return( NULL );
}
load = VIPS_FILE_LOAD(
g_object_new( G_TYPE_FROM_CLASS( load_class ), NULL ) );
/* May as well set flags here, should be quick.
*/
if( load_class->get_flags )
g_object_set( load,
"flags", load_class->get_flags( load ),
NULL );
return( load );
return( G_OBJECT_CLASS_NAME( load_class ) );
}
/* Abstract base class for image savers.
@ -465,22 +590,24 @@ G_DEFINE_ABSTRACT_TYPE( VipsFileSave, vips_file_save, VIPS_TYPE_FILE );
static void
vips_file_save_print_class( VipsObjectClass *object_class, VipsBuf *buf )
{
VipsFileSaveClass *class = VIPS_FILE_SAVE_CLASS( object_class );
const char **p;
VIPS_OBJECT_CLASS( vips_file_save_parent_class )->
print_class( object_class, buf );
vips_buf_appends( buf, ", " );
/*
VipsFileSaveClass *class = VIPS_FILE_SAVE_CLASS( object_class );
if( class->save )
vips_buf_appends( buf, "save " );
*/
}
static int
vips_file_save_build( VipsObject *object )
{
/*
VipsFile *file = VIPS_FILE( object );
VipsFileSave *save = VIPS_FILE_SAVE( object );
*/
if( VIPS_OBJECT_CLASS( vips_file_save_parent_class )->
build( object ) )
@ -507,7 +634,7 @@ vips_file_save_class_init( VipsFileSaveClass *class )
}
static void
vips_file_save_init( VipsFile *object )
vips_file_save_init( VipsFileSave *object )
{
}
@ -517,30 +644,28 @@ static void *
vips_file_save_new_from_filename_sub( VipsFileSaveClass *save_class,
const char *filename )
{
VipsFileClass *file = VIPS_FILE_CLASS( save_class );
VipsFileClass *class = VIPS_FILE_CLASS( save_class );
if( save_class->save &&
vips_filename_suffix_match( filename, file->suffs ) )
if( vips_filename_suffix_match( filename, class->suffs ) )
return( save_class );
return( NULL );
}
/**
* vips_file_save_new_from_filename:
* vips_file_find_save:
* @filename: name to find a file for
*
* Searches for a file you could use to save a file.
* Searches for an operation you could use to save a file.
*
* See also: vips_file_write(), vips_file_for_file().
* See also: vips_file_write().
*
* Returns: a file on success, %NULL on error
* Returns: the name of an operation on success, %NULL on error
*/
VipsFileSave *
vips_file_save_new_from_filename( const char *filename )
const char *
vips_file_find_save( const char *filename )
{
VipsFileSaveClass *save_class;
VipsFileSave *save;
if( !(save_class = (VipsFileSaveClass *) vips_file_map(
"VipsFileSave",
@ -553,33 +678,37 @@ vips_file_save_new_from_filename( const char *filename )
return( NULL );
}
save = VIPS_FILE_SAVE(
g_object_new( G_TYPE_FROM_CLASS( save_class ), NULL ) );
return( save );
return( G_OBJECT_CLASS_NAME( save_class ) );
}
/**
* vips_file_read:
* @filename: file to load
* @out: write the file to this image
* @out: output image
* @...: %NULL-terminated list of optional named arguments
*
* Searches for a file for this file, then loads the file into @out.
* Loads @filename into @out using the loader recommended by
* vips_file_find_load().
*
* See also: vips_file_write().
*
* Returns: 0 on success, -1 on error
*/
int
vips_file_read( const char *filename, VipsImage *out )
vips_file_read( const char *filename, VipsImage **out, ... )
{
VipsFileLoad *load;
const char *operation;
va_list ap;
int result;
if( !(load = vips_file_load_new_from_file( filename )) )
if( !(operation = vips_file_find_load( filename )) )
return( -1 );
g_object_unref( load );
return( 0 );
va_start( ap, out );
result = vips_call_split( operation, ap, filename, out );
va_end( ap );
return( result );
}
/**
@ -587,21 +716,27 @@ vips_file_read( const char *filename, VipsImage *out )
* @in: image to write
* @filename: file to write to
*
* Searches for a file for this name, then saves @im to it.
* Saves @in to @filename using the saver recommended by
* vips_file_find_save().
*
* See also: vips_file_read().
*
* Returns: 0 on success, -1 on error
*/
int
vips_file_write( VipsImage *in, const char *filename )
vips_file_write( VipsImage *in, const char *filename, ... )
{
VipsFileClass *file;
const char *operation;
va_list ap;
int result;
if( !(file = vips_file_for_name( filename )) ||
file->save( in, filename ) )
if( !(operation = vips_file_find_save( filename )) )
return( -1 );
return( 0 );
va_start( ap, filename );
result = vips_call_split( operation, ap, in, filename );
va_end( ap );
return( result );
}

544
libvips/file/jpegload.c Normal file
View File

@ -0,0 +1,544 @@
/* load jpeg from a file
*
* 28/11/03 JC
* - better no-overshoot on tile loop
* 12/11/04
* - better demand size choice for eval
* 30/6/05 JC
* - update im_error()/im_warn()
* - now loads and saves exif data
* 30/7/05
* - now loads ICC profiles
* - now saves ICC profiles from the VIPS header
* 24/8/05
* - jpeg load sets vips xres/yres from exif, if possible
* - jpeg save sets exif xres/yres from vips, if possible
* 29/8/05
* - cut from old vips_jpeg.c
* 13/10/06
* - add </libexif/ prefix if required
* 11/2/08
* - spot CMYK jpegs and set Type
* - spot Adobe CMYK JPEG and invert ink density
* 15/2/08
* - added "shrink" parameter
* 16/6/09
* - added "fail" option ... fail on any warnings
* 12/10/09
* - also set scale_num on shrink (thanks Guido)
* 4/2/10
* - gtkdoc
* 4/12/10
* - attach the jpeg thumbnail and multiscan fields (thanks Mike)
* 21/2/10
* - only accept the first APP1 block which starts "Exif..." as exif
* data, some jpegs seem to have several APP1s, argh
* 20/4/2011
* - added im_bufjpeg2vips()
* 12/10/2011
* - read XMP data
* 3/11/11
* - attach exif tags as coded values
* 24/11/11
* - redo as a class
*/
/*
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
*/
/*
#define DEBUG_VERBOSE
#define DEBUG
*/
#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 <setjmp.h>
#ifdef HAVE_EXIF
#ifdef UNTAGGED_EXIF
#include <exif-data.h>
#include <exif-loader.h>
#include <exif-ifd.h>
#include <exif-utils.h>
#else /*!UNTAGGED_EXIF*/
#include <libexif/exif-data.h>
#include <libexif/exif-loader.h>
#include <libexif/exif-ifd.h>
#include <libexif/exif-utils.h>
#endif /*UNTAGGED_EXIF*/
#endif /*HAVE_EXIF*/
#include <vips/vips.h>
#include <vips/buf.h>
#include <vips/internal.h>
/* jpeglib includes jconfig.h, which can define HAVE_STDLIB_H ... which we
* also define. Make sure it's turned off.
*/
#ifdef HAVE_STDLIB_H
#undef HAVE_STDLIB_H
#endif /*HAVE_STDLIB_H*/
#include <jpeglib.h>
#include <jerror.h>
typedef struct _VipsFileLoadJpeg {
VipsFileLoad parent_object;
/* Shrink by this much during load.
*/
int shrink;
/* Fail on first warning.
*/
gboolean fail;
} VipsFileLoadJpeg;
typedef VipsFileLoadJpegClass VipsFileLoadJpeg;
G_DEFINE_TYPE( VipsFileLoadJpeg, vips_file_load_jpeg, VIPS_TYPE_FILE_LOAD );
/* Define a new error handler for when we bomb out.
*/
typedef struct {
/* Public fields.
*/
struct jpeg_error_mgr pub;
/* Private stuff for us.
*/
jmp_buf jmp; /* longjmp() here to get back to VIPS */
FILE *fp; /* fclose() if non-NULL */
} ErrorManager;
/* New output message method - send to VIPS.
*/
METHODDEF(void)
new_output_message( j_common_ptr cinfo )
{
char buffer[JMSG_LENGTH_MAX];
(*cinfo->err->format_message)( cinfo, buffer );
im_error( "VipsFileLoadJpeg", _( "%s" ), buffer );
#ifdef DEBUG
printf( "VipsFileLoadJpeg: new_output_message: \"%s\"\n", buffer );
#endif /*DEBUG*/
}
/* New error_exit handler.
*/
METHODDEF(void)
new_error_exit( j_common_ptr cinfo )
{
ErrorManager *eman = (ErrorManager *) cinfo->err;
#ifdef DEBUG
printf( "VipsFileLoadJpeg: new_error_exit\n" );
#endif /*DEBUG*/
/* Close the fp if necessary.
*/
if( eman->fp ) {
(void) fclose( eman->fp );
eman->fp = NULL;
}
/* Send the error message to VIPS. This method is overridden above.
*/
(*cinfo->err->output_message)( cinfo );
/* Jump back.
*/
longjmp( eman->jmp, 1 );
}
#ifdef HAVE_EXIF
#ifdef DEBUG_VERBOSE
/* Print exif for debugging ... hacked from exif-0.6.9/actions.c
*/
static void
show_tags( ExifData *data )
{
int i;
unsigned int tag;
const char *name;
printf( "show EXIF tags:\n" );
for( i = 0; i < EXIF_IFD_COUNT; i++ )
printf( "%-7.7s", exif_ifd_get_name( i ) );
printf( "\n" );
for( tag = 0; tag < 0xffff; tag++ ) {
name = exif_tag_get_title( tag );
if( !name )
continue;
printf( " 0x%04x %-29.29s", tag, name );
for( i = 0; i < EXIF_IFD_COUNT; i++ )
if( exif_content_get_entry( data->ifd[i], tag ) )
printf( " * " );
else
printf( " - " );
printf( "\n" );
}
}
static void
show_entry( ExifEntry *entry, void *client )
{
char exif_text[256];
printf( "%s", exif_tag_get_title( entry->tag ) );
printf( "|" );
printf( "%s", exif_entry_get_value( entry, exif_text, 256 ) );
printf( "|" );
printf( "%s", exif_format_get_name( entry->format ) );
printf( "|" );
printf( "%d bytes", entry->size );
printf( "\n" );
}
static void
show_ifd( ExifContent *content, void *client )
{
exif_content_foreach_entry( content, show_entry, client );
printf( "-\n" );
}
void
show_values( ExifData *data )
{
ExifByteOrder order;
order = exif_data_get_byte_order( data );
printf( "EXIF tags in '%s' byte order\n",
exif_byte_order_get_name( order ) );
printf( "%-20.20s", "Tag" );
printf( "|" );
printf( "%-58.58s", "Value" );
printf( "\n" );
exif_data_foreach_content( data, show_ifd, NULL );
if( data->size )
printf( "contains thumbnail of %d bytes\n", data->size );
}
#endif /*DEBUG_VERBOSE*/
#endif /*HAVE_EXIF*/
#ifdef HAVE_EXIF
static int
vips_exif_get_int( ExifData *ed,
ExifEntry *entry, unsigned long component, int *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_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 );
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( ve->image,
vips_buf_all( &name ), vips_buf_all( &value ) );
}
static void
attach_exif_content( ExifContent *content, VipsExif *ve )
{
exif_content_foreach_entry( content,
(ExifContentForeachEntryFunc) attach_exif_entry, ve );
}
/* Just find the first occurence of the tag (is this correct?)
*/
static ExifEntry *
find_entry( ExifData *ed, ExifTag tag )
{
int i;
for( i = 0; i < EXIF_IFD_COUNT; i++ ) {
ExifEntry *entry;
if( (entry = exif_content_get_entry( ed->ifd[i], tag )) )
return( entry );
}
return( NULL );
}
static int
get_entry_rational( ExifData *ed, ExifTag tag, double *out )
{
ExifEntry *entry;
if( !(entry = find_entry( ed, tag )) ||
entry->format != EXIF_FORMAT_RATIONAL ||
entry->components != 1 )
return( -1 );
return( vips_exif_get_double( ed, entry, 0, out ) );
}
static int
get_entry_short( ExifData *ed, ExifTag tag, int *out )
{
ExifEntry *entry;
if( !(entry = find_entry( ed, tag )) ||
entry->format != EXIF_FORMAT_SHORT ||
entry->components != 1 )
return( -1 );
return( vips_exif_get_int( ed, entry, 0, out ) );
}
static void
set_vips_resolution( IMAGE *im, ExifData *ed )
{
double xres, yres;
int unit;
if( get_entry_rational( ed, EXIF_TAG_X_RESOLUTION, &xres ) ||
get_entry_rational( ed, EXIF_TAG_Y_RESOLUTION, &yres ) ||
get_entry_short( ed, EXIF_TAG_RESOLUTION_UNIT, &unit ) ) {
im_warn( "im_jpeg2vips",
"%s", _( "error reading resolution" ) );
return;
}
switch( unit ) {
case 2:
/* In inches.
*/
xres /= 25.4;
yres /= 25.4;
break;
case 3:
/* In cm.
*/
xres /= 10.0;
yres /= 10.0;
break;
default:
im_warn( "im_jpeg2vips", "%s", _( "bad resolution unit" ) );
return;
}
im->Xres = xres;
im->Yres = yres;
}
static int
attach_thumbnail( IMAGE *im, ExifData *ed )
{
if( ed->size > 0 ) {
char *thumb_copy;
thumb_copy = im_malloc( NULL, ed->size );
memcpy( thumb_copy, ed->data, ed->size );
if( im_meta_set_blob( im, "jpeg-thumbnail-data",
(im_callback_fn) im_free, thumb_copy, ed->size ) ) {
im_free( thumb_copy );
return( -1 );
}
}
return( 0 );
}
#endif /*HAVE_EXIF*/
static int
vips_file_load_jpeg_build( VipsObject *object )
{
VipsFileLoadJpeg *jpeg = (VipsFileLoadJpeg *) object;
if( jpeg->shrink != 1 &&
jpeg->shrink != 2 &&
jpeg->shrink != 4 &&
jpeg->shrink != 8 ) {
vips_error( "VipsFormatLoadJpeg",
_( "bad shrink factor %d" ), jpeg->shrink );
return( -1 );
}
if( VIPS_OBJECT_CLASS( vips_file_load_jpeg_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static void
vips_file_load_jpeg_class_init( VipsFileLoadJpegClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
object_class->nickname = "jpegload";
object_class->description = _( "load jpeg from file" );
object_class->build = vips_file_load_jpeg_build;
VIPS_ARG_INT( class, "shrink", 5,
_( "Shrink" ),
_( "Shrink factor on load" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsFileLoadJpeg, shrink ),
1, 16, 1 );
VIPS_ARG_BOOL( class, "fail", 6,
_( "Fail" ),
_( "Fail on first warning" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsFileLoadJpeg, fail ),
FALSE );
}
static void
vips_file_load_jpeg_init( VipsFileLoadJpeg *object )
{
jpeg->shrink = 1;
}

View File

@ -46,7 +46,6 @@
*
* VIPS has a simple system for representing image load and save operations in
* a generic way.
*
* You can ask for a loader for a certain file or select a saver based on a
* filename. Once you have found a format, you can use it to load a file of
* that type, save an image to a file of that type, query files for their type
@ -55,7 +54,7 @@
*
* If you define a new format, support for
* it automatically appears in all VIPS user-interfaces. It will also be
* transparently supported by vips_image_new_from_file() and friends.
* transparently supported by im_open().
*
* VIPS comes with VipsFormat for TIFF, JPEG, PNG, Analyze, PPM, OpenEXR, CSV,
* Matlab, Radiance, RAW, VIPS and one that wraps libMagick.
@ -74,13 +73,14 @@
*
* @VIPS_FORMAT_BIGENDIAN means that image pixels are most-significant byte
* first. Depending on the native byte order of the host machine, you may
* need to swap bytes. See copy_swap().
* need to swap bytes. See im_copy_swap().
*/
/**
* VipsFormat:
*
* #VipsFormat has these virtual methods:
* Actually, we never make %VipsFormat objects, we just use virtual methods on
* the class object. It is defined as:
*
* |[
* typedef struct _VipsFormatClass {
@ -114,13 +114,12 @@
* header() This function should load the image header,
* but not load any pixel data. If you don't define it, VIPS will use your
* load() method instead. Return 0 for success, -1 for error, setting
* vips_error().
* im_error().
* </para>
* </listitem>
* <listitem>
* <para>
* load() This function should load the image, or perhaps use
* vips_image_generate() to
* load() This function should load the image, or perhaps use im_generate() to
* attach something to load sections of the image on demand.
* Users can embed
* load options in the filename, see (for example) im_jpeg2vips().
@ -227,9 +226,10 @@ G_DEFINE_TYPE( VipsFormatTiff, vips_format_tiff, VIPS_TYPE_FORMAT );
static void *
format_add_class( VipsFormatClass *format, GSList **formats )
{
/* Append so we don't reverse the list of formats.
*/
*formats = g_slist_append( *formats, format );
if( !G_TYPE_IS_ABSTRACT( G_OBJECT_CLASS_TYPE( format ) ) )
/* Append so we don't reverse the list of formats.
*/
*formats = g_slist_append( *formats, format );
return( NULL );
}
@ -242,34 +242,33 @@ format_compare( VipsFormatClass *a, VipsFormatClass *b )
/**
* vips_format_map:
* @base: base class to search below (eg. "VipsFormatLoad")
* @fn: function to apply to each #VipsFormatClass
* @a: user data
* @b: user data
*
* Apply a function to every #VipsFormatClass that VIPS knows about. Formats
* Apply a function to every %VipsFormatClass that VIPS knows about. Formats
* are presented to the function in priority order.
*
* Like all VIPS map functions, if @fn returns %NULL, iteration continues. If
* it returns non-%NULL, iteration terminates and that value is returned. The
* map function returns %NULL if all calls return %NULL.
*
* See also: vips_slist_map().
* See also: im_slist_map().
*
* Returns: the result of iteration
*/
void *
vips_format_map( const char *base, VipsSListMap2Fn fn, void *a, void *b )
vips_format_map( VSListMap2Fn fn, void *a, void *b )
{
GSList *formats;
void *result;
formats = NULL;
(void) vips_class_map_all( g_type_from_name( base ),
(void) vips_class_map_all( g_type_from_name( "VipsFormat" ),
(VipsClassMapFn) format_add_class, (void *) &formats );
formats = g_slist_sort( formats, (GCompareFunc) format_compare );
result = vips_slist_map2( formats, fn, a, b );
result = im_slist_map2( formats, fn, a, b );
g_slist_free( formats );
return( result );
@ -300,10 +299,16 @@ vips_format_print_class( VipsObjectClass *object_class, VipsBuf *buf )
vips_buf_appends( buf, ") " );
}
vips_buf_appends( buf, "priority=%d ", class->priority );
if( class->is_a )
vips_buf_appends( buf, "is_a " );
if( class->header )
vips_buf_appends( buf, "header " );
if( class->load )
vips_buf_appends( buf, "load " );
if( class->save )
vips_buf_appends( buf, "save " );
if( class->get_flags )
vips_buf_appends( buf, "get_flags " );
}
static void
@ -312,15 +317,8 @@ vips_format_class_init( VipsFormatClass *class )
VipsObjectClass *object_class = (VipsObjectClass *) class;
object_class->nickname = "format";
object_class->description = _( "file format support" );
object_class->description = _( "VIPS file formats" );
object_class->print_class = vips_format_print_class;
VIPS_ARG_STRING( class, "filename", 12,
_( "Filename" ),
_( "Format filename" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsFormat, filename ),
NULL );
}
static void
@ -328,206 +326,232 @@ vips_format_init( VipsFormat *object )
{
}
/* Abstract base class for image load.
/**
* vips_format_get_flags:
* @format: format to test
* @filename: file to test
*
* Get a set of flags for this file.
*
* Returns: flags for this format and file
*/
VipsFormatFlags
vips_format_get_flags( VipsFormatClass *format, const char *filename )
{
return( format->get_flags ? format->get_flags( filename ) : 0 );
}
/* VIPS format class.
*/
G_DEFINE_ABSTRACT_TYPE( VipsFormatLoad, vips_formats_load, VIPS_TYPE_FORMAT );
static const char *vips_suffs[] = { ".v", NULL };
static void
vips_format_load_print_class( VipsObjectClass *object_class, VipsBuf *buf )
int
im_isvips( const char *filename )
{
VipsFormatLoadClass *class = VIPS_FORMAT_LOAD_CLASS( object_class );
const char **p;
unsigned char buf[4];
VIPS_OBJECT_CLASS( vips_format_load_parent_class )->
print_class( object_class, buf );
vips_buf_appends( buf, ", " );
if( im__get_bytes( filename, buf, 4 ) ) {
if( buf[0] == 0x08 && buf[1] == 0xf2 &&
buf[2] == 0xa6 && buf[3] == 0xb6 )
/* SPARC-order VIPS image.
*/
return( 1 );
else if( buf[3] == 0x08 && buf[2] == 0xf2 &&
buf[1] == 0xa6 && buf[0] == 0xb6 )
/* INTEL-order VIPS image.
*/
return( 1 );
}
if( class->header )
vips_buf_appends( buf, "header " );
if( class->load )
vips_buf_appends( buf, "load " );
if( class->get_flags )
vips_buf_appends( buf, "get_flags " );
return( 0 );
}
static int
vips_format_load_build( VipsObject *object )
file2vips( const char *filename, IMAGE *out )
{
VipsFormat *format = VIPS_FORMAT( object );
VipsFormatLoad *load = VIPS_FORMAT_LOAD( object );
IMAGE *im;
g_object_set( object, "out", vips_image_new(), NULL );
if( VIPS_OBJECT_CLASS( vips_format_load_parent_class )->
build( object ) )
if( !(im = im_open_local( out, filename, "r" )) ||
im_copy( im, out ) )
return( -1 );
return( 0 );
}
static int
vips2file( IMAGE *im, const char *filename )
{
IMAGE *out;
if( !(out = im_open_local( im, filename, "w" )) ||
im_copy( im, out ) )
return( -1 );
return( 0 );
}
static VipsFormatFlags
vips_flags( const char *filename )
{
VipsFormatFlags flags;
unsigned char buf[4];
flags = VIPS_FORMAT_PARTIAL;
if( im__get_bytes( filename, buf, 4 ) &&
buf[0] == 0x08 &&
buf[1] == 0xf2 &&
buf[2] == 0xa6 &&
buf[3] == 0xb6 )
flags |= VIPS_FORMAT_BIGENDIAN;
return( flags );
}
/* Vips format adds no new members.
*/
typedef VipsFormat VipsFormatVips;
typedef VipsFormatClass VipsFormatVipsClass;
static void
vips_format_load_class_init( VipsFormatLoadClass *class )
vips_format_vips_class_init( VipsFormatVipsClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsFormatClass *format_class = (VipsFormatClass *) class;
object_class->nickname = "formatload";
object_class->description = _( "format loaders" );
object_class->print_class = vips_format_load_print_class;
object_class->build = vips_format_load_build;
VIPS_ARG_ENUM( class, "flags", 6,
_( "Flags" ),
_( "Flags for this format" ),
VIPS_ARGUMENT_OPTIONAL_OUTPUT,
G_STRUCT_OFFSET( VipsFormatLoad, flags ),
VIPS_TYPE_FORMAT_FLAGS, VIPS_FORMAT_NONE );
VIPS_ARG_IMAGE( class, "out", 1,
_( "Output" ),
_( "Output image" ),
VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsFormatLoad, out ) );
object_class->nickname = "vips";
object_class->description = _( "VIPS" );
format_class->is_a = im_isvips;
format_class->header = file2vips;
format_class->load = file2vips;
format_class->save = vips2file;
format_class->get_flags = vips_flags;
format_class->suffs = vips_suffs;
}
static void
vips_format_load_init( VipsFormatLoad *object )
vips_format_vips_init( VipsFormatVips *object )
{
}
G_DEFINE_TYPE( VipsFormatVips, vips_format_vips, VIPS_TYPE_FORMAT );
/* Called on startup: register the base vips formats.
*/
void
im__format_init( void )
{
extern GType vips_format_csv_get_type();
extern GType vips_format_ppm_get_type();
extern GType vips_format_analyze_get_type();
extern GType vips_format_rad_get_type();
vips_format_vips_get_type();
#ifdef HAVE_JPEG
extern GType vips_format_jpeg_get_type();
vips_format_jpeg_get_type();
#endif /*HAVE_JPEG*/
#ifdef HAVE_PNG
extern GType vips_format_png_get_type();
vips_format_png_get_type();
#endif /*HAVE_PNG*/
vips_format_csv_get_type();
vips_format_ppm_get_type();
vips_format_analyze_get_type();
#ifdef HAVE_OPENEXR
extern GType vips_format_exr_get_type();
vips_format_exr_get_type();
#endif /*HAVE_OPENEXR*/
#ifdef HAVE_MATIO
extern GType vips_format_mat_get_type();
vips_format_mat_get_type();
#endif /*HAVE_MATIO*/
#ifdef HAVE_CFITSIO
extern GType vips_format_fits_get_type();
vips_format_fits_get_type();
#endif /*HAVE_CFITSIO*/
vips_format_rad_get_type();
#ifdef HAVE_MAGICK
extern GType vips_format_magick_get_type();
vips_format_magick_get_type();
#endif /*HAVE_MAGICK*/
#ifdef HAVE_TIFF
extern GType vips_format_tiff_get_type();
vips_format_tiff_get_type();
#endif /*HAVE_TIFF*/
}
/* Can this format open this file?
*/
static void *
vips_format_load_new_from_file_sub( VipsFormatLoadClass *load_class,
const char *filename )
format_for_file_sub( VipsFormatClass *format,
const char *name, const char *filename )
{
if( load_class->is_a ) {
if( load_class->is_a( filename ) )
return( load_class );
if( format->is_a ) {
if( format->is_a( filename ) )
return( format );
}
else if( vips_filename_suffix_match( filename, load_class->suffs ) )
return( load_class );
else if( im_filename_suffix_match( filename, format->suffs ) )
return( format );
return( NULL );
}
/**
* vips_format_load_new_from_file:
* vips_format_for_file:
* @filename: file to find a format for
*
* Searches for a format you could use to load a file. Set some more options
* after this, then call _build() to actually load in the file.
* Searches for a format you could use to load a file.
*
* See also: vips_format_read(), vips_format_for_name().
*
* Returns: a format on success, %NULL on error
*/
VipsFormatLoad *
vips_format_load_new_from_file( const char *filename )
VipsFormatClass *
vips_format_for_file( const char *filename )
{
VipsFormatLoadClass *load_class;
VipsFormatLoad *load;
char name[FILENAME_MAX];
char options[FILENAME_MAX];
VipsFormatClass *format;
if( !vips_existsf( "%s", filename ) ) {
vips_error( "VipsFormatLoad",
_( "file \"%s\" not found" ), filename );
/* Break any options off the name ... eg. "fred.tif:jpeg,tile"
* etc.
*/
im_filename_split( filename, name, options );
if( !im_existsf( "%s", name ) ) {
im_error( "VipsFormat", _( "file \"%s\" not found" ), name );
return( NULL );
}
if( !(load_class = (VipsFormatLoadClass *) vips_format_map(
"VipsFormatLoad",
(VipsSListMap2Fn) vips_format_load_new_from_file_sub,
(void *) filename, NULL )) ) {
vips_error( "VipsFormatLoad",
if( !(format = (VipsFormatClass *) vips_format_map(
(VSListMap2Fn) format_for_file_sub,
(void *) filename, (void *) name )) ) {
im_error( "VipsFormat",
_( "file \"%s\" not a known format" ), name );
return( NULL );
}
load = VIPS_FORMAT_LOAD(
g_object_new( G_TYPE_FROM_CLASS( load_class ), NULL ) );
/* May as well set flags here, should be quick.
*/
if( load_class->get_flags )
g_object_set( load,
"flags", load_class->get_flags( load ),
NULL );
return( load );
return( format );
}
/* Abstract base class for image savers.
*/
G_DEFINE_ABSTRACT_TYPE( VipsFormatSave, vips_format_save, VIPS_TYPE_FORMAT );
static void
vips_format_save_print_class( VipsObjectClass *object_class, VipsBuf *buf )
{
VipsFormatSaveClass *class = VIPS_FORMAT_SAVE_CLASS( object_class );
const char **p;
VIPS_OBJECT_CLASS( vips_format_save_parent_class )->
print_class( object_class, buf );
vips_buf_appends( buf, ", " );
if( class->save )
vips_buf_appends( buf, "save " );
}
static int
vips_format_save_build( VipsObject *object )
{
VipsFormat *format = VIPS_FORMAT( object );
VipsFormatSave *save = VIPS_FORMAT_SAVE( object );
if( VIPS_OBJECT_CLASS( vips_format_save_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static void
vips_format_save_class_init( VipsFormatSaveClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
object_class->nickname = "formatsave";
object_class->description = _( "format savers" );
object_class->print_class = vips_format_save_print_class;
object_class->build = vips_format_save_build;
VIPS_ARG_IMAGE( class, "in", 1,
_( "Input" ),
_( "Image to save" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsFormatSave, in ) );
}
static void
vips_format_save_init( VipsFormat *object )
{
}
/* Can we write this filename with this format?
/* Can we write this filename with this format? Ignore formats without a save
* method.
*/
static void *
vips_format_save_new_from_filename_sub( VipsFormatSaveClass *save_class,
const char *filename )
format_for_name_sub( VipsFormatClass *format, const char *name )
{
VipsFormatClass *format = VIPS_FORMAT_CLASS( save_class );
if( save_class->save &&
vips_filename_suffix_match( filename, format->suffs ) )
return( save_class );
if( format->save &&
im_filename_suffix_match( name, format->suffs ) )
return( format );
return( NULL );
}
/**
* vips_format_save_new_from_filename:
* vips_format_for_name:
* @filename: name to find a format for
*
* Searches for a format you could use to save a file.
@ -536,27 +560,22 @@ vips_format_save_new_from_filename_sub( VipsFormatSaveClass *save_class,
*
* Returns: a format on success, %NULL on error
*/
VipsFormatSave *
vips_format_save_new_from_filename( const char *filename )
VipsFormatClass *
vips_format_for_name( const char *filename )
{
VipsFormatSaveClass *save_class;
VipsFormatSave *save;
VipsFormatClass *format;
if( !(save_class = (VipsFormatSaveClass *) vips_format_map(
"VipsFormatSave",
(VipsSListMap2Fn) vips_format_save_new_from_filename_sub,
if( !(format = (VipsFormatClass *) vips_format_map(
(VSListMap2Fn) format_for_name_sub,
(void *) filename, NULL )) ) {
vips_error( "VipsFormatSave",
im_error( "VipsFormat",
_( "\"%s\" is not a supported image format." ),
filename );
return( NULL );
}
save = VIPS_FORMAT_SAVE(
g_object_new( G_TYPE_FROM_CLASS( save_class ), NULL ) );
return( save );
return( format );
}
/**
@ -571,13 +590,13 @@ vips_format_save_new_from_filename( const char *filename )
* Returns: 0 on success, -1 on error
*/
int
vips_format_read( const char *filename, VipsImage *out )
vips_format_read( const char *filename, IMAGE *out )
{
VipsFormatLoad *load;
VipsFormatClass *format;
if( !(load = vips_format_load_new_from_file( filename )) )
if( !(format = vips_format_for_file( filename )) ||
format->load( filename, out ) )
return( -1 );
g_object_unref( load );
return( 0 );
}
@ -604,4 +623,3 @@ vips_format_write( IMAGE *in, const char *filename )
return( 0 );
}

View File

@ -57,6 +57,7 @@ EXTRA_DIST = version.h.in internal.h enumtemplate
# well
vips_scan_headers = \
${top_srcdir}/libvips/include/vips/memory.h \
${top_srcdir}/libvips/include/vips/file.h \
${top_srcdir}/libvips/include/vips/arithmetic.h \
${top_srcdir}/libvips/include/vips/conversion.h \
${top_srcdir}/libvips/include/vips/util.h \

View File

@ -6,6 +6,9 @@
G_BEGIN_DECLS
/* enumerations from "../../../libvips/include/vips/file.h" */
GType vips_file_flags_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_FILE_FLAGS (vips_file_flags_get_type())
/* enumerations from "../../../libvips/include/vips/arithmetic.h" */
GType vips_operation_math_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_OPERATION_MATH (vips_operation_math_get_type())

View File

@ -28,8 +28,8 @@
*/
#ifndef IM_FILE_H
#define IM_FILE_H
#ifndef VIPS_FILE_H
#define VIPS_FILE_H
#ifdef __cplusplus
extern "C" {
@ -64,13 +64,6 @@ typedef struct _VipsFileClass {
VipsOperationClass parent_class;
/*< public >*/
/* Is a file in this file.
*/
gboolean (*is_a)( const char * );
/* Null-terminated list of allowed suffixes, eg. ".tif", ".tiff".
*/
const char **suffs;
/* Loop over files in this order, default 0. We need this because
* some files can be read by several loaders (eg. tiff can be read
@ -79,6 +72,11 @@ typedef struct _VipsFileClass {
*/
int priority;
/* Null-terminated list of recommended suffixes, eg. ".tif", ".tiff".
* This is used by both load and save, so it's in the base class.
*/
const char **suffs;
} VipsFileClass;
GType vips_file_get_type( void );
@ -86,7 +84,7 @@ GType vips_file_get_type( void );
/* Map over and find files. This uses type introspection to loop over
* subclasses of VipsFile.
*/
void *vips_file_map( VipsSListMap2Fn fn, void *a, void *b );
void *vips_file_map( const char *base, VipsSListMap2Fn fn, void *a, void *b );
#define VIPS_TYPE_FILE_LOAD (vips_file_load_get_type())
#define VIPS_FILE_LOAD( obj ) \
@ -115,14 +113,22 @@ typedef struct _VipsFileLoad {
VipsFile parent_object;
/*< public >*/
/* Open to memory (default is to open via disc).
*/
gboolean memory;
/* Flags read from the file.
*/
VipsFileFlags flags;
/* The image we've loaded.
/* The image we generate.
*/
VipsImage *out;
/* The behind-the-scenes real image we decompress to.
*/
VipsImage *real;
} VipsFileLoad;
typedef struct _VipsFileLoadClass {
@ -130,17 +136,27 @@ typedef struct _VipsFileLoadClass {
/*< public >*/
/* Is a file in this format.
*/
gboolean (*is_a)( const char * );
/* Get the flags for this file in this file.
*/
VipsFileFlags (*get_flags)( VipsFileLoad * );
/* Read the header into @out.
*/
int (*header)( VipsFileLoad * );
/* Read the whole image into @out.
*/
int (*load)( VipsFileLoad * );
} VipsFileLoadClass;
GType vips_file_load_get_type( void );
VipsFileLoad *vips_file_load_new_from_file( const char *filename );
VipsFileLoad *vips_file_for_file( const char *filename );
const char *vips_file_find_load( const char *filename );
#define VIPS_TYPE_FILE_SAVE (vips_file_save_get_type())
#define VIPS_FILE_SAVE( obj ) \
@ -176,21 +192,15 @@ typedef struct _VipsFileSaveClass {
GType vips_file_save_get_type( void );
VipsFileSave *vips_file_save_new_from_filename( const char *filename )
const char *vips_file_find_save( const char *filename );
/* Read/write an image convenience functions.
*/
int vips_file_read( const char *filename, VipsImage *out );
int vips_file_write( VipsImage *in, const char *filename );
int vips_file_read( const char *filename, VipsImage **out, ... );
int vips_file_write( VipsImage *in, const char *filename, ... );
#ifdef __cplusplus
}
#endif /*__cplusplus*/
#endif /*IM_FILE_H*/
#endif /*VIPS_FILE_H*/

View File

@ -50,14 +50,21 @@ extern "C" {
(G_TYPE_INSTANCE_GET_CLASS( (obj), \
VIPS_TYPE_FORMAT, VipsFormatClass ))
/* Image file properties.
*/
typedef enum {
VIPS_FORMAT_NONE = 0, /* No flags set */
VIPS_FORMAT_PARTIAL = 1, /* Lazy read OK (eg. tiled tiff) */
VIPS_FORMAT_BIGENDIAN = 2 /* Most-significant byte first */
} VipsFormatFlags;
/* Don't instantiate these things, just use the class stuff.
*/
typedef struct _VipsFormat {
VipsObject parent_object;
/*< public >*/
/* Filename for load or save.
*/
char *filename;
} VipsFormat;
typedef struct _VipsFormatClass {
@ -68,9 +75,21 @@ typedef struct _VipsFormatClass {
*/
gboolean (*is_a)( const char * );
/* Null-terminated list of allowed suffixes, eg. ".tif", ".tiff".
/* Read just the header into the VipsImage.
*/
const char **suffs;
int (*header)( const char *, VipsImage * );
/* Load the whole image.
*/
int (*load)( const char *, VipsImage * );
/* Write the VipsImage to the file in this format.
*/
int (*save)( VipsImage *, const char * );
/* Get the flags for this file in this format.
*/
VipsFormatFlags (*get_flags)( const char * );
/* Loop over formats in this order, default 0. We need this because
* some formats can be read by several loaders (eg. tiff can be read
@ -79,6 +98,9 @@ typedef struct _VipsFormatClass {
*/
int priority;
/* Null-terminated list of allowed suffixes, eg. ".tif", ".tiff".
*/
const char **suffs;
} VipsFormatClass;
GType vips_format_get_type( void );
@ -87,108 +109,17 @@ GType vips_format_get_type( void );
* subclasses of VipsFormat.
*/
void *vips_format_map( VipsSListMap2Fn fn, void *a, void *b );
VipsFormatClass *vips_format_for_file( const char *filename );
VipsFormatClass *vips_format_for_name( const char *filename );
#define VIPS_TYPE_FORMAT_LOAD (vips_format_load_get_type())
#define VIPS_FORMAT_LOAD( obj ) \
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \
VIPS_TYPE_FORMAT_LOAD, VipsFormatLoad ))
#define VIPS_FORMAT_LOAD_CLASS( klass ) \
(G_TYPE_CHECK_CLASS_CAST( (klass), \
VIPS_TYPE_FORMAT_LOAD, VipsFormatLoadClass))
#define VIPS_IS_FORMAT_LOAD( obj ) \
(G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_FORMAT_LOAD ))
#define VIPS_IS_FORMAT_LOAD_CLASS( klass ) \
(G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_FORMAT_LOAD ))
#define VIPS_FORMAT_LOAD_GET_CLASS( obj ) \
(G_TYPE_INSTANCE_GET_CLASS( (obj), \
VIPS_TYPE_FORMAT_LOAD, VipsFormatLoadClass ))
/* Image file properties.
*/
typedef enum {
VIPS_FORMAT_NONE = 0, /* No flags set */
VIPS_FORMAT_PARTIAL = 1, /* Lazy read OK (eg. tiled tiff) */
VIPS_FORMAT_BIGENDIAN = 2 /* Most-significant byte first */
} VipsFormatFlags;
typedef struct _VipsFormatLoad {
VipsFormat parent_object;
/*< public >*/
/* Flags read from the file.
*/
VipsFormatFlags flags;
/* The image we've loaded.
*/
VipsImage *out;
} VipsFormatLoad;
typedef struct _VipsFormatLoadClass {
VipsFormatClass parent_class;
/*< public >*/
/* Get the flags for this file in this format.
*/
VipsFormatFlags (*get_flags)( VipsFormatLoad * );
} VipsFormatLoadClass;
GType vips_format_load_get_type( void );
VipsFormatLoad *vips_format_load_new_from_file( const char *filename );
VipsFormatLoad *vips_format_for_file( const char *filename );
#define VIPS_TYPE_FORMAT_SAVE (vips_format_save_get_type())
#define VIPS_FORMAT_SAVE( obj ) \
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \
VIPS_TYPE_FORMAT_SAVE, VipsFormatSave ))
#define VIPS_FORMAT_SAVE_CLASS( klass ) \
(G_TYPE_CHECK_CLASS_CAST( (klass), \
VIPS_TYPE_FORMAT_SAVE, VipsFormatSaveClass))
#define VIPS_IS_FORMAT_SAVE( obj ) \
(G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_FORMAT_SAVE ))
#define VIPS_IS_FORMAT_SAVE_CLASS( klass ) \
(G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_FORMAT_SAVE ))
#define VIPS_FORMAT_SAVE_GET_CLASS( obj ) \
(G_TYPE_INSTANCE_GET_CLASS( (obj), \
VIPS_TYPE_FORMAT_SAVE, VipsFormatSaveClass ))
typedef struct _VipsFormatSave {
VipsFormat parent_object;
/*< public >*/
/* The image we are to save.
*/
VipsImage *in;
} VipsFormatSave;
typedef struct _VipsFormatSaveClass {
VipsFormatClass parent_class;
/*< public >*/
} VipsFormatSaveClass;
GType vips_format_save_get_type( void );
VipsFormatSave *vips_format_save_new_from_filename( const char *filename )
VipsFormatFlags vips_format_get_flags( VipsFormatClass *format,
const char *filename );
/* Read/write an image convenience functions.
*/
int vips_format_read( const char *filename, VipsImage *out );
int vips_format_write( VipsImage *in, const char *filename );
/* Low-level read/write operations.
*/
int im_jpeg2vips( const char *filename, VipsImage *out );

View File

@ -108,7 +108,6 @@ extern "C" {
#include <vips/image.h>
#include <vips/memory.h>
#include <vips/error.h>
#include <vips/file.h>
#include <vips/format.h>
#include <vips/region.h>
#include <vips/generate.h>
@ -117,6 +116,7 @@ extern "C" {
#include <vips/threadpool.h>
#include <vips/header.h>
#include <vips/operation.h>
#include <vips/file.h>
#include <vips/enumtypes.h>

View File

@ -41,6 +41,7 @@ INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
# well
vips_scan_headers = \
${top_srcdir}/libvips/include/vips/memory.h \
${top_srcdir}/libvips/include/vips/file.h \
${top_srcdir}/libvips/include/vips/conversion.h \
${top_srcdir}/libvips/include/vips/arithmetic.h \
${top_srcdir}/libvips/include/vips/util.h \

View File

@ -4,6 +4,25 @@
/* auto-generated enums for vips introspection */
#include <vips/vips.h>
/* enumerations from "../../libvips/include/vips/file.h" */
GType
vips_file_flags_get_type( void )
{
static GType etype = 0;
if( etype == 0 ) {
static const GEnumValue values[] = {
{VIPS_FILE_NONE, "VIPS_FILE_NONE", "none"},
{VIPS_FILE_PARTIAL, "VIPS_FILE_PARTIAL", "partial"},
{VIPS_FILE_BIGENDIAN, "VIPS_FILE_BIGENDIAN", "bigendian"},
{0, NULL, NULL}
};
etype = g_enum_register_static( "VipsFileFlags", values );
}
return( etype );
}
/* enumerations from "../../libvips/include/vips/conversion.h" */
GType
vips_extend_get_type( void )