diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 501483c4..10be5040 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -1987,6 +1987,7 @@ vips_jpegload( const char *filename, VipsImage **out, ... ) * * @Q: quality factor * @profile: attach this ICC profile + * @optimize_coding: compute optimal Huffman coding tables * * Write a VIPS image to a file as JPEG. * @@ -2039,6 +2040,7 @@ vips_jpegsave( VipsImage *in, const char *filename, ... ) * * @Q: JPEG quality factor * @profile: attach this ICC profile + * @optimize_coding: compute optimal Huffman coding tables * * As vips_jpegsave(), but save to a memory buffer. * @@ -2087,6 +2089,7 @@ vips_jpegsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) * * @Q: JPEG quality factor * @profile: attach this ICC profile + * @optimize_coding: compute optimal Huffman coding tables * * As vips_jpegsave(), but save as a mime jpeg on stdout. * diff --git a/libvips/foreign/jpeg.h b/libvips/foreign/jpeg.h index ac0f6f3c..53abd6f1 100644 --- a/libvips/foreign/jpeg.h +++ b/libvips/foreign/jpeg.h @@ -54,9 +54,9 @@ void vips__new_output_message( j_common_ptr cinfo ); void vips__new_error_exit( j_common_ptr cinfo ); int vips__jpeg_write_file( VipsImage *in, - const char *filename, int Q, const char *profile ); + const char *filename, int Q, const char *profile, gboolean optimize_coding ); int vips__jpeg_write_buffer( VipsImage *in, - void **obuf, size_t *olen, int Q, const char *profile ); + void **obuf, size_t *olen, int Q, const char *profile, gboolean optimize_coding ); int vips__isjpeg( const char *filename ); int vips__jpeg_read_file( const char *name, VipsImage *out, diff --git a/libvips/foreign/jpegsave.c b/libvips/foreign/jpegsave.c index 9ce8b0d5..5af0e4d3 100644 --- a/libvips/foreign/jpegsave.c +++ b/libvips/foreign/jpegsave.c @@ -89,6 +89,10 @@ typedef struct _VipsForeignSaveJpeg { */ char *profile; + /* Compute optimal Huffman coding tables. + */ + gboolean optimize_coding; + } VipsForeignSaveJpeg; typedef VipsForeignSaveClass VipsForeignSaveJpegClass; @@ -134,6 +138,13 @@ vips_foreign_save_jpeg_class_init( VipsForeignSaveJpegClass *class ) VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsForeignSaveJpeg, profile ), NULL ); + + VIPS_ARG_BOOL( class, "optimize_coding", 12, + _( "optimize_coding" ), + _( "Compute optimal Huffman coding tables" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSaveJpeg, optimize_coding ), + FALSE ); } static void @@ -168,7 +179,7 @@ vips_foreign_save_jpeg_file_build( VipsObject *object ) return( -1 ); if( vips__jpeg_write_file( save->ready, file->filename, - jpeg->Q, jpeg->profile ) ) + jpeg->Q, jpeg->profile, jpeg->optimize_coding ) ) return( -1 ); return( 0 ); @@ -233,7 +244,7 @@ vips_foreign_save_jpeg_buffer_build( VipsObject *object ) return( -1 ); if( vips__jpeg_write_buffer( save->ready, - &obuf, &olen, jpeg->Q, jpeg->profile ) ) + &obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding ) ) return( -1 ); area = vips_area_new_blob( (VipsCallbackFn) vips_free, obuf, olen ); @@ -294,7 +305,7 @@ vips_foreign_save_jpeg_mime_build( VipsObject *object ) return( -1 ); if( vips__jpeg_write_buffer( save->ready, - &obuf, &olen, jpeg->Q, jpeg->profile ) ) + &obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding ) ) return( -1 ); printf( "Content-length: %zd\r\n", olen ); diff --git a/libvips/foreign/vips2jpeg.c b/libvips/foreign/vips2jpeg.c index de255b9a..6e1a9fc1 100644 --- a/libvips/foreign/vips2jpeg.c +++ b/libvips/foreign/vips2jpeg.c @@ -847,7 +847,7 @@ write_jpeg_block( REGION *region, Rect *area, void *a ) /* Write a VIPS image to a JPEG compress struct. */ static int -write_vips( Write *write, int qfac, const char *profile ) +write_vips( Write *write, int qfac, const char *profile, gboolean optimize_coding ) { VipsImage *in; J_COLOR_SPACE space; @@ -900,6 +900,10 @@ write_vips( Write *write, int qfac, const char *profile ) jpeg_set_defaults( &write->cinfo ); jpeg_set_quality( &write->cinfo, qfac, TRUE ); + /* Compute optimal Huffman coding tables. + */ + write->cinfo.optimize_coding = optimize_coding; + /* Build compress tables. */ jpeg_start_compress( &write->cinfo, TRUE ); @@ -942,7 +946,7 @@ write_vips( Write *write, int qfac, const char *profile ) */ int vips__jpeg_write_file( VipsImage *in, - const char *filename, int Q, const char *profile ) + const char *filename, int Q, const char *profile, gboolean optimize_coding ) { Write *write; @@ -972,7 +976,7 @@ vips__jpeg_write_file( VipsImage *in, /* Convert! */ - if( write_vips( write, Q, profile ) ) { + if( write_vips( write, Q, profile, optimize_coding ) ) { write_destroy( write ); return( -1 ); } @@ -1218,7 +1222,7 @@ buf_dest( j_compress_ptr cinfo, void **obuf, size_t *olen ) int vips__jpeg_write_buffer( VipsImage *in, - void **obuf, size_t *olen, int Q, const char *profile ) + void **obuf, size_t *olen, int Q, const char *profile, gboolean optimize_coding ) { Write *write; @@ -1247,7 +1251,7 @@ vips__jpeg_write_buffer( VipsImage *in, /* Convert! */ - if( write_vips( write, Q, profile ) ) { + if( write_vips( write, Q, profile, optimize_coding ) ) { write_destroy( write ); return( -1 );