Merge branch 'master' of github.com:jcupitt/libvips

This commit is contained in:
John Cupitt 2015-04-19 12:31:48 +01:00
commit 88a9ebd74a
6 changed files with 161 additions and 13 deletions

View File

@ -696,6 +696,22 @@ FIND_JPEG(
with_jpeg=no
])
# JPEG extension parameters available in libjpeg-turbo >=1.5.0, mozjpeg >=3.0
if test x"$with_jpeg" = "xyes"; then
AC_MSG_CHECKING([for JPEG extension parameters])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdio.h>
#include <jpeglib.h>
]], [[
J_BOOLEAN_PARAM test;
]])], [
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_JPEG_EXT_PARAMS],1,[libjpeg has extension parameters])
], [
AC_MSG_RESULT([no])
])
fi
# libexif
AC_ARG_WITH([libexif],
AS_HELP_STRING([--without-libexif], [build without libexif (default: test)]))

View File

@ -2080,6 +2080,9 @@ vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... )
* @interlace: %gboolean, write an interlaced (progressive) jpeg
* @strip: %gboolean, remove all metadata from image
* @no-subsample: %gboolean, disable chroma subsampling
* @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block
* @overshoot_deringing: %gboolean, overshoot samples with extreme values
* @optimize_scans: %gboolean, split DCT coefficients into separate scans
*
* Write a VIPS image to a file as JPEG.
*
@ -2117,6 +2120,20 @@ vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... )
* If @no-subsample is set, chrominance subsampling is disabled. This will
* improve quality at the cost of larger file size. Useful for high Q factors.
*
* If @trellis_quant is set and the version of libjpeg supports it
* (e.g. mozjpeg >= 3.0), apply trellis quantisation to each 8x8 block.
* Reduces file size but increases compression time.
*
* If @overshoot_deringing is set and the version of libjpeg supports it
* (e.g. mozjpeg >= 3.0), apply overshooting to samples with extreme values
* for example 0 and 255 for 8-bit. Overshooting may reduce ringing artifacts
* from compression, in particular in areas where black text appears on a
* white background.
*
* If @optimize_scans is set and the version of libjpeg supports it
* (e.g. mozjpeg >= 3.0), split the spectrum of DCT coefficients into
* separate scans. Reduces file size but increases compression time.
*
* See also: vips_jpegsave_buffer(), vips_image_write_to_file().
*
* Returns: 0 on success, -1 on error.
@ -2149,6 +2166,9 @@ vips_jpegsave( VipsImage *in, const char *filename, ... )
* @interlace: write an interlaced (progressive) jpeg
* @strip: remove all metadata from image
* @no-subsample: disable chroma subsampling
* @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block
* @overshoot_deringing: %gboolean, overshoot samples with extreme values
* @optimize_scans: %gboolean, split DCT coefficients into separate scans
*
* As vips_jpegsave(), but save to a memory buffer.
*
@ -2200,6 +2220,9 @@ vips_jpegsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
* @optimize_coding: compute optimal Huffman coding tables
* @strip: remove all metadata from image
* @no-subsample: disable chroma subsampling
* @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block
* @overshoot_deringing: %gboolean, overshoot samples with extreme values
* @optimize_scans: %gboolean, split DCT coefficients into separate scans
*
* As vips_jpegsave(), but save as a mime jpeg on stdout.
*

View File

@ -91,6 +91,18 @@ typedef struct _VipsForeignSaveJpeg {
*/
gboolean no_subsample;
/* Apply trellis quantisation to each 8x8 block.
*/
gboolean trellis_quant;
/* Apply overshooting to samples with extreme values e.g. 0 & 255 for 8-bit.
*/
gboolean overshoot_deringing;
/* Split the spectrum of DCT coefficients into separate scans.
*/
gboolean optimize_scans;
} VipsForeignSaveJpeg;
typedef VipsForeignSaveClass VipsForeignSaveJpegClass;
@ -161,6 +173,27 @@ vips_foreign_save_jpeg_class_init( VipsForeignSaveJpegClass *class )
G_STRUCT_OFFSET( VipsForeignSaveJpeg, no_subsample ),
FALSE );
VIPS_ARG_BOOL( class, "trellis_quant", 15,
_( "Trellis quantisation" ),
_( "Apply trellis quantisation to each 8x8 block" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJpeg, trellis_quant ),
FALSE );
VIPS_ARG_BOOL( class, "overshoot_deringing", 16,
_( "Overshoot de-ringing" ),
_( "Apply overshooting to samples with extreme values" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJpeg, overshoot_deringing ),
FALSE );
VIPS_ARG_BOOL( class, "optimize_scans", 17,
_( "Optimize scans" ),
_( "Split the spectrum of DCT coefficients into separate scans" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJpeg, optimize_scans ),
FALSE );
}
static void
@ -196,7 +229,8 @@ vips_foreign_save_jpeg_file_build( VipsObject *object )
if( vips__jpeg_write_file( save->ready, file->filename,
jpeg->Q, jpeg->profile, jpeg->optimize_coding,
jpeg->interlace, save->strip, jpeg->no_subsample ) )
jpeg->interlace, save->strip, jpeg->no_subsample,
jpeg->trellis_quant, jpeg->overshoot_deringing, jpeg->optimize_scans) )
return( -1 );
return( 0 );
@ -259,7 +293,8 @@ vips_foreign_save_jpeg_buffer_build( VipsObject *object )
if( vips__jpeg_write_buffer( save->ready,
&obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding,
jpeg->interlace, save->strip, jpeg->no_subsample ) )
jpeg->interlace, save->strip, jpeg->no_subsample,
jpeg->trellis_quant, jpeg->overshoot_deringing, jpeg->optimize_scans) )
return( -1 );
blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen );
@ -321,7 +356,8 @@ vips_foreign_save_jpeg_mime_build( VipsObject *object )
if( vips__jpeg_write_buffer( save->ready,
&obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding,
jpeg->interlace, save->strip, jpeg->no_subsample ) )
jpeg->interlace, save->strip, jpeg->no_subsample,
jpeg->trellis_quant, jpeg->overshoot_deringing, jpeg->optimize_scans) )
return( -1 );
printf( "Content-length: %zd\r\n", olen );

View File

@ -143,7 +143,9 @@ read_free( Read *read )
VIPS_FREEF( DestroyImage, read->image );
VIPS_FREEF( DestroyImageInfo, read->image_info );
VIPS_FREE( read->frames );
DestroyExceptionInfo( &read->exception );
if ( (&read->exception)->signature == MagickSignature ) {
DestroyExceptionInfo( &read->exception );
}
VIPS_FREEF( vips_g_mutex_free, read->lock );
}

View File

@ -861,7 +861,8 @@ write_jpeg_block( VipsRegion *region, VipsRect *area, void *a )
static int
write_vips( Write *write, int qfac, const char *profile,
gboolean optimize_coding, gboolean progressive, gboolean strip,
gboolean no_subsample )
gboolean no_subsample, gboolean trellis_quant,
gboolean overshoot_deringing, gboolean optimize_scans )
{
VipsImage *in;
J_COLOR_SPACE space;
@ -909,6 +910,14 @@ write_vips( Write *write, int qfac, const char *profile,
if( !(write->row_pointer = VIPS_ARRAY( NULL, in->Ysize, JSAMPROW )) )
return( -1 );
#ifdef HAVE_JPEG_EXT_PARAMS
/* Reset compression profile to libjpeg defaults
*/
if( jpeg_c_int_param_supported( &write->cinfo, JINT_COMPRESS_PROFILE ) ) {
jpeg_c_set_int_param( &write->cinfo, JINT_COMPRESS_PROFILE, JCP_FASTEST );
}
#endif
/* Rest to default.
*/
jpeg_set_defaults( &write->cinfo );
@ -918,6 +927,64 @@ write_vips( Write *write, int qfac, const char *profile,
*/
write->cinfo.optimize_coding = optimize_coding;
#ifdef HAVE_JPEG_EXT_PARAMS
/* Apply trellis quantisation to each 8x8 block. Infers "optimize_coding".
*/
if( trellis_quant ) {
if ( jpeg_c_bool_param_supported(
&write->cinfo, JBOOLEAN_TRELLIS_QUANT ) ) {
jpeg_c_set_bool_param( &write->cinfo,
JBOOLEAN_TRELLIS_QUANT, TRUE );
write->cinfo.optimize_coding = TRUE;
}
else {
vips_warn( "vips2jpeg", "%s", _( "trellis_quant unsupported" ) );
}
}
/* Apply overshooting to samples with extreme values e.g. 0 & 255 for 8-bit.
*/
if( overshoot_deringing ) {
if ( jpeg_c_bool_param_supported(
&write->cinfo, JBOOLEAN_OVERSHOOT_DERINGING ) ) {
jpeg_c_set_bool_param( &write->cinfo,
JBOOLEAN_OVERSHOOT_DERINGING, TRUE );
}
else {
vips_warn( "vips2jpeg", "%s", _( "overshoot_deringing unsupported" ) );
}
}
/* Split the spectrum of DCT coefficients into separate scans.
* Requires progressive output. Must be set before jpeg_simple_progression.
*/
if( optimize_scans ) {
if( progressive ) {
if( jpeg_c_bool_param_supported(
&write->cinfo, JBOOLEAN_OPTIMIZE_SCANS ) ) {
jpeg_c_set_bool_param( &write->cinfo, JBOOLEAN_OPTIMIZE_SCANS, TRUE );
}
else {
vips_warn( "vips2jpeg", "%s", _( "Ignoring optimize_scans" ) );
}
}
else {
vips_warn( "vips2jpeg", "%s",
_( "Ignoring optimize_scans for baseline" ) );
}
}
#else
/* Using jpeglib.h without extension parameters, warn of ignored options.
*/
if ( trellis_quant ) {
vips_warn( "vips2jpeg", "%s", _( "Ignoring trellis_quant" ) );
}
if ( overshoot_deringing ) {
vips_warn( "vips2jpeg", "%s", _( "Ignoring overshoot_deringing" ) );
}
if ( optimize_scans ) {
vips_warn( "vips2jpeg", "%s", _( "Ignoring optimize_scans" ) );
}
#endif
/* Enable progressive write.
*/
if( progressive )
@ -982,7 +1049,8 @@ int
vips__jpeg_write_file( VipsImage *in,
const char *filename, int Q, const char *profile,
gboolean optimize_coding, gboolean progressive, gboolean strip,
gboolean no_subsample )
gboolean no_subsample, gboolean trellis_quant,
gboolean overshoot_deringing, gboolean optimize_scans )
{
Write *write;
@ -1013,8 +1081,8 @@ vips__jpeg_write_file( VipsImage *in,
/* Convert!
*/
if( write_vips( write,
Q, profile, optimize_coding, progressive, strip,
no_subsample ) ) {
Q, profile, optimize_coding, progressive, strip, no_subsample,
trellis_quant, overshoot_deringing, optimize_scans ) ) {
write_destroy( write );
return( -1 );
}
@ -1262,7 +1330,8 @@ int
vips__jpeg_write_buffer( VipsImage *in,
void **obuf, size_t *olen, int Q, const char *profile,
gboolean optimize_coding, gboolean progressive,
gboolean strip, gboolean no_subsample )
gboolean strip, gboolean no_subsample, gboolean trellis_quant,
gboolean overshoot_deringing, gboolean optimize_scans )
{
Write *write;
@ -1292,8 +1361,8 @@ vips__jpeg_write_buffer( VipsImage *in,
/* Convert!
*/
if( write_vips( write,
Q, profile, optimize_coding, progressive, strip,
no_subsample ) ) {
Q, profile, optimize_coding, progressive, strip, no_subsample,
trellis_quant, overshoot_deringing, optimize_scans ) ) {
write_destroy( write );
return( -1 );

View File

@ -40,11 +40,13 @@ extern const char *vips__jpeg_suffs[];
int vips__jpeg_write_file( VipsImage *in,
const char *filename, int Q, const char *profile,
gboolean optimize_coding, gboolean progressive, gboolean strip,
gboolean no_subsample );
gboolean no_subsample, gboolean trellis_quant,
gboolean overshoot_deringing, gboolean optimize_scans );
int vips__jpeg_write_buffer( VipsImage *in,
void **obuf, size_t *olen, int Q, const char *profile,
gboolean optimize_coding, gboolean progressive, gboolean strip,
gboolean no_subsample );
gboolean no_subsample, gboolean trellis_quant,
gboolean overshoot_deringing, gboolean optimize_scans );
int vips__isjpeg_buffer( void *buf, size_t len );
int vips__isjpeg( const char *filename );