move csvsave to the new target API
This commit is contained in:
parent
726895b3d1
commit
fe47ce12e9
@ -61,6 +61,8 @@ im_csv2vips( const char *filename, IMAGE *out )
|
|||||||
char mode[FILENAME_MAX];
|
char mode[FILENAME_MAX];
|
||||||
char *p, *q, *r;
|
char *p, *q, *r;
|
||||||
|
|
||||||
|
VipsImage *x;
|
||||||
|
|
||||||
/* Parse mode string.
|
/* Parse mode string.
|
||||||
*/
|
*/
|
||||||
im_filename_split( filename, name, mode );
|
im_filename_split( filename, name, mode );
|
||||||
@ -76,9 +78,18 @@ im_csv2vips( const char *filename, IMAGE *out )
|
|||||||
lines = atoi( r );
|
lines = atoi( r );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( vips__csv_read( name, out,
|
if( vips_csvload( name, &x,
|
||||||
start_skip, lines, whitespace, separator, FALSE ) )
|
"skip", start_skip,
|
||||||
|
"lines", lines,
|
||||||
|
"whitespace", whitespace,
|
||||||
|
"separator", separator,
|
||||||
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
if( vips_image_write( x, out ) ) {
|
||||||
|
g_object_unref( x );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
g_object_unref( x );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
@ -118,352 +118,6 @@ skip_white( FILE *fp, const char whitemap[256] )
|
|||||||
return( ch );
|
return( ch );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
skip_to_quote( FILE *fp )
|
|
||||||
{
|
|
||||||
int ch;
|
|
||||||
|
|
||||||
do {
|
|
||||||
ch = vips__fgetc( fp );
|
|
||||||
|
|
||||||
/* Ignore \" in strings.
|
|
||||||
*/
|
|
||||||
if( ch == '\\' )
|
|
||||||
ch = vips__fgetc( fp );
|
|
||||||
else if( ch == '"' )
|
|
||||||
break;
|
|
||||||
} while( ch != EOF &&
|
|
||||||
ch != '\n' );
|
|
||||||
|
|
||||||
ungetc( ch, fp );
|
|
||||||
|
|
||||||
return( ch );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
skip_to_sep( FILE *fp, const char sepmap[256] )
|
|
||||||
{
|
|
||||||
int ch;
|
|
||||||
|
|
||||||
do {
|
|
||||||
ch = vips__fgetc( fp );
|
|
||||||
} while( ch != EOF &&
|
|
||||||
ch != '\n' &&
|
|
||||||
!sepmap[ch] );
|
|
||||||
|
|
||||||
ungetc( ch, fp );
|
|
||||||
|
|
||||||
return( ch );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read a single item. Syntax is:
|
|
||||||
*
|
|
||||||
* element :
|
|
||||||
* whitespace* item whitespace* [EOF|EOL|separator]
|
|
||||||
*
|
|
||||||
* item :
|
|
||||||
* double |
|
|
||||||
* "anything" |
|
|
||||||
* empty
|
|
||||||
*
|
|
||||||
* the anything in quotes can contain " escaped with \
|
|
||||||
*
|
|
||||||
* Return the char that caused failure on fail (EOF or \n).
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
read_double( FILE *fp, const char whitemap[256], const char sepmap[256],
|
|
||||||
int lineno, int colno, double *out, gboolean fail )
|
|
||||||
{
|
|
||||||
int ch;
|
|
||||||
|
|
||||||
/* The fscanf() may change this ... but all other cases need a zero.
|
|
||||||
*/
|
|
||||||
*out = 0;
|
|
||||||
|
|
||||||
ch = skip_white( fp, whitemap );
|
|
||||||
if( ch == EOF ||
|
|
||||||
ch == '\n' )
|
|
||||||
return( ch );
|
|
||||||
|
|
||||||
if( ch == '"' ) {
|
|
||||||
(void) vips__fgetc( fp );
|
|
||||||
(void) skip_to_quote( fp );
|
|
||||||
(void) vips__fgetc( fp );
|
|
||||||
}
|
|
||||||
else if( !sepmap[ch] &&
|
|
||||||
fscanf( fp, "%lf", out ) != 1 ) {
|
|
||||||
/* Only a warning, since (for example) exported spreadsheets
|
|
||||||
* will often have text or date fields.
|
|
||||||
*/
|
|
||||||
g_warning( _( "error parsing number, line %d, column %d" ),
|
|
||||||
lineno, colno );
|
|
||||||
if( fail )
|
|
||||||
return( EOF );
|
|
||||||
|
|
||||||
/* Step over the bad data to the next separator.
|
|
||||||
*/
|
|
||||||
(void) skip_to_sep( fp, sepmap );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't need to check result, we have read a field successfully.
|
|
||||||
*/
|
|
||||||
ch = skip_white( fp, whitemap );
|
|
||||||
|
|
||||||
/* If it's a separator, we have to step over it.
|
|
||||||
*/
|
|
||||||
if( ch != EOF &&
|
|
||||||
sepmap[ch] )
|
|
||||||
(void) vips__fgetc( fp );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
read_csv( FILE *fp, VipsImage *out,
|
|
||||||
int skip,
|
|
||||||
int lines,
|
|
||||||
const char *whitespace, const char *separator,
|
|
||||||
gboolean read_image,
|
|
||||||
gboolean fail )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char whitemap[256];
|
|
||||||
char sepmap[256];
|
|
||||||
const char *p;
|
|
||||||
fpos_t pos;
|
|
||||||
int columns;
|
|
||||||
int ch;
|
|
||||||
double d;
|
|
||||||
double *buf;
|
|
||||||
int y;
|
|
||||||
|
|
||||||
/* Make our char maps.
|
|
||||||
*/
|
|
||||||
for( i = 0; i < 256; i++ ) {
|
|
||||||
whitemap[i] = 0;
|
|
||||||
sepmap[i] = 0;
|
|
||||||
}
|
|
||||||
for( p = whitespace; *p; p++ )
|
|
||||||
whitemap[(int) *p] = 1;
|
|
||||||
for( p = separator; *p; p++ )
|
|
||||||
sepmap[(int) *p] = 1;
|
|
||||||
|
|
||||||
/* Skip first few lines.
|
|
||||||
*/
|
|
||||||
for( i = 0; i < skip; i++ )
|
|
||||||
if( !skip_line( fp ) ) {
|
|
||||||
vips_error( "csv2vips",
|
|
||||||
"%s", _( "end of file while skipping start" ) );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse the first line to get number of columns. Only bother checking
|
|
||||||
* fgetpos() the first time we use it: assume it's working after this.
|
|
||||||
*/
|
|
||||||
if( fgetpos( fp, &pos ) ) {
|
|
||||||
vips_error_system( errno, "csv2vips",
|
|
||||||
"%s", _( "unable to seek" ) );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
for( columns = 0;
|
|
||||||
(ch = read_double( fp, whitemap, sepmap,
|
|
||||||
skip + 1, columns + 1, &d, fail )) == 0;
|
|
||||||
columns++ )
|
|
||||||
;
|
|
||||||
(void) fsetpos( fp, &pos );
|
|
||||||
|
|
||||||
if( columns == 0 ) {
|
|
||||||
vips_error( "csv2vips", "%s", _( "empty line" ) );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If lines is -1, we have to scan the whole file to get the
|
|
||||||
* number of lines out.
|
|
||||||
*/
|
|
||||||
if( lines == -1 ) {
|
|
||||||
(void) fgetpos( fp, &pos );
|
|
||||||
for( lines = 0; skip_line( fp ); lines++ )
|
|
||||||
;
|
|
||||||
(void) fsetpos( fp, &pos );
|
|
||||||
}
|
|
||||||
|
|
||||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
|
||||||
vips_image_init_fields( out,
|
|
||||||
columns, lines, 1,
|
|
||||||
VIPS_FORMAT_DOUBLE,
|
|
||||||
VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, 1.0, 1.0 );
|
|
||||||
|
|
||||||
/* Just reading the header? We are done.
|
|
||||||
*/
|
|
||||||
if( !read_image )
|
|
||||||
return( 0 );
|
|
||||||
|
|
||||||
if( !(buf = VIPS_ARRAY( out,
|
|
||||||
VIPS_IMAGE_N_ELEMENTS( out ), double )) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
for( y = 0; y < lines; y++ ) {
|
|
||||||
int x;
|
|
||||||
|
|
||||||
for( x = 0; x < columns; x++ ) {
|
|
||||||
int lineno = y + skip + 1;
|
|
||||||
int colno = x + 1;
|
|
||||||
|
|
||||||
ch = read_double( fp, whitemap, sepmap,
|
|
||||||
lineno, colno, &d, fail );
|
|
||||||
if( ch == EOF ) {
|
|
||||||
vips_error( "csv2vips",
|
|
||||||
_( "unexpected EOF, line %d col %d" ),
|
|
||||||
lineno, colno );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
else if( ch == '\n' ) {
|
|
||||||
vips_error( "csv2vips",
|
|
||||||
_( "unexpected EOL, line %d col %d" ),
|
|
||||||
lineno, colno );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
else if( ch )
|
|
||||||
/* Parse error.
|
|
||||||
*/
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
buf[x] = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( vips_image_write_line( out, y, (VipsPel *) buf ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
/* Skip over the '\n' to the next line.
|
|
||||||
*/
|
|
||||||
skip_line( fp );
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
vips__csv_read( const char *filename, VipsImage *out,
|
|
||||||
int skip, int lines, const char *whitespace, const char *separator,
|
|
||||||
gboolean fail )
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
if( !(fp = vips__file_open_read( filename, NULL, TRUE )) )
|
|
||||||
return( -1 );
|
|
||||||
if( read_csv( fp, out,
|
|
||||||
skip, lines, whitespace, separator, TRUE, fail ) ) {
|
|
||||||
fclose( fp );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
fclose( fp );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
vips__csv_read_header( const char *filename, VipsImage *out,
|
|
||||||
int skip, int lines, const char *whitespace, const char *separator,
|
|
||||||
gboolean fail )
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
if( !(fp = vips__file_open_read( filename, NULL, TRUE )) )
|
|
||||||
return( -1 );
|
|
||||||
if( read_csv( fp, out,
|
|
||||||
skip, lines, whitespace, separator, FALSE, fail ) ) {
|
|
||||||
fclose( fp );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
fclose( fp );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *vips__foreign_csv_suffs[] = { ".csv", NULL };
|
|
||||||
|
|
||||||
#define PRINT_INT( TYPE ) fprintf( fp, "%d", *((TYPE*)p) );
|
|
||||||
#define PRINT_FLOAT( TYPE ) fprintf( fp, "%g", *((TYPE*)p) );
|
|
||||||
#define PRINT_COMPLEX( TYPE ) fprintf( fp, "(%g, %g)", \
|
|
||||||
((TYPE*)p)[0], ((TYPE*)p)[1] );
|
|
||||||
|
|
||||||
static int
|
|
||||||
vips2csv( VipsImage *in, FILE *fp, const char *sep )
|
|
||||||
{
|
|
||||||
int w = VIPS_IMAGE_N_ELEMENTS( in );
|
|
||||||
int es = VIPS_IMAGE_SIZEOF_ELEMENT( in );
|
|
||||||
|
|
||||||
int x, y;
|
|
||||||
VipsPel *p;
|
|
||||||
|
|
||||||
p = in->data;
|
|
||||||
for( y = 0; y < in->Ysize; y++ ) {
|
|
||||||
for( x = 0; x < w; x++ ) {
|
|
||||||
if( x > 0 )
|
|
||||||
fprintf( fp, "%s", sep );
|
|
||||||
|
|
||||||
switch( in->BandFmt ) {
|
|
||||||
case VIPS_FORMAT_UCHAR:
|
|
||||||
PRINT_INT( unsigned char ); break;
|
|
||||||
case VIPS_FORMAT_CHAR:
|
|
||||||
PRINT_INT( char ); break;
|
|
||||||
case VIPS_FORMAT_USHORT:
|
|
||||||
PRINT_INT( unsigned short ); break;
|
|
||||||
case VIPS_FORMAT_SHORT:
|
|
||||||
PRINT_INT( short ); break;
|
|
||||||
case VIPS_FORMAT_UINT:
|
|
||||||
PRINT_INT( unsigned int ); break;
|
|
||||||
case VIPS_FORMAT_INT:
|
|
||||||
PRINT_INT( int ); break;
|
|
||||||
case VIPS_FORMAT_FLOAT:
|
|
||||||
PRINT_FLOAT( float ); break;
|
|
||||||
case VIPS_FORMAT_DOUBLE:
|
|
||||||
PRINT_FLOAT( double ); break;
|
|
||||||
case VIPS_FORMAT_COMPLEX:
|
|
||||||
PRINT_COMPLEX( float ); break;
|
|
||||||
case VIPS_FORMAT_DPCOMPLEX:
|
|
||||||
PRINT_COMPLEX( double ); break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
p += es;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf( fp, "\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
vips__csv_write( VipsImage *in, const char *filename, const char *separator )
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
VipsImage *memory;
|
|
||||||
|
|
||||||
if( vips_check_mono( "vips2csv", in ) ||
|
|
||||||
vips_check_uncoded( "vips2csv", in ) ||
|
|
||||||
!(memory = vips_image_copy_memory( in )) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
if( !(fp = vips__file_open_write( filename, TRUE )) ) {
|
|
||||||
VIPS_UNREF( memory );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( vips2csv( memory, fp, separator ) ) {
|
|
||||||
fclose( fp );
|
|
||||||
VIPS_UNREF( memory );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
fclose( fp );
|
|
||||||
VIPS_UNREF( memory );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read to non-whitespace, or buffer overflow.
|
/* Read to non-whitespace, or buffer overflow.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
*
|
*
|
||||||
* 2/12/11
|
* 2/12/11
|
||||||
* - wrap a class around the csv writer
|
* - wrap a class around the csv writer
|
||||||
|
* 21/2/20
|
||||||
|
* - rewrite for the VipsTarget API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -52,9 +54,7 @@
|
|||||||
typedef struct _VipsForeignSaveCsv {
|
typedef struct _VipsForeignSaveCsv {
|
||||||
VipsForeignSave parent_object;
|
VipsForeignSave parent_object;
|
||||||
|
|
||||||
/* Filename for save.
|
VipsTarget *target;
|
||||||
*/
|
|
||||||
char *filename;
|
|
||||||
|
|
||||||
const char *separator;
|
const char *separator;
|
||||||
} VipsForeignSaveCsv;
|
} VipsForeignSaveCsv;
|
||||||
@ -64,17 +64,119 @@ typedef VipsForeignSaveClass VipsForeignSaveCsvClass;
|
|||||||
G_DEFINE_TYPE( VipsForeignSaveCsv, vips_foreign_save_csv,
|
G_DEFINE_TYPE( VipsForeignSaveCsv, vips_foreign_save_csv,
|
||||||
VIPS_TYPE_FOREIGN_SAVE );
|
VIPS_TYPE_FOREIGN_SAVE );
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_csv_dispose( GObject *gobject )
|
||||||
|
{
|
||||||
|
VipsForeignSaveCsv *csv = (VipsForeignSaveCsv *) gobject;
|
||||||
|
|
||||||
|
if( csv->target )
|
||||||
|
vips_target_finish( csv->target );
|
||||||
|
VIPS_UNREF( csv->target );
|
||||||
|
|
||||||
|
G_OBJECT_CLASS( vips_foreign_save_csv_parent_class )->
|
||||||
|
dispose( gobject );
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRINT_INT( TYPE ) { \
|
||||||
|
TYPE *pt = (TYPE *) p; \
|
||||||
|
\
|
||||||
|
for( x = 0; x < image->Xsize; x++ ) { \
|
||||||
|
if( x > 0 ) \
|
||||||
|
vips_target_writes( csv->target, csv->separator ); \
|
||||||
|
vips_target_writef( csv->target, "%d", pt[x] ); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRINT_FLOAT( TYPE ) { \
|
||||||
|
TYPE *pt = (TYPE *) p; \
|
||||||
|
char buf[G_ASCII_DTOSTR_BUF_SIZE]; \
|
||||||
|
\
|
||||||
|
for( x = 0; x < image->Xsize; x++ ) { \
|
||||||
|
if( x > 0 ) \
|
||||||
|
vips_target_writes( csv->target, csv->separator ); \
|
||||||
|
g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE, pt[x] ); \
|
||||||
|
vips_target_writes( csv->target, buf ); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRINT_COMPLEX( TYPE ) { \
|
||||||
|
TYPE *pt = (TYPE *) p; \
|
||||||
|
char buf[G_ASCII_DTOSTR_BUF_SIZE]; \
|
||||||
|
\
|
||||||
|
for( x = 0; x < image->Xsize; x++ ) { \
|
||||||
|
if( x > 0 ) \
|
||||||
|
vips_target_writes( csv->target, csv->separator ); \
|
||||||
|
VIPS_TARGET_PUTC( csv->target, '(' ); \
|
||||||
|
g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE, pt[0] ); \
|
||||||
|
vips_target_writes( csv->target, buf ); \
|
||||||
|
VIPS_TARGET_PUTC( csv->target, ',' ); \
|
||||||
|
g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE, pt[1] ); \
|
||||||
|
vips_target_writes( csv->target, buf ); \
|
||||||
|
VIPS_TARGET_PUTC( csv->target, ')' ); \
|
||||||
|
pt += 2; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_csv_block( VipsRegion *region, VipsRect *area, void *a )
|
||||||
|
{
|
||||||
|
VipsForeignSaveCsv *csv = (VipsForeignSaveCsv *) a;
|
||||||
|
VipsImage *image = region->im;
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
for( y = 0; y < area->height; y++ ) {
|
||||||
|
VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + y );
|
||||||
|
|
||||||
|
switch( image->BandFmt ) {
|
||||||
|
case VIPS_FORMAT_UCHAR:
|
||||||
|
PRINT_INT( unsigned char ); break;
|
||||||
|
case VIPS_FORMAT_CHAR:
|
||||||
|
PRINT_INT( char ); break;
|
||||||
|
case VIPS_FORMAT_USHORT:
|
||||||
|
PRINT_INT( unsigned short ); break;
|
||||||
|
case VIPS_FORMAT_SHORT:
|
||||||
|
PRINT_INT( short ); break;
|
||||||
|
case VIPS_FORMAT_UINT:
|
||||||
|
PRINT_INT( unsigned int ); break;
|
||||||
|
case VIPS_FORMAT_INT:
|
||||||
|
PRINT_INT( int ); break;
|
||||||
|
case VIPS_FORMAT_FLOAT:
|
||||||
|
PRINT_FLOAT( float ); break;
|
||||||
|
case VIPS_FORMAT_DOUBLE:
|
||||||
|
PRINT_FLOAT( double ); break;
|
||||||
|
case VIPS_FORMAT_COMPLEX:
|
||||||
|
PRINT_COMPLEX( float ); break;
|
||||||
|
case VIPS_FORMAT_DPCOMPLEX:
|
||||||
|
PRINT_COMPLEX( double ); break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( vips_target_writes( csv->target, "\n" ) )
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_foreign_save_csv_build( VipsObject *object )
|
vips_foreign_save_csv_build( VipsObject *object )
|
||||||
{
|
{
|
||||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||||
VipsForeignSaveCsv *csv = (VipsForeignSaveCsv *) object;
|
VipsForeignSaveCsv *csv = (VipsForeignSaveCsv *) object;
|
||||||
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_csv_parent_class )->
|
if( VIPS_OBJECT_CLASS( vips_foreign_save_csv_parent_class )->
|
||||||
build( object ) )
|
build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips__csv_write( save->ready, csv->filename, csv->separator ) )
|
if( vips_check_mono( class->nickname, save->ready ) ||
|
||||||
|
vips_check_uncoded( class->nickname, save->ready ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
if( vips_sink_disc( save->ready, vips_foreign_save_csv_block, csv ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -85,27 +187,18 @@ vips_foreign_save_csv_class_init( VipsForeignSaveCsvClass *class )
|
|||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
|
||||||
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
|
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
|
||||||
|
|
||||||
|
gobject_class->dispose = vips_foreign_save_csv_dispose;
|
||||||
gobject_class->set_property = vips_object_set_property;
|
gobject_class->set_property = vips_object_set_property;
|
||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "csvsave";
|
object_class->nickname = "csvsave_base";
|
||||||
object_class->description = _( "save image to csv file" );
|
object_class->description = _( "save image to csv" );
|
||||||
object_class->build = vips_foreign_save_csv_build;
|
object_class->build = vips_foreign_save_csv_build;
|
||||||
|
|
||||||
foreign_class->suffs = vips__foreign_csv_suffs;
|
|
||||||
|
|
||||||
save_class->saveable = VIPS_SAVEABLE_MONO;
|
save_class->saveable = VIPS_SAVEABLE_MONO;
|
||||||
|
|
||||||
VIPS_ARG_STRING( class, "filename", 1,
|
|
||||||
_( "Filename" ),
|
|
||||||
_( "Filename to save to" ),
|
|
||||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
|
||||||
G_STRUCT_OFFSET( VipsForeignSaveCsv, filename ),
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
VIPS_ARG_STRING( class, "separator", 13,
|
VIPS_ARG_STRING( class, "separator", 13,
|
||||||
_( "Separator" ),
|
_( "Separator" ),
|
||||||
_( "Separator characters" ),
|
_( "Separator characters" ),
|
||||||
@ -120,6 +213,117 @@ vips_foreign_save_csv_init( VipsForeignSaveCsv *csv )
|
|||||||
csv->separator = g_strdup( "\t" );
|
csv->separator = g_strdup( "\t" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _VipsForeignSaveCsvFile {
|
||||||
|
VipsForeignSaveCsv parent_object;
|
||||||
|
|
||||||
|
char *filename;
|
||||||
|
} VipsForeignSaveCsvFile;
|
||||||
|
|
||||||
|
typedef VipsForeignSaveCsvClass VipsForeignSaveCsvFileClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsForeignSaveCsvFile, vips_foreign_save_csv_file,
|
||||||
|
vips_foreign_save_csv_get_type() );
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_csv_file_build( VipsObject *object )
|
||||||
|
{
|
||||||
|
VipsForeignSaveCsv *csv = (VipsForeignSaveCsv *) object;
|
||||||
|
VipsForeignSaveCsvFile *file = (VipsForeignSaveCsvFile *) object;
|
||||||
|
|
||||||
|
if( file->filename &&
|
||||||
|
!(csv->target = vips_target_new_to_file( file->filename )) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( VIPS_OBJECT_CLASS( vips_foreign_save_csv_file_parent_class )->
|
||||||
|
build( object ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *vips_foreign_save_csv_file_suffs[] = {
|
||||||
|
".csv",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_csv_file_class_init( VipsForeignSaveCsvFileClass *class )
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||||
|
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||||
|
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||||
|
|
||||||
|
gobject_class->set_property = vips_object_set_property;
|
||||||
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
|
object_class->nickname = "csvsave";
|
||||||
|
object_class->build = vips_foreign_save_csv_file_build;
|
||||||
|
|
||||||
|
foreign_class->suffs = vips_foreign_save_csv_file_suffs;
|
||||||
|
|
||||||
|
VIPS_ARG_STRING( class, "filename", 1,
|
||||||
|
_( "Filename" ),
|
||||||
|
_( "Filename to save to" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignSaveCsvFile, filename ),
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_csv_file_init( VipsForeignSaveCsvFile *file )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _VipsForeignSaveCsvTarget {
|
||||||
|
VipsForeignSaveCsv parent_object;
|
||||||
|
|
||||||
|
VipsTarget *target;
|
||||||
|
} VipsForeignSaveCsvTarget;
|
||||||
|
|
||||||
|
typedef VipsForeignSaveCsvClass VipsForeignSaveCsvTargetClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsForeignSaveCsvTarget, vips_foreign_save_csv_target,
|
||||||
|
vips_foreign_save_csv_get_type() );
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_csv_target_build( VipsObject *object )
|
||||||
|
{
|
||||||
|
VipsForeignSaveCsv *csv = (VipsForeignSaveCsv *) object;
|
||||||
|
VipsForeignSaveCsvTarget *target = (VipsForeignSaveCsvTarget *) object;
|
||||||
|
|
||||||
|
if( target->target ) {
|
||||||
|
csv->target = target->target;
|
||||||
|
g_object_ref( csv->target );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( VIPS_OBJECT_CLASS( vips_foreign_save_csv_target_parent_class )->
|
||||||
|
build( object ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_csv_target_class_init( VipsForeignSaveCsvTargetClass *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 = "csvsave_target";
|
||||||
|
object_class->build = vips_foreign_save_csv_target_build;
|
||||||
|
|
||||||
|
VIPS_ARG_OBJECT( class, "target", 1,
|
||||||
|
_( "Target" ),
|
||||||
|
_( "Target to save to" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignSaveCsvTarget, target ),
|
||||||
|
VIPS_TYPE_TARGET );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_csv_target_init( VipsForeignSaveCsvTarget *target )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_csvsave: (method)
|
* vips_csvsave: (method)
|
||||||
* @in: image to save
|
* @in: image to save
|
||||||
@ -155,3 +359,32 @@ vips_csvsave( VipsImage *in, const char *filename, ... )
|
|||||||
|
|
||||||
return( result );
|
return( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_csvsave_target: (method)
|
||||||
|
* @in: image to save
|
||||||
|
* @target: save image to this target
|
||||||
|
* @...: %NULL-terminated list of optional named arguments
|
||||||
|
*
|
||||||
|
* Optional arguments:
|
||||||
|
*
|
||||||
|
* * @separator: separator string
|
||||||
|
*
|
||||||
|
* As vips_csvsave(), but save to a target.
|
||||||
|
*
|
||||||
|
* See also: vips_csvsave().
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_csvsave_target( VipsImage *in, VipsTarget *target, ... )
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
va_start( ap, target );
|
||||||
|
result = vips_call_split( "csvsave_target", ap, in, target );
|
||||||
|
va_end( ap );
|
||||||
|
|
||||||
|
return( result );
|
||||||
|
}
|
||||||
|
@ -2036,7 +2036,8 @@ vips_foreign_operation_init( void )
|
|||||||
|
|
||||||
extern GType vips_foreign_load_csv_file_get_type( void );
|
extern GType vips_foreign_load_csv_file_get_type( void );
|
||||||
extern GType vips_foreign_load_csv_source_get_type( void );
|
extern GType vips_foreign_load_csv_source_get_type( void );
|
||||||
extern GType vips_foreign_save_csv_get_type( void );
|
extern GType vips_foreign_save_csv_file_get_type( void );
|
||||||
|
extern GType vips_foreign_save_csv_target_get_type( void );
|
||||||
|
|
||||||
extern GType vips_foreign_load_matrix_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_save_matrix_get_type( void );
|
||||||
@ -2112,7 +2113,8 @@ vips_foreign_operation_init( void )
|
|||||||
|
|
||||||
vips_foreign_load_csv_file_get_type();
|
vips_foreign_load_csv_file_get_type();
|
||||||
vips_foreign_load_csv_source_get_type();
|
vips_foreign_load_csv_source_get_type();
|
||||||
vips_foreign_save_csv_get_type();
|
vips_foreign_save_csv_file_get_type();
|
||||||
|
vips_foreign_save_csv_target_get_type();
|
||||||
vips_foreign_load_matrix_get_type();
|
vips_foreign_load_matrix_get_type();
|
||||||
vips_foreign_save_matrix_get_type();
|
vips_foreign_save_matrix_get_type();
|
||||||
vips_foreign_print_matrix_get_type();
|
vips_foreign_print_matrix_get_type();
|
||||||
|
@ -186,10 +186,11 @@ vips_foreign_save_ppm_block( VipsRegion *region, VipsRect *area, void *a )
|
|||||||
{
|
{
|
||||||
VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) a;
|
VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) a;
|
||||||
VipsImage *image = region->im;
|
VipsImage *image = region->im;
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < area->height; i++ ) {
|
int y;
|
||||||
VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + i );
|
|
||||||
|
for( y = 0; y < area->height; y++ ) {
|
||||||
|
VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + y );
|
||||||
|
|
||||||
if( ppm->fn( ppm, image, p ) )
|
if( ppm->fn( ppm, image, p ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -450,7 +451,6 @@ vips_foreign_save_ppm_file_init( VipsForeignSavePpmFile *file )
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /*HAVE_PPM*/
|
#endif /*HAVE_PPM*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -513,6 +513,8 @@ int vips_csvload_source( VipsSource *source, VipsImage **out, ... )
|
|||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
int vips_csvsave( VipsImage *in, const char *filename, ... )
|
int vips_csvsave( VipsImage *in, const char *filename, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
|
int vips_csvsave_target( VipsImage *in, VipsTarget *target, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
|
||||||
int vips_matrixload( const char *filename, VipsImage **out, ... )
|
int vips_matrixload( const char *filename, VipsImage **out, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
|
Loading…
Reference in New Issue
Block a user