Commit f8fdd19a7 for imagemagick.org
commit f8fdd19a795a766c3ec6d1d3b2f79e28bcbdb0be
Author: Cristy <urban-warrior@imagemagick.org>
Date: Fri Jul 24 20:33:40 2026 -0400
https://github.com/ImageMagick/ImageMagick/issues/8858
diff --git a/coders/jxl.c b/coders/jxl.c
index d61db4be5..ede90274b 100644
--- a/coders/jxl.c
+++ b/coders/jxl.c
@@ -934,6 +934,44 @@ ModuleExport void UnregisterJXLImage(void)
%
*/
+static inline float JXLGetDistance(float quality)
+{
+#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0,9,0)
+ return(JxlEncoderDistanceFromQuality(quality));
+#else
+ return(quality >= 100.0f ? 0.0f : quality >= 30.0 ? 0.1f+(100.0f-quality)*
+ 0.09f : 53.0f/3000.0f*quality*quality-23.0f/20.0f*quality+25.0f);
+#endif
+}
+
+static inline MagickBooleanType JXLParseOption(const char *option,
+ const double minimum,const double maximum,double *value)
+{
+ char
+ *sentinel;
+
+ double
+ number;
+
+ number=StringToDouble(option,&sentinel);
+ if ((sentinel == option) || (number < minimum) || (number > maximum))
+ return(MagickFalse);
+ *value=number;
+ return(MagickTrue);
+}
+
+static inline MagickBooleanType JXLSameFrameType(const Image *image,
+ const Image *frame)
+{
+ if (image->depth != frame->depth)
+ return(MagickFalse);
+ if (image->alpha_trait != frame->alpha_trait)
+ return(MagickFalse);
+ if (image->colorspace != frame->colorspace)
+ return(MagickFalse);
+ return(MagickTrue);
+}
+
static JxlEncoderStatus JXLWriteMetadata(const Image *image,
JxlEncoder *jxl_info, const StringInfo *icc_profile)
{
@@ -961,26 +999,6 @@ static JxlEncoderStatus JXLWriteMetadata(const Image *image,
return(jxl_status);
}
-static inline float JXLGetDistance(float quality)
-{
- return quality >= 100.0f ? 0.0f
- : quality >= 30
- ? 0.1f + (100 - quality) * 0.09f
- : 53.0f / 3000.0f * quality * quality - 23.0f / 20.0f * quality + 25.0f;
-}
-
-static inline MagickBooleanType JXLSameFrameType(const Image *image,
- const Image *frame)
-{
- if (image->depth != frame->depth)
- return(MagickFalse);
- if (image->alpha_trait != frame->alpha_trait)
- return(MagickFalse);
- if (image->colorspace != frame->colorspace)
- return(MagickFalse);
- return(MagickTrue);
-}
-
static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image,
ExceptionInfo *exception)
{
@@ -1111,6 +1129,36 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image,
return(MagickFalse);
}
JXLSetFormat(image,&pixel_format,exception);
+ option=GetImageOption(image_info,"jxl:distance");
+ if (option != (const char *) NULL)
+ {
+ if (JXLParseOption(option,0.0,25.0,&distance) == MagickFalse)
+ (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
+ "InvalidSetting","`%s'",option);
+ }
+ else
+ {
+ option=GetImageOption(image_info,"jxl:quality");
+ if (option != (const char *) NULL)
+ {
+ double
+ quality;
+
+ if (JXLParseOption(option,0.0,100.0,&quality) == MagickFalse)
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionWarning,"InvalidSetting","`%s'",option);
+ else
+ distance=(double) JXLGetDistance((float) quality);
+ }
+ }
+ if (distance < 0.0)
+ {
+ if (image_info->quality == 100)
+ distance=0.0;
+ else
+ if (image_info->quality != 0)
+ distance=(double) JXLGetDistance((float) image_info->quality);
+ }
JxlEncoderInitBasicInfo(&basic_info);
basic_info.xsize=(uint32_t) image->columns;
basic_info.ysize=(uint32_t) image->rows;
@@ -1137,7 +1185,7 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image,
basic_info.alpha_exponent_bits=basic_info.exponent_bits_per_sample;
basic_info.num_extra_channels=1;
}
- if (image_info->quality == 100)
+ if (distance == 0.0)
{
basic_info.uses_original_profile=JXL_TRUE;
icc_profile=GetImageProfile(image,"icc");
@@ -1159,21 +1207,6 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image,
JxlEncoderDestroy(jxl_info);
ThrowWriterException(CoderError,"UnableToWriteImageData");
}
- option=GetImageOption(image_info,"jxl:distance");
- if (option != (const char *) NULL)
- distance=StringToDouble(option,(char **) NULL);
- else
- {
- option=GetImageOption(image_info,"jxl:quality");
- if (option != (const char *) NULL)
- {
- double quality = StringToDouble(option,(char **) NULL);
- if (quality >= 100.0)
- distance=0.0;
- else
- distance=(100.0-quality)/100.0*15.0;
- }
- }
frame_settings=JxlEncoderFrameSettingsCreate(jxl_info,
(JxlEncoderFrameSettings *) NULL);
if (frame_settings == (JxlEncoderFrameSettings *) NULL)
@@ -1182,21 +1215,16 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image,
JxlEncoderDestroy(jxl_info);
ThrowWriterException(CoderError,"MemoryAllocationFailed");
}
- if (image_info->quality == 100)
- {
- (void) JxlEncoderSetFrameDistance(frame_settings,0.f);
- (void) JxlEncoderSetFrameLossless(frame_settings,JXL_TRUE);
- }
- else
- if (image_info->quality != 0)
- (void) JxlEncoderSetFrameDistance(frame_settings,
- JXLGetDistance((float) image_info->quality));
if (distance >= 0.0)
{
if (distance <= 0.0)
- (void) JxlEncoderSetFrameLossless(frame_settings,1);
+ {
+ (void) JxlEncoderSetFrameDistance(frame_settings,0.f);
+ (void) JxlEncoderSetFrameLossless(frame_settings,JXL_TRUE);
+ }
else
- (void) JxlEncoderSetFrameDistance(frame_settings,(float) distance);
+ (void) JxlEncoderSetFrameDistance(frame_settings,JXLGetDistance((float)
+ distance));
}
option=GetImageOption(image_info,"jxl:effort");
if (option != (const char *) NULL)