move ppm save into the class
no separate save function now
This commit is contained in:
parent
7a047f5332
commit
17b994419b
@ -16,7 +16,6 @@ libforeign_la_SOURCES = \
|
|||||||
radiance.c \
|
radiance.c \
|
||||||
radload.c \
|
radload.c \
|
||||||
radsave.c \
|
radsave.c \
|
||||||
ppm.c \
|
|
||||||
ppmload.c \
|
ppmload.c \
|
||||||
ppmsave.c \
|
ppmsave.c \
|
||||||
csv.c \
|
csv.c \
|
||||||
|
@ -1135,22 +1135,7 @@ build_scan_properties( VipsImage *image )
|
|||||||
char *date;
|
char *date;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef HAVE_DATE_TIME_FORMAT_ISO8601
|
date = vips__get_iso8601();
|
||||||
{
|
|
||||||
GDateTime *now;
|
|
||||||
|
|
||||||
now = g_date_time_new_now_local();
|
|
||||||
date = g_date_time_format_iso8601( now );
|
|
||||||
g_date_time_unref( now );
|
|
||||||
}
|
|
||||||
#else /*!HAVE_DATE_TIME_FORMAT_ISO8601*/
|
|
||||||
{
|
|
||||||
GTimeVal now;
|
|
||||||
|
|
||||||
g_get_current_time( &now );
|
|
||||||
date = g_time_val_to_iso8601( &now );
|
|
||||||
}
|
|
||||||
#endif /*HAVE_DATE_TIME_FORMAT_ISO8601*/
|
|
||||||
|
|
||||||
vips_dbuf_init( &dbuf );
|
vips_dbuf_init( &dbuf );
|
||||||
vips_dbuf_writef( &dbuf, "<?xml version=\"1.0\"?>\n" );
|
vips_dbuf_writef( &dbuf, "<?xml version=\"1.0\"?>\n" );
|
||||||
|
@ -1993,7 +1993,7 @@ vips_foreign_operation_init( void )
|
|||||||
extern GType vips_foreign_save_rad_stream_get_type( void );
|
extern GType vips_foreign_save_rad_stream_get_type( void );
|
||||||
extern GType vips_foreign_load_mat_get_type( 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_file_get_type( void );
|
||||||
extern GType vips_foreign_save_ppm_get_type( void );
|
extern GType vips_foreign_save_ppm_file_get_type( void );
|
||||||
extern GType vips_foreign_load_png_get_type( void );
|
extern GType vips_foreign_load_png_get_type( void );
|
||||||
extern GType vips_foreign_load_png_buffer_get_type( void );
|
extern GType vips_foreign_load_png_buffer_get_type( void );
|
||||||
extern GType vips_foreign_load_png_stream_get_type( void );
|
extern GType vips_foreign_load_png_stream_get_type( void );
|
||||||
@ -2077,7 +2077,7 @@ vips_foreign_operation_init( void )
|
|||||||
|
|
||||||
#ifdef HAVE_PPM
|
#ifdef HAVE_PPM
|
||||||
vips_foreign_load_ppm_file_get_type();
|
vips_foreign_load_ppm_file_get_type();
|
||||||
vips_foreign_save_ppm_get_type();
|
vips_foreign_save_ppm_file_get_type();
|
||||||
#endif /*HAVE_PPM*/
|
#endif /*HAVE_PPM*/
|
||||||
|
|
||||||
#ifdef HAVE_RADIANCE
|
#ifdef HAVE_RADIANCE
|
||||||
|
@ -1,330 +0,0 @@
|
|||||||
/* Read a ppm file.
|
|
||||||
*
|
|
||||||
|
|
||||||
* 4/2/10
|
|
||||||
* - gtkdoc
|
|
||||||
|
|
||||||
* 13/11/19
|
|
||||||
* - redone with streams
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif /*HAVE_CONFIG_H*/
|
|
||||||
#include <vips/intl.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_PPM
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <vips/vips.h>
|
|
||||||
#include <vips/internal.h>
|
|
||||||
|
|
||||||
#include "pforeign.h"
|
|
||||||
|
|
||||||
struct _Write;
|
|
||||||
|
|
||||||
typedef int (*write_fn)( struct _Write *write, VipsPel *p );
|
|
||||||
|
|
||||||
/* What we track during a PPM write.
|
|
||||||
*/
|
|
||||||
typedef struct _Write {
|
|
||||||
VipsImage *in;
|
|
||||||
VipsStreamo *streamo;
|
|
||||||
write_fn fn;
|
|
||||||
} Write;
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_destroy( Write *write )
|
|
||||||
{
|
|
||||||
if( write->streamo )
|
|
||||||
vips_streamo_finish( write->streamo );
|
|
||||||
VIPS_UNREF( write->streamo );
|
|
||||||
|
|
||||||
vips_free( write );
|
|
||||||
}
|
|
||||||
|
|
||||||
static Write *
|
|
||||||
write_new( VipsImage *in, VipsStreamo *streamo )
|
|
||||||
{
|
|
||||||
Write *write;
|
|
||||||
|
|
||||||
if( !(write = VIPS_NEW( NULL, Write )) )
|
|
||||||
return( NULL );
|
|
||||||
|
|
||||||
write->in = in;
|
|
||||||
write->streamo = streamo;
|
|
||||||
g_object_ref( streamo );
|
|
||||||
write->fn = NULL;
|
|
||||||
|
|
||||||
return( write );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
write_ppm_line_ascii( Write *write, VipsPel *p )
|
|
||||||
{
|
|
||||||
const int sk = VIPS_IMAGE_SIZEOF_PEL( write->in );
|
|
||||||
int x, k;
|
|
||||||
|
|
||||||
for( x = 0; x < write->in->Xsize; x++ ) {
|
|
||||||
for( k = 0; k < write->in->Bands; k++ ) {
|
|
||||||
switch( write->in->BandFmt ) {
|
|
||||||
case VIPS_FORMAT_UCHAR:
|
|
||||||
vips_streamo_writef( write->streamo,
|
|
||||||
"%d ", p[k] );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIPS_FORMAT_USHORT:
|
|
||||||
vips_streamo_writef( write->streamo,
|
|
||||||
"%d ", ((unsigned short *) p)[k] );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIPS_FORMAT_UINT:
|
|
||||||
vips_streamo_writef( write->streamo,
|
|
||||||
"%d ", ((unsigned int *) p)[k] );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p += sk;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( vips_streamo_writef( write->streamo, "\n" ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
write_ppm_line_ascii_squash( Write *write, VipsPel *p )
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
|
|
||||||
for( x = 0; x < write->in->Xsize; x++ )
|
|
||||||
vips_streamo_writef( write->streamo, "%d ", p[x] ? 0 : 1 );
|
|
||||||
|
|
||||||
if( vips_streamo_writef( write->streamo, "\n" ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
write_ppm_line_binary( Write *write, VipsPel *p )
|
|
||||||
{
|
|
||||||
if( vips_streamo_write( write->streamo,
|
|
||||||
p, VIPS_IMAGE_SIZEOF_LINE( write->in ) ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
write_ppm_line_binary_squash( Write *write, VipsPel *p )
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
int bits;
|
|
||||||
int n_bits;
|
|
||||||
|
|
||||||
bits = 0;
|
|
||||||
n_bits = 0;
|
|
||||||
for( x = 0; x < write->in->Xsize; x++ ) {
|
|
||||||
bits = VIPS_LSHIFT_INT( bits, 1 );
|
|
||||||
n_bits += 1;
|
|
||||||
bits |= p[x] ? 0 : 1;
|
|
||||||
|
|
||||||
if( n_bits == 8 ) {
|
|
||||||
if( VIPS_STREAMO_PUTC( write->streamo, bits ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
bits = 0;
|
|
||||||
n_bits = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Flush any remaining bits in this line.
|
|
||||||
*/
|
|
||||||
if( n_bits &&
|
|
||||||
VIPS_STREAMO_PUTC( write->streamo, bits ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
write_ppm_block( VipsRegion *region, VipsRect *area, void *a )
|
|
||||||
{
|
|
||||||
Write *write = (Write *) a;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < area->height; i++ ) {
|
|
||||||
VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + i );
|
|
||||||
|
|
||||||
if( write->fn( write, p ) )
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
write_ppm( Write *write, gboolean ascii, gboolean squash )
|
|
||||||
{
|
|
||||||
VipsImage *in = write->in;
|
|
||||||
|
|
||||||
char *magic;
|
|
||||||
time_t timebuf;
|
|
||||||
|
|
||||||
magic = "unset";
|
|
||||||
if( in->BandFmt == VIPS_FORMAT_FLOAT && in->Bands == 3 )
|
|
||||||
magic = "PF";
|
|
||||||
else if( in->BandFmt == VIPS_FORMAT_FLOAT && in->Bands == 1 )
|
|
||||||
magic = "Pf";
|
|
||||||
else if( in->Bands == 1 && ascii && squash )
|
|
||||||
magic = "P1";
|
|
||||||
else if( in->Bands == 1 && ascii )
|
|
||||||
magic = "P2";
|
|
||||||
else if( in->Bands == 1 && !ascii && squash )
|
|
||||||
magic = "P4";
|
|
||||||
else if( in->Bands == 1 && !ascii )
|
|
||||||
magic = "P5";
|
|
||||||
else if( in->Bands == 3 && ascii )
|
|
||||||
magic = "P3";
|
|
||||||
else if( in->Bands == 3 && !ascii )
|
|
||||||
magic = "P6";
|
|
||||||
else
|
|
||||||
g_assert_not_reached();
|
|
||||||
|
|
||||||
vips_streamo_writef( write->streamo, "%s\n", magic );
|
|
||||||
time( &timebuf );
|
|
||||||
vips_streamo_writef( write->streamo,
|
|
||||||
"#vips2ppm - %s\n", ctime( &timebuf ) );
|
|
||||||
vips_streamo_writef( write->streamo, "%d %d\n", in->Xsize, in->Ysize );
|
|
||||||
|
|
||||||
if( !squash )
|
|
||||||
switch( in->BandFmt ) {
|
|
||||||
case VIPS_FORMAT_UCHAR:
|
|
||||||
vips_streamo_writef( write->streamo,
|
|
||||||
"%d\n", UCHAR_MAX );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIPS_FORMAT_USHORT:
|
|
||||||
vips_streamo_writef( write->streamo,
|
|
||||||
"%d\n", USHRT_MAX );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIPS_FORMAT_UINT:
|
|
||||||
vips_streamo_writef( write->streamo,
|
|
||||||
"%d\n", UINT_MAX );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIPS_FORMAT_FLOAT:
|
|
||||||
{
|
|
||||||
double scale;
|
|
||||||
|
|
||||||
if( vips_image_get_double( in, "pfm-scale", &scale ) )
|
|
||||||
scale = 1;
|
|
||||||
if( !vips_amiMSBfirst() )
|
|
||||||
scale *= -1;
|
|
||||||
vips_streamo_writef( write->streamo,
|
|
||||||
"%g\n", scale );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( squash )
|
|
||||||
write->fn = ascii ?
|
|
||||||
write_ppm_line_ascii_squash :
|
|
||||||
write_ppm_line_binary_squash;
|
|
||||||
else
|
|
||||||
write->fn = ascii ?
|
|
||||||
write_ppm_line_ascii :
|
|
||||||
write_ppm_line_binary;
|
|
||||||
|
|
||||||
if( vips_sink_disc( write->in, write_ppm_block, write ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
vips__ppm_save_stream( VipsImage *in, VipsStreamo *streamo,
|
|
||||||
gboolean ascii, gboolean squash )
|
|
||||||
{
|
|
||||||
Write *write;
|
|
||||||
|
|
||||||
if( vips_check_uintorf( "vips2ppm", in ) ||
|
|
||||||
vips_check_bands_1or3( "vips2ppm", in ) ||
|
|
||||||
vips_check_uncoded( "vips2ppm", in ) ||
|
|
||||||
vips_image_pio_input( in ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
if( ascii &&
|
|
||||||
in->BandFmt == VIPS_FORMAT_FLOAT ) {
|
|
||||||
g_warning( "%s",
|
|
||||||
_( "float images must be binary -- disabling ascii" ) );
|
|
||||||
ascii = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* One bit images must come from a 8 bit, one band source.
|
|
||||||
*/
|
|
||||||
if( squash &&
|
|
||||||
(in->Bands != 1 ||
|
|
||||||
in->BandFmt != VIPS_FORMAT_UCHAR) ) {
|
|
||||||
g_warning( "%s",
|
|
||||||
_( "can only squash 1 band uchar images -- "
|
|
||||||
"disabling squash" ) );
|
|
||||||
squash = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !(write = write_new( in, streamo )) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
if( write_ppm( write, ascii, squash ) ) {
|
|
||||||
write_destroy( write );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
write_destroy( write );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /*HAVE_PPM*/
|
|
@ -62,6 +62,12 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* TODO
|
||||||
|
*
|
||||||
|
* - make partial
|
||||||
|
* - only use mmap on filename streams?
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
*/
|
*/
|
||||||
@ -147,110 +153,32 @@ vips_foreign_load_ppm_is_a_stream( VipsStreami *streami )
|
|||||||
return( FALSE );
|
return( FALSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The largest number/field/whatever we can read.
|
|
||||||
*/
|
|
||||||
#define MAX_THING (80)
|
|
||||||
|
|
||||||
/* After this, the next getc will be the first char of the next line (or EOF).
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
skip_line( VipsStreamib *streamib )
|
get_int( VipsStreamib *streamib, int *i )
|
||||||
{
|
{
|
||||||
int ch;
|
const char *txt;
|
||||||
|
|
||||||
while( (ch = VIPS_STREAMIB_GETC( streamib )) != '\n' &&
|
if( vips_streamib_skip_whitespace( streamib ) ||
|
||||||
ch != EOF )
|
!(txt = vips_streamib_get_non_whitespace( streamib )) )
|
||||||
;
|
|
||||||
|
|
||||||
if( ch == EOF )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
*i = atoi( txt );
|
||||||
}
|
|
||||||
|
|
||||||
/* After this, the next getc will be the first char of the next block of
|
|
||||||
* non-whitespace (or EOF).
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
skip_white_space( VipsStreamib *streamib )
|
|
||||||
{
|
|
||||||
int ch;
|
|
||||||
|
|
||||||
while( isspace( ch = VIPS_STREAMIB_GETC( streamib ) ) )
|
|
||||||
;
|
|
||||||
VIPS_STREAMIB_UNGETC( streamib );
|
|
||||||
|
|
||||||
/* # skip comments too.
|
|
||||||
*/
|
|
||||||
if( ch == '#' &&
|
|
||||||
(skip_line( streamib ) ||
|
|
||||||
skip_white_space( streamib )) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* After this, the next getc will be the first char of the next block of
|
|
||||||
* whitespace (or EOF). buf will be filled with up to length bytes, and
|
|
||||||
* null-terminated.
|
|
||||||
*
|
|
||||||
* If the first getc is whitespace, stop instantly and return nothing.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
read_non_white_space( VipsStreamib *streamib, char *buf, int length )
|
|
||||||
{
|
|
||||||
int ch;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < length - 1 &&
|
|
||||||
!isspace( ch = VIPS_STREAMIB_GETC( streamib ) ) &&
|
|
||||||
ch != EOF; i++ )
|
|
||||||
buf[i] = ch;
|
|
||||||
buf[i] = '\0';
|
|
||||||
|
|
||||||
/* If we stopped before seeing any whitespace, skip to the end of the
|
|
||||||
* block of non-whitespace.
|
|
||||||
*/
|
|
||||||
if( !isspace( ch ) )
|
|
||||||
while( !isspace( ch = VIPS_STREAMIB_GETC( streamib ) ) &&
|
|
||||||
ch != EOF )
|
|
||||||
;
|
|
||||||
|
|
||||||
/* If we finally stopped on whitespace, step back one so the next get
|
|
||||||
* will be whitespace (or EOF).
|
|
||||||
*/
|
|
||||||
if( isspace( ch ) )
|
|
||||||
VIPS_STREAMIB_UNGETC( streamib );
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
read_int( VipsStreamib *streamib, int *i )
|
get_float( VipsStreamib *streamib, float *f )
|
||||||
{
|
{
|
||||||
char buf[MAX_THING];
|
const char *txt;
|
||||||
|
|
||||||
if( skip_white_space( streamib ) )
|
if( vips_streamib_skip_whitespace( streamib ) ||
|
||||||
|
!(txt = vips_streamib_get_non_whitespace( streamib )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
read_non_white_space( streamib, buf, MAX_THING );
|
|
||||||
*i = atoi( buf );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
read_float( VipsStreamib *streamib, float *f )
|
|
||||||
{
|
|
||||||
char buf[MAX_THING];
|
|
||||||
|
|
||||||
if( skip_white_space( streamib ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
read_non_white_space( streamib, buf, MAX_THING );
|
|
||||||
/* We don't want the locale str -> float conversion.
|
/* We don't want the locale str -> float conversion.
|
||||||
*/
|
*/
|
||||||
*f = g_ascii_strtod( buf, NULL );
|
*f = g_ascii_strtod( txt, NULL );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -289,6 +217,9 @@ vips_foreign_load_ppm_parse_header( VipsForeignLoadPpm *ppm )
|
|||||||
1, 1, 1, 0, 0, 0, 0, 0
|
1, 1, 1, 0, 0, 0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if( vips_streami_rewind( ppm->streami ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
/* Read in the magic number.
|
/* Read in the magic number.
|
||||||
*/
|
*/
|
||||||
buf[0] = VIPS_STREAMIB_GETC( ppm->streamib );
|
buf[0] = VIPS_STREAMIB_GETC( ppm->streamib );
|
||||||
@ -312,8 +243,8 @@ vips_foreign_load_ppm_parse_header( VipsForeignLoadPpm *ppm )
|
|||||||
|
|
||||||
/* Read in size.
|
/* Read in size.
|
||||||
*/
|
*/
|
||||||
if( read_int( ppm->streamib, &ppm->width ) ||
|
if( get_int( ppm->streamib, &ppm->width ) ||
|
||||||
read_int( ppm->streamib, &ppm->height ) )
|
get_int( ppm->streamib, &ppm->height ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
/* Read in max value / scale for >1 bit images.
|
/* Read in max value / scale for >1 bit images.
|
||||||
@ -321,7 +252,7 @@ vips_foreign_load_ppm_parse_header( VipsForeignLoadPpm *ppm )
|
|||||||
if( ppm->bits > 1 ) {
|
if( ppm->bits > 1 ) {
|
||||||
if( ppm->index == 6 ||
|
if( ppm->index == 6 ||
|
||||||
ppm->index == 7 ) {
|
ppm->index == 7 ) {
|
||||||
if( read_float( ppm->streamib, &ppm->scale ) )
|
if( get_float( ppm->streamib, &ppm->scale ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
/* Scale > 0 means big-endian.
|
/* Scale > 0 means big-endian.
|
||||||
@ -329,7 +260,7 @@ vips_foreign_load_ppm_parse_header( VipsForeignLoadPpm *ppm )
|
|||||||
ppm->msb_first = ppm->scale > 0;
|
ppm->msb_first = ppm->scale > 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( read_int( ppm->streamib, &ppm->max_value ) )
|
if( get_int( ppm->streamib, &ppm->max_value ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( ppm->max_value > 255 )
|
if( ppm->max_value > 255 )
|
||||||
@ -445,6 +376,8 @@ vips_foreign_load_ppm_header( VipsForeignLoad *load )
|
|||||||
|
|
||||||
vips_foreign_load_ppm_set_image( ppm, load->out );
|
vips_foreign_load_ppm_set_image( ppm, load->out );
|
||||||
|
|
||||||
|
vips_streami_minimise( ppm->streami );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,7 +432,7 @@ load_1bit_ascii( VipsForeignLoadPpm *ppm, VipsImage *image )
|
|||||||
for( x = 0; x < image->Xsize; x++ ) {
|
for( x = 0; x < image->Xsize; x++ ) {
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
if( read_int( ppm->streamib, &val ) )
|
if( get_int( ppm->streamib, &val ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( val )
|
if( val )
|
||||||
@ -567,7 +500,7 @@ load_ascii( VipsForeignLoadPpm *ppm, VipsImage *image )
|
|||||||
for( x = 0; x < image->Xsize * image->Bands; x++ ) {
|
for( x = 0; x < image->Xsize * image->Bands; x++ ) {
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
if( read_int( ppm->streamib, &val ) )
|
if( get_int( ppm->streamib, &val ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
switch( image->BandFmt ) {
|
switch( image->BandFmt ) {
|
||||||
@ -620,9 +553,12 @@ vips_foreign_load_ppm_load( VipsForeignLoad *load )
|
|||||||
else
|
else
|
||||||
loader = load_ascii;
|
loader = load_ascii;
|
||||||
|
|
||||||
if( loader( ppm, load->real ) )
|
if( vips_streami_decode( ppm->streami ) ||
|
||||||
|
loader( ppm, load->real ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
vips_streami_minimise( ppm->streami );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,44 +46,292 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
#include "pforeign.h"
|
#include "pforeign.h"
|
||||||
|
|
||||||
#ifdef HAVE_PPM
|
#ifdef HAVE_PPM
|
||||||
|
|
||||||
|
typedef struct _VipsForeignSavePpm VipsForeignSavePpm;
|
||||||
|
|
||||||
|
typedef int (*VipsSavePpmFn)( VipsForeignSavePpm *, VipsImage *, VipsPel * );
|
||||||
|
|
||||||
typedef struct _VipsForeignSavePpm {
|
typedef struct _VipsForeignSavePpm {
|
||||||
VipsForeignSave parent_object;
|
VipsForeignSave parent_object;
|
||||||
|
|
||||||
char *filename;
|
VipsStreamo *streamo;
|
||||||
gboolean ascii;
|
gboolean ascii;
|
||||||
gboolean squash;
|
gboolean squash;
|
||||||
|
|
||||||
|
VipsSavePpmFn fn;
|
||||||
} VipsForeignSavePpm;
|
} VipsForeignSavePpm;
|
||||||
|
|
||||||
typedef VipsForeignSaveClass VipsForeignSavePpmClass;
|
typedef VipsForeignSaveClass VipsForeignSavePpmClass;
|
||||||
|
|
||||||
G_DEFINE_TYPE( VipsForeignSavePpm, vips_foreign_save_ppm,
|
G_DEFINE_ABSTRACT_TYPE( VipsForeignSavePpm, vips_foreign_save_ppm,
|
||||||
VIPS_TYPE_FOREIGN_SAVE );
|
VIPS_TYPE_FOREIGN_SAVE );
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_ppm_dispose( GObject *gobject )
|
||||||
|
{
|
||||||
|
VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) gobject;
|
||||||
|
|
||||||
|
if( ppm->streamo )
|
||||||
|
vips_streamo_finish( ppm->streamo );
|
||||||
|
VIPS_UNREF( ppm->streamo );
|
||||||
|
|
||||||
|
G_OBJECT_CLASS( vips_foreign_save_ppm_parent_class )->
|
||||||
|
dispose( gobject );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_ppm_line_ascii( VipsForeignSavePpm *ppm,
|
||||||
|
VipsImage *image, VipsPel *p )
|
||||||
|
{
|
||||||
|
const int n_elements = image->Xsize * image->Bands;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < n_elements; i++ ) {
|
||||||
|
switch( image->BandFmt ) {
|
||||||
|
case VIPS_FORMAT_UCHAR:
|
||||||
|
vips_streamo_writef( ppm->streamo,
|
||||||
|
"%d ", p[i] );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_FORMAT_USHORT:
|
||||||
|
vips_streamo_writef( ppm->streamo,
|
||||||
|
"%d ", ((unsigned short *) p)[i] );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_FORMAT_UINT:
|
||||||
|
vips_streamo_writef( ppm->streamo,
|
||||||
|
"%d ", ((unsigned int *) p)[i] );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( vips_streamo_writes( ppm->streamo, "\n" ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_ppm_line_ascii_squash( VipsForeignSavePpm *ppm,
|
||||||
|
VipsImage *image, VipsPel *p )
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
for( x = 0; x < image->Xsize; x++ )
|
||||||
|
vips_streamo_writef( ppm->streamo, "%d ", p[x] ? 0 : 1 );
|
||||||
|
|
||||||
|
if( vips_streamo_writes( ppm->streamo, "\n" ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_ppm_line_binary( VipsForeignSavePpm *ppm,
|
||||||
|
VipsImage *image, VipsPel *p )
|
||||||
|
{
|
||||||
|
if( vips_streamo_write( ppm->streamo,
|
||||||
|
p, VIPS_IMAGE_SIZEOF_LINE( image ) ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_ppm_line_binary_squash( VipsForeignSavePpm *ppm,
|
||||||
|
VipsImage *image, VipsPel *p )
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int bits;
|
||||||
|
int n_bits;
|
||||||
|
|
||||||
|
bits = 0;
|
||||||
|
n_bits = 0;
|
||||||
|
for( x = 0; x < image->Xsize; x++ ) {
|
||||||
|
bits = VIPS_LSHIFT_INT( bits, 1 );
|
||||||
|
n_bits += 1;
|
||||||
|
bits |= p[x] ? 0 : 1;
|
||||||
|
|
||||||
|
if( n_bits == 8 ) {
|
||||||
|
if( VIPS_STREAMO_PUTC( ppm->streamo, bits ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
bits = 0;
|
||||||
|
n_bits = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flush any remaining bits in this line.
|
||||||
|
*/
|
||||||
|
if( n_bits &&
|
||||||
|
VIPS_STREAMO_PUTC( ppm->streamo, bits ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_ppm_block( VipsRegion *region, VipsRect *area, void *a )
|
||||||
|
{
|
||||||
|
VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) a;
|
||||||
|
VipsImage *image = region->im;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < area->height; i++ ) {
|
||||||
|
VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + i );
|
||||||
|
|
||||||
|
if( ppm->fn( ppm, image, p ) )
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_ppm( VipsForeignSavePpm *ppm, VipsImage *image )
|
||||||
|
{
|
||||||
|
char *magic;
|
||||||
|
char *date;
|
||||||
|
|
||||||
|
magic = "unset";
|
||||||
|
if( image->BandFmt == VIPS_FORMAT_FLOAT &&
|
||||||
|
image->Bands == 3 )
|
||||||
|
magic = "PF";
|
||||||
|
else if( image->BandFmt == VIPS_FORMAT_FLOAT &&
|
||||||
|
image->Bands == 1 )
|
||||||
|
magic = "Pf";
|
||||||
|
else if( image->Bands == 1 &&
|
||||||
|
ppm->ascii &&
|
||||||
|
ppm->squash )
|
||||||
|
magic = "P1";
|
||||||
|
else if( image->Bands == 1 &&
|
||||||
|
ppm->ascii )
|
||||||
|
magic = "P2";
|
||||||
|
else if( image->Bands == 1 &&
|
||||||
|
!ppm->ascii &&
|
||||||
|
ppm->squash )
|
||||||
|
magic = "P4";
|
||||||
|
else if( image->Bands == 1 &&
|
||||||
|
!ppm->ascii )
|
||||||
|
magic = "P5";
|
||||||
|
else if( image->Bands == 3 &&
|
||||||
|
ppm->ascii )
|
||||||
|
magic = "P3";
|
||||||
|
else if( image->Bands == 3 &&
|
||||||
|
!ppm->ascii )
|
||||||
|
magic = "P6";
|
||||||
|
else
|
||||||
|
g_assert_not_reached();
|
||||||
|
|
||||||
|
vips_streamo_writef( ppm->streamo, "%s\n", magic );
|
||||||
|
date = vips__get_iso8601();
|
||||||
|
vips_streamo_writef( ppm->streamo,
|
||||||
|
"#vips2ppm - %s\n", date );
|
||||||
|
g_free( date );
|
||||||
|
vips_streamo_writef( ppm->streamo,
|
||||||
|
"%d %d\n", image->Xsize, image->Ysize );
|
||||||
|
|
||||||
|
if( !ppm->squash )
|
||||||
|
switch( image->BandFmt ) {
|
||||||
|
case VIPS_FORMAT_UCHAR:
|
||||||
|
vips_streamo_writef( ppm->streamo,
|
||||||
|
"%d\n", UCHAR_MAX );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_FORMAT_USHORT:
|
||||||
|
vips_streamo_writef( ppm->streamo,
|
||||||
|
"%d\n", USHRT_MAX );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_FORMAT_UINT:
|
||||||
|
vips_streamo_writef( ppm->streamo,
|
||||||
|
"%d\n", UINT_MAX );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_FORMAT_FLOAT:
|
||||||
|
{
|
||||||
|
double scale;
|
||||||
|
char buf[G_ASCII_DTOSTR_BUF_SIZE];
|
||||||
|
|
||||||
|
if( vips_image_get_double( image,
|
||||||
|
"pfm-scale", &scale ) )
|
||||||
|
scale = 1;
|
||||||
|
if( !vips_amiMSBfirst() )
|
||||||
|
scale *= -1;
|
||||||
|
/* Need to be locale independent.
|
||||||
|
*/
|
||||||
|
g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE, scale );
|
||||||
|
vips_streamo_writes( ppm->streamo, buf );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ppm->squash )
|
||||||
|
ppm->fn = ppm->ascii ?
|
||||||
|
vips_foreign_save_ppm_line_ascii_squash :
|
||||||
|
vips_foreign_save_ppm_line_binary_squash;
|
||||||
|
else
|
||||||
|
ppm->fn = ppm->ascii ?
|
||||||
|
vips_foreign_save_ppm_line_ascii :
|
||||||
|
vips_foreign_save_ppm_line_binary;
|
||||||
|
|
||||||
|
if( vips_sink_disc( image, vips_foreign_save_ppm_block, ppm ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_foreign_save_ppm_build( VipsObject *object )
|
vips_foreign_save_ppm_build( VipsObject *object )
|
||||||
{
|
{
|
||||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||||
VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) object;
|
VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) object;
|
||||||
|
|
||||||
VipsStreamo *streamo;
|
VipsImage *image;
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_ppm_parent_class )->
|
if( VIPS_OBJECT_CLASS( vips_foreign_save_ppm_parent_class )->
|
||||||
build( object ) )
|
build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( !(streamo = vips_streamo_new_to_filename( ppm->filename )) )
|
image = save->ready;
|
||||||
return( -1 );
|
if( vips_check_uintorf( "vips2ppm", image ) ||
|
||||||
if( vips__ppm_save_stream( save->ready, streamo,
|
vips_check_bands_1or3( "vips2ppm", image ) ||
|
||||||
ppm->ascii, ppm->squash ) ) {
|
vips_check_uncoded( "vips2ppm", image ) ||
|
||||||
VIPS_UNREF( streamo );
|
vips_image_pio_input( image ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
if( ppm->ascii &&
|
||||||
|
image->BandFmt == VIPS_FORMAT_FLOAT ) {
|
||||||
|
g_warning( "%s",
|
||||||
|
_( "float images must be binary -- disabling ascii" ) );
|
||||||
|
ppm->ascii = FALSE;
|
||||||
}
|
}
|
||||||
VIPS_UNREF( streamo );
|
|
||||||
|
/* One bit images must come from a 8 bit, one band source.
|
||||||
|
*/
|
||||||
|
if( ppm->squash &&
|
||||||
|
(image->Bands != 1 ||
|
||||||
|
image->BandFmt != VIPS_FORMAT_UCHAR) ) {
|
||||||
|
g_warning( "%s",
|
||||||
|
_( "can only squash 1 band uchar images -- "
|
||||||
|
"disabling squash" ) );
|
||||||
|
ppm->squash = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( vips_foreign_save_ppm( ppm, image ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -114,11 +362,12 @@ vips_foreign_save_ppm_class_init( VipsForeignSavePpmClass *class )
|
|||||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||||
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
|
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
|
||||||
|
|
||||||
|
gobject_class->dispose = vips_foreign_save_ppm_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 = "ppmsave";
|
object_class->nickname = "ppmsave_base";
|
||||||
object_class->description = _( "save image to ppm file" );
|
object_class->description = _( "save to ppm" );
|
||||||
object_class->build = vips_foreign_save_ppm_build;
|
object_class->build = vips_foreign_save_ppm_build;
|
||||||
|
|
||||||
foreign_class->suffs = vips__ppm_suffs;
|
foreign_class->suffs = vips__ppm_suffs;
|
||||||
@ -126,13 +375,6 @@ vips_foreign_save_ppm_class_init( VipsForeignSavePpmClass *class )
|
|||||||
save_class->saveable = VIPS_SAVEABLE_RGB;
|
save_class->saveable = VIPS_SAVEABLE_RGB;
|
||||||
save_class->format_table = bandfmt_ppm;
|
save_class->format_table = bandfmt_ppm;
|
||||||
|
|
||||||
VIPS_ARG_STRING( class, "filename", 1,
|
|
||||||
_( "Filename" ),
|
|
||||||
_( "Filename to save to" ),
|
|
||||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
|
||||||
G_STRUCT_OFFSET( VipsForeignSavePpm, filename ),
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
VIPS_ARG_BOOL( class, "ascii", 10,
|
VIPS_ARG_BOOL( class, "ascii", 10,
|
||||||
_( "ASCII" ),
|
_( "ASCII" ),
|
||||||
_( "save as ascii" ),
|
_( "save as ascii" ),
|
||||||
@ -146,6 +388,7 @@ vips_foreign_save_ppm_class_init( VipsForeignSavePpmClass *class )
|
|||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsForeignSavePpm, squash ),
|
G_STRUCT_OFFSET( VipsForeignSavePpm, squash ),
|
||||||
FALSE );
|
FALSE );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -153,6 +396,60 @@ vips_foreign_save_ppm_init( VipsForeignSavePpm *ppm )
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _VipsForeignSavePpmFile {
|
||||||
|
VipsForeignSavePpm parent_object;
|
||||||
|
|
||||||
|
char *filename;
|
||||||
|
} VipsForeignSavePpmFile;
|
||||||
|
|
||||||
|
typedef VipsForeignSavePpmClass VipsForeignSavePpmFileClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsForeignSavePpmFile, vips_foreign_save_ppm_file,
|
||||||
|
vips_foreign_save_ppm_get_type() );
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_ppm_file_build( VipsObject *object )
|
||||||
|
{
|
||||||
|
VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) object;
|
||||||
|
VipsForeignSavePpmFile *file = (VipsForeignSavePpmFile *) object;
|
||||||
|
|
||||||
|
if( file->filename &&
|
||||||
|
!(ppm->streamo =
|
||||||
|
vips_streamo_new_to_filename( file->filename )) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( VIPS_OBJECT_CLASS( vips_foreign_save_ppm_file_parent_class )->
|
||||||
|
build( object ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_ppm_file_class_init( VipsForeignSavePpmFileClass *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";
|
||||||
|
object_class->description = _( "save image to ppm file" );
|
||||||
|
object_class->build = vips_foreign_save_ppm_file_build;
|
||||||
|
|
||||||
|
VIPS_ARG_STRING( class, "filename", 1,
|
||||||
|
_( "Filename" ),
|
||||||
|
_( "Filename to save to" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignSavePpmFile, filename ),
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_ppm_file_init( VipsForeignSavePpmFile *file )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /*HAVE_PPM*/
|
#endif /*HAVE_PPM*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -506,11 +506,11 @@ getheader( /* get header from file */
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
for(;;) {
|
for(;;) {
|
||||||
const unsigned char *line;
|
const char *line;
|
||||||
|
|
||||||
if( !(line = vips_streamib_get_line( streamib )) )
|
if( !(line = vips_streamib_get_line( streamib )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( strcmp( (char *) line, "" ) == 0 )
|
if( strcmp( line, "" ) == 0 )
|
||||||
/* Blank line. We've parsed the header successfully.
|
/* Blank line. We've parsed the header successfully.
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
@ -725,14 +725,14 @@ int
|
|||||||
vips__rad_israd( VipsStreami *streami )
|
vips__rad_israd( VipsStreami *streami )
|
||||||
{
|
{
|
||||||
VipsStreamib *streamib;
|
VipsStreamib *streamib;
|
||||||
const unsigned char *line;
|
const char *line;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
/* Just test that the first line is the magic string.
|
/* Just test that the first line is the magic string.
|
||||||
*/
|
*/
|
||||||
streamib = vips_streamib_new( streami );
|
streamib = vips_streamib_new( streami );
|
||||||
result = (line = vips_streamib_get_line( streamib )) &&
|
result = (line = vips_streamib_get_line( streamib )) &&
|
||||||
strcmp( (char *) line, "#?RADIANCE" ) == 0;
|
strcmp( line, "#?RADIANCE" ) == 0;
|
||||||
VIPS_UNREF( streamib );
|
VIPS_UNREF( streamib );
|
||||||
|
|
||||||
return( result );
|
return( result );
|
||||||
@ -832,7 +832,7 @@ static int
|
|||||||
rad2vips_get_header( Read *read, VipsImage *out )
|
rad2vips_get_header( Read *read, VipsImage *out )
|
||||||
{
|
{
|
||||||
VipsInterpretation interpretation;
|
VipsInterpretation interpretation;
|
||||||
const unsigned char *line;
|
const char *line;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
int i, j;
|
int i, j;
|
||||||
@ -1082,7 +1082,7 @@ vips2rad_put_header( Write *write )
|
|||||||
{
|
{
|
||||||
vips2rad_make_header( write );
|
vips2rad_make_header( write );
|
||||||
|
|
||||||
vips_streamo_writef( write->streamo, "#?RADIANCE\n" );
|
vips_streamo_writes( write->streamo, "#?RADIANCE\n" );
|
||||||
vips_streamo_writef( write->streamo, "%s%s\n", FMTSTR, write->format );
|
vips_streamo_writef( write->streamo, "%s%s\n", FMTSTR, write->format );
|
||||||
vips_streamo_writef( write->streamo, "%s%e\n", EXPOSSTR, write->expos );
|
vips_streamo_writef( write->streamo, "%s%e\n", EXPOSSTR, write->expos );
|
||||||
vips_streamo_writef( write->streamo,
|
vips_streamo_writef( write->streamo,
|
||||||
@ -1099,9 +1099,9 @@ vips2rad_put_header( Write *write )
|
|||||||
write->prims[GRN][CIEX], write->prims[GRN][CIEY],
|
write->prims[GRN][CIEX], write->prims[GRN][CIEY],
|
||||||
write->prims[BLU][CIEX], write->prims[BLU][CIEY],
|
write->prims[BLU][CIEX], write->prims[BLU][CIEY],
|
||||||
write->prims[WHT][CIEX], write->prims[WHT][CIEY] );
|
write->prims[WHT][CIEX], write->prims[WHT][CIEY] );
|
||||||
vips_streamo_writef( write->streamo, "\n" );
|
vips_streamo_writes( write->streamo, "\n" );
|
||||||
vips_streamo_writef( write->streamo,
|
vips_streamo_writes( write->streamo,
|
||||||
"%s", resolu2str( resolu_buf, &write->rs ) );
|
resolu2str( resolu_buf, &write->rs ) );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
@ -297,8 +297,10 @@ int vips_streamib_require( VipsStreamib *streamib, int require );
|
|||||||
#define VIPS_STREAMIB_PEEK( S ) ((S)->input_buffer + (S)->read_point)
|
#define VIPS_STREAMIB_PEEK( S ) ((S)->input_buffer + (S)->read_point)
|
||||||
#define VIPS_STREAMIB_FETCH( S ) ((S)->input_buffer[(S)->read_point++])
|
#define VIPS_STREAMIB_FETCH( S ) ((S)->input_buffer[(S)->read_point++])
|
||||||
|
|
||||||
const unsigned char *vips_streamib_get_line( VipsStreamib *streamib );
|
const char *vips_streamib_get_line( VipsStreamib *streamib );
|
||||||
unsigned char *vips_streamib_get_line_copy( VipsStreamib *streamib );
|
char *vips_streamib_get_line_copy( VipsStreamib *streamib );
|
||||||
|
const char *vips_streamib_get_non_whitespace( VipsStreamib *streamib );
|
||||||
|
int vips_streamib_skip_whitespace( VipsStreamib *streamib );
|
||||||
|
|
||||||
#define VIPS_TYPE_STREAMIW (vips_streamiw_get_type())
|
#define VIPS_TYPE_STREAMIW (vips_streamiw_get_type())
|
||||||
#define VIPS_STREAMIW( obj ) \
|
#define VIPS_STREAMIW( obj ) \
|
||||||
@ -400,13 +402,12 @@ int vips_streamo_write( VipsStreamo *streamo, const void *data, size_t length );
|
|||||||
void vips_streamo_finish( VipsStreamo *streamo );
|
void vips_streamo_finish( VipsStreamo *streamo );
|
||||||
|
|
||||||
int vips_streamo_putc( VipsStreamo *streamo, int ch );
|
int vips_streamo_putc( VipsStreamo *streamo, int ch );
|
||||||
|
|
||||||
#define VIPS_STREAMO_PUTC( S, C ) ( \
|
#define VIPS_STREAMO_PUTC( S, C ) ( \
|
||||||
(S)->write_point <= VIPS_STREAMO_BUFFER_SIZE ? \
|
(S)->write_point <= VIPS_STREAMO_BUFFER_SIZE ? \
|
||||||
((S)->output_buffer[(S)->write_point++] = (C), 0) : \
|
((S)->output_buffer[(S)->write_point++] = (C), 0) : \
|
||||||
vips_streamo_putc( (S), (C) ) \
|
vips_streamo_putc( (S), (C) ) \
|
||||||
)
|
)
|
||||||
|
int vips_streamo_writes( VipsStreamo *streamo, const char *str );
|
||||||
int vips_streamo_writef( VipsStreamo *streamo, const char *fmt, ... )
|
int vips_streamo_writef( VipsStreamo *streamo, const char *fmt, ... )
|
||||||
__attribute__((format(printf, 2, 3)));
|
__attribute__((format(printf, 2, 3)));
|
||||||
|
|
||||||
|
@ -344,6 +344,8 @@ guint32 vips__random_add( guint32 seed, int value );
|
|||||||
const char *vips__icc_dir( void );
|
const char *vips__icc_dir( void );
|
||||||
const char *vips__windows_prefix( void );
|
const char *vips__windows_prefix( void );
|
||||||
|
|
||||||
|
char *vips__get_iso8601( void );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include <vips/intl.h>
|
#include <vips/intl.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -326,11 +327,11 @@ vips_streamib_require( VipsStreamib *streamib, int require )
|
|||||||
* slower vips_streamib_get_line_copy().
|
* slower vips_streamib_get_line_copy().
|
||||||
*
|
*
|
||||||
* The return value is owned by @streamib and must not be freed. It
|
* The return value is owned by @streamib and must not be freed. It
|
||||||
* is valid until the next call to vips_streamib_get_line().
|
* is valid until the next get call @streamib.
|
||||||
*
|
*
|
||||||
* Returns: the next line from the file, or NULL on EOF or read error.
|
* Returns: the next line of text, or NULL on EOF or read error.
|
||||||
*/
|
*/
|
||||||
const unsigned char *
|
const char *
|
||||||
vips_streamib_get_line( VipsStreamib *streamib )
|
vips_streamib_get_line( VipsStreamib *streamib )
|
||||||
{
|
{
|
||||||
int write_point;
|
int write_point;
|
||||||
@ -379,7 +380,7 @@ vips_streamib_get_line( VipsStreamib *streamib )
|
|||||||
|
|
||||||
VIPS_DEBUG_MSG( " %s\n", streamib->line );
|
VIPS_DEBUG_MSG( " %s\n", streamib->line );
|
||||||
|
|
||||||
return( streamib->line );
|
return( (const char *) streamib->line );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -395,9 +396,9 @@ vips_streamib_get_line( VipsStreamib *streamib )
|
|||||||
* This is slower than vips_streamib_get_line(), but can work with lines of
|
* This is slower than vips_streamib_get_line(), but can work with lines of
|
||||||
* any length.
|
* any length.
|
||||||
*
|
*
|
||||||
* Returns: the next line from the file, or NULL on EOF or read error.
|
* Returns: the next line of text, or NULL on EOF or read error.
|
||||||
*/
|
*/
|
||||||
unsigned char *
|
char *
|
||||||
vips_streamib_get_line_copy( VipsStreamib *streamib )
|
vips_streamib_get_line_copy( VipsStreamib *streamib )
|
||||||
{
|
{
|
||||||
static const unsigned char null = '\0';
|
static const unsigned char null = '\0';
|
||||||
@ -406,7 +407,7 @@ vips_streamib_get_line_copy( VipsStreamib *streamib )
|
|||||||
|
|
||||||
GByteArray *buffer;
|
GByteArray *buffer;
|
||||||
int ch;
|
int ch;
|
||||||
unsigned char *result;
|
char *result;
|
||||||
|
|
||||||
buffer = g_byte_array_new();
|
buffer = g_byte_array_new();
|
||||||
|
|
||||||
@ -435,9 +436,87 @@ vips_streamib_get_line_copy( VipsStreamib *streamib )
|
|||||||
|
|
||||||
g_byte_array_append( buffer, &null, 1 );
|
g_byte_array_append( buffer, &null, 1 );
|
||||||
|
|
||||||
result = (unsigned char *) g_byte_array_free( buffer, FALSE );
|
result = (char *) g_byte_array_free( buffer, FALSE );
|
||||||
|
|
||||||
VIPS_DEBUG_MSG( " %s\n", result );
|
VIPS_DEBUG_MSG( " %s\n", result );
|
||||||
|
|
||||||
return( result );
|
return( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_streamib_get_non_whitespace:
|
||||||
|
* @streamib: stream to operate on
|
||||||
|
*
|
||||||
|
* Fetch the next chunk of non-whitespace text from the stream, and
|
||||||
|
* null-terminate it.
|
||||||
|
*
|
||||||
|
* After this, the next getc will be the first char of the next block of
|
||||||
|
* whitespace (or EOF).
|
||||||
|
*
|
||||||
|
* If the first getc is whitespace, stop instantly and return the empty
|
||||||
|
* string.
|
||||||
|
*
|
||||||
|
* If the item is longer than some arbitrary (but large) limit, it is
|
||||||
|
* truncated.
|
||||||
|
*
|
||||||
|
* The return value is owned by @streamib and must not be freed. It
|
||||||
|
* is valid until the next get call @streamib.
|
||||||
|
*
|
||||||
|
* Returns: the next block of non-whitespace, or NULL on EOF or read error.
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
vips_streamib_get_non_whitespace( VipsStreamib *streamib )
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < VIPS_STREAMIB_BUFFER_SIZE &&
|
||||||
|
!isspace( ch = VIPS_STREAMIB_GETC( streamib ) ) &&
|
||||||
|
ch != EOF; i++ )
|
||||||
|
streamib->line[i] = ch;
|
||||||
|
streamib->line[i] = '\0';
|
||||||
|
|
||||||
|
/* If we stopped before seeing any whitespace, skip to the end of the
|
||||||
|
* block of non-whitespace.
|
||||||
|
*/
|
||||||
|
if( !isspace( ch ) )
|
||||||
|
while( !isspace( ch = VIPS_STREAMIB_GETC( streamib ) ) &&
|
||||||
|
ch != EOF )
|
||||||
|
;
|
||||||
|
|
||||||
|
/* If we finally stopped on whitespace, step back one so the next get
|
||||||
|
* will be whitespace (or EOF).
|
||||||
|
*/
|
||||||
|
if( isspace( ch ) )
|
||||||
|
VIPS_STREAMIB_UNGETC( streamib );
|
||||||
|
|
||||||
|
return( (const char *) streamib->line );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_streamib_skip_whitespace:
|
||||||
|
* @streamib: stream to operate on
|
||||||
|
*
|
||||||
|
* After this, the next getc will be the first char of the next block of
|
||||||
|
* non-whitespace (or EOF).
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_streamib_skip_whitespace( VipsStreamib *streamib )
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
while( isspace( ch = VIPS_STREAMIB_GETC( streamib ) ) )
|
||||||
|
;
|
||||||
|
VIPS_STREAMIB_UNGETC( streamib );
|
||||||
|
|
||||||
|
/* # skip comments too.
|
||||||
|
*/
|
||||||
|
if( ch == '#' &&
|
||||||
|
(!vips_streamib_get_line( streamib ) ||
|
||||||
|
vips_streamib_skip_whitespace( streamib )) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
@ -402,35 +402,6 @@ vips_streamo_finish( VipsStreamo *streamo )
|
|||||||
class->finish( streamo );
|
class->finish( streamo );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* vips_streamo_writef:
|
|
||||||
* @streamo: output stream to operate on
|
|
||||||
* @fmt: <function>printf()</function>-style format string
|
|
||||||
* @...: arguments to format string
|
|
||||||
*
|
|
||||||
* Format the string and write to @streamo.
|
|
||||||
*
|
|
||||||
* Returns: 0 on success, and -1 on error.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
vips_streamo_writef( VipsStreamo *streamo, const char *fmt, ... )
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
char *line;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
va_start( ap, fmt );
|
|
||||||
line = g_strdup_vprintf( fmt, ap );
|
|
||||||
va_end( ap );
|
|
||||||
|
|
||||||
result = vips_streamo_write( streamo,
|
|
||||||
(unsigned char *) line, strlen( line ) );
|
|
||||||
|
|
||||||
g_free( line );
|
|
||||||
|
|
||||||
return( result );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_streamo_putc:
|
* vips_streamo_putc:
|
||||||
* @streamo: output stream to operate on
|
* @streamo: output stream to operate on
|
||||||
@ -455,6 +426,50 @@ vips_streamo_putc( VipsStreamo *streamo, int ch )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_streamo_writes:
|
||||||
|
* @streamo: output stream to operate on
|
||||||
|
* @str: string to write
|
||||||
|
*
|
||||||
|
* Write a null-terminated string to @streamo.
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, and -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_streamo_writes( VipsStreamo *streamo, const char *str )
|
||||||
|
{
|
||||||
|
return( vips_streamo_write( streamo,
|
||||||
|
(unsigned char *) str, strlen( str ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_streamo_writef:
|
||||||
|
* @streamo: output stream to operate on
|
||||||
|
* @fmt: <function>printf()</function>-style format string
|
||||||
|
* @...: arguments to format string
|
||||||
|
*
|
||||||
|
* Format the string and write to @streamo.
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, and -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_streamo_writef( VipsStreamo *streamo, const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char *line;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
va_start( ap, fmt );
|
||||||
|
line = g_strdup_vprintf( fmt, ap );
|
||||||
|
va_end( ap );
|
||||||
|
|
||||||
|
result = vips_streamo_writes( streamo, line );
|
||||||
|
|
||||||
|
g_free( line );
|
||||||
|
|
||||||
|
return( result );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_streamo_write_amp:
|
* vips_streamo_write_amp:
|
||||||
* @streamo: output stream to operate on
|
* @streamo: output stream to operate on
|
||||||
|
@ -2024,3 +2024,28 @@ vips__windows_prefix( void )
|
|||||||
return( (const char *) g_once( &once,
|
return( (const char *) g_once( &once,
|
||||||
(GThreadFunc) vips__windows_prefix_once, NULL ) );
|
(GThreadFunc) vips__windows_prefix_once, NULL ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
vips__get_iso8601( void )
|
||||||
|
{
|
||||||
|
char *date;
|
||||||
|
|
||||||
|
#ifdef HAVE_DATE_TIME_FORMAT_ISO8601
|
||||||
|
{
|
||||||
|
GDateTime *now;
|
||||||
|
|
||||||
|
now = g_date_time_new_now_local();
|
||||||
|
date = g_date_time_format_iso8601( now );
|
||||||
|
g_date_time_unref( now );
|
||||||
|
}
|
||||||
|
#else /*!HAVE_DATE_TIME_FORMAT_ISO8601*/
|
||||||
|
{
|
||||||
|
GTimeVal now;
|
||||||
|
|
||||||
|
g_get_current_time( &now );
|
||||||
|
date = g_time_val_to_iso8601( &now );
|
||||||
|
}
|
||||||
|
#endif /*HAVE_DATE_TIME_FORMAT_ISO8601*/
|
||||||
|
|
||||||
|
return( date );
|
||||||
|
}
|
||||||
|
@ -957,22 +957,7 @@ vips__xml_properties( VipsImage *image )
|
|||||||
VipsDbuf dbuf;
|
VipsDbuf dbuf;
|
||||||
char *date;
|
char *date;
|
||||||
|
|
||||||
#ifdef HAVE_DATE_TIME_FORMAT_ISO8601
|
date = vips__get_iso8601();
|
||||||
{
|
|
||||||
GDateTime *now;
|
|
||||||
|
|
||||||
now = g_date_time_new_now_local();
|
|
||||||
date = g_date_time_format_iso8601( now );
|
|
||||||
g_date_time_unref( now );
|
|
||||||
}
|
|
||||||
#else /*!HAVE_DATE_TIME_FORMAT_ISO8601*/
|
|
||||||
{
|
|
||||||
GTimeVal now;
|
|
||||||
|
|
||||||
g_get_current_time( &now );
|
|
||||||
date = g_time_val_to_iso8601( &now );
|
|
||||||
}
|
|
||||||
#endif /*HAVE_DATE_TIME_FORMAT_ISO8601*/
|
|
||||||
|
|
||||||
vips_dbuf_init( &dbuf );
|
vips_dbuf_init( &dbuf );
|
||||||
vips_dbuf_writef( &dbuf, "<?xml version=\"1.0\"?>\n" );
|
vips_dbuf_writef( &dbuf, "<?xml version=\"1.0\"?>\n" );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user