new-style vips load/save works
also image.c uses the new system instead of VipsFormat
This commit is contained in:
parent
19b3c7eeb2
commit
43587801f7
5
TODO
5
TODO
@ -1,9 +1,6 @@
|
||||
- need vips load/save class, so we can detect vips files for native read /
|
||||
write
|
||||
- we have to open the image to see flags argh
|
||||
|
||||
jpeg load needs to set suffs
|
||||
|
||||
get image.c using the new system for vips_image_new_from_file()
|
||||
|
||||
CLI stuff image->new_from_string() needs to use new system too, chcek this
|
||||
|
||||
|
@ -234,7 +234,7 @@ vips_file_print_class( VipsObjectClass *object_class, VipsBuf *buf )
|
||||
|
||||
VIPS_OBJECT_CLASS( vips_file_parent_class )->
|
||||
print_class( object_class, buf );
|
||||
vips_buf_appends( buf, ", " );
|
||||
vips_buf_appends( buf, " " );
|
||||
|
||||
if( class->suffs ) {
|
||||
vips_buf_appends( buf, "(" );
|
||||
@ -243,7 +243,7 @@ vips_file_print_class( VipsObjectClass *object_class, VipsBuf *buf )
|
||||
if( p[1] )
|
||||
vips_buf_appends( buf, ", " );
|
||||
}
|
||||
vips_buf_appends( buf, ") " );
|
||||
vips_buf_appends( buf, "), " );
|
||||
}
|
||||
|
||||
vips_buf_appendf( buf, "priority=%d", class->priority );
|
||||
|
@ -901,11 +901,14 @@ vips_file_load_jpeg_load( VipsFileLoad *load )
|
||||
return( result );
|
||||
}
|
||||
|
||||
static const char *jpeg_suffs[] = { ".jpg", ".jpeg", ".jpe", NULL };
|
||||
|
||||
static void
|
||||
vips_file_load_jpeg_class_init( VipsFileLoadJpegClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsFileClass *file_class = (VipsFileClass *) class;
|
||||
VipsFileLoadClass *load_class = (VipsFileLoadClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
@ -915,6 +918,8 @@ vips_file_load_jpeg_class_init( VipsFileLoadJpegClass *class )
|
||||
object_class->description = _( "load jpeg from file" );
|
||||
object_class->build = vips_file_load_jpeg_build;
|
||||
|
||||
file_class->suffs = jpeg_suffs;
|
||||
|
||||
load_class->is_a = vips_file_load_jpeg_is_a;
|
||||
load_class->header = vips_file_load_jpeg_header;
|
||||
load_class->load = vips_file_load_jpeg_load;
|
||||
@ -932,7 +937,6 @@ vips_file_load_jpeg_class_init( VipsFileLoadJpegClass *class )
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsFileLoadJpeg, fail ),
|
||||
FALSE );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -852,7 +852,6 @@ vips_file_save_jpeg_class_init( VipsFileSaveJpegClass *class )
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsFileSaveJpeg, profile ),
|
||||
NULL );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -46,7 +46,7 @@
|
||||
typedef VipsFileLoad VipsFileLoadVips;
|
||||
typedef VipsFileLoadClass VipsFileLoadVipsClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsFileLoadVips, vips_file_load_vips, VIPS_TYPE_FILE_SAVE );
|
||||
G_DEFINE_TYPE( VipsFileLoadVips, vips_file_load_vips, VIPS_TYPE_FILE_LOAD );
|
||||
|
||||
static int
|
||||
vips_file_load_vips_build( VipsObject *object )
|
||||
@ -79,24 +79,53 @@ vips_file_load_vips_is_a( const char *filename )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_file_load_vips_get_flags( VipsFileLoad *load )
|
||||
{
|
||||
VipsFile *file = VIPS_FILE( load );
|
||||
unsigned char buf[4];
|
||||
|
||||
load->flags = VIPS_FILE_PARTIAL;
|
||||
|
||||
if( vips__get_bytes( file->filename, buf, 4 ) &&
|
||||
buf[0] == 0x08 &&
|
||||
buf[1] == 0xf2 &&
|
||||
buf[2] == 0xa6 &&
|
||||
buf[3] == 0xb6 )
|
||||
load->flags |= VIPS_FORMAT_BIGENDIAN;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_file_load_vips_header( VipsFileLoad *load )
|
||||
{
|
||||
VipsFile *file = VIPS_FILE( load );
|
||||
|
||||
if( !(load->out = vips_image_new_from_file( file->filename )) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_file_load_vips_load( VipsFileLoad *load )
|
||||
{
|
||||
VipsFile *file = VIPS_FILE( load );
|
||||
|
||||
if( !(load->real = vips_image_new_from_file( file->filename )) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static const char *vips_suffs[] = { ".v", NULL };
|
||||
|
||||
static void
|
||||
vips_file_load_jpeg_class_init( VipsFileLoadJpegClass *class )
|
||||
vips_file_load_vips_class_init( VipsFileLoadVipsClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsFileClass *file_class = (VipsLoadClass *) class;
|
||||
VipsFileClass *file_class = (VipsFileClass *) class;
|
||||
VipsFileLoadClass *load_class = (VipsFileLoadClass *) class;
|
||||
|
||||
object_class->nickname = "vipsload";
|
||||
@ -106,9 +135,9 @@ vips_file_load_jpeg_class_init( VipsFileLoadJpegClass *class )
|
||||
file_class->suffs = vips_suffs;
|
||||
|
||||
load_class->is_a = vips_file_load_vips_is_a;
|
||||
load_class->get_flags = vips_file_load_vips_get_flags;
|
||||
load_class->header = vips_file_load_vips_header;
|
||||
load_class->load = vips_file_load_vips_load;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -61,7 +61,7 @@ vips_file_save_vips_build( VipsObject *object )
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_write_to_file( save->in, file->filename ) )
|
||||
if( vips_image_write_to_file( save->ready, file->filename ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
@ -105,7 +105,6 @@ vips_file_save_vips_class_init( VipsFileSaveVipsClass *class )
|
||||
|
||||
save_class->saveable = VIPS_SAVEABLE_ANY;
|
||||
save_class->format_table = vips_bandfmt_vips;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -104,7 +104,7 @@ void *vips_file_map( const char *base, VipsSListMap2Fn fn, void *a, void *b );
|
||||
/* Image file properties.
|
||||
*/
|
||||
typedef enum {
|
||||
VIPS_FILE_NONE = 0, /* No flags set */
|
||||
VIPS_FILE_NONE = 0, /* No flags set */
|
||||
VIPS_FILE_PARTIAL = 1, /* Lazy read OK (eg. tiled tiff) */
|
||||
VIPS_FILE_BIGENDIAN = 2 /* Most-significant byte first */
|
||||
} VipsFileFlags;
|
||||
|
@ -460,187 +460,7 @@ vips_image_rewind( VipsObject *object )
|
||||
image->mode = mode;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
vips_format_is_vips( VipsFormatClass *format )
|
||||
{
|
||||
return( strcmp( VIPS_OBJECT_CLASS( format )->nickname, "vips" ) == 0 );
|
||||
}
|
||||
|
||||
/* Lazy open.
|
||||
*/
|
||||
|
||||
/* What we track during a delayed open.
|
||||
*/
|
||||
typedef struct {
|
||||
VipsImage *image;
|
||||
VipsFormatClass *format;/* Read in pixels with this */
|
||||
char *filename; /* Get pixels from here */
|
||||
gboolean disc; /* Read via disc requested */
|
||||
|
||||
VipsImage *real; /* The real decompressed image */
|
||||
} Lazy;
|
||||
|
||||
static void
|
||||
lazy_free_cb( VipsImage *image, Lazy *lazy )
|
||||
{
|
||||
VIPS_DEBUG_MSG( "lazy_free: %p \"%s\"\n", lazy, lazy->filename );
|
||||
|
||||
g_free( lazy->filename );
|
||||
VIPS_UNREF( lazy->real );
|
||||
g_free( lazy );
|
||||
}
|
||||
|
||||
static Lazy *
|
||||
lazy_new( VipsImage *image,
|
||||
VipsFormatClass *format, const char *filename, gboolean disc )
|
||||
{
|
||||
Lazy *lazy;
|
||||
|
||||
lazy = g_new( Lazy, 1 );
|
||||
VIPS_DEBUG_MSG( "lazy_new: %p \"%s\"\n", lazy, filename );
|
||||
lazy->image = image;
|
||||
lazy->format = format;
|
||||
lazy->filename = g_strdup( filename );
|
||||
lazy->disc = disc;
|
||||
lazy->real = NULL;
|
||||
g_signal_connect( image, "close", G_CALLBACK( lazy_free_cb ), lazy );
|
||||
|
||||
return( lazy );
|
||||
}
|
||||
|
||||
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 VipsImage *
|
||||
lazy_real_image( Lazy *lazy )
|
||||
{
|
||||
VipsImage *real;
|
||||
|
||||
/* 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()
|
||||
*/
|
||||
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 *
|
||||
open_lazy_start( VipsImage *out, void *a, void *dummy )
|
||||
{
|
||||
Lazy *lazy = (Lazy *) a;
|
||||
|
||||
if( !lazy->real ) {
|
||||
if( !(lazy->real = lazy_real_image( lazy )) ||
|
||||
lazy->format->load( lazy->filename, lazy->real ) ||
|
||||
vips_image_pio_input( lazy->real ) ) {
|
||||
VIPS_UNREF( lazy->real );
|
||||
return( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
return( vips_region_new( lazy->real ) );
|
||||
}
|
||||
|
||||
/* Just copy.
|
||||
*/
|
||||
static int
|
||||
open_lazy_generate( 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 );
|
||||
}
|
||||
|
||||
/* Lazy open ... init the header with the first OpenLazyFn, delay actually
|
||||
* decoding pixels with the second OpenLazyFn until the first generate().
|
||||
*/
|
||||
static int
|
||||
vips_image_open_lazy( VipsImage *image,
|
||||
VipsFormatClass *format, const char *filename, gboolean disc )
|
||||
{
|
||||
Lazy *lazy;
|
||||
|
||||
lazy = lazy_new( image, format, filename, disc );
|
||||
|
||||
/* 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( format->header( filename, image ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( image, 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( image,
|
||||
open_lazy_start, open_lazy_generate, vips_stop_one,
|
||||
lazy, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Lazy save.
|
||||
/* Delayed save.
|
||||
*/
|
||||
|
||||
/* If we write to (eg.) TIFF, actually do the write
|
||||
@ -648,7 +468,7 @@ vips_image_open_lazy( VipsImage *image,
|
||||
* parameters here.
|
||||
*/
|
||||
typedef struct {
|
||||
int (*save_fn)(); /* Save function */
|
||||
const char *file_op; /* Save function */
|
||||
char *filename; /* Save args */
|
||||
} SaveBlock;
|
||||
|
||||
@ -657,7 +477,7 @@ typedef struct {
|
||||
static void
|
||||
vips_image_save_cb( VipsImage *image, int *result, SaveBlock *sb )
|
||||
{
|
||||
if( sb->save_fn( image, sb->filename ) )
|
||||
if( vips_call( sb->file_op, image, sb->filename, NULL ) )
|
||||
*result = -1;
|
||||
|
||||
g_free( sb->filename );
|
||||
@ -665,12 +485,12 @@ vips_image_save_cb( VipsImage *image, int *result, SaveBlock *sb )
|
||||
}
|
||||
|
||||
static void
|
||||
vips_attach_save( VipsImage *image, int (*save_fn)(), const char *filename )
|
||||
vips_attach_save( VipsImage *image, const char *file_op, const char *filename )
|
||||
{
|
||||
SaveBlock *sb;
|
||||
|
||||
sb = g_new( SaveBlock, 1 );
|
||||
sb->save_fn = save_fn;
|
||||
sb->file_op = file_op;
|
||||
sb->filename = g_strdup( filename );
|
||||
g_signal_connect( image, "written",
|
||||
G_CALLBACK( vips_image_save_cb ), sb );
|
||||
@ -771,15 +591,24 @@ vips_image_build( VipsObject *object )
|
||||
if( !(file_op = vips_file_find_load( filename )) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_format_is_vips( format ) ) {
|
||||
if( strcmp( file_op, "vipsload" ) == 0 ) {
|
||||
/* We may need to byteswap.
|
||||
*/
|
||||
VipsFormatFlags flags =
|
||||
vips_format_get_flags( format, filename );
|
||||
gboolean native = (flags & VIPS_FORMAT_BIGENDIAN) ==
|
||||
vips_amiMSBfirst();
|
||||
VipsImage *t;
|
||||
VipsFormatFlags flags;
|
||||
|
||||
if( vips_call( file_op, filename, &t,
|
||||
"flags", &flags,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
|
||||
if( (flags & VIPS_FORMAT_BIGENDIAN) ==
|
||||
vips_amiMSBfirst() ) {
|
||||
/* Native byte order .. open directly into
|
||||
* this image.
|
||||
*/
|
||||
g_object_unref( t );
|
||||
|
||||
if( native ) {
|
||||
if( vips_image_open_input( image ) )
|
||||
return( -1 );
|
||||
|
||||
@ -787,41 +616,49 @@ vips_image_build( VipsObject *object )
|
||||
image->dtype = VIPS_IMAGE_MMAPINRW;
|
||||
}
|
||||
else {
|
||||
VipsImage *x;
|
||||
VipsImage *t2;
|
||||
|
||||
if( !(x = vips_image_new()) )
|
||||
return( -1 );
|
||||
vips_object_local( image, x );
|
||||
if( vips_image_open_input( x ) )
|
||||
if( vips_copy( t, &t2,
|
||||
"swap", TRUE,
|
||||
NULL ) ) {
|
||||
g_object_unref( t );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t );
|
||||
|
||||
/* Byteswap t and copy into this image.
|
||||
*/
|
||||
image->dtype = VIPS_IMAGE_PARTIAL;
|
||||
if( im_copy_swap( x, image ) )
|
||||
if( vips_image_write( t2, image ) ) {
|
||||
g_object_unref( t2 );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t2 );
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Make this a partial, generate into it from the
|
||||
* converter.
|
||||
*/
|
||||
image->dtype = VIPS_IMAGE_PARTIAL;
|
||||
VipsImage *t;
|
||||
|
||||
if( vips_image_open_lazy( image, format,
|
||||
filename, mode[1] == 'd' ) )
|
||||
if( vips_call( file_op, filename, &t, NULL ) )
|
||||
return( -1 );
|
||||
if( vips_image_write( t, image ) ) {
|
||||
g_object_unref( t );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if( !(format = vips_format_for_name( filename )) )
|
||||
if( !(file_op = vips_file_find_save( filename )) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_format_is_vips( format ) )
|
||||
if( strcmp( file_op, "vipssave" ) == 0 )
|
||||
image->dtype = VIPS_IMAGE_OPENOUT;
|
||||
else {
|
||||
image->dtype = VIPS_IMAGE_PARTIAL;
|
||||
vips_attach_save( image,
|
||||
format->save, filename );
|
||||
vips_attach_save( image, file_op, filename );
|
||||
}
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user