sync
This commit is contained in:
parent
584e11e88d
commit
2c641c6644
7
TODO
7
TODO
@ -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)
|
||||
|
||||
|
||||
|
||||
|
@ -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@
|
||||
|
@ -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
544
libvips/file/jpegload.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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())
|
||||
|
@ -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*/
|
||||
|
@ -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 );
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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 )
|
||||
|
Loading…
Reference in New Issue
Block a user