webp write is stream-based
This commit is contained in:
parent
98410042ac
commit
ad7d2b796f
@ -2025,6 +2025,7 @@ vips_foreign_operation_init( void )
|
||||
extern GType vips_foreign_load_webp_stream_get_type( void );
|
||||
extern GType vips_foreign_load_webp_file_get_type( void );
|
||||
extern GType vips_foreign_load_webp_buffer_get_type( void );
|
||||
extern GType vips_foreign_save_webp_stream_get_type( void );
|
||||
extern GType vips_foreign_save_webp_file_get_type( void );
|
||||
extern GType vips_foreign_save_webp_buffer_get_type( void );
|
||||
extern GType vips_foreign_load_pdf_get_type( void );
|
||||
@ -2126,6 +2127,7 @@ vips_foreign_operation_init( void )
|
||||
vips_foreign_load_webp_stream_get_type();
|
||||
vips_foreign_load_webp_file_get_type();
|
||||
vips_foreign_load_webp_buffer_get_type();
|
||||
vips_foreign_save_webp_stream_get_type();
|
||||
vips_foreign_save_webp_file_get_type();
|
||||
vips_foreign_save_webp_buffer_get_type();
|
||||
#endif /*HAVE_LIBWEBP*/
|
||||
|
@ -214,13 +214,7 @@ int vips__webp_read_header_stream( VipsStreamInput *input, VipsImage *out,
|
||||
int vips__webp_read_stream( VipsStreamInput *input, VipsImage *out,
|
||||
int page, int n, double scale );
|
||||
|
||||
int vips__webp_write_file( VipsImage *out, const char *filename,
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset,
|
||||
gboolean smart_subsample, gboolean near_lossless,
|
||||
int alpha_q, int reduction_effort,
|
||||
gboolean min_size, int kmin, int kmax,
|
||||
gboolean strip );
|
||||
int vips__webp_write_buffer( VipsImage *out, void **buf, size_t *len,
|
||||
int vips__webp_write_stream( VipsImage *image, VipsStreamOutput *output,
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset,
|
||||
gboolean smart_subsample, gboolean near_lossless,
|
||||
int alpha_q, int reduction_effort,
|
||||
|
@ -16,6 +16,8 @@
|
||||
* - support array of delays
|
||||
* 8/7/19
|
||||
* - set loop even if we strip
|
||||
* 14/10/19
|
||||
* - revise for stream IO
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -508,52 +510,7 @@ vips_webp_add_metadata( VipsWebPWrite *write, VipsImage *image, gboolean strip )
|
||||
}
|
||||
|
||||
int
|
||||
vips__webp_write_file( VipsImage *image, const char *filename,
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset,
|
||||
gboolean smart_subsample, gboolean near_lossless,
|
||||
int alpha_q, int reduction_effort,
|
||||
gboolean min_size, int kmin, int kmax,
|
||||
gboolean strip )
|
||||
{
|
||||
VipsWebPWrite write;
|
||||
FILE *fp;
|
||||
|
||||
if( vips_webp_write_init( &write, image,
|
||||
Q, lossless, preset, smart_subsample, near_lossless,
|
||||
alpha_q, reduction_effort, min_size, kmin, kmax, strip ) )
|
||||
return( -1 );
|
||||
|
||||
if( write_webp( &write, image ) ) {
|
||||
vips_webp_write_unset( &write );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( vips_webp_add_metadata( &write, image, strip ) ) {
|
||||
vips_webp_write_unset( &write );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( !(fp = vips__file_open_write( filename, FALSE )) ) {
|
||||
vips_webp_write_unset( &write );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( vips__file_write(
|
||||
write.memory_writer.mem, write.memory_writer.size, 1, fp ) ) {
|
||||
fclose( fp );
|
||||
vips_webp_write_unset( &write );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
fclose( fp );
|
||||
|
||||
vips_webp_write_unset( &write );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
vips__webp_write_buffer( VipsImage *image, void **obuf, size_t *olen,
|
||||
vips__webp_write_stream( VipsImage *image, VipsStreamOutput *output,
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset,
|
||||
gboolean smart_subsample, gboolean near_lossless,
|
||||
int alpha_q, int reduction_effort,
|
||||
@ -577,11 +534,13 @@ vips__webp_write_buffer( VipsImage *image, void **obuf, size_t *olen,
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
*obuf = write.memory_writer.mem;
|
||||
*olen = write.memory_writer.size;
|
||||
write.memory_writer.mem = NULL;
|
||||
write.memory_writer.size = 0;
|
||||
write.memory_writer.max_size = 0;
|
||||
if( vips_stream_output_write( output,
|
||||
write.memory_writer.mem, write.memory_writer.size ) ) {
|
||||
vips_webp_write_unset( &write );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
vips_stream_output_finish( output );
|
||||
|
||||
vips_webp_write_unset( &write );
|
||||
|
||||
|
@ -219,6 +219,69 @@ vips_foreign_save_webp_init( VipsForeignSaveWebp *webp )
|
||||
webp->kmax = INT_MAX;
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignSaveWebpStream {
|
||||
VipsForeignSaveWebp parent_object;
|
||||
|
||||
VipsStreamOutput *output;
|
||||
|
||||
} VipsForeignSaveWebpStream;
|
||||
|
||||
typedef VipsForeignSaveWebpClass VipsForeignSaveWebpStreamClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsForeignSaveWebpStream, vips_foreign_save_webp_stream,
|
||||
vips_foreign_save_webp_get_type() );
|
||||
|
||||
static int
|
||||
vips_foreign_save_webp_stream_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||
VipsForeignSaveWebp *webp = (VipsForeignSaveWebp *) object;
|
||||
VipsForeignSaveWebpStream *stream =
|
||||
(VipsForeignSaveWebpStream *) object;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_webp_stream_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_stream( save->ready, stream->output,
|
||||
webp->Q, webp->lossless, webp->preset,
|
||||
webp->smart_subsample, webp->near_lossless,
|
||||
webp->alpha_q, webp->reduction_effort,
|
||||
webp->min_size, webp->kmin, webp->kmax,
|
||||
save->strip ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_save_webp_stream_class_init(
|
||||
VipsForeignSaveWebpStreamClass *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 = "webpsave_stream";
|
||||
object_class->description = _( "save image to webp stream" );
|
||||
object_class->build = vips_foreign_save_webp_stream_build;
|
||||
|
||||
VIPS_ARG_OBJECT( class, "output", 1,
|
||||
_( "Output" ),
|
||||
_( "Stream to save to" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignSaveWebpStream, output ),
|
||||
VIPS_TYPE_STREAM_OUTPUT );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_save_webp_stream_init( VipsForeignSaveWebpStream *stream )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
typedef struct _VipsForeignSaveWebpFile {
|
||||
VipsForeignSaveWebp parent_object;
|
||||
|
||||
@ -240,17 +303,24 @@ vips_foreign_save_webp_file_build( VipsObject *object )
|
||||
VipsForeignSaveWebp *webp = (VipsForeignSaveWebp *) object;
|
||||
VipsForeignSaveWebpFile *file = (VipsForeignSaveWebpFile *) object;
|
||||
|
||||
VipsStreamOutput *output;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_webp_file_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_file( save->ready, file->filename,
|
||||
if( !(output = vips_stream_output_new_from_filename( file->filename )) )
|
||||
return( -1 );
|
||||
if( vips__webp_write_stream( save->ready, output,
|
||||
webp->Q, webp->lossless, webp->preset,
|
||||
webp->smart_subsample, webp->near_lossless,
|
||||
webp->alpha_q, webp->reduction_effort,
|
||||
webp->min_size, webp->kmin, webp->kmax,
|
||||
save->strip ) )
|
||||
save->strip ) ) {
|
||||
VIPS_UNREF( output );
|
||||
return( -1 );
|
||||
}
|
||||
VIPS_UNREF( output );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -300,28 +370,31 @@ vips_foreign_save_webp_buffer_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||
VipsForeignSaveWebp *webp = (VipsForeignSaveWebp *) object;
|
||||
VipsForeignSaveWebpBuffer *file = (VipsForeignSaveWebpBuffer *) object;
|
||||
VipsForeignSaveWebpBuffer *buffer =
|
||||
(VipsForeignSaveWebpBuffer *) object;
|
||||
|
||||
void *obuf;
|
||||
size_t olen;
|
||||
VipsStreamOutput *output;
|
||||
VipsBlob *blob;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_webp_buffer_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_buffer( save->ready, &obuf, &olen,
|
||||
if( !(output = vips_stream_output_new_memory()) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_stream( save->ready, output,
|
||||
webp->Q, webp->lossless, webp->preset,
|
||||
webp->smart_subsample, webp->near_lossless,
|
||||
webp->alpha_q, webp->reduction_effort,
|
||||
webp->min_size, webp->kmin, webp->kmax,
|
||||
save->strip ) )
|
||||
save->strip ) ) {
|
||||
VIPS_UNREF( output );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* obuf is a g_free() buffer, not vips_free().
|
||||
*/
|
||||
blob = vips_blob_new( (VipsCallbackFn) g_free, obuf, olen );
|
||||
g_object_set( file, "buffer", blob, NULL );
|
||||
g_object_get( output, "blob", &blob, NULL );
|
||||
g_object_set( buffer, "buffer", blob, NULL );
|
||||
vips_area_unref( VIPS_AREA( blob ) );
|
||||
|
||||
return( 0 );
|
||||
@ -370,31 +443,40 @@ vips_foreign_save_webp_mime_build( VipsObject *object )
|
||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||
VipsForeignSaveWebp *webp = (VipsForeignSaveWebp *) object;
|
||||
|
||||
void *obuf;
|
||||
size_t olen;
|
||||
VipsStreamOutput *output;
|
||||
VipsBlob *blob;
|
||||
void *data;
|
||||
size_t len;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_webp_mime_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_buffer( save->ready, &obuf, &olen,
|
||||
if( !(output = vips_stream_output_new_memory()) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_stream( save->ready, output,
|
||||
webp->Q, webp->lossless, webp->preset,
|
||||
webp->smart_subsample, webp->near_lossless,
|
||||
webp->alpha_q, webp->reduction_effort,
|
||||
webp->min_size, webp->kmin, webp->kmax,
|
||||
save->strip ) )
|
||||
return( -1 );
|
||||
|
||||
printf( "Content-length: %zu\r\n", olen );
|
||||
printf( "Content-type: image/webp\r\n" );
|
||||
printf( "\r\n" );
|
||||
if( fwrite( obuf, sizeof( char ), olen, stdout ) != olen ) {
|
||||
vips_error( "VipsWebp", "%s", _( "error writing output" ) );
|
||||
save->strip ) ) {
|
||||
VIPS_UNREF( output );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
g_object_get( output, "blob", &blob, NULL );
|
||||
data = VIPS_AREA( blob )->data;
|
||||
len = VIPS_AREA( blob )->length;
|
||||
vips_area_unref( VIPS_AREA( blob ) );
|
||||
|
||||
printf( "Content-length: %zu\r\n", len );
|
||||
printf( "Content-type: image/webp\r\n" );
|
||||
printf( "\r\n" );
|
||||
(void) fwrite( data, sizeof( char ), len, stdout );
|
||||
fflush( stdout );
|
||||
|
||||
g_free( obuf );
|
||||
VIPS_UNREF( output );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -585,3 +667,42 @@ vips_webpsave_mime( VipsImage *in, ... )
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_webpsave_stream: (method)
|
||||
* @in: image to save
|
||||
* @output: save image to this stream
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* * @Q: %gint, quality factor
|
||||
* * @lossless: %gboolean, enables lossless compression
|
||||
* * @preset: #VipsForeignWebpPreset, choose lossy compression preset
|
||||
* * @smart_subsample: %gboolean, enables high quality chroma subsampling
|
||||
* * @near_lossless: %gboolean, preprocess in lossless mode (controlled by Q)
|
||||
* * @alpha_q: %gint, set alpha quality in lossless mode
|
||||
* * @reduction_effort: %gint, level of CPU effort to reduce file size
|
||||
* * @min_size: %gboolean, minimise size
|
||||
* * @kmin: %gint, minimum number of frames between keyframes
|
||||
* * @kmax: %gint, maximum number of frames between keyframes
|
||||
* * @strip: %gboolean, remove all metadata from image
|
||||
*
|
||||
* As vips_webpsave(), but save to a stream.
|
||||
*
|
||||
* See also: vips_webpsave().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_webpsave_stream( VipsImage *in, VipsStreamOutput *output, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, output );
|
||||
result = vips_call_split( "webpsave_stream", ap, in, output );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
@ -406,6 +406,8 @@ int vips_webpload( const char *filename, VipsImage **out, ... )
|
||||
int vips_webpload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
int vips_webpsave_stream( VipsImage *in, VipsStreamOutput *output, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_webpsave( VipsImage *in, const char *filename, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_webpsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
||||
|
Loading…
Reference in New Issue
Block a user