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;
|
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.
|
/* Apply trellis quantisation to each 8x8 block.
|
||||||
*/
|
*/
|
||||||
gboolean trellis_quant;
|
gboolean trellis_quant;
|
||||||
@ -194,6 +198,12 @@ vips_foreign_save_jpeg_class_init( VipsForeignSaveJpegClass *class )
|
|||||||
G_STRUCT_OFFSET( VipsForeignSaveJpeg, quant_table ),
|
G_STRUCT_OFFSET( VipsForeignSaveJpeg, quant_table ),
|
||||||
0, 8, 0 );
|
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
|
static void
|
||||||
@ -230,7 +240,7 @@ vips_foreign_save_jpeg_target_build( VipsObject *object )
|
|||||||
jpeg->Q, jpeg->profile, jpeg->optimize_coding,
|
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->trellis_quant, jpeg->overshoot_deringing,
|
||||||
jpeg->optimize_scans, jpeg->quant_table ) )
|
jpeg->optimize_scans, jpeg->quant_table, jpeg->force_subsample ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -297,7 +307,7 @@ vips_foreign_save_jpeg_file_build( VipsObject *object )
|
|||||||
jpeg->Q, jpeg->profile, jpeg->optimize_coding,
|
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->trellis_quant, jpeg->overshoot_deringing,
|
||||||
jpeg->optimize_scans, jpeg->quant_table ) ) {
|
jpeg->optimize_scans, jpeg->quant_table, jpeg->force_subsample ) ) {
|
||||||
VIPS_UNREF( target );
|
VIPS_UNREF( target );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
@ -367,7 +377,7 @@ vips_foreign_save_jpeg_buffer_build( VipsObject *object )
|
|||||||
jpeg->Q, jpeg->profile, jpeg->optimize_coding,
|
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->trellis_quant, jpeg->overshoot_deringing,
|
||||||
jpeg->optimize_scans, jpeg->quant_table ) ) {
|
jpeg->optimize_scans, jpeg->quant_table, jpeg->force_subsample ) ) {
|
||||||
VIPS_UNREF( target );
|
VIPS_UNREF( target );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
@ -440,7 +450,7 @@ vips_foreign_save_jpeg_mime_build( VipsObject *object )
|
|||||||
jpeg->Q, jpeg->profile, jpeg->optimize_coding,
|
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->trellis_quant, jpeg->overshoot_deringing,
|
||||||
jpeg->optimize_scans, jpeg->quant_table ) ) {
|
jpeg->optimize_scans, jpeg->quant_table, jpeg->force_subsample ) ) {
|
||||||
VIPS_UNREF( target );
|
VIPS_UNREF( target );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ int vips__jpeg_write_target( VipsImage *in, VipsTarget *target,
|
|||||||
gboolean optimize_coding, gboolean progressive, gboolean strip,
|
gboolean optimize_coding, gboolean progressive, gboolean strip,
|
||||||
gboolean no_subsample, gboolean trellis_quant,
|
gboolean no_subsample, gboolean trellis_quant,
|
||||||
gboolean overshoot_deringing, gboolean optimize_scans,
|
gboolean overshoot_deringing, gboolean optimize_scans,
|
||||||
int quant_table );
|
int quant_table, gboolean force_subsample );
|
||||||
|
|
||||||
int vips__jpeg_read_source( VipsSource *source, VipsImage *out,
|
int vips__jpeg_read_source( VipsSource *source, VipsImage *out,
|
||||||
gboolean header_only, int shrink, int fail, gboolean autorotate );
|
gboolean header_only, int shrink, int fail, gboolean autorotate );
|
||||||
|
@ -480,7 +480,8 @@ static int
|
|||||||
write_vips( Write *write, int qfac, const char *profile,
|
write_vips( Write *write, int qfac, const char *profile,
|
||||||
gboolean optimize_coding, gboolean progressive, gboolean strip,
|
gboolean optimize_coding, gboolean progressive, gboolean strip,
|
||||||
gboolean no_subsample, gboolean trellis_quant,
|
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;
|
VipsImage *in;
|
||||||
J_COLOR_SPACE space;
|
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
|
/* Turn off chroma subsampling. Follow IM and do it automatically for
|
||||||
* high Q.
|
* high Q.
|
||||||
*/
|
*/
|
||||||
if( no_subsample ||
|
if( !force_subsample && (
|
||||||
qfac >= 90 ) {
|
no_subsample ||
|
||||||
|
qfac >= 90 )) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for( i = 0; i < in->Bands; 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,
|
int Q, const char *profile,
|
||||||
gboolean optimize_coding, gboolean progressive,
|
gboolean optimize_coding, gboolean progressive,
|
||||||
gboolean strip, gboolean no_subsample, gboolean trellis_quant,
|
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;
|
Write *write;
|
||||||
|
|
||||||
@ -802,7 +805,7 @@ vips__jpeg_write_target( VipsImage *in, VipsTarget *target,
|
|||||||
if( write_vips( write,
|
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,
|
trellis_quant, overshoot_deringing, optimize_scans,
|
||||||
quant_table ) ) {
|
quant_table, force_subsample ) ) {
|
||||||
write_destroy( write );
|
write_destroy( write );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
@ -254,6 +254,20 @@ class TestForeign:
|
|||||||
# format area at the end
|
# format area at the end
|
||||||
assert y.startswith("hello world")
|
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")
|
@skip_if_no("jpegload")
|
||||||
def test_truncated(self):
|
def test_truncated(self):
|
||||||
# This should open (there's enough there for the header)
|
# This should open (there's enough there for the header)
|
||||||
|
Loading…
Reference in New Issue
Block a user