revise streamo, ppm save uses it
streamo is simpler, and has a fast putc.
This commit is contained in:
parent
7aec350f1c
commit
3bbadc0198
@ -149,7 +149,7 @@ int vips__ppm_isppm( const char *filename );
|
|||||||
VipsForeignFlags vips__ppm_flags( const char *filename );
|
VipsForeignFlags vips__ppm_flags( const char *filename );
|
||||||
extern const char *vips__ppm_suffs[];
|
extern const char *vips__ppm_suffs[];
|
||||||
|
|
||||||
int vips__ppm_save( VipsImage *in, const char *filename,
|
int vips__ppm_save_stream( VipsImage *in, VipsStreamo *streamo,
|
||||||
gboolean ascii, gboolean squash );
|
gboolean ascii, gboolean squash );
|
||||||
|
|
||||||
int vips__rad_israd( VipsStreami *streami );
|
int vips__rad_israd( VipsStreami *streami );
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
* linebreaks
|
* linebreaks
|
||||||
* 29/7/19 Kyle-Kyle
|
* 29/7/19 Kyle-Kyle
|
||||||
* - fix a loop with malformed ppm
|
* - fix a loop with malformed ppm
|
||||||
|
* 13/11/19
|
||||||
|
* - ppm save redone with streams
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -555,22 +557,22 @@ typedef int (*write_fn)( struct _Write *write, VipsPel *p );
|
|||||||
*/
|
*/
|
||||||
typedef struct _Write {
|
typedef struct _Write {
|
||||||
VipsImage *in;
|
VipsImage *in;
|
||||||
FILE *fp;
|
VipsStreamo *streamo;
|
||||||
char *name;
|
|
||||||
write_fn fn;
|
write_fn fn;
|
||||||
} Write;
|
} Write;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_destroy( Write *write )
|
write_destroy( Write *write )
|
||||||
{
|
{
|
||||||
VIPS_FREEF( fclose, write->fp );
|
if( write->streamo )
|
||||||
VIPS_FREE( write->name );
|
vips_streamo_finish( write->streamo );
|
||||||
|
VIPS_UNREF( write->streamo );
|
||||||
|
|
||||||
vips_free( write );
|
vips_free( write );
|
||||||
}
|
}
|
||||||
|
|
||||||
static Write *
|
static Write *
|
||||||
write_new( VipsImage *in, const char *name )
|
write_new( VipsImage *in, VipsStreamo *streamo )
|
||||||
{
|
{
|
||||||
Write *write;
|
Write *write;
|
||||||
|
|
||||||
@ -578,13 +580,9 @@ write_new( VipsImage *in, const char *name )
|
|||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
write->in = in;
|
write->in = in;
|
||||||
write->name = vips_strdup( NULL, name );
|
write->streamo = streamo;
|
||||||
write->fp = vips__file_open_write( name, FALSE );
|
g_object_ref( streamo );
|
||||||
|
write->fn = NULL;
|
||||||
if( !write->name || !write->fp ) {
|
|
||||||
write_destroy( write );
|
|
||||||
return( NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
return( write );
|
return( write );
|
||||||
}
|
}
|
||||||
@ -599,17 +597,17 @@ write_ppm_line_ascii( Write *write, VipsPel *p )
|
|||||||
for( k = 0; k < write->in->Bands; k++ ) {
|
for( k = 0; k < write->in->Bands; k++ ) {
|
||||||
switch( write->in->BandFmt ) {
|
switch( write->in->BandFmt ) {
|
||||||
case VIPS_FORMAT_UCHAR:
|
case VIPS_FORMAT_UCHAR:
|
||||||
fprintf( write->fp,
|
vips_streamo_writef( write->streamo,
|
||||||
"%d ", p[k] );
|
"%d ", p[k] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_USHORT:
|
case VIPS_FORMAT_USHORT:
|
||||||
fprintf( write->fp,
|
vips_streamo_writef( write->streamo,
|
||||||
"%d ", ((unsigned short *) p)[k] );
|
"%d ", ((unsigned short *) p)[k] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_UINT:
|
case VIPS_FORMAT_UINT:
|
||||||
fprintf( write->fp,
|
vips_streamo_writef( write->streamo,
|
||||||
"%d ", ((unsigned int *) p)[k] );
|
"%d ", ((unsigned int *) p)[k] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -621,11 +619,8 @@ write_ppm_line_ascii( Write *write, VipsPel *p )
|
|||||||
p += sk;
|
p += sk;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !fprintf( write->fp, "\n" ) ) {
|
if( vips_streamo_writef( write->streamo, "\n" ) )
|
||||||
vips_error_system( errno, "vips2ppm",
|
|
||||||
"%s", _( "write error" ) );
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -636,13 +631,10 @@ write_ppm_line_ascii_squash( Write *write, VipsPel *p )
|
|||||||
int x;
|
int x;
|
||||||
|
|
||||||
for( x = 0; x < write->in->Xsize; x++ )
|
for( x = 0; x < write->in->Xsize; x++ )
|
||||||
fprintf( write->fp, "%d ", p[x] ? 0 : 1 );
|
vips_streamo_writef( write->streamo, "%d ", p[x] ? 0 : 1 );
|
||||||
|
|
||||||
if( !fprintf( write->fp, "\n" ) ) {
|
if( vips_streamo_writef( write->streamo, "\n" ) )
|
||||||
vips_error_system( errno, "vips2ppm",
|
|
||||||
"%s", _( "write error" ) );
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -650,8 +642,8 @@ write_ppm_line_ascii_squash( Write *write, VipsPel *p )
|
|||||||
static int
|
static int
|
||||||
write_ppm_line_binary( Write *write, VipsPel *p )
|
write_ppm_line_binary( Write *write, VipsPel *p )
|
||||||
{
|
{
|
||||||
if( vips__file_write( p, VIPS_IMAGE_SIZEOF_LINE( write->in ), 1,
|
if( vips_streamo_write( write->streamo,
|
||||||
write->fp ) )
|
p, VIPS_IMAGE_SIZEOF_LINE( write->in ) ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -672,11 +664,8 @@ write_ppm_line_binary_squash( Write *write, VipsPel *p )
|
|||||||
bits |= p[x] ? 0 : 1;
|
bits |= p[x] ? 0 : 1;
|
||||||
|
|
||||||
if( n_bits == 8 ) {
|
if( n_bits == 8 ) {
|
||||||
if( fputc( bits, write->fp ) == EOF ) {
|
if( VIPS_STREAMO_PUTC( write->streamo, bits ) )
|
||||||
vips_error_system( errno, "vips2ppm",
|
|
||||||
"%s", _( "write error" ) );
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
|
||||||
|
|
||||||
bits = 0;
|
bits = 0;
|
||||||
n_bits = 0;
|
n_bits = 0;
|
||||||
@ -685,13 +674,9 @@ write_ppm_line_binary_squash( Write *write, VipsPel *p )
|
|||||||
|
|
||||||
/* Flush any remaining bits in this line.
|
/* Flush any remaining bits in this line.
|
||||||
*/
|
*/
|
||||||
if( n_bits ) {
|
if( n_bits &&
|
||||||
if( fputc( bits, write->fp ) == EOF ) {
|
VIPS_STREAMO_PUTC( write->streamo, bits ) )
|
||||||
vips_error_system( errno, "vips2ppm",
|
return( -1 );
|
||||||
"%s", _( "write error" ) );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -740,23 +725,27 @@ write_ppm( Write *write, gboolean ascii, gboolean squash )
|
|||||||
else
|
else
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
|
|
||||||
fprintf( write->fp, "%s\n", magic );
|
vips_streamo_writef( write->streamo, "%s\n", magic );
|
||||||
time( &timebuf );
|
time( &timebuf );
|
||||||
fprintf( write->fp, "#vips2ppm - %s\n", ctime( &timebuf ) );
|
vips_streamo_writef( write->streamo,
|
||||||
fprintf( write->fp, "%d %d\n", in->Xsize, in->Ysize );
|
"#vips2ppm - %s\n", ctime( &timebuf ) );
|
||||||
|
vips_streamo_writef( write->streamo, "%d %d\n", in->Xsize, in->Ysize );
|
||||||
|
|
||||||
if( !squash )
|
if( !squash )
|
||||||
switch( in->BandFmt ) {
|
switch( in->BandFmt ) {
|
||||||
case VIPS_FORMAT_UCHAR:
|
case VIPS_FORMAT_UCHAR:
|
||||||
fprintf( write->fp, "%d\n", UCHAR_MAX );
|
vips_streamo_writef( write->streamo,
|
||||||
|
"%d\n", UCHAR_MAX );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_USHORT:
|
case VIPS_FORMAT_USHORT:
|
||||||
fprintf( write->fp, "%d\n", USHRT_MAX );
|
vips_streamo_writef( write->streamo,
|
||||||
|
"%d\n", USHRT_MAX );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_UINT:
|
case VIPS_FORMAT_UINT:
|
||||||
fprintf( write->fp, "%d\n", UINT_MAX );
|
vips_streamo_writef( write->streamo,
|
||||||
|
"%d\n", UINT_MAX );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_FLOAT:
|
case VIPS_FORMAT_FLOAT:
|
||||||
@ -767,7 +756,8 @@ write_ppm( Write *write, gboolean ascii, gboolean squash )
|
|||||||
scale = 1;
|
scale = 1;
|
||||||
if( !vips_amiMSBfirst() )
|
if( !vips_amiMSBfirst() )
|
||||||
scale *= -1;
|
scale *= -1;
|
||||||
fprintf( write->fp, "%g\n", scale );
|
vips_streamo_writef( write->streamo,
|
||||||
|
"%g\n", scale );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -791,7 +781,7 @@ write_ppm( Write *write, gboolean ascii, gboolean squash )
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vips__ppm_save( VipsImage *in, const char *filename,
|
vips__ppm_save_stream( VipsImage *in, VipsStreamo *streamo,
|
||||||
gboolean ascii, gboolean squash )
|
gboolean ascii, gboolean squash )
|
||||||
{
|
{
|
||||||
Write *write;
|
Write *write;
|
||||||
@ -820,7 +810,7 @@ vips__ppm_save( VipsImage *in, const char *filename,
|
|||||||
squash = FALSE;
|
squash = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !(write = write_new( in, filename )) )
|
if( !(write = write_new( in, streamo )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( write_ppm( write, ascii, squash ) ) {
|
if( write_ppm( write, ascii, squash ) ) {
|
||||||
|
@ -70,13 +70,20 @@ 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;
|
||||||
|
|
||||||
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( vips__ppm_save( save->ready, ppm->filename,
|
if( !(streamo = vips_streamo_new_to_filename( ppm->filename )) )
|
||||||
ppm->ascii, ppm->squash ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
if( vips__ppm_save_stream( save->ready, streamo,
|
||||||
|
ppm->ascii, ppm->squash ) ) {
|
||||||
|
VIPS_UNREF( streamo );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
VIPS_UNREF( streamo );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
@ -365,11 +365,11 @@ typedef struct _VipsStreamo {
|
|||||||
*/
|
*/
|
||||||
VipsBlob *blob;
|
VipsBlob *blob;
|
||||||
|
|
||||||
/* Buffer small writes here.
|
/* Buffer small writes here. write_point is the index of the next
|
||||||
|
* character to write.
|
||||||
*/
|
*/
|
||||||
unsigned char output_buffer[VIPS_STREAMO_BUFFER_SIZE];
|
unsigned char output_buffer[VIPS_STREAMO_BUFFER_SIZE];
|
||||||
unsigned char *write_point;
|
int write_point;
|
||||||
int bytes_remaining;
|
|
||||||
|
|
||||||
} VipsStreamo;
|
} VipsStreamo;
|
||||||
|
|
||||||
@ -395,6 +395,14 @@ VipsStreamo *vips_streamo_new_to_memory( void );
|
|||||||
int vips_streamo_write( VipsStreamo *streamo, const void *data, size_t length );
|
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 );
|
||||||
|
|
||||||
|
#define VIPS_STREAMO_PUTC( S, C ) ( \
|
||||||
|
(S)->write_point <= VIPS_STREAMO_BUFFER_SIZE ? \
|
||||||
|
((S)->output_buffer[(S)->write_point++] = (C), 0) : \
|
||||||
|
vips_streamo_putc( (S), (C) ) \
|
||||||
|
)
|
||||||
|
|
||||||
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)));
|
||||||
|
|
||||||
|
@ -198,8 +198,7 @@ static void
|
|||||||
vips_streamo_init( VipsStreamo *streamo )
|
vips_streamo_init( VipsStreamo *streamo )
|
||||||
{
|
{
|
||||||
streamo->blob = vips_blob_new( NULL, NULL, 0 );
|
streamo->blob = vips_blob_new( NULL, NULL, 0 );
|
||||||
streamo->bytes_remaining = VIPS_STREAMO_BUFFER_SIZE;
|
streamo->write_point = 0;
|
||||||
streamo->write_point = streamo->output_buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -323,18 +322,14 @@ vips_streamo_write_unbuffered( VipsStreamo *streamo,
|
|||||||
static int
|
static int
|
||||||
vips_streamo_flush( VipsStreamo *streamo )
|
vips_streamo_flush( VipsStreamo *streamo )
|
||||||
{
|
{
|
||||||
int bytes_in_buffer =
|
g_assert( streamo->write_point >= 0 );
|
||||||
VIPS_STREAMO_BUFFER_SIZE - streamo->bytes_remaining;
|
g_assert( streamo->write_point <= VIPS_STREAMO_BUFFER_SIZE );
|
||||||
|
|
||||||
g_assert( bytes_in_buffer >= 0 );
|
if( streamo->write_point > 0 ) {
|
||||||
g_assert( bytes_in_buffer <= VIPS_STREAMO_BUFFER_SIZE );
|
|
||||||
|
|
||||||
if( bytes_in_buffer > 0 ) {
|
|
||||||
if( vips_streamo_write_unbuffered( streamo,
|
if( vips_streamo_write_unbuffered( streamo,
|
||||||
streamo->output_buffer, bytes_in_buffer ) )
|
streamo->output_buffer, streamo->write_point ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
streamo->bytes_remaining = VIPS_STREAMO_BUFFER_SIZE;
|
streamo->write_point = 0;
|
||||||
streamo->write_point = streamo->output_buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -355,27 +350,20 @@ vips_streamo_write( VipsStreamo *streamo, const void *buffer, size_t length )
|
|||||||
{
|
{
|
||||||
VIPS_DEBUG_MSG( "vips_streamo_write: %zd bytes\n", length );
|
VIPS_DEBUG_MSG( "vips_streamo_write: %zd bytes\n", length );
|
||||||
|
|
||||||
if( streamo->bytes_remaining >= length ) {
|
if( length > VIPS_STREAMO_BUFFER_SIZE - streamo->write_point &&
|
||||||
memcpy( streamo->write_point, buffer, length );
|
vips_streamo_flush( streamo ) )
|
||||||
streamo->bytes_remaining -= length;
|
return( -1 );
|
||||||
streamo->write_point += length;
|
|
||||||
|
if( length > VIPS_STREAMO_BUFFER_SIZE - streamo->write_point ) {
|
||||||
|
/* Still too large? Do an unbuffered write.
|
||||||
|
*/
|
||||||
|
if( vips_streamo_write_unbuffered( streamo, buffer, length ) )
|
||||||
|
return( -1 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( vips_streamo_flush( streamo ) )
|
memcpy( streamo->output_buffer + streamo->write_point,
|
||||||
return( -1 );
|
buffer, length );
|
||||||
|
streamo->write_point += length;
|
||||||
if( streamo->bytes_remaining >= length ) {
|
|
||||||
memcpy( streamo->write_point, buffer, length );
|
|
||||||
streamo->bytes_remaining -= length;
|
|
||||||
streamo->write_point += length;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* The buffer is empty and we still have too much
|
|
||||||
* data. Write directly.
|
|
||||||
*/
|
|
||||||
if( vips_streamo_write_unbuffered( streamo,
|
|
||||||
buffer, length ) )
|
|
||||||
return( -1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -443,6 +431,30 @@ vips_streamo_writef( VipsStreamo *streamo, const char *fmt, ... )
|
|||||||
return( result );
|
return( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_streamo_putc:
|
||||||
|
* @streamo: output stream to operate on
|
||||||
|
* @ch: character to write
|
||||||
|
*
|
||||||
|
* Write a single character @ch to @streamo. See the macro VIPS_STREAMO_PUTC()
|
||||||
|
* for a faster way to do this.
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_streamo_putc( VipsStreamo *streamo, int ch )
|
||||||
|
{
|
||||||
|
VIPS_DEBUG_MSG( "vips_streamo_putc: %d\n", ch );
|
||||||
|
|
||||||
|
if( streamo->write_point > VIPS_STREAMO_BUFFER_SIZE &&
|
||||||
|
vips_streamo_flush( streamo ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
streamo->output_buffer[streamo->write_point++] = ch;
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_streamo_write_amp:
|
* vips_streamo_write_amp:
|
||||||
* @streamo: output stream to operate on
|
* @streamo: output stream to operate on
|
||||||
@ -497,8 +509,7 @@ vips_streamo_write_amp( VipsStreamo *streamo, const char *str )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( !vips_streamo_write( streamo,
|
if( !vips_streamo_putc( streamo, *p ) )
|
||||||
(guchar *) p, 1 ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user