ClampPixel vs ClampToQuantum

Post any defects you find in the released or beta versions of the ImageMagick software here. Include the ImageMagick version, OS, and any command-line required to reproduce the problem. Got a patch for a bug? Post it here.
Post Reply
argv[0]
Posts: 10
Joined: 2013-07-24T01:05:06-07:00
Authentication code: 6789

ClampPixel vs ClampToQuantum

Post by argv[0] »

Code: Select all

static inline Quantum ClampPixel(const MagickRealType value)
{
  if (value < 0.0f)
    return(0);
  if (value >= (MagickRealType) QuantumRange)
    return((Quantum) QuantumRange);
#if !defined(MAGICKCORE_HDRI_SUPPORT)
  return((Quantum) (value+0.5f));
#else
  return((Quantum) value);
#endif
}

Code: Select all

static inline Quantum ClampToQuantum(const MagickRealType value)
{
#if defined(MAGICKCORE_HDRI_SUPPORT)
  return((Quantum) value);
#else
  if (value <= 0.0f)
    return((Quantum) 0);
  if (value >= (MagickRealType) QuantumRange)
    return(QuantumRange);
  return((Quantum) (value+0.5f));
#endif
}
Part of "diff -ru ImageMagick-6.9.0-2/magick/composite.c ImageMagick-6.9.0-4/magick/composite.c" output:

Code: Select all

@@ -2850,14 +2847,14 @@
           composite.blue=(MagickRealType) QuantumRange-composite.blue;
           composite.index=(MagickRealType) QuantumRange-composite.index;
         }
-      SetPixelRed(q,ClampToQuantum(composite.red));
-      SetPixelGreen(q,ClampToQuantum(composite.green));
-      SetPixelBlue(q,ClampToQuantum(composite.blue));
-      SetPixelOpacity(q,ClampToQuantum(composite.opacity));
+      SetPixelRed(q,ClampPixel(composite.red));
+      SetPixelGreen(q,ClampPixel(composite.green));
+      SetPixelBlue(q,ClampPixel(composite.blue));
+      SetPixelOpacity(q,ClampPixel(composite.opacity));
       if (image->colorspace == CMYKColorspace)
-        SetPixelIndex(indexes+x,ClampToQuantum(composite.index));
+        SetPixelIndex(indexes+x,ClampPixel(composite.index));
       p++;
-      if (p >= (pixels+composite_image->columns))
+      if (p >= (pixels+source_image->columns))
         p=pixels;
       q++;
     }
As a result in ImageMagick-6.9.0-4 any composite operation on floating-point TIFF clamps all channels to 1.0.
Composite operations in ImageMagick-6.9.0-2 doesn't clamp floating-point image.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: ClampPixel vs ClampToQuantum

Post by magick »

We're following the SVG compositing specification. The conundrum is "should" rather than "must" in this statement:
In addition to the base set of 12 Porter-Duff operations, a number of blending operations are supported. These blending operations are extensions of the base Porter-Duff set and provide enhanced compositing behavior. The extended operations may result in color and opacity values outside the range zero to one. The opacity value should be clamped between zero and one inclusive, and the pre-multiplied color value should be clamped between zero and the opacity value inclusive.
@ http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/. The question is "should" ImageMagick clamp the values or "must" it? Or do we set an option to support either behavior?
argv[0]
Posts: 10
Joined: 2013-07-24T01:05:06-07:00
Authentication code: 6789

Re: ClampPixel vs ClampToQuantum

Post by argv[0] »

Well. Standard is standard. But clamping makes HDRI processing difficult. May be worth to add "-define compose:clamping=(true|false)" (or something else) to control this behavior?
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: ClampPixel vs ClampToQuantum

Post by magick »

We could revert and enforce clamping with the -clamp option for HDRI. Let's do that. Will add a patch likely by tomorrow.
argv[0]
Posts: 10
Joined: 2013-07-24T01:05:06-07:00
Authentication code: 6789

Re: ClampPixel vs ClampToQuantum

Post by argv[0] »

ImageMagick-6.9.1-1 has the same problem.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: ClampPixel vs ClampToQuantum

Post by magick »

The SVG compositing specification @ http://www.w3.org/TR/SVGCompositing/ says:
  • 3.1 Alpha Compositing Syntax

    This section in normative.

    When compositing using Porter-Duff extended blending operations color and opacity values may fall outside the range zero to one.

    A User Agent MUST clamp color and opacity values between zero and one inclusive.
    A User Agent MUST clamp premultiplied color values between zero and one inclusive.
Seems definitive, clamping is required. That will be the default behavior. However, we'll add an option as you suggested to prevent clamping.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: ClampPixel vs ClampToQuantum

Post by fmw42 »

Has this been added to 6.9.1.2 or is/will it be in 6.9.1.3 and is it in the IM 7 beta, yet? I have the same issue. There are times when clamping mathematical compose methods causes issues in my scripts.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: ClampPixel vs ClampToQuantum

Post by magick »

Install ImageMagick-6.9.1-3 Beta, available now. Turn off clamping with -define compose:clamp=false or -set option:compose:clamp=false.
argv[0]
Posts: 10
Joined: 2013-07-24T01:05:06-07:00
Authentication code: 6789

Re: ClampPixel vs ClampToQuantum

Post by argv[0] »

It works (with a little patch). Thanks a lot!

Code: Select all

--- magick/composite.c.orig 2015-04-21 12:23:35.000000000 +0000
+++ magick/composite.c  2015-04-22 18:10:30.714484466 +0000
@@ -2860,9 +2860,9 @@
         ClampPixel(composite.red) : ClampToQuantum(composite.red));
       SetPixelGreen(q,clamp != MagickFalse ?
         ClampPixel(composite.green) : ClampToQuantum(composite.green));
-      SetPixelRed(q,clamp != MagickFalse ?
+      SetPixelBlue(q,clamp != MagickFalse ?
         ClampPixel(composite.blue) : ClampToQuantum(composite.blue));
-      SetPixelRed(q,clamp != MagickFalse ?
+      SetPixelOpacity(q,clamp != MagickFalse ?
         ClampPixel(composite.opacity) : ClampToQuantum(composite.opacity));
       if (image->colorspace == CMYKColorspace)
         SetPixelIndex(indexes+x,clamp != MagickFalse ?
Post Reply