add ppm load/save to a connection

plus some more tests
This commit is contained in:
John Cupitt 2020-06-27 15:23:18 +01:00
parent c9af99c2f7
commit d831ad34d5
7 changed files with 230 additions and 3 deletions

View File

@ -6,7 +6,8 @@
- tiffsave has a "depth" param to set max pyr depth
- libtiff LOGLUV images load and save as libvips XYZ
- add gifload_source, csvload_source, csvsave_target, matrixload_source,
matrixsave_source, pdfload_source, heifload_source, heifsave_target
matrixsave_source, pdfload_source, heifload_source, heifsave_target,
ppmload_source, ppmsave_target
- revise vipsthumbnail flags
- add VIPS_LEAK env var
- add vips_pipe_read_limit_set(), --vips-pipe-read-limit,

View File

@ -2047,7 +2047,9 @@ vips_foreign_operation_init( void )
extern GType vips_foreign_load_mat_get_type( void );
extern GType vips_foreign_load_ppm_file_get_type( void );
extern GType vips_foreign_load_ppm_source_get_type( void );
extern GType vips_foreign_save_ppm_file_get_type( void );
extern GType vips_foreign_save_ppm_target_get_type( void );
extern GType vips_foreign_load_png_file_get_type( void );
extern GType vips_foreign_load_png_buffer_get_type( void );
@ -2157,7 +2159,9 @@ vips_foreign_operation_init( void )
#ifdef HAVE_PPM
vips_foreign_load_ppm_file_get_type();
vips_foreign_load_ppm_source_get_type();
vips_foreign_save_ppm_file_get_type();
vips_foreign_save_ppm_target_get_type();
#endif /*HAVE_PPM*/
#ifdef HAVE_RADIANCE

View File

@ -35,8 +35,10 @@
* - redone with source/target
* - sequential load, plus mmap for filename sources
* - faster plus lower memory use
* 02/02/2020
* 02/02/20
* - ban max_vaue < 0
* 27/6/20
* - add ppmload_source
*/
/*
@ -193,6 +195,21 @@ vips_foreign_load_ppm_dispose( GObject *gobject )
dispose( gobject );
}
static int
vips_foreign_load_ppm_build( VipsObject *object )
{
VipsForeignLoadPpm *ppm = (VipsForeignLoadPpm *) object;
if( ppm->source )
ppm->sbuf = vips_sbuf_new_from_source( ppm->source );
if( VIPS_OBJECT_CLASS( vips_foreign_load_ppm_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
/* Scan the header into our class.
*/
static int
@ -626,6 +643,7 @@ vips_foreign_load_ppm_class_init( VipsForeignLoadPpmClass *class )
object_class->nickname = "ppmload_base";
object_class->description = _( "load ppm base class" );
object_class->build = vips_foreign_load_ppm_build;
foreign_class->suffs = vips__ppm_suffs;
@ -720,6 +738,62 @@ vips_foreign_load_ppm_file_init( VipsForeignLoadPpmFile *file )
{
}
typedef struct _VipsForeignLoadPpmSource {
VipsForeignLoadPpm parent_object;
VipsSource *source;
} VipsForeignLoadPpmSource;
typedef VipsForeignLoadPpmClass VipsForeignLoadPpmSourceClass;
G_DEFINE_TYPE( VipsForeignLoadPpmSource, vips_foreign_load_ppm_source,
vips_foreign_load_ppm_get_type() );
static int
vips_foreign_load_ppm_source_build( VipsObject *object )
{
VipsForeignLoadPpm *ppm = (VipsForeignLoadPpm *) object;
VipsForeignLoadPpmSource *source = (VipsForeignLoadPpmSource *) object;
if( source->source ) {
ppm->source = source->source;
g_object_ref( ppm->source );
}
if( VIPS_OBJECT_CLASS( vips_foreign_load_ppm_source_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static void
vips_foreign_load_ppm_source_class_init( VipsForeignLoadPpmFileClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "ppmload_source";
object_class->build = vips_foreign_load_ppm_source_build;
VIPS_ARG_OBJECT( class, "source", 1,
_( "Source" ),
_( "Source to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadPpmSource, source ),
VIPS_TYPE_SOURCE );
}
static void
vips_foreign_load_ppm_source_init( VipsForeignLoadPpmSource *source )
{
}
#endif /*HAVE_PPM*/
/**
@ -751,3 +825,35 @@ vips_ppmload( const char *filename, VipsImage **out, ... )
return( result );
}
/**
* vips_ppmload_source:
* @source: source to load
* @out: (out): output image
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* * @skip: skip this many lines at start of file
* * @lines: read this many lines from file
* * @whitespace: set of whitespace characters
* * @separator: set of separator characters
* * @fail: %gboolean, fail on errors
*
* Exactly as vips_ppmload(), but read from a source.
*
* See also: vips_ppmload().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_ppmload_source( VipsSource *source, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "ppmload_source", ap, source, out );
va_end( ap );
return( result );
}

View File

@ -6,6 +6,8 @@
* - redone with targets
* 18/6/20
* - add "bitdepth" param, cf. tiffsave
* 27/6/20
* - add ppmsave_target
*/
/*
@ -469,6 +471,61 @@ vips_foreign_save_ppm_file_init( VipsForeignSavePpmFile *file )
{
}
typedef struct _VipsForeignSavePpmTarget {
VipsForeignSavePpm parent_object;
VipsTarget *target;
} VipsForeignSavePpmTarget;
typedef VipsForeignSavePpmClass VipsForeignSavePpmTargetClass;
G_DEFINE_TYPE( VipsForeignSavePpmTarget, vips_foreign_save_ppm_target,
vips_foreign_save_ppm_get_type() );
static int
vips_foreign_save_ppm_target_build( VipsObject *object )
{
VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) object;
VipsForeignSavePpmTarget *target =
(VipsForeignSavePpmTarget *) object;
if( target->target ) {
ppm->target = target->target;
g_object_ref( ppm->target );
}
return( VIPS_OBJECT_CLASS(
vips_foreign_save_ppm_target_parent_class )->
build( object ) );
}
static void
vips_foreign_save_ppm_target_class_init(
VipsForeignSavePpmTargetClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "ppmsave_target";
object_class->build = vips_foreign_save_ppm_target_build;
VIPS_ARG_OBJECT( class, "target", 1,
_( "Target" ),
_( "Target to save to" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignSavePpmTarget, target ),
VIPS_TYPE_TARGET );
}
static void
vips_foreign_save_ppm_target_init( VipsForeignSavePpmTarget *target )
{
}
#endif /*HAVE_PPM*/
/**
@ -512,3 +569,28 @@ vips_ppmsave( VipsImage *in, const char *filename, ... )
return( result );
}
/**
* vips_ppmsave_target: (method)
* @in: image to save
* @target: save image to this target
* @...: %NULL-terminated list of optional named arguments
*
* As vips_ppmsave(), but save to a target.
*
* See also: vips_ppmsave().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_ppmsave_target( VipsImage *in, VipsTarget *target, ... )
{
va_list ap;
int result;
va_start( ap, target );
result = vips_call_split( "ppmsave_target", ap, in, target );
va_end( ap );
return( result );
}

View File

@ -587,8 +587,12 @@ int vips_pngsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
int vips_ppmload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));
int vips_ppmload_source( VipsSource *source, VipsImage **out, ... )
__attribute__((sentinel));
int vips_ppmsave( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));
int vips_ppmsave_target( VipsImage *in, VipsTarget *target, ... )
__attribute__((sentinel));
int vips_matload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));

View File

@ -94,5 +94,35 @@ class TestConnection:
assert x.get("blob") == y
@skip_if_no("matrixload_source")
@skip_if_no("matrixsave_target")
def test_connection_matrix(self):
x = pyvips.Target.new_to_memory()
self.mono.matrixsave_target(x)
y = pyvips.Source.new_from_memory(x.get("blob"))
im = pyvips.Image.matrixload_source(y)
assert (im - self.mono).abs().max() == 0
@skip_if_no("csvload_source")
@skip_if_no("csvsave_target")
def test_connection_csv(self):
x = pyvips.Target.new_to_memory()
self.mono.csvsave_target(x)
y = pyvips.Source.new_from_memory(x.get("blob"))
im = pyvips.Image.csvload_source(y)
assert (im - self.mono).abs().max() == 0
@skip_if_no("ppmload_source")
@skip_if_no("ppmsave_target")
def test_connection_ppm(self):
x = pyvips.Target.new_to_memory()
self.mono.ppmsave_target(x)
y = pyvips.Source.new_from_memory(x.get("blob"))
im = pyvips.Image.ppmload_source(y)
assert (im - self.mono).abs().max() == 0
if __name__ == '__main__':
pytest.main()

View File

@ -327,7 +327,7 @@ class TestForeign:
assert( len_mono1 < len_mono2 )
# we can't test palette save since we can't be sure libimagequant is
# available
# available and there's no easy test for its presence
@skip_if_no("tiffload")
def test_tiff(self):