start adding png stream save
doesn't pass the test suite yet
This commit is contained in:
parent
1bdadeed61
commit
55d2ba8a4d
@ -190,14 +190,10 @@ int vips__png_read_stream( VipsStreamInput *input, VipsImage *out,
|
||||
gboolean vips__png_isinterlaced_stream( VipsStreamInput *input );
|
||||
extern const char *vips__png_suffs[];
|
||||
|
||||
int vips__png_write( VipsImage *in, const char *filename,
|
||||
int vips__png_write_stream( VipsImage *in, VipsStreamOutput *output,
|
||||
int compress, int interlace, const char *profile,
|
||||
VipsForeignPngFilter filter, gboolean strip,
|
||||
gboolean palette, int colours, int Q, double dither );
|
||||
int vips__png_write_buf( VipsImage *in,
|
||||
void **obuf, size_t *olen, int compression, int interlace,
|
||||
const char *profile, VipsForeignPngFilter filter, gboolean strip,
|
||||
gboolean palette, int colours, int Q, double dither );
|
||||
|
||||
/* Map WEBP metadata names to vips names.
|
||||
*/
|
||||
|
@ -179,6 +179,63 @@ vips_foreign_save_png_init( VipsForeignSavePng *png )
|
||||
png->dither = 1.0;
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignSavePngStream {
|
||||
VipsForeignSavePng parent_object;
|
||||
|
||||
VipsStreamOutput *output;
|
||||
} VipsForeignSavePngStream;
|
||||
|
||||
typedef VipsForeignSavePngClass VipsForeignSavePngStreamClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsForeignSavePngStream, vips_foreign_save_png_stream,
|
||||
vips_foreign_save_png_get_type() );
|
||||
|
||||
static int
|
||||
vips_foreign_save_png_stream_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||
VipsForeignSavePng *png = (VipsForeignSavePng *) object;
|
||||
VipsForeignSavePngStream *stream = (VipsForeignSavePngStream *) object;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_png_stream_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__png_write_stream( save->ready, stream->output,
|
||||
png->compression, png->interlace, png->profile, png->filter,
|
||||
save->strip, png->palette, png->colours, png->Q, png->dither ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_save_png_stream_class_init( VipsForeignSavePngStreamClass *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 = "pngsave_stream";
|
||||
object_class->description = _( "save image to png stream" );
|
||||
object_class->build = vips_foreign_save_png_stream_build;
|
||||
|
||||
VIPS_ARG_OBJECT( class, "output", 1,
|
||||
_( "Output" ),
|
||||
_( "Stream to save to" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignSavePngStream, output ),
|
||||
VIPS_TYPE_STREAM_OUTPUT );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_save_png_stream_init( VipsForeignSavePngStream *stream )
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignSavePngFile {
|
||||
VipsForeignSavePng parent_object;
|
||||
|
||||
@ -197,15 +254,23 @@ vips_foreign_save_png_file_build( VipsObject *object )
|
||||
VipsForeignSavePng *png = (VipsForeignSavePng *) object;
|
||||
VipsForeignSavePngFile *png_file = (VipsForeignSavePngFile *) object;
|
||||
|
||||
VipsStreamOutput *output;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_png_file_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__png_write( save->ready,
|
||||
png_file->filename, png->compression, png->interlace,
|
||||
png->profile, png->filter, save->strip, png->palette,
|
||||
png->colours, png->Q, png->dither ) )
|
||||
if( !(output = vips_stream_output_new_from_filename(
|
||||
png_file->filename )) )
|
||||
return( -1 );
|
||||
if( vips__png_write_stream( save->ready, output,
|
||||
png->compression, png->interlace,
|
||||
png->profile, png->filter, save->strip, png->palette,
|
||||
png->colours, png->Q, png->dither ) ) {
|
||||
VIPS_UNREF( output );
|
||||
return( -1 );
|
||||
}
|
||||
VIPS_UNREF( output );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -252,27 +317,32 @@ vips_foreign_save_png_buffer_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||
VipsForeignSavePng *png = (VipsForeignSavePng *) object;
|
||||
VipsForeignSavePngBuffer *buffer = (VipsForeignSavePngBuffer *) object;
|
||||
|
||||
void *obuf;
|
||||
size_t olen;
|
||||
VipsStreamOutput *output;
|
||||
VipsBlob *blob;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_png_buffer_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__png_write_buf( save->ready, &obuf, &olen,
|
||||
png->compression, png->interlace, png->profile, png->filter,
|
||||
save->strip, png->palette, png->colours, png->Q, png->dither ) )
|
||||
if( !(output = vips_stream_output_new_memory()) )
|
||||
return( -1 );
|
||||
|
||||
/* vips__png_write_buf() makes a buffer that needs g_free(), not
|
||||
* vips_free().
|
||||
*/
|
||||
blob = vips_blob_new( (VipsCallbackFn) g_free, obuf, olen );
|
||||
g_object_set( object, "buffer", blob, NULL );
|
||||
if( vips__png_write_stream( save->ready, output,
|
||||
png->compression, png->interlace, png->profile, png->filter,
|
||||
save->strip, png->palette, png->colours, png->Q,
|
||||
png->dither ) ) {
|
||||
VIPS_UNREF( output );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
g_object_get( output, "blob", &blob, NULL );
|
||||
g_object_set( buffer, "buffer", blob, NULL );
|
||||
vips_area_unref( VIPS_AREA( blob ) );
|
||||
|
||||
VIPS_UNREF( output );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
@ -427,3 +497,39 @@ vips_pngsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_pngsave_stream: (method)
|
||||
* @in: image to save
|
||||
* @output: save image to this stream
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* * @compression: compression level
|
||||
* * @interlace: interlace image
|
||||
* * @profile: ICC profile to embed
|
||||
* * @filter: libpng row filter flag(s)
|
||||
* * @palette: enable quantisation to 8bpp palette
|
||||
* * @colours: max number of palette colours for quantisation
|
||||
* * @Q: quality for 8bpp quantisation (does not exceed @colours)
|
||||
* * @dither: amount of dithering for 8bpp quantization
|
||||
*
|
||||
* As vips_pngsave(), but save to a stream.
|
||||
*
|
||||
* See also: vips_pngsave(), vips_image_write_to_stream().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_pngsave_stream( VipsImage *in, VipsStreamOutput *output, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, output );
|
||||
result = vips_call_split( "pngsave_stream", ap, in, output );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ read_new( VipsStreamInput *input, VipsImage *out, gboolean fail )
|
||||
|
||||
g_signal_connect( out, "close",
|
||||
G_CALLBACK( read_close_cb ), read );
|
||||
g_signal_connect( out, "minimise",
|
||||
g_signal_connect( out, "minimise",
|
||||
G_CALLBACK( read_minimise_cb ), read );
|
||||
|
||||
if( !(read->pPng = png_create_read_struct(
|
||||
@ -780,8 +780,7 @@ typedef struct {
|
||||
VipsImage *in;
|
||||
VipsImage *memory;
|
||||
|
||||
FILE *fp;
|
||||
VipsDbuf dbuf;
|
||||
VipsStreamOutput *output;
|
||||
|
||||
png_structp pPng;
|
||||
png_infop pInfo;
|
||||
@ -791,9 +790,8 @@ typedef struct {
|
||||
static void
|
||||
write_finish( Write *write )
|
||||
{
|
||||
VIPS_FREEF( fclose, write->fp );
|
||||
VIPS_UNREF( write->memory );
|
||||
vips_dbuf_destroy( &write->dbuf );
|
||||
VIPS_UNREF( write->output );
|
||||
if( write->pPng )
|
||||
png_destroy_write_struct( &write->pPng, &write->pInfo );
|
||||
}
|
||||
@ -804,8 +802,17 @@ write_destroy( VipsImage *out, Write *write )
|
||||
write_finish( write );
|
||||
}
|
||||
|
||||
static void
|
||||
user_write_data( png_structp pPng, png_bytep data, png_size_t length )
|
||||
{
|
||||
Write *write = (Write *) png_get_io_ptr( pPng );
|
||||
|
||||
if( vips_stream_output_write( write->output, data, length ) )
|
||||
png_error( pPng, "not enough data" );
|
||||
}
|
||||
|
||||
static Write *
|
||||
write_new( VipsImage *in )
|
||||
write_new( VipsImage *in, VipsStreamOutput *output )
|
||||
{
|
||||
Write *write;
|
||||
|
||||
@ -814,8 +821,8 @@ write_new( VipsImage *in )
|
||||
memset( write, 0, sizeof( Write ) );
|
||||
write->in = in;
|
||||
write->memory = NULL;
|
||||
write->fp = NULL;
|
||||
vips_dbuf_init( &write->dbuf );
|
||||
write->output = output;
|
||||
g_object_ref( output );
|
||||
g_signal_connect( in, "close",
|
||||
G_CALLBACK( write_destroy ), write );
|
||||
|
||||
@ -833,6 +840,8 @@ write_new( VipsImage *in )
|
||||
PNG_SKIP_sRGB_CHECK_PROFILE, PNG_OPTION_ON );
|
||||
#endif /*PNG_SKIP_sRGB_CHECK_PROFILE*/
|
||||
|
||||
png_set_write_fn( write->pPng, write, user_write_data, NULL );
|
||||
|
||||
/* Catch PNG errors from png_create_info_struct().
|
||||
*/
|
||||
if( setjmp( png_jmpbuf( write->pPng ) ) )
|
||||
@ -1176,80 +1185,25 @@ write_vips( Write *write,
|
||||
}
|
||||
|
||||
int
|
||||
vips__png_write( VipsImage *in, const char *filename,
|
||||
int compress, int interlace, const char *profile,
|
||||
VipsForeignPngFilter filter, gboolean strip,
|
||||
gboolean palette, int colours, int Q, double dither )
|
||||
{
|
||||
Write *write;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips__png_write: writing \"%s\"\n", filename );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( !(write = write_new( in )) )
|
||||
return( -1 );
|
||||
|
||||
/* Make output.
|
||||
*/
|
||||
if( !(write->fp = vips__file_open_write( filename, FALSE )) )
|
||||
return( -1 );
|
||||
png_init_io( write->pPng, write->fp );
|
||||
|
||||
/* Convert it!
|
||||
*/
|
||||
if( write_vips( write,
|
||||
compress, interlace, profile, filter, strip, palette,
|
||||
colours, Q, dither ) ) {
|
||||
vips_error( "vips2png",
|
||||
_( "unable to write \"%s\"" ), filename );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
write_finish( write );
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips__png_write: done\n" );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
user_write_data( png_structp png_ptr, png_bytep data, png_size_t length )
|
||||
{
|
||||
Write *write = (Write *) png_get_io_ptr( png_ptr );
|
||||
|
||||
vips_dbuf_write( &write->dbuf, data, length );
|
||||
}
|
||||
|
||||
int
|
||||
vips__png_write_buf( VipsImage *in,
|
||||
void **obuf, size_t *olen, int compression, int interlace,
|
||||
vips__png_write_stream( VipsImage *in, VipsStreamOutput *output,
|
||||
int compression, int interlace,
|
||||
const char *profile, VipsForeignPngFilter filter, gboolean strip,
|
||||
gboolean palette, int colours, int Q, double dither )
|
||||
{
|
||||
Write *write;
|
||||
|
||||
if( !(write = write_new( in )) )
|
||||
if( !(write = write_new( in, output )) )
|
||||
return( -1 );
|
||||
|
||||
png_set_write_fn( write->pPng, write, user_write_data, NULL );
|
||||
|
||||
/* Convert it!
|
||||
*/
|
||||
if( write_vips( write,
|
||||
compression, interlace, profile, filter, strip, palette,
|
||||
colours, Q, dither ) ) {
|
||||
write_finish( write );
|
||||
vips_error( "vips2png",
|
||||
"%s", _( "unable to write to buffer" ) );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
*obuf = vips_dbuf_steal( &write->dbuf, olen );
|
||||
|
||||
write_finish( write );
|
||||
|
||||
return( 0 );
|
||||
|
@ -369,6 +369,8 @@ int vips_jpegload( const char *filename, VipsImage **out, ... )
|
||||
int vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
int vips_jpegsave_stream( VipsImage *in, VipsStreamOutput *output, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_jpegsave( VipsImage *in, const char *filename, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_jpegsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
||||
@ -547,6 +549,8 @@ int vips_pngload( const char *filename, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_pngsave_stream( VipsImage *in, VipsStreamOutput *output, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_pngsave( VipsImage *in, const char *filename, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_pngsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
||||
|
Loading…
Reference in New Issue
Block a user