add force subsample argument that overrides the Q deduced subsampling directive

This commit is contained in:
elad laufer 2020-02-16 18:37:32 +02:00
parent 71e9071769
commit c626c9de14
4 changed files with 37 additions and 10 deletions

View File

@ -77,6 +77,10 @@ typedef struct _VipsForeignSaveJpeg {
*/
gboolean no_subsample;
/* Force chroma subsampling, if Q >= 90 then subsampling is disabled, use this flag to force it
*/
gboolean force_subsample;
/* Apply trellis quantisation to each 8x8 block.
*/
gboolean trellis_quant;
@ -194,6 +198,12 @@ vips_foreign_save_jpeg_class_init( VipsForeignSaveJpegClass *class )
G_STRUCT_OFFSET( VipsForeignSaveJpeg, quant_table ),
0, 8, 0 );
VIPS_ARG_BOOL( class, "force_subsample", 19,
_( "Force subsample" ),
_( "Force chroma subsample" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJpeg, force_subsample ),
FALSE );
}
static void
@ -230,7 +240,7 @@ vips_foreign_save_jpeg_target_build( VipsObject *object )
jpeg->Q, jpeg->profile, jpeg->optimize_coding,
jpeg->interlace, save->strip, jpeg->no_subsample,
jpeg->trellis_quant, jpeg->overshoot_deringing,
jpeg->optimize_scans, jpeg->quant_table ) )
jpeg->optimize_scans, jpeg->quant_table, jpeg->force_subsample ) )
return( -1 );
return( 0 );
@ -297,7 +307,7 @@ vips_foreign_save_jpeg_file_build( VipsObject *object )
jpeg->Q, jpeg->profile, jpeg->optimize_coding,
jpeg->interlace, save->strip, jpeg->no_subsample,
jpeg->trellis_quant, jpeg->overshoot_deringing,
jpeg->optimize_scans, jpeg->quant_table ) ) {
jpeg->optimize_scans, jpeg->quant_table, jpeg->force_subsample ) ) {
VIPS_UNREF( target );
return( -1 );
}
@ -367,7 +377,7 @@ vips_foreign_save_jpeg_buffer_build( VipsObject *object )
jpeg->Q, jpeg->profile, jpeg->optimize_coding,
jpeg->interlace, save->strip, jpeg->no_subsample,
jpeg->trellis_quant, jpeg->overshoot_deringing,
jpeg->optimize_scans, jpeg->quant_table ) ) {
jpeg->optimize_scans, jpeg->quant_table, jpeg->force_subsample ) ) {
VIPS_UNREF( target );
return( -1 );
}
@ -440,7 +450,7 @@ vips_foreign_save_jpeg_mime_build( VipsObject *object )
jpeg->Q, jpeg->profile, jpeg->optimize_coding,
jpeg->interlace, save->strip, jpeg->no_subsample,
jpeg->trellis_quant, jpeg->overshoot_deringing,
jpeg->optimize_scans, jpeg->quant_table ) ) {
jpeg->optimize_scans, jpeg->quant_table, jpeg->force_subsample ) ) {
VIPS_UNREF( target );
return( -1 );
}

View File

@ -166,7 +166,7 @@ int vips__jpeg_write_target( VipsImage *in, VipsTarget *target,
gboolean optimize_coding, gboolean progressive, gboolean strip,
gboolean no_subsample, gboolean trellis_quant,
gboolean overshoot_deringing, gboolean optimize_scans,
int quant_table );
int quant_table, gboolean force_subsample );
int vips__jpeg_read_source( VipsSource *source, VipsImage *out,
gboolean header_only, int shrink, int fail, gboolean autorotate );

View File

@ -480,7 +480,8 @@ static int
write_vips( Write *write, int qfac, const char *profile,
gboolean optimize_coding, gboolean progressive, gboolean strip,
gboolean no_subsample, gboolean trellis_quant,
gboolean overshoot_deringing, gboolean optimize_scans, int quant_table )
gboolean overshoot_deringing, gboolean optimize_scans, int quant_table,
gboolean force_subsample)
{
VipsImage *in;
J_COLOR_SPACE space;
@ -630,8 +631,9 @@ write_vips( Write *write, int qfac, const char *profile,
/* Turn off chroma subsampling. Follow IM and do it automatically for
* high Q.
*/
if( no_subsample ||
qfac >= 90 ) {
if( !force_subsample && (
no_subsample ||
qfac >= 90 )) {
int i;
for( i = 0; i < in->Bands; i++ ) {
@ -775,7 +777,8 @@ vips__jpeg_write_target( VipsImage *in, VipsTarget *target,
int Q, const char *profile,
gboolean optimize_coding, gboolean progressive,
gboolean strip, gboolean no_subsample, gboolean trellis_quant,
gboolean overshoot_deringing, gboolean optimize_scans, int quant_table )
gboolean overshoot_deringing, gboolean optimize_scans, int quant_table,
gboolean force_subsample)
{
Write *write;
@ -802,7 +805,7 @@ vips__jpeg_write_target( VipsImage *in, VipsTarget *target,
if( write_vips( write,
Q, profile, optimize_coding, progressive, strip, no_subsample,
trellis_quant, overshoot_deringing, optimize_scans,
quant_table ) ) {
quant_table, force_subsample ) ) {
write_destroy( write );
return( -1 );
}

View File

@ -254,6 +254,20 @@ class TestForeign:
# format area at the end
assert y.startswith("hello world")
@skip_if_no("jpegload")
def test_jpegsave(self):
im = pyvips.Image.new_from_file(JPEG_FILE)
# higher Q should mean a bigger buffer
b1 = im.jpegsave_buffer(Q=10)
b2 = im.jpegsave_buffer(Q=90)
assert len(b2) > len(b1)
# force subsampling should result in smaller buffer
b1 = im.jpegsave_buffer(Q=90, force_subsample=True)
b2 = im.jpegsave_buffer(Q=90)
assert len(b2) > len(b1)
@skip_if_no("jpegload")
def test_truncated(self):
# This should open (there's enough there for the header)