move tiffload to streams

test_descriptors seems to fail now though, odd
This commit is contained in:
John Cupitt 2019-10-17 10:58:56 +01:00
parent fb2ab23e26
commit 226819b8a8
9 changed files with 283 additions and 446 deletions

View File

@ -52,6 +52,56 @@
#include "../foreign/pforeign.h" #include "../foreign/pforeign.h"
#ifdef HAVE_TIFF
static gboolean
im_istifftiled( const char *filename )
{
VipsStreamInput *input;
gboolean result;
if( !(input = vips_stream_input_new_from_filename( filename )) )
return( FALSE );
result = vips__istiff_stream( input );
VIPS_UNREF( input );
return( result );
}
static int
im_tiff_read_header( const char *filename, VipsImage *out,
int page, int n, gboolean autorotate )
{
VipsStreamInput *input;
if( !(input = vips_stream_input_new_from_filename( filename )) )
return( -1 );
if( vips__tiff_read_header_stream( input, out, page, n, autorotate ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
return( 0 );
}
static int
im_tiff_read( const char *filename, VipsImage *out,
int page, int n, gboolean autorotate )
{
VipsStreamInput *input;
if( !(input = vips_stream_input_new_from_filename( filename )) )
return( -1 );
if( vips__tiff_read_stream( input, out, page, n, autorotate ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
return( 0 );
}
#endif /*HAVE_TIFF*/
static int static int
tiff2vips( const char *name, IMAGE *out, gboolean header_only ) tiff2vips( const char *name, IMAGE *out, gboolean header_only )
{ {
@ -88,18 +138,18 @@ tiff2vips( const char *name, IMAGE *out, gboolean header_only )
if( !header_only && if( !header_only &&
!seq && !seq &&
!vips__istifftiled( filename ) && !im_istifftiled( filename ) &&
out->dtype == VIPS_IMAGE_PARTIAL ) { out->dtype == VIPS_IMAGE_PARTIAL ) {
if( vips__image_wio_output( out ) ) if( vips__image_wio_output( out ) )
return( -1 ); return( -1 );
} }
if( header_only ) { if( header_only ) {
if( vips__tiff_read_header( filename, out, page, 1, FALSE ) ) if( im_tiff_read_header( filename, out, page, 1, FALSE ) )
return( -1 ); return( -1 );
} }
else { else {
if( vips__tiff_read( filename, out, page, 1, FALSE ) ) if( im_tiff_read( filename, out, page, 1, FALSE ) )
return( -1 ); return( -1 );
} }
#else #else

View File

@ -2007,6 +2007,7 @@ vips_foreign_operation_init( void )
extern GType vips_foreign_save_jpeg_mime_get_type( void ); extern GType vips_foreign_save_jpeg_mime_get_type( void );
extern GType vips_foreign_load_tiff_file_get_type( void ); extern GType vips_foreign_load_tiff_file_get_type( void );
extern GType vips_foreign_load_tiff_buffer_get_type( void ); extern GType vips_foreign_load_tiff_buffer_get_type( void );
extern GType vips_foreign_load_tiff_stream_get_type( void );
extern GType vips_foreign_save_tiff_file_get_type( void ); extern GType vips_foreign_save_tiff_file_get_type( void );
extern GType vips_foreign_save_tiff_buffer_get_type( void ); extern GType vips_foreign_save_tiff_buffer_get_type( void );
extern GType vips_foreign_load_vips_get_type( void ); extern GType vips_foreign_load_vips_get_type( void );
@ -2135,6 +2136,7 @@ vips_foreign_operation_init( void )
#ifdef HAVE_TIFF #ifdef HAVE_TIFF
vips_foreign_load_tiff_file_get_type(); vips_foreign_load_tiff_file_get_type();
vips_foreign_load_tiff_buffer_get_type(); vips_foreign_load_tiff_buffer_get_type();
vips_foreign_load_tiff_stream_get_type();
vips_foreign_save_tiff_file_get_type(); vips_foreign_save_tiff_file_get_type();
vips_foreign_save_tiff_buffer_get_type(); vips_foreign_save_tiff_buffer_get_type();
#endif /*HAVE_TIFF*/ #endif /*HAVE_TIFF*/

View File

@ -79,22 +79,6 @@ int vips__tiff_write_buf( VipsImage *in,
VipsRegionShrink region_shrink, VipsRegionShrink region_shrink,
int level, gboolean lossless ); int level, gboolean lossless );
int vips__tiff_read_header( const char *filename, VipsImage *out,
int page, int n, gboolean autorotate );
int vips__tiff_read( const char *filename, VipsImage *out,
int page, int n, gboolean autorotate );
gboolean vips__istiff( const char *filename );
gboolean vips__istifftiled( const char *filename );
gboolean vips__istiff_buffer( const void *buf, size_t len );
gboolean vips__istifftiled_buffer( const void *buf, size_t len );
int vips__tiff_read_header_buffer( const void *buf, size_t len, VipsImage *out,
int page, int n, gboolean autorotate );
int vips__tiff_read_buffer( const void *buf, size_t len, VipsImage *out,
int page, int n, gboolean autorotate );
gboolean vips__istiff_stream( VipsStreamInput *input ); gboolean vips__istiff_stream( VipsStreamInput *input );
gboolean vips__istifftiled_stream( VipsStreamInput *input ); gboolean vips__istifftiled_stream( VipsStreamInput *input );
int vips__tiff_read_header_stream( VipsStreamInput *input, VipsImage *out, int vips__tiff_read_header_stream( VipsStreamInput *input, VipsImage *out,

View File

@ -132,174 +132,6 @@ vips__tiff_openout( const char *path, gboolean bigtiff )
return( tif ); return( tif );
} }
/* Open TIFF for input from a file.
*/
TIFF *
vips__tiff_openin( const char *path )
{
/* No mmap --- no performance advantage with libtiff, and it burns up
* our VM if the tiff file is large.
*/
const char *mode = "rm";
TIFF *tif;
#ifdef DEBUG
printf( "vips__tiff_openin( \"%s\" )\n", path );
#endif /*DEBUG*/
/* Need the utf-16 version on Windows.
*/
#ifdef OS_WIN32
{
GError *error = NULL;
wchar_t *path16;
if( !(path16 = (wchar_t *)
g_utf8_to_utf16( path, -1, NULL, NULL, &error )) ) {
vips_g_error( &error );
return( NULL );
}
tif = TIFFOpenW( path16, mode );
g_free( path16 );
}
#else /*!OS_WIN32*/
tif = TIFFOpen( path, mode );
#endif /*OS_WIN32*/
if( !tif ) {
vips_error( "tiff",
_( "unable to open \"%s\" for input" ), path );
return( NULL );
}
return( tif );
}
/* TIFF input from a memory buffer.
*/
typedef struct _VipsTiffOpeninBuffer {
size_t position;
const void *data;
size_t length;
} VipsTiffOpeninBuffer;
static tsize_t
openin_buffer_read( thandle_t st, tdata_t data, tsize_t size )
{
VipsTiffOpeninBuffer *buffer = (VipsTiffOpeninBuffer *) st;
size_t available;
size_t copied;
if( buffer->position > buffer->length ) {
vips_error( "openin_buffer_read",
"%s", _( "read beyond end of buffer" ) );
return( 0 );
}
available = buffer->length - buffer->position;
copied = VIPS_MIN( size, available );
memcpy( data,
(unsigned char *) buffer->data + buffer->position, copied );
buffer->position += copied;
return( copied );
}
static tsize_t
openin_buffer_write( thandle_t st, tdata_t buffer, tsize_t size )
{
g_assert_not_reached();
return( 0 );
}
static int
openin_buffer_close( thandle_t st )
{
return( 0 );
}
/* After calling this, ->pos is not bound by the size of the buffer, it can
* have any positive value.
*/
static toff_t
openin_buffer_seek( thandle_t st, toff_t position, int whence )
{
VipsTiffOpeninBuffer *buffer = (VipsTiffOpeninBuffer *) st;
if( whence == SEEK_SET )
buffer->position = position;
else if( whence == SEEK_CUR )
buffer->position += position;
else if( whence == SEEK_END )
buffer->position = buffer->length + position;
else
g_assert_not_reached();
return( buffer->position );
}
static toff_t
openin_buffer_size( thandle_t st )
{
VipsTiffOpeninBuffer *buffer = (VipsTiffOpeninBuffer *) st;
return( buffer->length );
}
static int
openin_buffer_map( thandle_t st, tdata_t *start, toff_t *len )
{
g_assert_not_reached();
return( 0 );
}
static void
openin_buffer_unmap( thandle_t st, tdata_t start, toff_t len )
{
g_assert_not_reached();
return;
}
TIFF *
vips__tiff_openin_buffer( VipsImage *image, const void *data, size_t length )
{
VipsTiffOpeninBuffer *buffer;
TIFF *tiff;
#ifdef DEBUG
printf( "vips__tiff_openin_buffer:\n" );
#endif /*DEBUG*/
buffer = VIPS_NEW( image, VipsTiffOpeninBuffer );
buffer->position = 0;
buffer->data = data;
buffer->length = length;
if( !(tiff = TIFFClientOpen( "memory input", "rm",
(thandle_t) buffer,
openin_buffer_read,
openin_buffer_write,
openin_buffer_seek,
openin_buffer_close,
openin_buffer_size,
openin_buffer_map,
openin_buffer_unmap )) ) {
vips_error( "vips__tiff_openin_buffer", "%s",
_( "unable to open memory buffer for input" ) );
return( NULL );
}
return( tiff );
}
/* TIFF input from a vips stream. /* TIFF input from a vips stream.
*/ */
@ -365,18 +197,20 @@ openin_stream_unmap( thandle_t st, tdata_t start, toff_t len )
} }
TIFF * TIFF *
vips__tiff_openin_stream( VipsImage *image, VipsStreamInput *input ) vips__tiff_openin_stream( VipsStreamInput *input )
{ {
TIFF *tiff; TIFF *tiff;
#ifdef DEBUG #ifdef DEBUG
printf( "vips__tiff_openin_buffer:\n" ); printf( "vips__tiff_openin_stream:\n" );
#endif /*DEBUG*/ #endif /*DEBUG*/
/* Unreffed on close(), see above. /* Unreffed on close(), see above.
*/ */
g_object_ref( input ); if( vips_stream_input_rewind( input ) )
return( NULL );
g_object_ref( input );
if( !(tiff = TIFFClientOpen( "stream input", "rm", if( !(tiff = TIFFClientOpen( "stream input", "rm",
(thandle_t) input, (thandle_t) input,
openin_stream_read, openin_stream_read,

View File

@ -37,15 +37,12 @@
extern "C" { extern "C" {
#endif /*__cplusplus*/ #endif /*__cplusplus*/
TIFF *vips__tiff_openout( const char *path, gboolean bigtiff ); TIFF *vips__tiff_openin_stream( VipsStreamInput *input );
TIFF *vips__tiff_openin( const char *path );
TIFF *vips__tiff_openin_buffer( VipsImage *image, TIFF *vips__tiff_openout( const char *path, gboolean bigtiff );
const void *data, size_t length );
TIFF *vips__tiff_openout_buffer( VipsImage *image, TIFF *vips__tiff_openout_buffer( VipsImage *image,
gboolean bigtiff, void **out_data, size_t *out_length ); gboolean bigtiff, void **out_data, size_t *out_length );
TIFF *vips__tiff_openin_stream( VipsImage *image, VipsStreamInput *input );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -189,6 +189,8 @@
* 7/6/19 * 7/6/19
* - istiff reads the first directory rather than just testing the magic * - istiff reads the first directory rather than just testing the magic
* number, so it ignores more TIFF-like, but not TIFF images * number, so it ignores more TIFF-like, but not TIFF images
* 17/10/19
* - switch to stream input
*/ */
/* /*
@ -2341,68 +2343,6 @@ rtiff_header_read_all( Rtiff *rtiff )
return( 0 ); return( 0 );
} }
static Rtiff *
rtiff_new_filename( const char *filename, VipsImage *out,
int page, int n, gboolean autorotate )
{
Rtiff *rtiff;
if( !(rtiff = rtiff_new( out, page, n, autorotate )) ||
!(rtiff->tiff = vips__tiff_openin( filename )) ||
rtiff_header_read_all( rtiff ) )
return( NULL );
rtiff->filename = vips_strdup( VIPS_OBJECT( out ), filename );
return( rtiff );
}
static Rtiff *
rtiff_new_buffer( const void *buf, size_t len, VipsImage *out,
int page, int n, gboolean autorotate )
{
Rtiff *rtiff;
if( !(rtiff = rtiff_new( out, page, n, autorotate )) ||
!(rtiff->tiff = vips__tiff_openin_buffer( out, buf, len )) ||
rtiff_header_read_all( rtiff ) )
return( NULL );
return( rtiff );
}
/* For istiffpyramid(), see vips_thumbnail_get_tiff_pyramid().
*/
int
vips__tiff_read( const char *filename, VipsImage *out,
int page, int n, gboolean autorotate )
{
Rtiff *rtiff;
#ifdef DEBUG
printf( "tiff2vips: libtiff version is \"%s\"\n", TIFFGetVersion() );
printf( "tiff2vips: libtiff starting for %s\n", filename );
#endif /*DEBUG*/
vips__tiff_init();
if( !(rtiff = rtiff_new_filename( filename, out,
page, n, autorotate )) )
return( -1 );
if( rtiff->header.tiled ) {
if( rtiff_read_tilewise( rtiff, out ) )
return( -1 );
}
else {
if( rtiff_read_stripwise( rtiff, out ) )
return( -1 );
}
return( 0 );
}
/* On a header-only read, we can just swap width/height if orientation is 6 or /* On a header-only read, we can just swap width/height if orientation is 6 or
* 8. * 8.
*/ */
@ -2426,186 +2366,17 @@ vips__tiff_read_header_orientation( Rtiff *rtiff, VipsImage *out )
} }
} }
int
vips__tiff_read_header( const char *filename, VipsImage *out,
int page, int n, gboolean autorotate )
{
Rtiff *rtiff;
vips__tiff_init();
if( !(rtiff =
rtiff_new_filename( filename, out, page, n, autorotate )) )
return( -1 );
if( rtiff_set_header( rtiff, out ) )
return( -1 );
vips__tiff_read_header_orientation( rtiff, out );
/* Just a header read: we can free the tiff read early and save an fd.
*/
rtiff_free( rtiff );
return( 0 );
}
typedef gboolean (*TiffPropertyFn)( TIFF *tif ); typedef gboolean (*TiffPropertyFn)( TIFF *tif );
static gboolean
vips__testtiff( const char *filename, TiffPropertyFn fn )
{
TIFF *tif;
gboolean property;
vips__tiff_init();
if( !(tif = vips__tiff_openin( filename )) ) {
vips_error_clear();
return( FALSE );
}
property = fn ? fn( tif ) : TRUE;
TIFFClose( tif );
return( property );
}
gboolean
vips__testtiff_buffer( const void *buf, size_t len, TiffPropertyFn fn )
{
VipsImage *im;
TIFF *tif;
gboolean property;
vips__tiff_init();
im = vips_image_new();
if( !(tif = vips__tiff_openin_buffer( im, buf, len )) ) {
g_object_unref( im );
vips_error_clear();
return( FALSE );
}
property = fn ? fn( tif ) : TRUE;
TIFFClose( tif );
g_object_unref( im );
return( property );
}
gboolean
vips__istifftiled( const char *filename )
{
return( vips__testtiff( filename, TIFFIsTiled ) );
}
/* We test for TIFF by trying to read the first directory. We could just test
* the magic number, but many formats (eg. ARW) use a TIFF-like container and
* we don't want to open those with vips tiffload.
*/
gboolean
vips__istiff( const char *filename )
{
return( vips__testtiff( filename, NULL ) );
}
gboolean
vips__istiff_buffer( const void *buf, size_t len )
{
return( vips__testtiff_buffer( buf, len, NULL ) );
}
int
vips__tiff_read_header_buffer( const void *buf, size_t len, VipsImage *out,
int page, int n, gboolean autorotate )
{
Rtiff *rtiff;
vips__tiff_init();
if( !(rtiff = rtiff_new_buffer( buf, len, out, page, n, autorotate )) )
return( -1 );
if( rtiff_set_header( rtiff, out ) )
return( -1 );
vips__tiff_read_header_orientation( rtiff, out );
return( 0 );
}
int
vips__tiff_read_buffer( const void *buf, size_t len,
VipsImage *out, int page, int n, gboolean autorotate )
{
Rtiff *rtiff;
#ifdef DEBUG
printf( "tiff2vips: libtiff version is \"%s\"\n", TIFFGetVersion() );
printf( "tiff2vips: libtiff starting for buffer %p\n", buf );
#endif /*DEBUG*/
vips__tiff_init();
if( !(rtiff = rtiff_new_buffer( buf, len, out, page, n, autorotate )) )
return( -1 );
if( rtiff->header.tiled ) {
if( rtiff_read_tilewise( rtiff, out ) )
return( -1 );
}
else {
if( rtiff_read_stripwise( rtiff, out ) )
return( -1 );
}
return( 0 );
}
gboolean
vips__istifftiled_buffer( const void *buf, size_t len )
{
VipsImage *im;
TIFF *tif;
gboolean tiled;
vips__tiff_init();
im = vips_image_new();
if( !(tif = vips__tiff_openin_buffer( im, buf, len )) ) {
g_object_unref( im );
vips_error_clear();
return( FALSE );
}
tiled = TIFFIsTiled( tif );
TIFFClose( tif );
g_object_unref( im );
return( tiled );
}
static gboolean static gboolean
vips__testtiff_stream( VipsStreamInput *input, TiffPropertyFn fn ) vips__testtiff_stream( VipsStreamInput *input, TiffPropertyFn fn )
{ {
VipsImage *im;
TIFF *tif; TIFF *tif;
gboolean property; gboolean property;
vips__tiff_init(); vips__tiff_init();
im = vips_image_new(); if( !(tif = vips__tiff_openin_stream( input )) ) {
if( vips_stream_input_rewind( input ) )
return( FALSE );
if( !(tif = vips__tiff_openin_stream( im, input )) ) {
g_object_unref( im );
vips_error_clear(); vips_error_clear();
return( FALSE ); return( FALSE );
} }
@ -2613,7 +2384,6 @@ vips__testtiff_stream( VipsStreamInput *input, TiffPropertyFn fn )
property = fn ? fn( tif ) : TRUE; property = fn ? fn( tif ) : TRUE;
TIFFClose( tif ); TIFFClose( tif );
g_object_unref( im );
return( property ); return( property );
} }
@ -2637,7 +2407,7 @@ rtiff_new_stream( VipsStreamInput *input, VipsImage *out,
Rtiff *rtiff; Rtiff *rtiff;
if( !(rtiff = rtiff_new( out, page, n, autorotate )) || if( !(rtiff = rtiff_new( out, page, n, autorotate )) ||
!(rtiff->tiff = vips__tiff_openin_stream( out, input )) || !(rtiff->tiff = vips__tiff_openin_stream( input )) ||
rtiff_header_read_all( rtiff ) ) rtiff_header_read_all( rtiff ) )
return( NULL ); return( NULL );

View File

@ -138,17 +138,37 @@ typedef VipsForeignLoadTiffClass VipsForeignLoadTiffFileClass;
G_DEFINE_TYPE( VipsForeignLoadTiffFile, vips_foreign_load_tiff_file, G_DEFINE_TYPE( VipsForeignLoadTiffFile, vips_foreign_load_tiff_file,
vips_foreign_load_tiff_get_type() ); vips_foreign_load_tiff_get_type() );
static gboolean
vips_foreign_load_tiff_file_is_a( const char *filename )
{
VipsStreamInput *input;
gboolean result;
if( !(input = vips_stream_input_new_from_filename( filename )) )
return( FALSE );
result = vips__istiff_stream( input );
VIPS_UNREF( input );
return( result );
}
static VipsForeignFlags static VipsForeignFlags
vips_foreign_load_tiff_file_get_flags_filename( const char *filename ) vips_foreign_load_tiff_file_get_flags_filename( const char *filename )
{ {
VipsStreamInput *input;
VipsForeignFlags flags; VipsForeignFlags flags;
if( !(input = vips_stream_input_new_from_filename( filename )) )
return( 0 );
flags = 0; flags = 0;
if( vips__istifftiled( filename ) ) if( vips__istifftiled_stream( input ) )
flags |= VIPS_FOREIGN_PARTIAL; flags |= VIPS_FOREIGN_PARTIAL;
else else
flags |= VIPS_FOREIGN_SEQUENTIAL; flags |= VIPS_FOREIGN_SEQUENTIAL;
VIPS_UNREF( input );
return( flags ); return( flags );
} }
@ -167,9 +187,16 @@ vips_foreign_load_tiff_file_header( VipsForeignLoad *load )
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load; VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load; VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load;
if( vips__tiff_read_header( file->filename, load->out, VipsStreamInput *input;
tiff->page, tiff->n, tiff->autorotate ) )
if( !(input = vips_stream_input_new_from_filename( file->filename )) )
return( -1 ); return( -1 );
if( vips__tiff_read_header_stream( input, load->out,
tiff->page, tiff->n, tiff->autorotate ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
VIPS_SETSTR( load->out->filename, file->filename ); VIPS_SETSTR( load->out->filename, file->filename );
@ -182,9 +209,16 @@ vips_foreign_load_tiff_file_load( VipsForeignLoad *load )
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load; VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load; VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load;
if( vips__tiff_read( file->filename, load->real, VipsStreamInput *input;
tiff->page, tiff->n, tiff->autorotate ) )
if( !(input = vips_stream_input_new_from_filename( file->filename )) )
return( -1 ); return( -1 );
if( vips__tiff_read_stream( input, load->real,
tiff->page, tiff->n, tiff->autorotate ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
return( 0 ); return( 0 );
} }
@ -211,7 +245,7 @@ vips_foreign_load_tiff_file_class_init( VipsForeignLoadTiffFileClass *class )
foreign_class->suffs = vips__foreign_tiff_suffs; foreign_class->suffs = vips__foreign_tiff_suffs;
load_class->is_a = vips__istiff; load_class->is_a = vips_foreign_load_tiff_file_is_a;
load_class->get_flags_filename = load_class->get_flags_filename =
vips_foreign_load_tiff_file_get_flags_filename; vips_foreign_load_tiff_file_get_flags_filename;
load_class->get_flags = vips_foreign_load_tiff_file_get_flags; load_class->get_flags = vips_foreign_load_tiff_file_get_flags;
@ -245,18 +279,37 @@ typedef VipsForeignLoadTiffClass VipsForeignLoadTiffBufferClass;
G_DEFINE_TYPE( VipsForeignLoadTiffBuffer, vips_foreign_load_tiff_buffer, G_DEFINE_TYPE( VipsForeignLoadTiffBuffer, vips_foreign_load_tiff_buffer,
vips_foreign_load_tiff_get_type() ); vips_foreign_load_tiff_get_type() );
static gboolean
vips_foreign_load_tiff_buffer_is_a_buffer( const void *buf, size_t len )
{
VipsStreamInput *input;
gboolean result;
if( !(input = vips_stream_input_new_from_memory( buf, len )) )
return( FALSE );
result = vips__istiff_stream( input );
VIPS_UNREF( input );
return( result );
}
static VipsForeignFlags static VipsForeignFlags
vips_foreign_load_tiff_buffer_get_flags( VipsForeignLoad *load ) vips_foreign_load_tiff_buffer_get_flags( VipsForeignLoad *load )
{ {
VipsForeignLoadTiffBuffer *buffer = (VipsForeignLoadTiffBuffer *) load; VipsForeignLoadTiffBuffer *buffer = (VipsForeignLoadTiffBuffer *) load;
VipsStreamInput *input;
VipsForeignFlags flags; VipsForeignFlags flags;
if( !(input = vips_stream_input_new_from_memory(
buffer->buf->data, buffer->buf->length )) )
return( FALSE );
flags = 0; flags = 0;
if( vips__istifftiled_buffer( buffer->buf->data, buffer->buf->length ) ) if( vips__istifftiled_stream( input ) )
flags |= VIPS_FOREIGN_PARTIAL; flags |= VIPS_FOREIGN_PARTIAL;
else else
flags |= VIPS_FOREIGN_SEQUENTIAL; flags |= VIPS_FOREIGN_SEQUENTIAL;
VIPS_UNREF( input );
return( flags ); return( flags );
} }
@ -267,10 +320,17 @@ vips_foreign_load_tiff_buffer_header( VipsForeignLoad *load )
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load; VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
VipsForeignLoadTiffBuffer *buffer = (VipsForeignLoadTiffBuffer *) load; VipsForeignLoadTiffBuffer *buffer = (VipsForeignLoadTiffBuffer *) load;
if( vips__tiff_read_header_buffer( VipsStreamInput *input;
buffer->buf->data, buffer->buf->length, load->out,
tiff->page, tiff->n, tiff->autorotate ) ) if( !(input = vips_stream_input_new_from_memory(
buffer->buf->data, buffer->buf->length )) )
return( FALSE );
if( vips__tiff_read_header_stream( input, load->out,
tiff->page, tiff->n, tiff->autorotate ) ) {
VIPS_UNREF( input );
return( -1 ); return( -1 );
}
VIPS_UNREF( input );
return( 0 ); return( 0 );
} }
@ -281,10 +341,17 @@ vips_foreign_load_tiff_buffer_load( VipsForeignLoad *load )
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load; VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
VipsForeignLoadTiffBuffer *buffer = (VipsForeignLoadTiffBuffer *) load; VipsForeignLoadTiffBuffer *buffer = (VipsForeignLoadTiffBuffer *) load;
if( vips__tiff_read_buffer( VipsStreamInput *input;
buffer->buf->data, buffer->buf->length, load->real,
tiff->page, tiff->n, tiff->autorotate ) ) if( !(input = vips_stream_input_new_from_memory(
buffer->buf->data, buffer->buf->length )) )
return( FALSE );
if( vips__tiff_read_stream( input, load->real,
tiff->page, tiff->n, tiff->autorotate ) ) {
VIPS_UNREF( input );
return( -1 ); return( -1 );
}
VIPS_UNREF( input );
return( 0 ); return( 0 );
} }
@ -303,7 +370,7 @@ vips_foreign_load_tiff_buffer_class_init(
object_class->nickname = "tiffload_buffer"; object_class->nickname = "tiffload_buffer";
object_class->description = _( "load tiff from buffer" ); object_class->description = _( "load tiff from buffer" );
load_class->is_a_buffer = vips__istiff_buffer; load_class->is_a_buffer = vips_foreign_load_tiff_buffer_is_a_buffer;
load_class->get_flags = vips_foreign_load_tiff_buffer_get_flags; load_class->get_flags = vips_foreign_load_tiff_buffer_get_flags;
load_class->header = vips_foreign_load_tiff_buffer_header; load_class->header = vips_foreign_load_tiff_buffer_header;
load_class->load = vips_foreign_load_tiff_buffer_load; load_class->load = vips_foreign_load_tiff_buffer_load;
@ -321,6 +388,96 @@ vips_foreign_load_tiff_buffer_init( VipsForeignLoadTiffBuffer *buffer )
{ {
} }
typedef struct _VipsForeignLoadTiffStream {
VipsForeignLoadTiff parent_object;
/* Load from a stream.
*/
VipsStreamInput *input;
} VipsForeignLoadTiffStream;
typedef VipsForeignLoadTiffClass VipsForeignLoadTiffStreamClass;
G_DEFINE_TYPE( VipsForeignLoadTiffStream, vips_foreign_load_tiff_stream,
vips_foreign_load_tiff_get_type() );
static VipsForeignFlags
vips_foreign_load_tiff_stream_get_flags( VipsForeignLoad *load )
{
VipsForeignLoadTiffStream *stream = (VipsForeignLoadTiffStream *) load;
VipsForeignFlags flags;
flags = 0;
if( vips__istifftiled_stream( stream->input ) )
flags |= VIPS_FOREIGN_PARTIAL;
else
flags |= VIPS_FOREIGN_SEQUENTIAL;
return( flags );
}
static int
vips_foreign_load_tiff_stream_header( VipsForeignLoad *load )
{
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
VipsForeignLoadTiffStream *stream = (VipsForeignLoadTiffStream *) load;
if( vips__tiff_read_header_stream( stream->input, load->out,
tiff->page, tiff->n, tiff->autorotate ) )
return( -1 );
return( 0 );
}
static int
vips_foreign_load_tiff_stream_load( VipsForeignLoad *load )
{
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
VipsForeignLoadTiffStream *stream = (VipsForeignLoadTiffStream *) load;
if( vips__tiff_read_stream( stream->input, load->real,
tiff->page, tiff->n, tiff->autorotate ) )
return( -1 );
return( 0 );
}
static void
vips_foreign_load_tiff_stream_class_init(
VipsForeignLoadTiffStreamClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "tiffload_stream";
object_class->description = _( "load tiff from stream" );
load_class->is_a_stream = vips__istiff_stream;
load_class->get_flags = vips_foreign_load_tiff_stream_get_flags;
load_class->header = vips_foreign_load_tiff_stream_header;
load_class->load = vips_foreign_load_tiff_stream_load;
VIPS_ARG_OBJECT( class, "input", 1,
_( "Input" ),
_( "Stream to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadTiffStream, input ),
VIPS_TYPE_STREAM_INPUT );
}
static void
vips_foreign_load_tiff_stream_init( VipsForeignLoadTiffStream *stream )
{
}
#endif /*HAVE_TIFF*/ #endif /*HAVE_TIFF*/
/** /**
@ -426,3 +583,35 @@ vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... )
return( result ); return( result );
} }
/**
* vips_tiffload_stream:
* @input: stream to load
* @out: (out): image to write
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* * @page: %gint, load this page
* * @n: %gint, load this many pages
* * @autorotate: %gboolean, use orientation tag to rotate the image
* during load
*
* Exactly as vips_tiffload(), but read from a stream.
*
* See also: vips_tiffload().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_tiffload_stream( VipsStreamInput *input, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "tiffload_stream", ap, input, out );
va_end( ap );
return( result );
}

View File

@ -1713,6 +1713,7 @@ wtiff_gather( Wtiff *wtiff )
wtiff->layer->below ) wtiff->layer->below )
for( layer = wtiff->layer->below; layer; for( layer = wtiff->layer->below; layer;
layer = layer->below ) { layer = layer->below ) {
VipsStreamInput *input;
TIFF *in; TIFF *in;
#ifdef DEBUG #ifdef DEBUG
@ -1720,15 +1721,23 @@ wtiff_gather( Wtiff *wtiff )
#endif /*DEBUG*/ #endif /*DEBUG*/
if( layer->lname ) { if( layer->lname ) {
if( !(in = vips__tiff_openin( layer->lname )) ) if( !(input =
vips_stream_input_new_from_filename(
layer->lname )) )
return( -1 ); return( -1 );
} }
else { else {
if( !(in = vips__tiff_openin_buffer( wtiff->im, if( !(input = vips_stream_input_new_from_memory(
layer->buf, layer->len )) ) layer->buf, layer->len )) )
return( -1 ); return( -1 );
} }
if( !(in = vips__tiff_openin_stream( input )) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
if( wtiff_copy_tiff( wtiff, wtiff->layer->tif, in ) ) { if( wtiff_copy_tiff( wtiff, wtiff->layer->tif, in ) ) {
TIFFClose( in ); TIFFClose( in );
return( -1 ); return( -1 );

View File

@ -481,6 +481,8 @@ int vips_tiffload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel)); __attribute__((sentinel));
int vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... ) int vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... )
__attribute__((sentinel)); __attribute__((sentinel));
int vips_tiffload_stream( VipsStreamInput *input, VipsImage **out, ... )
__attribute__((sentinel));
int vips_tiffsave( VipsImage *in, const char *filename, ... ) int vips_tiffsave( VipsImage *in, const char *filename, ... )
__attribute__((sentinel)); __attribute__((sentinel));
int vips_tiffsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) int vips_tiffsave_buffer( VipsImage *in, void **buf, size_t *len, ... )