revise streamo, ppm save uses it
streamo is simpler, and has a fast putc.
This commit is contained in:
parent
7aec350f1c
commit
3bbadc0198
@ -149,8 +149,8 @@ int vips__ppm_isppm( const char *filename );
|
||||
VipsForeignFlags vips__ppm_flags( const char *filename );
|
||||
extern const char *vips__ppm_suffs[];
|
||||
|
||||
int vips__ppm_save( VipsImage *in, const char *filename,
|
||||
gboolean ascii, gboolean squash );
|
||||
int vips__ppm_save_stream( VipsImage *in, VipsStreamo *streamo,
|
||||
gboolean ascii, gboolean squash );
|
||||
|
||||
int vips__rad_israd( VipsStreami *streami );
|
||||
int vips__rad_header( VipsStreami *streami, VipsImage *out );
|
||||
|
@ -36,6 +36,8 @@
|
||||
* linebreaks
|
||||
* 29/7/19 Kyle-Kyle
|
||||
* - 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 {
|
||||
VipsImage *in;
|
||||
FILE *fp;
|
||||
char *name;
|
||||
VipsStreamo *streamo;
|
||||
write_fn fn;
|
||||
} Write;
|
||||
|
||||
static void
|
||||
write_destroy( Write *write )
|
||||
{
|
||||
VIPS_FREEF( fclose, write->fp );
|
||||
VIPS_FREE( write->name );
|
||||
if( write->streamo )
|
||||
vips_streamo_finish( write->streamo );
|
||||
VIPS_UNREF( write->streamo );
|
||||
|
||||
vips_free( write );
|
||||
}
|
||||
|
||||
static Write *
|
||||
write_new( VipsImage *in, const char *name )
|
||||
write_new( VipsImage *in, VipsStreamo *streamo )
|
||||
{
|
||||
Write *write;
|
||||
|
||||
@ -578,14 +580,10 @@ write_new( VipsImage *in, const char *name )
|
||||
return( NULL );
|
||||
|
||||
write->in = in;
|
||||
write->name = vips_strdup( NULL, name );
|
||||
write->fp = vips__file_open_write( name, FALSE );
|
||||
write->streamo = streamo;
|
||||
g_object_ref( streamo );
|
||||
write->fn = NULL;
|
||||
|
||||
if( !write->name || !write->fp ) {
|
||||
write_destroy( write );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
return( write );
|
||||
}
|
||||
|
||||
@ -599,17 +597,17 @@ write_ppm_line_ascii( Write *write, VipsPel *p )
|
||||
for( k = 0; k < write->in->Bands; k++ ) {
|
||||
switch( write->in->BandFmt ) {
|
||||
case VIPS_FORMAT_UCHAR:
|
||||
fprintf( write->fp,
|
||||
vips_streamo_writef( write->streamo,
|
||||
"%d ", p[k] );
|
||||
break;
|
||||
|
||||
case VIPS_FORMAT_USHORT:
|
||||
fprintf( write->fp,
|
||||
vips_streamo_writef( write->streamo,
|
||||
"%d ", ((unsigned short *) p)[k] );
|
||||
break;
|
||||
|
||||
case VIPS_FORMAT_UINT:
|
||||
fprintf( write->fp,
|
||||
vips_streamo_writef( write->streamo,
|
||||
"%d ", ((unsigned int *) p)[k] );
|
||||
break;
|
||||
|
||||
@ -621,11 +619,8 @@ write_ppm_line_ascii( Write *write, VipsPel *p )
|
||||
p += sk;
|
||||
}
|
||||
|
||||
if( !fprintf( write->fp, "\n" ) ) {
|
||||
vips_error_system( errno, "vips2ppm",
|
||||
"%s", _( "write error" ) );
|
||||
if( vips_streamo_writef( write->streamo, "\n" ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -636,13 +631,10 @@ write_ppm_line_ascii_squash( Write *write, VipsPel *p )
|
||||
int 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" ) ) {
|
||||
vips_error_system( errno, "vips2ppm",
|
||||
"%s", _( "write error" ) );
|
||||
if( vips_streamo_writef( write->streamo, "\n" ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -650,8 +642,8 @@ write_ppm_line_ascii_squash( Write *write, VipsPel *p )
|
||||
static int
|
||||
write_ppm_line_binary( Write *write, VipsPel *p )
|
||||
{
|
||||
if( vips__file_write( p, VIPS_IMAGE_SIZEOF_LINE( write->in ), 1,
|
||||
write->fp ) )
|
||||
if( vips_streamo_write( write->streamo,
|
||||
p, VIPS_IMAGE_SIZEOF_LINE( write->in ) ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
@ -672,11 +664,8 @@ write_ppm_line_binary_squash( Write *write, VipsPel *p )
|
||||
bits |= p[x] ? 0 : 1;
|
||||
|
||||
if( n_bits == 8 ) {
|
||||
if( fputc( bits, write->fp ) == EOF ) {
|
||||
vips_error_system( errno, "vips2ppm",
|
||||
"%s", _( "write error" ) );
|
||||
if( VIPS_STREAMO_PUTC( write->streamo, bits ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
if( n_bits ) {
|
||||
if( fputc( bits, write->fp ) == EOF ) {
|
||||
vips_error_system( errno, "vips2ppm",
|
||||
"%s", _( "write error" ) );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
if( n_bits &&
|
||||
VIPS_STREAMO_PUTC( write->streamo, bits ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -740,23 +725,27 @@ write_ppm( Write *write, gboolean ascii, gboolean squash )
|
||||
else
|
||||
g_assert_not_reached();
|
||||
|
||||
fprintf( write->fp, "%s\n", magic );
|
||||
vips_streamo_writef( write->streamo, "%s\n", magic );
|
||||
time( &timebuf );
|
||||
fprintf( write->fp, "#vips2ppm - %s\n", ctime( &timebuf ) );
|
||||
fprintf( write->fp, "%d %d\n", in->Xsize, in->Ysize );
|
||||
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:
|
||||
fprintf( write->fp, "%d\n", UCHAR_MAX );
|
||||
vips_streamo_writef( write->streamo,
|
||||
"%d\n", UCHAR_MAX );
|
||||
break;
|
||||
|
||||
case VIPS_FORMAT_USHORT:
|
||||
fprintf( write->fp, "%d\n", USHRT_MAX );
|
||||
vips_streamo_writef( write->streamo,
|
||||
"%d\n", USHRT_MAX );
|
||||
break;
|
||||
|
||||
case VIPS_FORMAT_UINT:
|
||||
fprintf( write->fp, "%d\n", UINT_MAX );
|
||||
vips_streamo_writef( write->streamo,
|
||||
"%d\n", UINT_MAX );
|
||||
break;
|
||||
|
||||
case VIPS_FORMAT_FLOAT:
|
||||
@ -767,7 +756,8 @@ write_ppm( Write *write, gboolean ascii, gboolean squash )
|
||||
scale = 1;
|
||||
if( !vips_amiMSBfirst() )
|
||||
scale *= -1;
|
||||
fprintf( write->fp, "%g\n", scale );
|
||||
vips_streamo_writef( write->streamo,
|
||||
"%g\n", scale );
|
||||
}
|
||||
break;
|
||||
|
||||
@ -791,7 +781,7 @@ write_ppm( Write *write, gboolean ascii, gboolean squash )
|
||||
}
|
||||
|
||||
int
|
||||
vips__ppm_save( VipsImage *in, const char *filename,
|
||||
vips__ppm_save_stream( VipsImage *in, VipsStreamo *streamo,
|
||||
gboolean ascii, gboolean squash )
|
||||
{
|
||||
Write *write;
|
||||
@ -820,7 +810,7 @@ vips__ppm_save( VipsImage *in, const char *filename,
|
||||
squash = FALSE;
|
||||
}
|
||||
|
||||
if( !(write = write_new( in, filename )) )
|
||||
if( !(write = write_new( in, streamo )) )
|
||||
return( -1 );
|
||||
|
||||
if( write_ppm( write, ascii, squash ) ) {
|
||||
|
@ -70,13 +70,20 @@ vips_foreign_save_ppm_build( VipsObject *object )
|
||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||
VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) object;
|
||||
|
||||
VipsStreamo *streamo;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_ppm_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__ppm_save( save->ready, ppm->filename,
|
||||
ppm->ascii, ppm->squash ) )
|
||||
if( !(streamo = vips_streamo_new_to_filename( ppm->filename )) )
|
||||
return( -1 );
|
||||
if( vips__ppm_save_stream( save->ready, streamo,
|
||||
ppm->ascii, ppm->squash ) ) {
|
||||
VIPS_UNREF( streamo );
|
||||
return( -1 );
|
||||
}
|
||||
VIPS_UNREF( streamo );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -365,11 +365,11 @@ typedef struct _VipsStreamo {
|
||||
*/
|
||||
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 *write_point;
|
||||
int bytes_remaining;
|
||||
int write_point;
|
||||
|
||||
} VipsStreamo;
|
||||
|
||||
@ -395,6 +395,14 @@ VipsStreamo *vips_streamo_new_to_memory( void );
|
||||
int vips_streamo_write( VipsStreamo *streamo, const void *data, size_t length );
|
||||
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, ... )
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
|
||||
|
@ -198,8 +198,7 @@ static void
|
||||
vips_streamo_init( VipsStreamo *streamo )
|
||||
{
|
||||
streamo->blob = vips_blob_new( NULL, NULL, 0 );
|
||||
streamo->bytes_remaining = VIPS_STREAMO_BUFFER_SIZE;
|
||||
streamo->write_point = streamo->output_buffer;
|
||||
streamo->write_point = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -323,18 +322,14 @@ vips_streamo_write_unbuffered( VipsStreamo *streamo,
|
||||
static int
|
||||
vips_streamo_flush( VipsStreamo *streamo )
|
||||
{
|
||||
int bytes_in_buffer =
|
||||
VIPS_STREAMO_BUFFER_SIZE - streamo->bytes_remaining;
|
||||
g_assert( streamo->write_point >= 0 );
|
||||
g_assert( streamo->write_point <= VIPS_STREAMO_BUFFER_SIZE );
|
||||
|
||||
g_assert( bytes_in_buffer >= 0 );
|
||||
g_assert( bytes_in_buffer <= VIPS_STREAMO_BUFFER_SIZE );
|
||||
|
||||
if( bytes_in_buffer > 0 ) {
|
||||
if( streamo->write_point > 0 ) {
|
||||
if( vips_streamo_write_unbuffered( streamo,
|
||||
streamo->output_buffer, bytes_in_buffer ) )
|
||||
streamo->output_buffer, streamo->write_point ) )
|
||||
return( -1 );
|
||||
streamo->bytes_remaining = VIPS_STREAMO_BUFFER_SIZE;
|
||||
streamo->write_point = streamo->output_buffer;
|
||||
streamo->write_point = 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 );
|
||||
|
||||
if( streamo->bytes_remaining >= length ) {
|
||||
memcpy( streamo->write_point, buffer, length );
|
||||
streamo->bytes_remaining -= length;
|
||||
streamo->write_point += length;
|
||||
if( length > VIPS_STREAMO_BUFFER_SIZE - streamo->write_point &&
|
||||
vips_streamo_flush( streamo ) )
|
||||
return( -1 );
|
||||
|
||||
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 {
|
||||
if( vips_streamo_flush( streamo ) )
|
||||
return( -1 );
|
||||
|
||||
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 );
|
||||
memcpy( streamo->output_buffer + streamo->write_point,
|
||||
buffer, length );
|
||||
streamo->write_point += length;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
@ -443,6 +431,30 @@ vips_streamo_writef( VipsStreamo *streamo, const char *fmt, ... )
|
||||
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:
|
||||
* @streamo: output stream to operate on
|
||||
@ -497,8 +509,7 @@ vips_streamo_write_amp( VipsStreamo *streamo, const char *str )
|
||||
return( -1 );
|
||||
}
|
||||
else {
|
||||
if( !vips_streamo_write( streamo,
|
||||
(guchar *) p, 1 ) )
|
||||
if( !vips_streamo_putc( streamo, *p ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user