add mmap ppm input
This commit is contained in:
parent
5f4b995551
commit
9a3842919a
@ -64,7 +64,7 @@
|
|||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
*
|
*
|
||||||
* - load filename streams with mmap ... we'll need to add get_flags_stream
|
* - load filename streams with mmap
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -330,22 +330,25 @@ vips_foreign_load_ppm_parse_header( VipsForeignLoadPpm *ppm )
|
|||||||
static VipsForeignFlags
|
static VipsForeignFlags
|
||||||
vips_foreign_load_ppm_get_flags( VipsForeignLoad *load )
|
vips_foreign_load_ppm_get_flags( VipsForeignLoad *load )
|
||||||
{
|
{
|
||||||
|
VipsForeignLoadPpm *ppm = (VipsForeignLoadPpm *) load;
|
||||||
|
|
||||||
VipsForeignFlags flags;
|
VipsForeignFlags flags;
|
||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
|
|
||||||
/* reenable this when mmap load goes back in
|
/* If this streami supports fast mmap and this PPM is >=8 bit binary,
|
||||||
*
|
* then we can mmap the file and support partial load. Otherwise,
|
||||||
VipsForeignLoadPpm *ppm = (VipsForeignLoadPpm *) load;
|
* it's sequential.
|
||||||
|
*/
|
||||||
if( !ppm->have_read_header &&
|
if( !ppm->have_read_header &&
|
||||||
vips_foreign_load_ppm_parse_header( ppm ) )
|
vips_foreign_load_ppm_parse_header( ppm ) )
|
||||||
return( 0 );
|
return( 0 );
|
||||||
if( !ppm->ascii && ppm->bits >= 8 )
|
if( vips_streami_is_mappable( ppm->streami ) &&
|
||||||
|
!ppm->ascii &&
|
||||||
|
ppm->bits >= 8 )
|
||||||
flags |= VIPS_FOREIGN_PARTIAL;
|
flags |= VIPS_FOREIGN_PARTIAL;
|
||||||
*/
|
else
|
||||||
|
flags |= VIPS_FOREIGN_SEQUENTIAL;
|
||||||
flags |= VIPS_FOREIGN_SEQUENTIAL;
|
|
||||||
|
|
||||||
return( flags );
|
return( flags );
|
||||||
}
|
}
|
||||||
@ -388,7 +391,9 @@ vips_foreign_load_ppm_header( VipsForeignLoad *load )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read a ppm/pgm file using mmap().
|
/* Read a ppm/pgm file using mmap().
|
||||||
load_mmap( VipsForeignLoadPpm *ppm, VipsImage *image )
|
*/
|
||||||
|
static int
|
||||||
|
vips_foreign_load_ppm_map( VipsForeignLoadPpm *ppm, VipsImage *image )
|
||||||
{
|
{
|
||||||
VipsImage **t = (VipsImage **)
|
VipsImage **t = (VipsImage **)
|
||||||
vips_object_local_array( VIPS_OBJECT( ppm ), 3 );
|
vips_object_local_array( VIPS_OBJECT( ppm ), 3 );
|
||||||
@ -400,7 +405,8 @@ load_mmap( VipsForeignLoadPpm *ppm, VipsImage *image )
|
|||||||
vips_streamib_unbuffer( ppm->streamib );
|
vips_streamib_unbuffer( ppm->streamib );
|
||||||
header_offset = vips_streami_seek( ppm->streami, 0, SEEK_CUR );
|
header_offset = vips_streami_seek( ppm->streami, 0, SEEK_CUR );
|
||||||
data = vips_streami_map( ppm->streami, &length );
|
data = vips_streami_map( ppm->streami, &length );
|
||||||
if( header_offset < 0 || !data )
|
if( header_offset < 0 ||
|
||||||
|
!data )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
data += header_offset;
|
data += header_offset;
|
||||||
length -= header_offset;
|
length -= header_offset;
|
||||||
@ -416,7 +422,6 @@ load_mmap( VipsForeignLoadPpm *ppm, VipsImage *image )
|
|||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_foreign_load_ppm_generate_binary( VipsRegion *or,
|
vips_foreign_load_ppm_generate_binary( VipsRegion *or,
|
||||||
@ -556,34 +561,46 @@ vips_foreign_load_ppm_load( VipsForeignLoad *load )
|
|||||||
VipsImage **t = (VipsImage **)
|
VipsImage **t = (VipsImage **)
|
||||||
vips_object_local_array( (VipsObject *) load, 2 );
|
vips_object_local_array( (VipsObject *) load, 2 );
|
||||||
|
|
||||||
VipsGenerateFn generate;
|
|
||||||
|
|
||||||
if( !ppm->have_read_header &&
|
if( !ppm->have_read_header &&
|
||||||
vips_foreign_load_ppm_parse_header( ppm ) )
|
vips_foreign_load_ppm_parse_header( ppm ) )
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
|
||||||
/* What sort of read are we doing?
|
/* If the stream is mappable and this is a binary file, we can map it.
|
||||||
*/
|
*/
|
||||||
if( !ppm->ascii && ppm->bits >= 8 ) {
|
if( vips_streami_is_mappable( ppm->streami ) &&
|
||||||
generate = vips_foreign_load_ppm_generate_binary;
|
!ppm->ascii &&
|
||||||
|
ppm->bits >= 8 ) {
|
||||||
/* The binary loader does not use the buffered IO object.
|
if( vips_foreign_load_ppm_map( ppm, load->real ) )
|
||||||
*/
|
return( -1 );
|
||||||
vips_streamib_unbuffer( ppm->streamib );
|
|
||||||
}
|
}
|
||||||
else if( !ppm->ascii && ppm->bits == 1 )
|
else {
|
||||||
generate = vips_foreign_load_ppm_generate_1bit_binary;
|
VipsGenerateFn generate;
|
||||||
else if( ppm->ascii && ppm->bits == 1 )
|
|
||||||
generate = vips_foreign_load_ppm_generate_1bit_ascii;
|
|
||||||
else
|
|
||||||
generate = vips_foreign_load_ppm_generate_ascii_int;
|
|
||||||
|
|
||||||
t[0] = vips_image_new();
|
/* What sort of read are we doing?
|
||||||
vips_foreign_load_ppm_set_image( ppm, t[0] );
|
*/
|
||||||
if( vips_image_generate( t[0], NULL, generate, NULL, ppm, NULL ) ||
|
if( !ppm->ascii && ppm->bits >= 8 ) {
|
||||||
vips_sequential( t[0], &t[1], NULL ) ||
|
generate = vips_foreign_load_ppm_generate_binary;
|
||||||
vips_image_write( t[1], load->real ) )
|
|
||||||
return( -1 );
|
/* The binary loader does not use the buffered IO
|
||||||
|
* object.
|
||||||
|
*/
|
||||||
|
vips_streamib_unbuffer( ppm->streamib );
|
||||||
|
}
|
||||||
|
else if( !ppm->ascii && ppm->bits == 1 )
|
||||||
|
generate = vips_foreign_load_ppm_generate_1bit_binary;
|
||||||
|
else if( ppm->ascii && ppm->bits == 1 )
|
||||||
|
generate = vips_foreign_load_ppm_generate_1bit_ascii;
|
||||||
|
else
|
||||||
|
generate = vips_foreign_load_ppm_generate_ascii_int;
|
||||||
|
|
||||||
|
t[0] = vips_image_new();
|
||||||
|
vips_foreign_load_ppm_set_image( ppm, t[0] );
|
||||||
|
if( vips_image_generate( t[0],
|
||||||
|
NULL, generate, NULL, ppm, NULL ) ||
|
||||||
|
vips_sequential( t[0], &t[1], NULL ) ||
|
||||||
|
vips_image_write( t[1], load->real ) )
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
if( vips_streami_decode( ppm->streami ) )
|
if( vips_streami_decode( ppm->streami ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
@ -197,7 +197,8 @@ typedef struct _VipsForeignLoadClass {
|
|||||||
* of flags. If you don't define it, vips will default to 0 (no flags
|
* of flags. If you don't define it, vips will default to 0 (no flags
|
||||||
* set).
|
* set).
|
||||||
*
|
*
|
||||||
* This operation is necessary for vips7 compatibility.
|
* This method is necessary for vips7 compatibility. Don't define
|
||||||
|
* it if you don't need vips7.
|
||||||
*/
|
*/
|
||||||
VipsForeignFlags (*get_flags_filename)( const char *filename );
|
VipsForeignFlags (*get_flags_filename)( const char *filename );
|
||||||
|
|
||||||
@ -217,8 +218,7 @@ typedef struct _VipsForeignLoadClass {
|
|||||||
* @header() needs to set the dhint on the image .. otherwise you get
|
* @header() needs to set the dhint on the image .. otherwise you get
|
||||||
* the default SMALLTILE.
|
* the default SMALLTILE.
|
||||||
*
|
*
|
||||||
* Return 0 for success, -1 for error, setting
|
* Return 0 for success, -1 for error, setting vips_error().
|
||||||
* vips_error().
|
|
||||||
*/
|
*/
|
||||||
int (*header)( VipsForeignLoad *load );
|
int (*header)( VipsForeignLoad *load );
|
||||||
|
|
||||||
|
@ -209,6 +209,7 @@ int vips_streami_unminimise( VipsStreami *streami );
|
|||||||
int vips_streami_decode( VipsStreami *streami );
|
int vips_streami_decode( VipsStreami *streami );
|
||||||
ssize_t vips_streami_read( VipsStreami *streami, void *data, size_t length );
|
ssize_t vips_streami_read( VipsStreami *streami, void *data, size_t length );
|
||||||
const void *vips_streami_map( VipsStreami *streami, size_t *length );
|
const void *vips_streami_map( VipsStreami *streami, size_t *length );
|
||||||
|
gboolean vips_streami_is_mappable( VipsStreami *streami );
|
||||||
gint64 vips_streami_seek( VipsStreami *streami, gint64 offset, int whence );
|
gint64 vips_streami_seek( VipsStreami *streami, gint64 offset, int whence );
|
||||||
int vips_streami_rewind( VipsStreami *streami );
|
int vips_streami_rewind( VipsStreami *streami );
|
||||||
size_t vips_streami_sniff_at_most( VipsStreami *streami,
|
size_t vips_streami_sniff_at_most( VipsStreami *streami,
|
||||||
|
@ -817,10 +817,11 @@ vips_streami_descriptor_to_memory( VipsStreami *streami )
|
|||||||
* @streami: input stream to operate on
|
* @streami: input stream to operate on
|
||||||
* @length_out: return the file length here, or NULL
|
* @length_out: return the file length here, or NULL
|
||||||
*
|
*
|
||||||
* Map the stream object entirely into memory, and return a pointer to the
|
* Map the stream object entirely into memory and return a pointer to the
|
||||||
* start. If @length_out is non-NULL, the file size if written to it.
|
* start. If @length_out is non-NULL, the file size if written to it.
|
||||||
*
|
*
|
||||||
* This operation can take a long time.
|
* This operation can take a long time. Use vips_streami_is_mappable() to
|
||||||
|
* check if a streami can be mapped efficiently.
|
||||||
*
|
*
|
||||||
* Returns: a pointer to the start of the file contents, or NULL on error.
|
* Returns: a pointer to the start of the file contents, or NULL on error.
|
||||||
*/
|
*/
|
||||||
@ -860,6 +861,30 @@ vips_streami_map( VipsStreami *streami, size_t *length_out )
|
|||||||
return( streami->data );
|
return( streami->data );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_streami_map:
|
||||||
|
* @streami: input stream to operate on
|
||||||
|
* @length_out: return the file length here, or NULL
|
||||||
|
*
|
||||||
|
* Map the stream object entirely into memory and return a pointer to the
|
||||||
|
* start. If @length_out is non-NULL, the file size if written to it.
|
||||||
|
*
|
||||||
|
* This operation can take a long time. Use vips_streami_is_mappable() to check
|
||||||
|
* if a streami can be mapped efficiently.
|
||||||
|
*
|
||||||
|
* Returns: a pointer to the start of the file contents, or NULL on error.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
vips_streami_is_mappable( VipsStreami *streami )
|
||||||
|
{
|
||||||
|
/* Already a memory object, or there's a filename we can map, or
|
||||||
|
* there's a seekable descriptor.
|
||||||
|
*/
|
||||||
|
return( streami->data ||
|
||||||
|
VIPS_STREAM( streami )->filename ||
|
||||||
|
(streami->is_pipe && VIPS_STREAM( streami )->descriptor) );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_streami_seek:
|
* vips_streami_seek:
|
||||||
* @streami: input stream to operate on
|
* @streami: input stream to operate on
|
||||||
|
Loading…
Reference in New Issue
Block a user