diff --git a/MagickCore/composite.c b/MagickCore/composite.c index 275873b6e0..267c93710e 100644 --- a/MagickCore/composite.c +++ b/MagickCore/composite.c @@ -83,6 +83,11 @@ #include "MagickCore/utility-private.h" #include "MagickCore/version.h" +/* + Define declarations. +*/ +#define MagickClamp(x) MagickMin(1.0,MagickMax(0.0,(x))) + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % @@ -2792,49 +2797,48 @@ MagickExport MagickBooleanType CompositeImage(Image *image, } case ColorBurnCompositeOp: { -#define MagickClamp(x) MagickMin(1.0,MagickMax(0.0,(x))) - double - Bca, burn = 0.0, Dd = (Da > 0.0) ? (Dca/Da) : 0.0, /* unpremultiplied dest */ - Sd = (Sa > 0.0) ? (Sca/Sa) : 0.0, /* unpremultiplied source */ - value; + Sd = (Sa > 0.0) ? (Sca/Sa) : 0.0; /* unpremultiplied source */ if (Sa == 0.0) { /* No source contribution. */ - value=Dca*(1.0-Sa); /* = Dca */ - pixel=(double) QuantumRange*gamma*MagickClamp(value); + pixel=(double) QuantumRange*gamma*MagickClamp(Dca*(1.0-Sa)); break; - } + } if ((Sca == 0.0) && (Dca == Da)) { /* Fully opaque destination, zero source color. */ - value=Sa*Da+Dca*(1.0-Sa); - pixel=(double) QuantumRange*gamma*MagickClamp(value); + pixel=(double) QuantumRange*gamma*MagickClamp(Sa*Da+Dca* + (1.0-Sa)); break; } if (Sd > 0.0) burn=1.0-(1.0-Dd)/Sd; - burn=MagickClamp(burn); - Bca=Sa*Da*burn+Sca*(1.0-Da)+Dca*(1.0-Sa); - value=MagickClamp(Bca); - pixel=(double) QuantumRange*gamma*value; + pixel=(double) QuantumRange*gamma*MagickClamp(Sa*Da* + MagickClamp(burn)+Sca*(1.0-Da)+Dca*(1.0-Sa)); break; } case ColorDodgeCompositeOp: { - if ((Sca*Da+Dca*Sa) >= Sa*Da) - pixel=(double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca* - (1.0-Sa)); + double + d = MagickClamp(Dca), + da = MagickClamp(Da), + s = MagickClamp(Sca), + sa = MagickClamp(Sa); + + if ((s*da+d*sa) >= (sa*da)) + pixel=sa*da+s*(1.0-da)+d*(1.0-sa); else - pixel=(double) QuantumRange*gamma*(Dca*Sa*Sa* - MagickSafeReciprocal(Sa-Sca)+Sca*(1.0-Da)+Dca*(1.0-Sa)); + pixel=(((sa-s) != 0.0) ? (d*sa*sa/(sa-s)) : 1.0)+s*(1.0-da)+d* + (1.0-sa); + pixel=QuantumRange*MagickClamp(pixel*gamma); break; } case ColorizeCompositeOp: @@ -2950,46 +2954,50 @@ MagickExport MagickBooleanType CompositeImage(Image *image, { if (compose_sync == MagickFalse) { - pixel=(double) QuantumRange*(Sc*MagickSafeReciprocal(Dc)); + pixel=QuantumRange*MagickClamp((double) Sc* + MagickSafeReciprocal((double) Dc)); break; } if ((fabs((double) Sca) < MagickEpsilon) && (fabs((double) Dca) < MagickEpsilon)) { - pixel=(double) QuantumRange*gamma*(Sca*(1.0-Da)+Dca*(1.0-Sa)); + pixel=(double) QuantumRange*MagickClamp(gamma*(Sca*(1.0-Da)+ + Dca*(1.0-Sa))); break; } if (fabs((double) Dca) < MagickEpsilon) { - pixel=(double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca* - (1.0-Sa)); + pixel=(double) QuantumRange*MagickClamp(gamma*(Sa*Da+ + Sca*(1.0-Da)+Dca*(1.0-Sa))); break; } - pixel=(double) QuantumRange*gamma*(Sca*Da*Da/Dca+Sca*(1.0-Da)+Dca* - (1.0-Sa)); + pixel=(double) QuantumRange*MagickClamp(gamma*(Sca*Da*Da/ + Dca+Sca*(1.0-Da)+Dca*(1.0-Sa))); break; } case DivideSrcCompositeOp: { if (compose_sync == MagickFalse) { - pixel=(double) QuantumRange*(Dc*MagickSafeReciprocal(Sc)); + pixel=(double) QuantumRange*MagickClamp(Dc* + MagickSafeReciprocal(Sc)); break; } if ((fabs((double) Dca) < MagickEpsilon) && (fabs((double) Sca) < MagickEpsilon)) { - pixel=(double) QuantumRange*gamma*(Dca*(1.0-Sa)+Sca*(1.0-Da)); + pixel=(double) QuantumRange*MagickClamp(gamma*(Dca*(1.0-Sa)+ + Sca*(1.0-Da))); break; } if (fabs((double) Sca) < MagickEpsilon) { - pixel=(double) QuantumRange*gamma*(Da*Sa+Dca*(1.0-Sa)+Sca* - (1.0-Da)); + pixel=(double) QuantumRange*MagickClamp(gamma*(Da*Sa+Dca* + (1.0-Sa)+Sca*(1.0-Da))); break; } - pixel=(double) QuantumRange*gamma*(Dca*Sa*SaSca+Dca*(1.0-Sa)+Sca* - (1.0-Da)); + pixel=(double) QuantumRange*MagickClamp(gamma*(Dca*Sa*SaSca+Dca* + (1.0-Sa)+Sca*(1.0-Da))); break; } case DstAtopCompositeOp: @@ -3020,22 +3028,17 @@ MagickExport MagickBooleanType CompositeImage(Image *image, } case FreezeCompositeOp: { - pixel=(double) QuantumRange*gamma*(1.0-(1.0-Sca)*(1.0-Sca)* - MagickSafeReciprocal(Dca)); - if (pixel < 0.0) - pixel=0.0; + pixel=ClampToQuantum(QuantumRange*gamma*(1.0-(1.0-Sca)*(1.0-Sca)* + MagickSafeReciprocal(Dca))); break; } case HardLightCompositeOp: { if ((2.0*Sca) < Sa) - { - pixel=(double) QuantumRange*gamma*(2.0*Sca*Dca+Sca*(1.0-Da)+Dca* - (1.0-Sa)); - break; - } - pixel=(double) QuantumRange*gamma*(Sa*Da-2.0*(Da-Dca)*(Sa-Sca)+Sca* - (1.0-Da)+Dca*(1.0-Sa)); + pixel=2.0*Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-Sa); + else + pixel=Sa*Da-2.0*(Da-Dca)*(Sa-Sca)+Sca*(1.0-Da)+Dca*(1.0-Sa); + pixel=(double) QuantumRange*MagickClamp(gamma*pixel); break; } case HardMixCompositeOp: @@ -3471,40 +3474,33 @@ MagickExport MagickBooleanType CompositeImage(Image *image, case SoftBurnCompositeOp: { if ((Sca+Dca) < 1.0) - pixel=(double) QuantumRange*gamma*(0.5*Dca* - MagickSafeReciprocal(1.0-Sca)); + pixel=0.5*Dca*MagickSafeReciprocal(1.0-Sca); else - pixel=(double) QuantumRange*gamma*(1.0-0.5*(1.0-Sca)* - MagickSafeReciprocal(Dca)); + pixel=1.0-0.5*(1.0-Sca)*MagickSafeReciprocal(Dca); + pixel=ClampToQuantum(QuantumRange*gamma*MagickClamp(pixel)); break; } case SoftDodgeCompositeOp: { if ((Sca+Dca) < 1.0) - pixel=(double) QuantumRange*gamma*(0.5*Sca* - MagickSafeReciprocal(1.0-Dca)); + pixel=0.5*Sca*MagickSafeReciprocal(1.0-Dca); else - pixel=(double) QuantumRange*gamma*(1.0-0.5*(1.0-Dca)* - MagickSafeReciprocal(Sca)); + pixel=1.0-0.5*(1.0-Dca)*MagickSafeReciprocal(Sca); + pixel=(double) QuantumRange*gamma*MagickClamp(pixel); break; } case SoftLightCompositeOp: { if ((2.0*Sca) < Sa) - { - pixel=(double) QuantumRange*gamma*(Dca*(Sa+(2.0*Sca-Sa)* - (1.0-DcaDa))+Sca*(1.0-Da)+Dca*(1.0-Sa)); - break; - } - if (((2.0*Sca) > Sa) && ((4.0*Dca) <= Da)) - { - pixel=(double) QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)* - (4.0*DcaDa*(4.0*DcaDa+1.0)*(DcaDa-1.0)+7.0*DcaDa)+Sca* - (1.0-Da)+Dca*(1.0-Sa)); - break; - } - pixel=(double) QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)* - (pow(DcaDa,0.5)-DcaDa)+Sca*(1.0-Da)+Dca*(1.0-Sa)); + pixel=Dca*(Sa+(2.0*Sca-Sa)*(1.0-DcaDa))+Sca*(1.0-Da)+Dca*(1.0-Sa); + else + if ((2.0*Sca) > Sa && (4.0*Dca) <= Da) + pixel=Dca*Sa+Da*(2.0*Sca-Sa)*(4.0*DcaDa*(4.0*DcaDa+1.0)* + (DcaDa-1.0)+7.0*DcaDa)+Sca*(1.0-Da)+Dca*(1.0-Sa); + else + pixel=Dca*Sa+Da*(2.0*Sca-Sa)*(sqrt(DcaDa)-DcaDa)+Sca*(1.0-Da)+ + Dca*(1.0-Sa); + pixel=(double) QuantumRange*MagickClamp(gamma*pixel); break; } case StampCompositeOp: