Commit 4793527c8 for imagemagick.org
commit 4793527c8d7a2971a94c931c862f251ba68444bb
Author: Nol Moonen <nolmoonen@hotmail.nl>
Date: Tue Sep 29 20:55:20 2026 +0200
Preserve Ultra HDR JPEG gain maps for scale operator (#8986)
* eliminate dead code
if the else case is hit, transform is not resize and applying the transform will always fail
* add scale support for uhdr
diff --git a/MagickCore/resize.c b/MagickCore/resize.c
index b3825f63a..c8be33d21 100644
--- a/MagickCore/resize.c
+++ b/MagickCore/resize.c
@@ -4538,6 +4538,17 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
scanline=(double *) RelinquishMagickMemory(scanline);
x_vector=(double *) RelinquishMagickMemory(x_vector);
scale_image->type=image->type;
+ {
+ char
+ transform[MagickPathExtent];
+
+ (void) FormatLocaleString(transform,MagickPathExtent,
+ "scale %.17gx%.17g %.17gx%.17g",(double) image->columns,
+ (double) image->rows,(double) scale_image->columns,
+ (double) scale_image->rows);
+ AppendImageProfileProperty(scale_image,"hdrgm","hdrgm:Transform",
+ transform,exception);
+ }
if (status == MagickFalse)
scale_image=DestroyImage(scale_image);
return(scale_image);
diff --git a/coders/uhdr.c b/coders/uhdr.c
index bf63037a3..9820d0682 100644
--- a/coders/uhdr.c
+++ b/coders/uhdr.c
@@ -1065,6 +1065,35 @@ static MagickBooleanType ResizeGainMapImage(Image **gainmap_image,
return(MagickTrue);
}
+static MagickBooleanType ScaleGainMapImage(Image **gainmap_image,
+ size_t *base_columns,size_t *base_rows,const size_t columns,
+ const size_t rows,ExceptionInfo *exception)
+{
+ Image
+ *scale_image;
+
+ size_t
+ target_columns,
+ target_rows;
+
+ target_columns=ScaleGainMapExtent((*gainmap_image)->columns,columns,
+ *base_columns);
+ target_rows=ScaleGainMapExtent((*gainmap_image)->rows,rows,*base_rows);
+ if ((target_columns == 0) || (target_rows == 0))
+ return(MagickFalse);
+ if ((target_columns != (*gainmap_image)->columns) ||
+ (target_rows != (*gainmap_image)->rows))
+ {
+ scale_image=ScaleImage(*gainmap_image,target_columns,target_rows,
+ exception);
+ if (ReplaceGainMapImage(gainmap_image,scale_image) == MagickFalse)
+ return(MagickFalse);
+ }
+ *base_columns=columns;
+ *base_rows=rows;
+ return(MagickTrue);
+}
+
static MagickBooleanType ApplyGainMapTransform(Image **gainmap_image,
size_t *base_columns,size_t *base_rows,const Image *image,
const char *transform,ExceptionInfo *exception)
@@ -1114,6 +1143,27 @@ static MagickBooleanType ApplyGainMapTransform(Image **gainmap_image,
CastDoubleToSizeT(columns),CastDoubleToSizeT(rows),filter_type,
exception));
}
+ else if (LocaleNCompare(transform,"scale ",6) == 0)
+ {
+ fields=sscanf(transform+6,"%lfx%lf %lfx%lf",&source_columns,
+ &source_rows,&columns,&rows);
+ if (fields != 4)
+ return(MagickFalse);
+ if ((IsNaN(source_columns) != 0) || (IsNaN(source_rows) != 0) ||
+ (IsNaN(columns) != 0) || (IsNaN(rows) != 0) ||
+ (source_columns > (double) MAGICK_SSIZE_MAX) ||
+ (source_rows > (double) MAGICK_SSIZE_MAX) ||
+ (columns <= 0.0) || (rows <= 0.0) ||
+ (columns > (double) MAGICK_SSIZE_MAX) ||
+ (rows > (double) MAGICK_SSIZE_MAX) ||
+ (columns != floor(columns)) || (rows != floor(rows)))
+ return(MagickFalse);
+ if (IsGainMapBaseGeometry(*base_columns,*base_rows,source_columns,
+ source_rows) == MagickFalse)
+ return(MagickFalse);
+ return(ScaleGainMapImage(gainmap_image,base_columns,base_rows,
+ CastDoubleToSizeT(columns),CastDoubleToSizeT(rows),exception));
+ }
return(MagickFalse);
}
@@ -1424,7 +1474,8 @@ static StringInfo *TransformGainMapProfile(const ImageInfo *image_info,
}
}
}
- else if (LocaleNCompare(transform,"resize ",7) == 0)
+ else if ((LocaleNCompare(transform,"resize ",7) == 0) ||
+ (LocaleNCompare(transform,"scale ", 6) == 0))
{
if (transform_pending != MagickFalse)
{
@@ -1465,17 +1516,7 @@ static StringInfo *TransformGainMapProfile(const ImageInfo *image_info,
}
else
{
- if (transform_pending != MagickFalse)
- {
- status=FlushGainMapTransform(&gainmap_images,
- &transform_state,exception);
- transform_pending=MagickFalse;
- }
- if (status != MagickFalse)
- status=ApplyGainMapTransform(&gainmap_images,&base_columns,
- &base_rows,image,transform,exception);
- if (status != MagickFalse)
- transformed=MagickTrue;
+ status=MagickFalse;
}
if (status == MagickFalse)
break;
diff --git a/tests/cli-uhdr.tap b/tests/cli-uhdr.tap
index 83c8edb2b..373f25f12 100755
--- a/tests/cli-uhdr.tap
+++ b/tests/cli-uhdr.tap
@@ -23,6 +23,7 @@ raw_source=cli-uhdr-offset-raw.jpg
source=cli-uhdr-offset-source.jpg
output=cli-uhdr-offset-output.jpg
transformed_output=cli-uhdr-offset-transformed.jpg
+scaled_output=cli-uhdr-offset-scaled.jpg
locale_output=cli-uhdr-offset-locale.jpg
jpeg_probe=cli-uhdr-jpeg-probe.jpg
whitespace_output=cli-uhdr-offset-whitespace.jpg
@@ -61,7 +62,7 @@ comments-local-second-line'
cleanup()
{
- rm -f "$raw_source" "$source" "$output" "$transformed_output" \
+ rm -f "$raw_source" "$source" "$output" "$transformed_output" "$scaled_output" \
"$locale_output" "$jpeg_probe" "$whitespace_output" "$invalid_output" \
"$iptc_source" "$iptc_output"
rm -f "$commented_source" "$comment_roundtrip" \
@@ -113,7 +114,7 @@ if [ "X$jpeg_format" != "XJPEG" ]; then
exit 0
fi
-echo "1..20"
+echo "1..21"
if ! ${MAGICK} \( "${SRCDIR}/rose.pnm" -depth 8 \) \
\( "${SRCDIR}/rose.pnm" -depth 16 \) \
-define uhdr:hdr-color-transfer=linear "UHDR:$raw_source" \
@@ -254,6 +255,17 @@ check_value "offset values survive a geometry transform" \
check_value "capacity values survive a geometry transform" \
"$transformed_capacity" "$capacity_min $capacity_max"
+if ${MAGICK} "UHDR:$source" -scale 50% \
+ "UHDR:$scaled_output" >/dev/null 2>&1; then
+ scaled_offsets=`${IDENTIFY} -quiet -format \
+ '%[hdrgm:OffsetSDR] %[hdrgm:OffsetHDR]' \
+ "UHDR:$scaled_output" 2>/dev/null`
+else
+ scaled_offsets=
+fi
+check_value "offset values survive a scale transform" \
+ "$scaled_offsets" "$source_offsets"
+
if ${MAGICK} "UHDR:$source" -quality 85 \
-define uhdr:gainmap-quality=35 -resize 50% \
"UHDR:$quality35_output" >/dev/null 2>&1 &&