add Q param to jxl save

for convenience
This commit is contained in:
John Cupitt 2021-04-14 12:29:38 +01:00
parent 209f2c5144
commit 633d35f4ae

View File

@ -1,7 +1,7 @@
/* save as jpeg2000 /* save as jpeg2000
* *
* 18/3/20 * 18/3/20
* - from jxlload.c * - from heifload.c
*/ */
/* /*
@ -33,8 +33,8 @@
/* /*
#define DEBUG_VERBOSE #define DEBUG_VERBOSE
#define DEBUG
*/ */
#define DEBUG
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
@ -59,10 +59,10 @@
* *
* - libjxl currently seems to be missing API to attach a profile * - libjxl currently seems to be missing API to attach a profile
* *
* - libjxl seems to only work in one shot mode, so there's no way to write in * - libjxl encode only works in one shot mode, so there's no way to write in
* chunks * chunks
* *
* - embed a preview image? EXIF? XMP? * - embed a preview image? EXIF? XMP? api for this is on the way
* *
* - check scRGB encoding * - check scRGB encoding
*/ */
@ -82,6 +82,7 @@ typedef struct _VipsForeignSaveJxl {
double distance; double distance;
int effort; int effort;
gboolean lossless; gboolean lossless;
int Q;
/* Base image properties. /* Base image properties.
*/ */
@ -140,6 +141,13 @@ vips_foreign_save_jxl_build( VipsObject *object )
build( object ) ) build( object ) )
return( -1 ); return( -1 );
/* If Q is set and distance is not, use Q to set a rough distance
* value. Q 75 is distance 1.0, Q 100 is distance 0.0.
*/
if( vips_object_argument_isset( object, "Q" ) &&
!vips_object_argument_isset( object, "distance" ) )
jxl->distance = (100 - jxl->Q) / 25.0;
jxl->runner = JxlThreadParallelRunnerCreate( NULL, jxl->runner = JxlThreadParallelRunnerCreate( NULL,
vips_concurrency_get() ); vips_concurrency_get() );
jxl->encoder = JxlEncoderCreate( NULL ); jxl->encoder = JxlEncoderCreate( NULL );
@ -258,7 +266,7 @@ vips_foreign_save_jxl_build( VipsObject *object )
} }
/* Render the entire image in memory. libjxl seems to be missing /* Render the entire image in memory. libjxl seems to be missing
* tile-based write. * tile-based write at the moment.
*/ */
if( vips_image_wio_input( save->ready ) ) if( vips_image_wio_input( save->ready ) )
return( -1 ); return( -1 );
@ -269,6 +277,14 @@ vips_foreign_save_jxl_build( VipsObject *object )
JxlEncoderOptionsSetEffort( options, jxl->effort ); JxlEncoderOptionsSetEffort( options, jxl->effort );
JxlEncoderOptionsSetLossless( options, jxl->lossless ); JxlEncoderOptionsSetLossless( options, jxl->lossless );
#ifdef DEBUG
printf( "jxl encode options:\n" );
printf( " tier = %d\n", jxl->tier );
printf( " distance = %g\n", jxl->distance );
printf( " effort = %d\n", jxl->effort );
printf( " lossless = %d\n", jxl->lossless );
#endif /*DEBUG*/
if( JxlEncoderAddImageFrame( options, &jxl->format, if( JxlEncoderAddImageFrame( options, &jxl->format,
VIPS_IMAGE_ADDR( save->ready, 0, 0 ), VIPS_IMAGE_ADDR( save->ready, 0, 0 ),
VIPS_IMAGE_SIZEOF_IMAGE( save->ready ) ) ) { VIPS_IMAGE_SIZEOF_IMAGE( save->ready ) ) ) {
@ -368,6 +384,13 @@ vips_foreign_save_jxl_class_init( VipsForeignSaveJxlClass *class )
G_STRUCT_OFFSET( VipsForeignSaveJxl, lossless ), G_STRUCT_OFFSET( VipsForeignSaveJxl, lossless ),
FALSE ); FALSE );
VIPS_ARG_INT( class, "Q", 14,
_( "Q" ),
_( "Quality factor" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJxl, Q ),
0, 100, 75 );
} }
static void static void
@ -570,6 +593,7 @@ vips_foreign_save_jxl_target_init( VipsForeignSaveJxlTarget *target )
* * @distance: %gdouble, maximum encoding error * * @distance: %gdouble, maximum encoding error
* * @effort: %gint, encoding effort * * @effort: %gint, encoding effort
* * @lossless: %gboolean, enables lossless compression * * @lossless: %gboolean, enables lossless compression
* * @Q: %gint, quality setting
* *
* Write a VIPS image to a file in JPEG-XL format. * Write a VIPS image to a file in JPEG-XL format.
* *
@ -580,6 +604,9 @@ vips_foreign_save_jxl_target_init( VipsForeignSaveJxlTarget *target )
* (highest quality), and maximum is 15 (lowest quality). Default is 1.0 * (highest quality), and maximum is 15 (lowest quality). Default is 1.0
* (visually lossless). * (visually lossless).
* *
* As a convenience, you can use @Q to set @distance. @Q of 75 is distance
* 1.0, @Q of 100 is distance 0.0.
*
* Set @lossless to enable lossless compresion. * Set @lossless to enable lossless compresion.
* *
* Returns: 0 on success, -1 on error. * Returns: 0 on success, -1 on error.
@ -610,6 +637,7 @@ vips_jxlsave( VipsImage *in, const char *filename, ... )
* * @distance: %gdouble, maximum encoding error * * @distance: %gdouble, maximum encoding error
* * @effort: %gint, encoding effort * * @effort: %gint, encoding effort
* * @lossless: %gboolean, enables lossless compression * * @lossless: %gboolean, enables lossless compression
* * @Q: %gint, quality setting
* *
* As vips_jxlsave(), but save to a memory buffer. * As vips_jxlsave(), but save to a memory buffer.
* *
@ -657,6 +685,7 @@ vips_jxlsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
* * @distance: %gdouble, maximum encoding error * * @distance: %gdouble, maximum encoding error
* * @effort: %gint, encoding effort * * @effort: %gint, encoding effort
* * @lossless: %gboolean, enables lossless compression * * @lossless: %gboolean, enables lossless compression
* * @Q: %gint, quality setting
* *
* As vips_jxlsave(), but save to a target. * As vips_jxlsave(), but save to a target.
* *