add force subsample argument that overrides the Q deduced subsampling directive
This commit is contained in:
parent
71e9071769
commit
c626c9de14
@ -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 );
|
||||
}
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user