add vips_matrixload(), vips_matrixsave()

read and write vips mat format to and from VipsImage

also fix a leak with vips_check_matrix()
This commit is contained in:
John Cupitt 2013-07-02 12:08:46 +01:00
parent e8d9dbe3bb
commit 9278498623
13 changed files with 713 additions and 137 deletions

View File

@ -1,4 +1,5 @@
1/7/13 started 7.35.0
- added vips_matrixload() and vips_matrixsave(), load and save vips mat format
28/6/13 started 7.34.1
- fix morphological operators on non-uchar images

6
TODO
View File

@ -1,4 +1,6 @@
- 3-way dilate on a float image seems to be broken
- move im_buildlut() to create package
others too? identity?
- object construction is threadsafe, but class construction is not
@ -37,8 +39,6 @@
because we step across tiles left to right: y doesn't change, only x does
- seems to leak with vips_check_matrix()?
- test with interpolators, do we add margins correctly?

View File

@ -13,6 +13,8 @@ libforeign_la_SOURCES = \
csv.c \
csvload.c \
csvsave.c \
matrixload.c \
matrixsave.c \
dzsave.c \
rawload.c \
rawsave.c \

View File

@ -25,6 +25,8 @@
* - rework as a set of fns ready for wrapping as a class
* 23/2/12
* - report positions for EOF/EOL errors
* 2/7/13
* - add array read/write
*/
/*
@ -88,7 +90,8 @@ skip_line( FILE *fp )
/* If we hit EOF and no \n, wait until the next call to report EOF.
*/
while( (ch = fgetc( fp )) != '\n' && ch != EOF )
while( (ch = fgetc( fp )) != '\n' &&
ch != EOF )
;
return( -1 );
@ -101,7 +104,9 @@ skip_white( FILE *fp, const char whitemap[256] )
do {
ch = fgetc( fp );
} while (ch != EOF && ch != '\n' && whitemap[ch] );
} while( ch != EOF &&
ch != '\n' &&
whitemap[ch] );
ungetc( ch, fp );
@ -122,7 +127,8 @@ skip_to_quote( FILE *fp )
ch = fgetc( fp );
else if( ch == '"' )
break;
} while( ch != EOF && ch != '\n' );
} while( ch != EOF &&
ch != '\n' );
ungetc( ch, fp );
@ -136,7 +142,9 @@ skip_to_sep( FILE *fp, const char sepmap[256] )
do {
ch = fgetc( fp );
} while (ch != EOF && ch != '\n' && !sepmap[ch] );
} while( ch != EOF &&
ch != '\n' &&
!sepmap[ch] );
ungetc( ch, fp );
@ -361,116 +369,6 @@ vips__csv_read_header( const char *filename, VipsImage *out,
return( 0 );
}
/* Read the header. Two numbers for width and height, and two optional
* numbers for scale and offset.
*/
static VipsImage *
vips__array_header( char *whitemap, char *sepmap, FILE *fp )
{
double header[4];
int i;
int ch;
VipsImage *out;
for( i = 0; i < 4 &&
(ch = read_double( fp, whitemap, sepmap,
1, i + 1, &header[i] )) == 0;
i++ )
;
if( i < 2 ) {
vips_error( "mask2vips", "%s", _( "no width / height" ) );
return( NULL );
}
if( floor( header[0] ) != header[0] ||
floor( header[1] ) != header[1] ) {
vips_error( "mask2vips", "%s", _( "width / height not int" ) );
return( NULL );
}
if( !(out = vips_image_new_array( header[0], header[1] )) )
return( NULL );
vips_image_set_double( out, "scale", i > 2 ? header[2] : 1.0 );
vips_image_set_double( out, "offset", i > 3 ? header[3] : 0.0 );
skip_line( fp );
return( out );
}
static int
vips__array_body( char *whitemap, char *sepmap, VipsImage *out, FILE *fp )
{
int x, y;
int ch;
for( y = 0; y < out->Ysize; y++ ) {
for( x = 0; x < out->Xsize; x++ ) {
double *d = (double *) VIPS_IMAGE_ADDR( out, x, y );
ch = read_double( fp, whitemap, sepmap,
y + 1, x + 1, d );
if( ch == EOF ) {
vips_error( "mask2vips",
_( "unexpected EOF, line %d col %d" ),
y + 1, x + 1 );
return( -1 );
}
else if( ch == '\n' ) {
vips_error( "mask2vips",
_( "unexpected EOL, line %d col %d" ),
y + 1, x + 1 );
return( -1 );
}
else if( ch )
/* Parse error.
*/
return( -1 );
}
skip_line( fp );
}
return( 0 );
}
VipsImage *
vips__array_read( const char *filename )
{
char whitemap[256];
char sepmap[256];
int i;
char *p;
FILE *fp;
VipsImage *out;
/* Make our char maps.
*/
for( i = 0; i < 256; i++ ) {
whitemap[i] = 0;
sepmap[i] = 0;
}
for( p = " \t\n"; *p; p++ )
whitemap[(int) *p] = 1;
for( p = ";,"; *p; p++ )
sepmap[(int) *p] = 1;
if( !(fp = vips__file_open_read( filename, NULL, TRUE )) )
return( NULL );
if( !(out = vips__array_header( whitemap, sepmap, fp )) ) {
fclose( fp );
return( NULL );
}
if( vips__array_body( whitemap, sepmap, out, fp ) ) {
g_object_unref( out );
fclose( fp );
return( NULL );
}
fclose( fp );
return( out );
}
const char *vips__foreign_csv_suffs[] = { ".csv", NULL };
#define PRINT_INT( TYPE ) fprintf( fp, "%d", *((TYPE*)p) );
@ -549,4 +447,259 @@ vips__csv_write( VipsImage *in, const char *filename, const char *separator )
return( 0 );
}
/* Read to non-whitespace, or buffer overflow.
*/
static int
fetch_nonwhite( FILE *fp, const char whitemap[256], char *buf, int max )
{
int ch;
int i;
for( i = 0; i < max - 1; i++ ) {
ch = fgetc( fp );
if( ch == EOF || ch == '\n' || whitemap[ch] )
break;
buf[i] = ch;
}
buf[i] = '\0';
/* We mustn't skip the terminator.
*/
ungetc( ch, fp );
return( ch );
}
/* Read a single double in ascii (not locale) encoding.
*
* Return the char that caused failure on fail (EOF or \n).
*/
static int
read_ascii_double( FILE *fp, const char whitemap[256], double *out )
{
int ch;
char buf[256];
ch = skip_white( fp, whitemap );
if( ch == EOF ||
ch == '\n' )
return( ch );
fetch_nonwhite( fp, whitemap, buf, 256 );
*out = g_ascii_strtod( buf, NULL );
return( 0 );
}
/* Read the header. Two numbers for width and height, and two optional
* numbers for scale and offset.
*/
static int
vips__array_header( char *whitemap, FILE *fp,
int *width, int *height, double *scale, double *offset )
{
double header[4];
double d;
int i;
int ch;
for( i = 0; i < 4 &&
(ch = read_ascii_double( fp, whitemap, &header[i] )) == 0;
i++ )
;
if( i < 2 ) {
vips_error( "mask2vips", "%s", _( "no width / height" ) );
return( -1 );
}
if( floor( header[0] ) != header[0] ||
floor( header[1] ) != header[1] ) {
vips_error( "mask2vips", "%s", _( "width / height not int" ) );
return( -1 );
}
if( i == 3 ) {
vips_error( "mask2vips", "%s", _( "bad scale / offset" ) );
return( -1 );
}
if( (ch = read_ascii_double( fp, whitemap, &d )) != '\n' ) {
vips_error( "mask2vips", "%s", _( "extra chars in header" ) );
return( -1 );
}
if( i > 2 &&
header[2] == 0.0 ) {
vips_error( "mask2vips", "%s", _( "zero scale" ) );
return( -1 );
}
*width = header[0];
*height = header[0];
*scale = i > 2 ? header[2] : 1.0;
*offset = i > 2 ? header[3] : 0.0;
skip_line( fp );
return( 0 );
}
#define WHITESPACE " \"\t\n;,"
/* Get the header from an array file.
*
* Also read the first line and make sure there are the right number of
* entries.
*/
int
vips__array_read_header( const char *filename,
int *width, int *height, double *scale, double *offset )
{
char whitemap[256];
int i;
char *p;
FILE *fp;
int ch;
double d;
for( i = 0; i < 256; i++ )
whitemap[i] = 0;
for( p = WHITESPACE; *p; p++ )
whitemap[(int) *p] = 1;
if( !(fp = vips__file_open_read( filename, NULL, TRUE )) )
return( -1 );
if( vips__array_header( whitemap, fp,
width, height, scale, offset ) ) {
fclose( fp );
return( -1 );
}
for( i = 0; i < *width; i++ ) {
ch = read_ascii_double( fp, whitemap, &d );
if( ch ) {
fclose( fp );
vips_error( "mask2vips", "%s", _( "line too short" ) );
return( -1 );
}
}
/* Deliberately don't check for line too long.
*/
fclose( fp );
return( 0 );
}
static int
vips__array_body( char *whitemap, VipsImage *out, FILE *fp )
{
int x, y;
for( y = 0; y < out->Ysize; y++ ) {
for( x = 0; x < out->Xsize; x++ ) {
int ch;
double d;
ch = read_ascii_double( fp, whitemap, &d );
if( ch == EOF ||
ch == '\n' ) {
vips_error( "mask2vips",
_( "line %d too short" ), y + 1 );
return( -1 );
}
*((double *) VIPS_IMAGE_ADDR( out, x, y )) = d;
/* Deliberately don't check for line too long.
*/
}
skip_line( fp );
}
return( 0 );
}
VipsImage *
vips__array_read( const char *filename )
{
char whitemap[256];
int i;
char *p;
FILE *fp;
int width;
int height;
double scale;
double offset;
VipsImage *out;
for( i = 0; i < 256; i++ )
whitemap[i] = 0;
for( p = WHITESPACE; *p; p++ )
whitemap[(int) *p] = 1;
if( !(fp = vips__file_open_read( filename, NULL, TRUE )) )
return( NULL );
if( vips__array_header( whitemap, fp,
&width, &height, &scale, &offset ) ) {
fclose( fp );
return( NULL );
}
if( !(out = vips_image_new_array( width, height )) )
return( NULL );
vips_image_set_double( out, "scale", scale );
vips_image_set_double( out, "offset", offset );
if( vips__array_body( whitemap, out, fp ) ) {
g_object_unref( out );
fclose( fp );
return( NULL );
}
fclose( fp );
return( out );
}
int
vips__array_write( VipsImage *in, const char *filename )
{
VipsImage *mask;
FILE *fp;
int x, y;
if( vips_check_matrix( "vips2mask", in, &mask ) )
return( -1 );
if( !(fp = vips__file_open_write( filename, TRUE )) ) {
g_object_unref( mask );
return( -1 );
}
fprintf( fp, "%d %d ", mask->Xsize, mask->Ysize );
if( vips_image_get_typeof( mask, "scale" ) &&
vips_image_get_typeof( mask, "offset" ) )
fprintf( fp, "%g %g ",
vips_image_get_scale( mask ),
vips_image_get_offset( mask ) );
fprintf( fp, "\n" );
for( y = 0; y < mask->Ysize; y++ ) {
for( x = 0; x < mask->Xsize; x++ )
fprintf( fp, "%g ",
*((double *) VIPS_IMAGE_ADDR( mask, x, y )) );
fprintf( fp, "\n" );
}
g_object_unref( mask );
fclose( fp );
return( 0 );
}
const char *vips__foreign_matrix_suffs[] = { ".mat", NULL };

View File

@ -45,6 +45,13 @@ int vips__csv_read_header( const char *filename, VipsImage *out,
int vips__csv_write( VipsImage *in, const char *filename,
const char *separator );
int vips__array_read_header( const char *filename,
int *width, int *height, double *scale, double *offset );
VipsImage *vips__array_read( const char *filename );
int vips__array_write( VipsImage *in, const char *filename );
extern const char *vips__foreign_matrix_suffs[];
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -1588,6 +1588,8 @@ vips_foreign_operation_init( void )
extern GType vips_foreign_save_png_buffer_get_type( void );
extern GType vips_foreign_load_csv_get_type( void );
extern GType vips_foreign_save_csv_get_type( void );
extern GType vips_foreign_load_matrix_get_type( void );
extern GType vips_foreign_save_matrix_get_type( void );
extern GType vips_foreign_load_fits_get_type( void );
extern GType vips_foreign_save_fits_get_type( void );
extern GType vips_foreign_load_analyze_get_type( void );
@ -1614,6 +1616,8 @@ vips_foreign_operation_init( void )
vips_foreign_save_ppm_get_type();
vips_foreign_load_csv_get_type();
vips_foreign_save_csv_get_type();
vips_foreign_load_matrix_get_type();
vips_foreign_save_matrix_get_type();
vips_foreign_load_analyze_get_type();
vips_foreign_load_raw_get_type();
vips_foreign_save_raw_get_type();

View File

@ -0,0 +1,202 @@
/* load matrix from a file
*
* 5/12/11
* - from csvload.c
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
#define DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>
#include <vips/buf.h>
#include <vips/internal.h>
#include "csv.h"
typedef struct _VipsForeignLoadMatrix {
VipsForeignLoad parent_object;
/* Filename for load.
*/
char *filename;
} VipsForeignLoadMatrix;
typedef VipsForeignLoadClass VipsForeignLoadMatrixClass;
G_DEFINE_TYPE( VipsForeignLoadMatrix, vips_foreign_load_matrix,
VIPS_TYPE_FOREIGN_LOAD );
static VipsForeignFlags
vips_foreign_load_matrix_get_flags_filename( const char *filename )
{
return( 0 );
}
static VipsForeignFlags
vips_foreign_load_matrix_get_flags( VipsForeignLoad *load )
{
VipsForeignLoadMatrix *matrix = (VipsForeignLoadMatrix *) load;
return( vips_foreign_load_matrix_get_flags_filename( matrix->filename ) );
}
static int
vips_foreign_load_matrix_header( VipsForeignLoad *load )
{
VipsForeignLoadMatrix *matrix = (VipsForeignLoadMatrix *) load;
int width;
int height;
double scale;
double offset;
if( vips__array_read_header( matrix->filename,
&width, &height, &scale, &offset ) )
return( -1 );
vips_image_init_fields( load->out,
width, height, 1,
VIPS_FORMAT_DOUBLE,
VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, 1.0, 1.0 );
vips_image_set_double( load->out, "scale", scale );
vips_image_set_double( load->out, "offset", offset );
return( 0 );
}
static int
vips_foreign_load_matrix_load( VipsForeignLoad *load )
{
VipsForeignLoadMatrix *matrix = (VipsForeignLoadMatrix *) load;
VipsImage *out;
if( !(out = vips__array_read( matrix->filename )) )
return( -1 );
if( vips_image_write( out, load->real ) ) {
g_object_unref( out );
return( -1 );
}
g_object_unref( out );
return( 0 );
}
static void
vips_foreign_load_matrix_class_init( VipsForeignLoadMatrixClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) 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 = "matrixload";
object_class->description = _( "load matrix from file" );
foreign_class->suffs = vips__foreign_matrix_suffs;
load_class->get_flags_filename =
vips_foreign_load_matrix_get_flags_filename;
load_class->get_flags = vips_foreign_load_matrix_get_flags;
load_class->header = vips_foreign_load_matrix_header;
load_class->load = vips_foreign_load_matrix_load;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadMatrix, filename ),
NULL );
}
static void
vips_foreign_load_matrix_init( VipsForeignLoadMatrix *matrix )
{
}
/**
* vips_matrixload:
* @filename: file to load
* @out: output image
* @...: %NULL-terminated list of optional named arguments
*
* Reads a matrix from a file.
*
* Matrix files have a simple format that's supposed to be easy to create with
* a text editor or a spreadsheet.
*
* The first line has four numbers for width, height, scale and
* offset (scale and offset may be omitted, in which case they default to 1.0
* and 0.0). Scale must be non-zero. Width and height must be positive
* integers. The numbers are separated by any mixture of spaces, commas,
* tabs and quotation marks ("). The scale and offset fields may be
* floating-point, and must use '.'
* as a decimal separator.
*
* Subsequent lines each hold one line of matrix data, with numbers again
* separated by any mixture of spaces, commas,
* tabs and quotation marks ("). The numbers may be floating-point, and must
* use '.'
* as a decimal separator.
*
* Extra characters at the ends of lines or at the end of the file are
* ignored.
*
* See also: vips_csvload().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_matrixload( const char *filename, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "matrixload", ap, filename, out );
va_end( ap );
return( result );
}

View File

@ -0,0 +1,157 @@
/* save to matrix
*
* 2/7/13
* - wrap a class around the matrix writer
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
#define DEBUG_VERBOSE
#define DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>
#include "csv.h"
typedef struct _VipsForeignSaveMatrix {
VipsForeignSave parent_object;
/* Filename for save.
*/
char *filename;
} VipsForeignSaveMatrix;
typedef VipsForeignSaveClass VipsForeignSaveMatrixClass;
G_DEFINE_TYPE( VipsForeignSaveMatrix, vips_foreign_save_matrix,
VIPS_TYPE_FOREIGN_SAVE );
static int
vips_foreign_save_matrix_build( VipsObject *object )
{
VipsForeignSave *save = (VipsForeignSave *) object;
VipsForeignSaveMatrix *matrix = (VipsForeignSaveMatrix *) object;
if( VIPS_OBJECT_CLASS( vips_foreign_save_matrix_parent_class )->
build( object ) )
return( -1 );
if( vips__array_write( save->ready, matrix->filename ) )
return( -1 );
return( 0 );
}
/* Save a bit of typing.
*/
#define UC VIPS_FORMAT_UCHAR
#define C VIPS_FORMAT_CHAR
#define US VIPS_FORMAT_USHORT
#define S VIPS_FORMAT_SHORT
#define UI VIPS_FORMAT_UINT
#define I VIPS_FORMAT_INT
#define F VIPS_FORMAT_FLOAT
#define X VIPS_FORMAT_COMPLEX
#define D VIPS_FORMAT_DOUBLE
#define DX VIPS_FORMAT_DPCOMPLEX
static int bandfmt_matrix[10] = {
/* UC C US S UI I F X D DX */
D, D, D, D, D, D, D, D, D, D
};
static void
vips_foreign_save_matrix_class_init( VipsForeignSaveMatrixClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "matrixsave";
object_class->description = _( "save image to matrix file" );
object_class->build = vips_foreign_save_matrix_build;
foreign_class->suffs = vips__foreign_matrix_suffs;
save_class->saveable = VIPS_SAVEABLE_MONO;
save_class->format_table = bandfmt_matrix;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to save to" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveMatrix, filename ),
NULL );
}
static void
vips_foreign_save_matrix_init( VipsForeignSaveMatrix *matrix )
{
}
/**
* vips_matrixsave:
* @in: image to save
* @filename: file to write to
* @...: %NULL-terminated list of optional named arguments
*
* Write @in to @filename in matrix format. See vips_matrixload() for a
* description of the format.
*
* See also: vips_matrixload().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_matrixsave( VipsImage *in, const char *filename, ... )
{
va_list ap;
int result;
va_start( ap, filename );
result = vips_call_split( "matrixsave", ap, in, filename );
va_end( ap );
return( result );
}

View File

@ -402,6 +402,11 @@ int vips_csvload( const char *filename, VipsImage **out, ... )
int vips_csvsave( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));
int vips_matrixload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));
int vips_matrixsave( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));
int vips_magickload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));

View File

@ -108,6 +108,8 @@ int vips_image_get_xoffset( const VipsImage *image );
int vips_image_get_yoffset( const VipsImage *image );
const char *vips_image_get_filename( const VipsImage *image );
const char *vips_image_get_mode( const VipsImage *image );
double vips_image_get_scale( const VipsImage *array );
double vips_image_get_offset( const VipsImage *array );
void *vips_image_get_data( VipsImage *image );
void vips_image_init_fields( VipsImage *image,
@ -122,9 +124,11 @@ int vips_image_copy_fieldsv( VipsImage *out, VipsImage *in1, ... )
int vips_image_copy_fields( VipsImage *out, VipsImage *in );
void vips_image_set( VipsImage *image, const char *field, GValue *value );
int vips_image_get( VipsImage *image, const char *field, GValue *value_copy );
int vips_image_get_as_string( VipsImage *image, const char *field, char **out );
GType vips_image_get_typeof( VipsImage *image, const char *field );
int vips_image_get( const VipsImage *image,
const char *field, GValue *value_copy );
int vips_image_get_as_string( const VipsImage *image,
const char *field, char **out );
GType vips_image_get_typeof( const VipsImage *image, const char *field );
gboolean vips_image_remove( VipsImage *image, const char *field );
typedef void *(*VipsImageMapFn)( VipsImage *image,
const char *field, GValue *value, void *a );
@ -132,17 +136,20 @@ void *vips_image_map( VipsImage *image, VipsImageMapFn fn, void *a );
void vips_image_set_area( VipsImage *image,
const char *field, VipsCallbackFn free_fn, void *data );
int vips_image_get_area( VipsImage *image, const char *field, void **data );
int vips_image_get_area( const VipsImage *image,
const char *field, void **data );
void vips_image_set_blob( VipsImage *image, const char *field,
VipsCallbackFn free_fn, void *data, size_t length );
int vips_image_get_blob( VipsImage *image, const char *field,
int vips_image_get_blob( const VipsImage *image, const char *field,
void **data, size_t *length );
int vips_image_get_int( VipsImage *image, const char *field, int *out );
int vips_image_get_int( const VipsImage *image, const char *field, int *out );
void vips_image_set_int( VipsImage *image, const char *field, int i );
int vips_image_get_double( VipsImage *image, const char *field, double *out );
int vips_image_get_double( const VipsImage *image,
const char *field, double *out );
void vips_image_set_double( VipsImage *image, const char *field, double d );
int vips_image_get_string( VipsImage *image, const char *field, char **out );
int vips_image_get_string( const VipsImage *image,
const char *field, char **out );
void vips_image_set_string( VipsImage *image,
const char *field, const char *str );

View File

@ -1173,8 +1173,9 @@ vips_check_hist( const char *domain, VipsImage *im )
* message otherwise.
*
* @out is set to be @im cast to double and stored in memory. Use
* VIPS_IMAGE_ADDR() to address values in @out. @out is unreffed for you
* when @im is unreffed.
* VIPS_IMAGE_ADDR() to address values in @out.
*
* You must unref @out when you are done with it.
*
* See also: vips_error().
*
@ -1183,6 +1184,8 @@ vips_check_hist( const char *domain, VipsImage *im )
int
vips_check_matrix( const char *domain, VipsImage *im, VipsImage **out )
{
*out = NULL;
if( im->Xsize > 1000 || im->Ysize > 1000 ) {
vips_error( domain, "%s", _( "matrix image too large" ) );
return( -1 );
@ -1195,7 +1198,6 @@ vips_check_matrix( const char *domain, VipsImage *im, VipsImage **out )
if( vips_cast( im, out, VIPS_FORMAT_DOUBLE, NULL ) )
return( -1 );
vips_object_local( im, *out );
if( vips_image_wio_input( *out ) )
return( -1 );

View File

@ -546,6 +546,30 @@ vips_image_get_mode( const VipsImage *image )
return( image->mode );
}
double
vips_image_get_scale( const VipsImage *array )
{
double scale;
scale = 1.0;
if( vips_image_get_typeof( array, "scale" ) )
vips_image_get_double( array, "scale", &scale );
return( scale );
}
double
vips_image_get_offset( const VipsImage *array )
{
double offset;
offset = 0.0;
if( vips_image_get_typeof( array, "offset" ) )
vips_image_get_double( array, "offset", &offset );
return( offset );
}
/**
* vips_image_get_data: (skip)
* @image: image to get data for
@ -857,7 +881,7 @@ vips_image_set( VipsImage *image, const char *field, GValue *value )
* Returns: 0 on success, -1 otherwise.
*/
int
vips_image_get( VipsImage *image, const char *field, GValue *value_copy )
vips_image_get( const VipsImage *image, const char *field, GValue *value_copy )
{
int i;
VipsMeta *meta;
@ -937,7 +961,7 @@ vips_image_get( VipsImage *image, const char *field, GValue *value_copy )
* field of that name.
*/
GType
vips_image_get_typeof( VipsImage *image, const char *field )
vips_image_get_typeof( const VipsImage *image, const char *field )
{
int i;
VipsMeta *meta;
@ -1079,7 +1103,7 @@ vips_image_set_area( VipsImage *image, const char *field,
}
static int
meta_get_value( VipsImage *image,
meta_get_value( const VipsImage *image,
const char *field, GType type, GValue *value_copy )
{
if( vips_image_get( image, field, value_copy ) )
@ -1114,7 +1138,7 @@ meta_get_value( VipsImage *image,
* Returns: 0 on success, -1 otherwise.
*/
int
vips_image_get_area( VipsImage *image, const char *field, void **data )
vips_image_get_area( const VipsImage *image, const char *field, void **data )
{
GValue value_copy = { 0 };
@ -1171,7 +1195,7 @@ vips_image_set_blob( VipsImage *image, const char *field,
* Returns: 0 on success, -1 otherwise.
*/
int
vips_image_get_blob( VipsImage *image, const char *field,
vips_image_get_blob( const VipsImage *image, const char *field,
void **data, size_t *length )
{
GValue value_copy = { 0 };
@ -1199,7 +1223,7 @@ vips_image_get_blob( VipsImage *image, const char *field,
* Returns: 0 on success, -1 otherwise.
*/
int
vips_image_get_int( VipsImage *image, const char *field, int *out )
vips_image_get_int( const VipsImage *image, const char *field, int *out )
{
int i;
GValue value_copy = { 0 };
@ -1265,7 +1289,7 @@ vips_image_set_int( VipsImage *image, const char *field, int i )
* Returns: 0 on success, -1 otherwise.
*/
int
vips_image_get_double( VipsImage *image, const char *field, double *out )
vips_image_get_double( const VipsImage *image, const char *field, double *out )
{
int i;
GValue value_copy = { 0 };
@ -1333,7 +1357,7 @@ vips_image_set_double( VipsImage *image, const char *field, double d )
* Returns: 0 on success, -1 otherwise.
*/
int
vips_image_get_string( VipsImage *image, const char *field, char **out )
vips_image_get_string( const VipsImage *image, const char *field, char **out )
{
int i;
GValue value_copy = { 0 };
@ -1396,7 +1420,8 @@ vips_image_set_string( VipsImage *image, const char *field, const char *str )
* Returns: 0 on success, -1 otherwise.
*/
int
vips_image_get_as_string( VipsImage *image, const char *field, char **out )
vips_image_get_as_string( const VipsImage *image,
const char *field, char **out )
{
GValue value = { 0 };
GType type;

View File

@ -104,6 +104,16 @@ typedef VipsResampleClass VipsQuadraticClass;
G_DEFINE_TYPE( VipsQuadratic, vips_quadratic, VIPS_TYPE_RESAMPLE );
static void
vips_quadratic_dispose( GObject *gobject )
{
VipsQuadratic *quadratic = (VipsQuadratic *) gobject;
VIPS_UNREF( quadratic->mat );
G_OBJECT_CLASS( vips_quadratic_parent_class )->dispose( gobject );
}
static int
vips_quadratic_gen( VipsRegion *or, void *vseq,
void *a, void *b, gboolean *stop )
@ -327,6 +337,7 @@ vips_quadratic_class_init( VipsQuadraticClass *class )
VIPS_DEBUG_MSG( "vips_quadratic_class_init\n" );
gobject_class->dispose = vips_quadratic_dispose;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;