This commit is contained in:
John Cupitt 2008-05-22 17:55:45 +00:00
parent 4e159c8f54
commit 755f5bff9e
5 changed files with 314 additions and 101 deletions

5
TODO
View File

@ -1,3 +1,8 @@
- read_vips() in im_open.c:179 needs moving to format and breaking into is_a,
header, load and save, as tiff etc.
make im_file2vips, im_vips2file?
- pluggable formats
for each format, store:

View File

@ -300,6 +300,12 @@ im_function *im_find_function( const char *name );
im_package *im_find_package( const char *name );
im_package *im_package_of_function( const char *name );
/* Map over and find formats.
*/
void *im_map_formats( VSListMap2Fn fn, void *a, void *b );
im_format *im_format_for_file( const char *filename );
im_format *im_format_for_name( const char *filename );
/* Allocate space for, and free im_object argument lists.
*/
int im_free_vargv( im_function *fn, im_object *vargv );

View File

@ -418,5 +418,124 @@ im_package im__format = {
list
};
/* Suffix sets.
*/
static const char *tiff_suffs[] = { ".tif", ".tiff", NULL };
static const char *jpeg_suffs[] = { ".jpg", ".jpeg", ".jpe", NULL };
static const char *png_suffs[] = { ".png", NULL };
static const char *csv_suffs[] = { ".csv", NULL };
static const char *ppm_suffs[] = { ".ppm", ".pgm", ".pbm", NULL };
static const char *exr_suffs[] = { ".exr", NULL };
static const char *analyze_suffs[] = { ".img", ".hdr", NULL };
static const char *magick_suffs[] = { NULL };
/* VIPS image formats.
*/
static im_format jpeg_desc = {
"jpeg", /* internal name */
N_( "JPEG" ), /* i18n'd visible name */
0, /* Priority */
jpeg_suffs, /* Allowed suffixes */
im_isjpeg, /* is_a */
im_jpeg2vips_header, /* Load header only */
im_jpeg2vips, /* Load */
im_vips2jpeg /* Save */
};
static im_format tiff_desc = {
"tiff", /* internal name */
N_( "TIFF" ), /* i18n'd visible name */
0, /* Priority */
tiff_suffs, /* Allowed suffixes */
im_istiff, /* is_a */
im_tiff2vips_header, /* Load header only */
im_tiff2vips, /* Load */
im_vips2tiff /* Save */
};
static im_format png_desc = {
"png", /* internal name */
N_( "PNG" ), /* i18n'd visible name */
0, /* Priority */
png_suffs, /* Allowed suffixes */
im_ispng, /* is_a */
im_png2vips_header, /* Load header only */
im_png2vips, /* Load */
im_vips2png /* Save */
};
static im_format csv_desc = {
"csv", /* internal name */
N_( "CSV" ), /* i18n'd visible name */
0, /* Priority */
csv_suffs, /* Allowed suffixes */
NULL, /* is_a */
im_csv2vips_header, /* Load header only */
im_csv2vips, /* Load */
im_vips2csv /* Save */
};
static im_format ppm_desc = {
"ppm", /* internal name */
N_( "PPM/PBM/PNM" ), /* i18n'd visible name */
0, /* Priority */
ppm_suffs, /* Allowed suffixes */
im_isppm, /* is_a */
im_ppm2vips_header, /* Load header only */
im_ppm2vips, /* Load */
im_vips2ppm /* Save */
};
static im_format analyze_desc = {
"analyze", /* internal name */
N_( "Analyze 6.0" ), /* i18n'd visible name */
0, /* Priority */
analyze_suffs, /* Allowed suffixes */
im_isanalyze, /* is_a */
im_analyze2vips_header, /* Load header only */
im_analyze2vips, /* Load */
NULL /* Save */
};
static im_format exr_desc = {
"exr", /* internal name */
N_( "OpenEXR" ), /* i18n'd visible name */
0, /* Priority */
exr_suffs, /* Allowed suffixes */
im_isexr, /* is_a */
im_exr2vips_header, /* Load header only */
im_exr2vips, /* Load */
NULL /* Save */
};
static im_format magick_desc = {
"magick", /* internal name */
N_( "ImageMagick-supported format" ), /* i18n'd visible name */
-1000, /* Priority */
magick_suffs, /* Allowed suffixes */
im_ismagick, /* is_a */
im_magick2vips_header, /* Load header only */
im_magick2vips, /* Load */
NULL /* Save */
};
/* Package up all these formats.
*/
static im_format *format_list[] = {
&csv_desc,
&jpeg_desc,
&magick_desc,
&png_desc,
&exr_desc,
&ppm_desc,
&analyze_desc,
&tiff_desc
};
/* Package of format.
*/
im_format_package im__format_format = {
"format",
IM_NUMBER( format_list ),
format_list
};

View File

@ -225,6 +225,30 @@ read_vips( const char *filename )
return( im2 );
}
/*
else if( im_isvips( name ) ) {
if( mode[1] == 'w' ) {
if( !(im = im_init( filename )) )
return( NULL );
if( im_openinrw( im ) ) {
im_close( im );
return( NULL );
}
if( im->Bbits != IM_BBITS_BYTE &&
im_isMSBfirst( im ) !=
im_amiMSBfirst() ) {
im_close( im );
im_error( "im_open", _( "open for read-"
"write for native format "
"images only" ) );
return( NULL );
}
}
else
im = read_vips( filename );
}
*/
/* Delayed save: if we write to TIFF or to JPEG format, actually do the write
* to a "p" and on preclose do im_vips2tiff() or whatever. Track save
* parameters here.
@ -416,6 +440,7 @@ IMAGE *
im_open( const char *filename, const char *mode )
{
IMAGE *im;
im_format *format;
/* Pass in a nonsense name for argv0 ... this init world is only here
* for old programs which are missing an im_init_world() call. We must
@ -431,107 +456,11 @@ im_open( const char *filename, const char *mode )
switch( mode[0] ) {
case 'r':
{
char name[FILENAME_MAX];
char options[FILENAME_MAX];
/* Break any options off the name ... eg. "fred.tif:jpeg,tile"
* etc.
*/
im_filename_split( filename, name, options );
/* Check for other formats.
FIXME ... should have a table to avoid all this
repetition
*/
if( !im_existsf( "%s", name ) ) {
im_error( "im_open",
_( "\"%s\" is not readable" ), name );
if( !(format = im_format_for_file( filename )) )
return( NULL );
}
else if( im_istiff( name ) ) {
/* If TIFF open fails, try going through libmagick.
*/
if( !(im = open_sub(
im_tiff2vips_header, im_tiff2vips,
filename )) &&
!(im = open_sub(
im_magick2vips_header, im_magick2vips,
filename )) )
return( NULL );
}
else if( im_isjpeg( name ) ) {
if( !(im = open_sub(
im_jpeg2vips_header, im_jpeg2vips, filename )) )
return( NULL );
}
else if( im_isexr( name ) ) {
if( !(im = open_sub(
im_exr2vips_header, im_exr2vips, filename )) )
return( NULL );
}
else if( im_isppm( name ) ) {
if( !(im = open_sub(
im_ppm2vips_header, im_ppm2vips, filename )) )
return( NULL );
}
else if( im_ispng( name ) ) {
if( !(im = open_sub(
im_png2vips_header, im_png2vips, filename )) )
return( NULL );
}
else if( im_filename_suffix_match( name, im_suffix_csv ) ) {
if( !(im = open_sub(
im_csv2vips_header, im_csv2vips, filename )) )
return( NULL );
}
else if( im_isvips( name ) ) {
if( mode[1] == 'w' ) {
/* Has to be native format for >8 bits.
*/
if( !(im = im_init( filename )) )
return( NULL );
if( im_openinrw( im ) ) {
im_close( im );
return( NULL );
}
if( im->Bbits != IM_BBITS_BYTE &&
im_isMSBfirst( im ) !=
im_amiMSBfirst() ) {
im_close( im );
im_error( "im_open", _( "open for read-"
"write for native format "
"images only" ) );
return( NULL );
}
}
else
im = read_vips( filename );
}
else if( im_isanalyze( name ) ) {
if( !(im = open_sub(
im_analyze2vips_header, im_analyze2vips,
filename )) )
return( NULL );
}
else if( im_ismagick( name ) ) {
/* Have this last as it can be very slow to detect
* failure.
*/
if( !(im = open_sub(
im_magick2vips_header, im_magick2vips,
filename )) )
return( NULL );
}
else {
im_error( "im_open", _( "\"%s\" is not "
"a supported format" ), filename );
if( !(im = open_sub(
format->header, format->load, filename )) )
return( NULL );
}
}
break;
case 'w':

View File

@ -72,6 +72,8 @@ extern im_package im__other;
extern im_package im__relational;
extern im_package im__video;
extern im_format_package im__format_format;
/* im_guess_prefix() args.
*/
static im_arg_desc guess_prefix_args[] = {
@ -419,12 +421,56 @@ static im_package *built_in[] = {
&im__video
};
/* List of loaded formats.
*/
static GSList *format_list = NULL;
static gint
format_compare( im_format *a, im_format *b )
{
return( a->priority - b->priority );
}
/* Sort the format list after a change.
*/
static void
format_sort( void )
{
format_list = g_slist_sort( format_list,
(GCompareFunc) format_compare );
}
/* Remove a package of formats.
*/
static void
format_remove( im_format_package *format )
{
int i;
for( i = 0; i < format->nfuncs; i++ )
format_list = g_slist_remove( format_list, format->table[i] );
format_sort();
}
/* Add a package of formats.
*/
static void
format_add( im_format_package *format )
{
int i;
for( i = 0; i < format->nfuncs; i++ )
format_list = g_slist_prepend( format_list, format->table[i] );
format_sort();
}
/* How we represent a loaded plugin.
*/
typedef struct _Plugin {
GModule *module; /* As loaded by g_module_open() */
char *name; /* Name we loaded */
im_package *pack; /* Package table */
im_format_package *format; /* Package format table */
} Plugin;
/* List of loaded plugins.
@ -438,6 +484,8 @@ plugin_free( Plugin *plug )
{
char *name = plug->name ? plug->name : "<unknown>";
if( plug->format )
format_remove( plug->format );
if( plug->module ) {
if( !g_module_close( plug->module ) ) {
im_error( "plugin",
@ -477,6 +525,7 @@ im_load_plugin( const char *name )
plug->module = NULL;
plug->name = NULL;
plug->pack = NULL;
plug->format = NULL;
plugin_list = g_slist_prepend( plugin_list, plug );
/* Attach name.
@ -511,22 +560,44 @@ im_load_plugin( const char *name )
return( NULL );
}
/* The format table is optional.
*/
if( !g_module_symbol( plug->module,
"format_table", (gpointer *) ((void *) &plug->format) ) )
plug->format = NULL;
/* Sanity check.
*/
if( !plug->pack->name || plug->pack->nfuncs < 0 ||
plug->pack->nfuncs > 10000 ) {
im_error( "plugin",
_( "corrupted package table in plugin \"%s\"" ),
name );
_( "corrupted package table in plugin \"%s\"" ), name );
plugin_free( plug );
return( NULL );
}
if( plug->format ) {
if( !plug->format->name || plug->format->nfuncs < 0 ||
plug->format->nfuncs > 10000 ) {
im_error( "plugin",
_( "corrupted format table in plugin \"%s\"" ),
name );
plugin_free( plug );
return( NULL );
}
}
#ifdef DEBUG
printf( "added package \"%s\" ...\n", plug->pack->name );
#endif /*DEBUG*/
/* Add any formats to our format list and sort again.
*/
if( plug->format )
format_add( plug->format );
return( plug->pack );
}
@ -700,6 +771,89 @@ im_package_of_function( const char *name )
return( pack );
}
/* Map a function over all formats.
*/
void *
im_map_formats( VSListMap2Fn fn, void *a, void *b )
{
return( im_slist_map2( format_list, fn, a, b ) );
}
/* Can this format open this file?
*/
static void *
format_for_file_sub( im_format *format,
const char *filename, const char *name )
{
if( format->is_a ) {
if( format->is_a( name ) )
return( format );
}
else if( im_filename_suffix_match( name, format->suffs ) )
return( format );
return( NULL );
}
im_format *
im_format_for_file( const char *filename )
{
char name[FILENAME_MAX];
char options[FILENAME_MAX];
im_format *format;
/* 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( "im_format_for_file",
_( "\"%s\" is not readable" ), name );
return( NULL );
}
format = (im_format *) im_map_formats(
(VSListMap2Fn) format_for_file_sub,
(void *) filename, (void *) name );
if( !format ) {
im_error( "im_format_for_file",
_( "\"%s\" is not in a supported format" ), name );
return( NULL );
}
return( format );
}
/* Can we write this filename with this format?
*/
static void *
format_for_name_sub( im_format *format,
const char *filename, const char *name )
{
if( im_filename_suffix_match( name, format->suffs ) )
return( format );
return( NULL );
}
im_format *
im_format_for_name( const char *filename )
{
char name[FILENAME_MAX];
char options[FILENAME_MAX];
/* Break any options off the name ... eg. "fred.tif:jpeg,tile"
* etc.
*/
im_filename_split( filename, name, options );
return( (im_format *) im_map_formats(
(VSListMap2Fn) format_for_name_sub,
(void *) filename, (void *) name ) );
}
/* Free any store we allocated for the argument list.
*/
int