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:
parent
e8d9dbe3bb
commit
9278498623
@ -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
6
TODO
@ -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?
|
||||
|
||||
|
||||
|
@ -13,6 +13,8 @@ libforeign_la_SOURCES = \
|
||||
csv.c \
|
||||
csvload.c \
|
||||
csvsave.c \
|
||||
matrixload.c \
|
||||
matrixsave.c \
|
||||
dzsave.c \
|
||||
rawload.c \
|
||||
rawsave.c \
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -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*/
|
||||
|
@ -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();
|
||||
|
202
libvips/foreign/matrixload.c
Normal file
202
libvips/foreign/matrixload.c
Normal 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 );
|
||||
}
|
||||
|
157
libvips/foreign/matrixsave.c
Normal file
157
libvips/foreign/matrixsave.c
Normal 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 );
|
||||
}
|
@ -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));
|
||||
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user