Commit c7fd5e5bb for imagemagick.org
commit c7fd5e5bbebf7ee801a1c0e98484925b23df83a0
Author: Madars <mad182@gmail.com>
Date: Sat Mar 21 14:23:36 2026 +0200
Fix composite -dissolve adding random noise (#8621)
Revert DissolveCompositeOp from stochastic per-pixel coin-flip
(GetPseudoRandomValue) back to the original deterministic weighted
alpha-blend formula. The random approach produced visible dithering
noise because each pixel was assigned either 100% source or 100%
destination instead of a smooth intermediate blend.
Also removes the RandomInfo infrastructure (includes, declaration,
acquire, destroy) that was only used for this broken dissolve
implementation.
Regression introduced in 49e5a1114 (issue #8579 refactoring).
diff --git a/MagickCore/composite.c b/MagickCore/composite.c
index 7757a861c..441c09877 100644
--- a/MagickCore/composite.c
+++ b/MagickCore/composite.c
@@ -71,8 +71,6 @@
#include "MagickCore/pixel-accessor.h"
#include "MagickCore/property.h"
#include "MagickCore/quantum.h"
-#include "MagickCore/random_.h"
-#include "MagickCore/random-private.h"
#include "MagickCore/resample.h"
#include "MagickCore/resource_.h"
#include "MagickCore/string_.h"
@@ -1461,9 +1459,6 @@ MagickExport MagickBooleanType CompositeImage(Image *image,
MagickStatusType
flags;
- RandomInfo
- *random_info;
-
ssize_t
y;
@@ -2196,7 +2191,6 @@ MagickExport MagickBooleanType CompositeImage(Image *image,
status=MagickTrue;
progress=0;
midpoint=((MagickRealType) QuantumRange+1.0)/2;
- random_info=AcquireRandomInfo();
source_view=AcquireVirtualCacheView(source_image,exception);
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
@@ -2929,10 +2923,8 @@ MagickExport MagickBooleanType CompositeImage(Image *image,
}
case DissolveCompositeOp:
{
- if (GetPseudoRandomValue(random_info) < (source_dissolve*Sa))
- pixel=Sc;
- else
- pixel=Dc;
+ pixel=gamma*(source_dissolve*Sa*Sc-source_dissolve*Sa*
+ canvas_dissolve*Da*Dc+canvas_dissolve*Da*Dc);
break;
}
case DivideDstCompositeOp:
@@ -3585,7 +3577,6 @@ MagickExport MagickBooleanType CompositeImage(Image *image,
}
source_view=DestroyCacheView(source_view);
image_view=DestroyCacheView(image_view);
- random_info=DestroyRandomInfo(random_info);
if (canvas_image != (Image * ) NULL)
canvas_image=DestroyImage(canvas_image);
else