/*
Programmers notes on SVG specification.
-
+
A Composition is defined by...
Color Function : f(Sc,Dc) where Sc and Dc are the normizalized colors
Blending areas : X = 1 for area of overlap ie: f(Sc,Dc)
Y = 1 for source preserved
Z = 1 for destination preserved
-
+
Conversion to transparency (then optimized)
Dca' = f(Sc, Dc)*Sa*Da + Y*Sca*(1-Da) + Z*Dca*(1-Sa)
Da' = X*Sa*Da + Y*Sa*(1-Da) + Z*Da*(1-Sa)
-
+
Where...
Sca = Sc*Sa normalized Source color divided by Source alpha
Dca = Dc*Da normalized Dest color divided by Dest alpha
Dc' = Dca'/Da' the desired color value for this channel.
-
+
Da' (alpha result) is stored as 'gamma' in the functions.
-
+
The compose functions defined is just simplifications of the above
formula on a case by case bases.
methods should use a 'Over' blending mode for Alpha Channel.
It however was not applied for composition modes of 'Plus', 'Minus',
the modulus versions of 'Add' and 'Subtract'.
-
+
Mathematical operator changes to be applied from IM v6.7...
-
+
1/ Modulus modes 'Add' and 'Subtract' are obsoleted and renamed
'ModulusAdd' and 'ModulusSubtract' for clarity.
-
+
2/ All mathematical compositions work as per the SVG specification
with regard to blending. This now includes 'ModulusAdd' and
'ModulusSubtract'.
-
+
3/ When the special channel flag 'sync' (syncronize channel updates)
is turned off (enabled by default) then mathematical compositions are
only performed on the channels specified, and are applied
MagickStatusType
flags;
- PixelInfo
- zero;
-
ssize_t
y;
assert(composite_image->signature == MagickSignature);
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
return(MagickFalse);
- GetPixelInfo(image,&zero);
destination_image=(Image *) NULL;
amount=0.5;
destination_dissolve=1.0;
switch (compose)
{
case ClearCompositeOp:
- case SrcCompositeOp:
+ case DstAtopCompositeOp:
+ case DstInCompositeOp:
case InCompositeOp:
- case SrcInCompositeOp:
case OutCompositeOp:
+ case SrcCompositeOp:
+ case SrcInCompositeOp:
case SrcOutCompositeOp:
- case DstInCompositeOp:
- case DstAtopCompositeOp:
{
/*
Modify destination outside the overlaid region.
/*
Blur Image by resampling.
*/
- pixel=zero;
resample_filter=AcquireResampleFilter(image,exception);
SetResampleFilter(resample_filter,CubicFilter,2.0);
destination_view=AcquireCacheView(destination_image);
Shift the pixel offset point as defined by the provided,
displacement/distortion map. -- Like a lens...
*/
- pixel=zero;
+ GetPixelInfo(image,&pixel);
image_view=AcquireCacheView(image);
destination_view=AcquireCacheView(destination_image);
composite_view=AcquireCacheView(composite_image);
status=MagickTrue;
progress=0;
midpoint=((MagickRealType) QuantumRange+1.0)/2;
- GetPixelInfo(composite_image,&zero);
image_view=AcquireCacheView(image);
composite_view=AcquireCacheView(composite_image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+// #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
hue,
saturation;
- PixelInfo
- composite,
- destination,
- source;
-
register const Quantum
*restrict p;
register ssize_t
x;
+MagickBooleanType composite_channels;
+
if (status == MagickFalse)
continue;
if (modify_outside_overlay == MagickFalse)
status=MagickFalse;
continue;
}
- source=zero;
- destination=zero;
hue=0.0;
saturation=0.0;
brightness=0.0;
if ((x-x_offset) >= (ssize_t) composite_image->columns)
break;
}
- destination.red=(MagickRealType) GetPixelRed(image,q);
- destination.green=(MagickRealType) GetPixelGreen(image,q);
- destination.blue=(MagickRealType) GetPixelBlue(image,q);
- if (image->colorspace == CMYKColorspace)
- destination.black=(MagickRealType) GetPixelBlack(image,q);
- if (image->colorspace == CMYKColorspace)
+ composite_channels=MagickFalse;
+ switch (compose)
+ {
+ case AtopCompositeOp:
+ case ClearCompositeOp:
+ case CopyCompositeOp:
+ case DstAtopCompositeOp:
+ case DstCompositeOp:
+ case DstInCompositeOp:
+ case DstOverCompositeOp:
+ case DstOutCompositeOp:
+ case InCompositeOp:
+ case OutCompositeOp:
+ case OverCompositeOp:
+ case ReplaceCompositeOp:
+ case SrcAtopCompositeOp:
+ case SrcCompositeOp:
+ case SrcInCompositeOp:
+ case SrcOutCompositeOp:
+ case SrcOverCompositeOp:
+ case XorCompositeOp:
{
- destination.red=(MagickRealType) QuantumRange-destination.red;
- destination.green=(MagickRealType) QuantumRange-destination.green;
- destination.blue=(MagickRealType) QuantumRange-destination.blue;
- destination.black=(MagickRealType) QuantumRange-destination.black;
+ composite_channels=MagickTrue;
+ break;
}
- if (image->matte != MagickFalse)
- destination.alpha=(MagickRealType) GetPixelAlpha(image,q);
- /*
- Handle destination modifications outside overlaid region.
- */
- composite=destination;
- if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
- ((x-x_offset) >= (ssize_t) composite_image->columns))
+ default:
+ break;
+ }
+ if (composite_channels != MagickFalse) {
+ MagickRealType
+ Da,
+ Dc,
+ gamma,
+ Sa,
+ Sc;
+
+ register ssize_t
+ i;
+
+ if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
+ ((x-x_offset) >= (ssize_t) composite_image->columns))
+ {
+ Quantum
+ source[MaxPixelChannels];
+
+ /*
+ Virtual composite:
+ Sc: source color.
+ Dc: destination color.
+ */
+ (void) GetOneVirtualPixel(composite_image,x-x_offset,y-y_offset,
+ source,exception);
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ MagickRealType
+ pixel;
+
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if (traits == UndefinedPixelTrait)
+ continue;
+ switch (compose)
+ {
+ case ClearCompositeOp:
+ case CopyCompositeOp:
+ case ReplaceCompositeOp:
+ case SrcCompositeOp:
+ {
+ pixel=0.0;
+ if (channel == AlphaPixelChannel)
+ pixel=(MagickRealType) TransparentAlpha;
+ break;
+ }
+ case DstAtopCompositeOp:
+ case InCompositeOp:
+ case OutCompositeOp:
+ case SrcInCompositeOp:
+ case SrcOutCompositeOp:
+ {
+ pixel=(MagickRealType) q[i];
+ if (channel == AlphaPixelChannel)
+ pixel=(MagickRealType) TransparentAlpha;
+ break;
+ }
+ default:
+ {
+ pixel=source[channel];
+ break;
+ }
+ }
+ q[i]=ClampToQuantum(pixel);
+ }
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ /*
+ Authentic composite:
+ Sa: source normalized alpha.
+ Da: destination normalized alpha.
+ */
+ Sa=QuantumScale*GetPixelAlpha(composite_image,p);
+ Da=QuantumScale*GetPixelAlpha(image,q);
+ switch (compose)
+ {
+ case DstOverCompositeOp:
+ {
+ gamma=Da*(-Sa)+Da+Sa;
+ break;
+ }
+ case DstAtopCompositeOp:
+ case DstInCompositeOp:
+ case InCompositeOp:
+ case SrcInCompositeOp:
+ {
+ gamma=Sa*Da;
+ break;
+ }
+ case DstOutCompositeOp:
+ {
+ gamma=Da*(1.0-Sa);
+ break;
+ }
+ case OutCompositeOp:
+ case SrcOutCompositeOp:
+ {
+ gamma=Sa*(1.0-Da);
+ break;
+ }
+ case OverCompositeOp:
+ case SrcOverCompositeOp:
+ {
+ gamma=Sa*(-Da)+Sa+Da;
+ break;
+ }
+ case XorCompositeOp:
+ {
+ gamma=Sa+Da-2.0*Sa*Da;
+ break;
+ }
+ default:
+ {
+ gamma=1.0;
+ break;
+ }
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
+ MagickRealType
+ pixel;
+
+ PixelChannel
+ channel;
+
+ PixelTrait
+ composite_traits,
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ composite_traits=GetPixelChannelMapTraits(composite_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (composite_traits == UndefinedPixelTrait))
+ continue;
+ /*
+ Sc: source color.
+ Dc: destination color.
+ */
+ Sc=(MagickRealType) GetPixelChannel(composite_image,channel,p);
+ Dc=(MagickRealType) q[i];
+ if ((traits & CopyPixelTrait) != 0)
+ {
+ if (channel != AlphaPixelChannel)
+ {
+ /*
+ Copy channel.
+ */
+ q[i]=Sc;
+ continue;
+ }
+ /*
+ Set alpha channel.
+ */
+ pixel=0.0;
+ switch (compose)
+ {
+ case CopyCompositeOp:
+ case DstAtopCompositeOp:
+ case ReplaceCompositeOp:
+ case SrcCompositeOp:
+ {
+ pixel=QuantumRange*Sa;
+ break;
+ }
+ case AtopCompositeOp:
+ case SrcAtopCompositeOp:
+ case DstCompositeOp:
+ {
+ pixel=QuantumRange*Da;
+ break;
+ }
+ default:
+ {
+ pixel=QuantumRange*gamma;
+ break;
+ }
+ }
+ q[i]=ClampToQuantum(pixel);
+ continue;
+ }
+ /*
+ Porter-Duff compositions.
+ */
+ pixel=0.0;
switch (compose)
{
- case DissolveCompositeOp:
- case BlendCompositeOp:
+ case AtopCompositeOp:
+ case SrcAtopCompositeOp:
{
- composite.alpha=destination_dissolve*(composite.alpha);
+ pixel=Sc*Sa+Dc*(1.0-Sa);
break;
}
- case ClearCompositeOp:
+ case CopyCompositeOp:
+ case ReplaceCompositeOp:
case SrcCompositeOp:
{
- CompositeClear(&destination,&composite);
+ pixel=Sc;
+ break;
+ }
+ case DstAtopCompositeOp:
+ {
+ pixel=Dc*Da+Sc*(1.0-Da);
+ break;
+ }
+ case DstCompositeOp:
+ {
+ pixel=Dc;
+ break;
+ }
+ case DstInCompositeOp:
+ {
+ pixel=gamma*(Sa*Dc*Sa);
+ break;
+ }
+ case DstOutCompositeOp:
+ {
+ pixel=gamma*(Da*Dc*(1.0-Sa));
+ break;
+ }
+ case DstOverCompositeOp:
+ {
+ pixel=gamma*(Da*Dc-Da*Sa*Sc+Sa*Sc);
break;
}
case InCompositeOp:
case SrcInCompositeOp:
+ {
+ pixel=gamma*(Da*Sc*Da);
+ break;
+ }
case OutCompositeOp:
case SrcOutCompositeOp:
- case DstInCompositeOp:
- case DstAtopCompositeOp:
- case CopyOpacityCompositeOp:
- case ChangeMaskCompositeOp:
{
- composite.alpha=(MagickRealType) TransparentAlpha;
+ pixel=gamma*(Sa*Sc*(1.0-Da));
break;
}
- default:
+ case OverCompositeOp:
+ case SrcOverCompositeOp:
+ {
+ pixel=gamma*(Sa*Sc-Sa*Da*Dc+Da*Dc);
+ break;
+ }
+ case XorCompositeOp:
{
- (void) GetOneVirtualPixelInfo(composite_image,
- GetPixelCacheVirtualMethod(composite_image),x-x_offset,y-
- y_offset,&composite,exception);
+ pixel=gamma*(Sc*Sa*(1.0-Da)+Dc*Da*(1.0-Sa));
break;
}
+ default:
+ break;
}
- if (image->colorspace == CMYKColorspace)
+ q[i]=ClampToQuantum(pixel);
+ }
+ } else {
+ PixelInfo
+ composite,
+ destination,
+ source,
+ zero;
+
+ GetPixelInfo(image,&zero);
+ source=zero;
+ destination=zero;
+ destination.red=(MagickRealType) GetPixelRed(image,q);
+ destination.green=(MagickRealType) GetPixelGreen(image,q);
+ destination.blue=(MagickRealType) GetPixelBlue(image,q);
+ if (image->colorspace == CMYKColorspace)
+ destination.black=(MagickRealType) GetPixelBlack(image,q);
+ if (image->colorspace == CMYKColorspace)
+ {
+ destination.red=(MagickRealType) QuantumRange-destination.red;
+ destination.green=(MagickRealType) QuantumRange-destination.green;
+ destination.blue=(MagickRealType) QuantumRange-destination.blue;
+ destination.black=(MagickRealType) QuantumRange-destination.black;
+ }
+ if (image->matte != MagickFalse)
+ destination.alpha=(MagickRealType) GetPixelAlpha(image,q);
+ /*
+ Handle destination modifications outside overlaid region.
+ */
+ composite=destination;
+ if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
+ ((x-x_offset) >= (ssize_t) composite_image->columns))
+ {
+ switch (compose)
{
- composite.red=(MagickRealType) QuantumRange-composite.red;
- composite.green=(MagickRealType) QuantumRange-composite.green;
- composite.blue=(MagickRealType) QuantumRange-composite.blue;
- composite.black=(MagickRealType) QuantumRange-composite.black;
+ case DissolveCompositeOp:
+ case BlendCompositeOp:
+ {
+ composite.alpha=destination_dissolve*(composite.alpha);
+ break;
+ }
+ case ClearCompositeOp:
+ case SrcCompositeOp:
+ {
+ CompositeClear(&destination,&composite);
+ break;
+ }
+ case InCompositeOp:
+ case SrcInCompositeOp:
+ case OutCompositeOp:
+ case SrcOutCompositeOp:
+ case DstInCompositeOp:
+ case DstAtopCompositeOp:
+ case CopyOpacityCompositeOp:
+ case ChangeMaskCompositeOp:
+ {
+ composite.alpha=(MagickRealType) TransparentAlpha;
+ break;
+ }
+ default:
+ {
+ (void) GetOneVirtualPixelInfo(composite_image,
+ GetPixelCacheVirtualMethod(composite_image),x-x_offset,y-
+ y_offset,&composite,exception);
+ break;
+ }
}
- SetPixelRed(image,ClampToQuantum(composite.red),q);
- SetPixelGreen(image,ClampToQuantum(composite.green),q);
- SetPixelBlue(image,ClampToQuantum(composite.blue),q);
- if (image->matte != MagickFalse)
- SetPixelAlpha(image,ClampToQuantum(composite.alpha),q);
- if (image->colorspace == CMYKColorspace)
- SetPixelBlack(image,ClampToQuantum(composite.black),q);
- q+=GetPixelChannels(image);
- continue;
- }
- /*
- Handle normal overlay of source onto destination.
- */
- source.red=(MagickRealType) GetPixelRed(composite_image,p);
- source.green=(MagickRealType) GetPixelGreen(composite_image,p);
- source.blue=(MagickRealType) GetPixelBlue(composite_image,p);
- if (composite_image->colorspace == CMYKColorspace)
- source.black=(MagickRealType) GetPixelBlack(composite_image,p);
- if (composite_image->colorspace == CMYKColorspace)
- {
- source.red=(MagickRealType) QuantumRange-source.red;
- source.green=(MagickRealType) QuantumRange-source.green;
- source.blue=(MagickRealType) QuantumRange-source.blue;
- source.black=(MagickRealType) QuantumRange-source.black;
- }
- if (composite_image->matte != MagickFalse)
- source.alpha=(MagickRealType) GetPixelAlpha(composite_image,p);
- /*
- Porter-Duff compositions.
- */
- switch (compose)
- {
- case ClearCompositeOp:
- {
- CompositeClear(&destination,&composite);
- break;
- }
- case SrcCompositeOp:
- case CopyCompositeOp:
- case ReplaceCompositeOp:
- {
- composite=source;
- break;
- }
- case NoCompositeOp:
- case DstCompositeOp:
- break;
- case OverCompositeOp:
- case SrcOverCompositeOp:
- {
- CompositePixelInfoOver(&source,source.alpha,&destination,
- destination.alpha,&composite);
- break;
- }
- case DstOverCompositeOp:
- {
- CompositePixelInfoOver(&destination,destination.alpha,&source,
- source.alpha,&composite);
- break;
- }
- case SrcInCompositeOp:
- case InCompositeOp:
- {
- CompositeIn(&source,&destination,&composite);
- break;
- }
- case DstInCompositeOp:
- {
- CompositeIn(&destination,&source,&composite);
- break;
- }
- case OutCompositeOp:
- case SrcOutCompositeOp:
- {
- CompositeOut(&source,&destination,&composite);
- break;
- }
- case DstOutCompositeOp:
- {
- CompositeOut(&destination,&source,&composite);
- break;
- }
- case AtopCompositeOp:
- case SrcAtopCompositeOp:
- {
- CompositeAtop(&source,&destination,&composite);
- break;
- }
- case DstAtopCompositeOp:
- {
- CompositeAtop(&destination,&source,&composite);
- break;
- }
- case XorCompositeOp:
- {
- CompositeXor(&source,&destination,&composite);
- break;
- }
- case PlusCompositeOp:
- {
- CompositePlus(image,&source,&destination,&composite);
- break;
- }
- case MinusDstCompositeOp:
- {
- CompositeMinus(image,&source,&destination,&composite);
- break;
- }
- case MinusSrcCompositeOp:
- {
- CompositeMinus(image,&destination,&source,&composite);
- break;
- }
- case ModulusAddCompositeOp:
- {
- CompositeModulusAdd(image,&source,&destination,&composite);
- break;
- }
- case ModulusSubtractCompositeOp:
- {
- CompositeModulusSubtract(image,&source,&destination,&composite);
- break;
- }
- case DifferenceCompositeOp:
- {
- CompositeDifference(image,&source,&destination,&composite);
- break;
- }
- case ExclusionCompositeOp:
- {
- CompositeExclusion(image,&source,&destination,&composite);
- break;
- }
- case MultiplyCompositeOp:
- {
- CompositeMultiply(image,&source,&destination,&composite);
- break;
- }
- case ScreenCompositeOp:
- {
- CompositeScreen(image,&source,&destination,&composite);
- break;
- }
- case DivideDstCompositeOp:
- {
- CompositeDivide(image,&source,&destination,&composite);
- break;
- }
- case DivideSrcCompositeOp:
- {
- CompositeDivide(image,&destination,&source,&composite);
- break;
- }
- case DarkenCompositeOp:
- {
- CompositeDarken(image,&source,&destination,&composite);
- break;
- }
- case LightenCompositeOp:
- {
- CompositeLighten(image,&source,&destination,&composite);
- break;
- }
- case DarkenIntensityCompositeOp:
- {
- CompositeDarkenIntensity(image,&source,&destination,&composite);
- break;
- }
- case LightenIntensityCompositeOp:
- {
- CompositeLightenIntensity(image,&source,&destination,&composite);
- break;
- }
- case MathematicsCompositeOp:
- {
- CompositeMathematics(image,&source,&destination,&geometry_info,
- &composite);
- break;
- }
- case ColorDodgeCompositeOp:
- {
- CompositeColorDodge(&source,&destination,&composite);
- break;
- }
- case ColorBurnCompositeOp:
- {
- CompositeColorBurn(&source,&destination,&composite);
- break;
- }
- case LinearDodgeCompositeOp:
- {
- CompositeLinearDodge(&source,&destination,&composite);
- break;
- }
- case LinearBurnCompositeOp:
- {
- CompositeLinearBurn(&source,&destination,&composite);
- break;
- }
- case HardLightCompositeOp:
- {
- CompositeHardLight(&source,&destination,&composite);
- break;
- }
- case OverlayCompositeOp:
- {
- CompositeHardLight(&destination,&source,&composite);
- break;
- }
- case SoftLightCompositeOp:
- {
- CompositeSoftLight(&source,&destination,&composite);
- break;
- }
- case LinearLightCompositeOp:
- {
- CompositeLinearLight(&source,&destination,&composite);
- break;
- }
- case PegtopLightCompositeOp:
- {
- CompositePegtopLight(&source,&destination,&composite);
- break;
- }
- case VividLightCompositeOp:
- {
- CompositeVividLight(&source,&destination,&composite);
- break;
- }
- case PinLightCompositeOp:
- {
- CompositePinLight(&source,&destination,&composite);
- break;
- }
- case ChangeMaskCompositeOp:
- {
- if ((composite.alpha > ((MagickRealType) QuantumRange/2.0)) ||
- (IsFuzzyEquivalencePixelInfo(&source,&destination) != MagickFalse))
- composite.alpha=(MagickRealType) TransparentAlpha;
- else
- composite.alpha=(MagickRealType) OpaqueAlpha;
- break;
- }
- case BumpmapCompositeOp:
- {
- if (source.alpha == TransparentAlpha)
+ if (image->colorspace == CMYKColorspace)
+ {
+ composite.red=(MagickRealType) QuantumRange-composite.red;
+ composite.green=(MagickRealType) QuantumRange-composite.green;
+ composite.blue=(MagickRealType) QuantumRange-composite.blue;
+ composite.black=(MagickRealType) QuantumRange-composite.black;
+ }
+ SetPixelRed(image,ClampToQuantum(composite.red),q);
+ SetPixelGreen(image,ClampToQuantum(composite.green),q);
+ SetPixelBlue(image,ClampToQuantum(composite.blue),q);
+ if (image->matte != MagickFalse)
+ SetPixelAlpha(image,ClampToQuantum(composite.alpha),q);
+ if (image->colorspace == CMYKColorspace)
+ SetPixelBlack(image,ClampToQuantum(composite.black),q);
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ /*
+ Handle normal overlay of source onto destination.
+ */
+ source.red=(MagickRealType) GetPixelRed(composite_image,p);
+ source.green=(MagickRealType) GetPixelGreen(composite_image,p);
+ source.blue=(MagickRealType) GetPixelBlue(composite_image,p);
+ if (composite_image->colorspace == CMYKColorspace)
+ source.black=(MagickRealType) GetPixelBlack(composite_image,p);
+ if (composite_image->colorspace == CMYKColorspace)
+ {
+ source.red=(MagickRealType) QuantumRange-source.red;
+ source.green=(MagickRealType) QuantumRange-source.green;
+ source.blue=(MagickRealType) QuantumRange-source.blue;
+ source.black=(MagickRealType) QuantumRange-source.black;
+ }
+ if (composite_image->matte != MagickFalse)
+ source.alpha=(MagickRealType) GetPixelAlpha(composite_image,p);
+ /*
+ Porter-Duff compositions.
+ */
+ switch (compose)
+ {
+ case ClearCompositeOp:
+ {
+ CompositeClear(&destination,&composite);
break;
- CompositeBumpmap(&source,&destination,&composite);
- break;
- }
- case DissolveCompositeOp:
- {
- CompositePixelInfoOver(&source,source_dissolve*source.alpha,
- &destination,(MagickRealType) (destination_dissolve*
- destination.alpha),&composite);
- break;
- }
- case BlendCompositeOp:
- {
- CompositePixelInfoBlend(&source,source_dissolve,&destination,
- destination_dissolve,&composite);
- break;
- }
- case ThresholdCompositeOp:
- {
- CompositeThreshold(&source,&destination,threshold,amount,&composite);
- break;
- }
- case ModulateCompositeOp:
- {
- double
- blue,
- green,
- red;
-
- ssize_t
- offset;
-
- if (source.alpha == TransparentAlpha)
- break;
- offset=(ssize_t) (GetPixelInfoIntensity(&source)-midpoint);
- if (offset == 0)
- break;
- CompositeHSB(destination.red,destination.green,destination.blue,&hue,
- &saturation,&brightness);
- brightness+=(0.01*percent_brightness*offset)/midpoint;
- saturation*=0.01*percent_saturation;
- HSBComposite(hue,saturation,brightness,&red,&green,&blue);
- composite.red=red;
- composite.green=green;
- composite.blue=blue;
- break;
- }
- case HueCompositeOp:
- {
- if (source.alpha == TransparentAlpha)
+ }
+ case SrcCompositeOp:
+ case CopyCompositeOp:
+ case ReplaceCompositeOp:
+ {
+ composite=source;
break;
- if (destination.alpha == TransparentAlpha)
- {
- composite=source;
+ }
+ case NoCompositeOp:
+ case DstCompositeOp:
+ break;
+ case OverCompositeOp:
+ case SrcOverCompositeOp:
+ {
+ CompositePixelInfoOver(&source,source.alpha,&destination,
+ destination.alpha,&composite);
+ break;
+ }
+ case DstOverCompositeOp:
+ {
+ CompositePixelInfoOver(&destination,destination.alpha,&source,
+ source.alpha,&composite);
+ break;
+ }
+ case SrcInCompositeOp:
+ case InCompositeOp:
+ {
+ CompositeIn(&source,&destination,&composite);
+ break;
+ }
+ case DstInCompositeOp:
+ {
+ CompositeIn(&destination,&source,&composite);
+ break;
+ }
+ case OutCompositeOp:
+ case SrcOutCompositeOp:
+ {
+ CompositeOut(&source,&destination,&composite);
+ break;
+ }
+ case DstOutCompositeOp:
+ {
+ CompositeOut(&destination,&source,&composite);
+ break;
+ }
+ case AtopCompositeOp:
+ case SrcAtopCompositeOp:
+ {
+ CompositeAtop(&source,&destination,&composite);
+ break;
+ }
+ case DstAtopCompositeOp:
+ {
+ CompositeAtop(&destination,&source,&composite);
+ break;
+ }
+ case XorCompositeOp:
+ {
+ CompositeXor(&source,&destination,&composite);
+ break;
+ }
+ case PlusCompositeOp:
+ {
+ CompositePlus(image,&source,&destination,&composite);
+ break;
+ }
+ case MinusDstCompositeOp:
+ {
+ CompositeMinus(image,&source,&destination,&composite);
+ break;
+ }
+ case MinusSrcCompositeOp:
+ {
+ CompositeMinus(image,&destination,&source,&composite);
+ break;
+ }
+ case ModulusAddCompositeOp:
+ {
+ CompositeModulusAdd(image,&source,&destination,&composite);
+ break;
+ }
+ case ModulusSubtractCompositeOp:
+ {
+ CompositeModulusSubtract(image,&source,&destination,&composite);
+ break;
+ }
+ case DifferenceCompositeOp:
+ {
+ CompositeDifference(image,&source,&destination,&composite);
+ break;
+ }
+ case ExclusionCompositeOp:
+ {
+ CompositeExclusion(image,&source,&destination,&composite);
+ break;
+ }
+ case MultiplyCompositeOp:
+ {
+ CompositeMultiply(image,&source,&destination,&composite);
+ break;
+ }
+ case ScreenCompositeOp:
+ {
+ CompositeScreen(image,&source,&destination,&composite);
+ break;
+ }
+ case DivideDstCompositeOp:
+ {
+ CompositeDivide(image,&source,&destination,&composite);
+ break;
+ }
+ case DivideSrcCompositeOp:
+ {
+ CompositeDivide(image,&destination,&source,&composite);
+ break;
+ }
+ case DarkenCompositeOp:
+ {
+ CompositeDarken(image,&source,&destination,&composite);
+ break;
+ }
+ case LightenCompositeOp:
+ {
+ CompositeLighten(image,&source,&destination,&composite);
+ break;
+ }
+ case DarkenIntensityCompositeOp:
+ {
+ CompositeDarkenIntensity(image,&source,&destination,&composite);
+ break;
+ }
+ case LightenIntensityCompositeOp:
+ {
+ CompositeLightenIntensity(image,&source,&destination,&composite);
+ break;
+ }
+ case MathematicsCompositeOp:
+ {
+ CompositeMathematics(image,&source,&destination,&geometry_info,
+ &composite);
+ break;
+ }
+ case ColorDodgeCompositeOp:
+ {
+ CompositeColorDodge(&source,&destination,&composite);
+ break;
+ }
+ case ColorBurnCompositeOp:
+ {
+ CompositeColorBurn(&source,&destination,&composite);
+ break;
+ }
+ case LinearDodgeCompositeOp:
+ {
+ CompositeLinearDodge(&source,&destination,&composite);
+ break;
+ }
+ case LinearBurnCompositeOp:
+ {
+ CompositeLinearBurn(&source,&destination,&composite);
+ break;
+ }
+ case HardLightCompositeOp:
+ {
+ CompositeHardLight(&source,&destination,&composite);
+ break;
+ }
+ case OverlayCompositeOp:
+ {
+ CompositeHardLight(&destination,&source,&composite);
+ break;
+ }
+ case SoftLightCompositeOp:
+ {
+ CompositeSoftLight(&source,&destination,&composite);
+ break;
+ }
+ case LinearLightCompositeOp:
+ {
+ CompositeLinearLight(&source,&destination,&composite);
+ break;
+ }
+ case PegtopLightCompositeOp:
+ {
+ CompositePegtopLight(&source,&destination,&composite);
+ break;
+ }
+ case VividLightCompositeOp:
+ {
+ CompositeVividLight(&source,&destination,&composite);
+ break;
+ }
+ case PinLightCompositeOp:
+ {
+ CompositePinLight(&source,&destination,&composite);
+ break;
+ }
+ case ChangeMaskCompositeOp:
+ {
+ if ((composite.alpha > ((MagickRealType) QuantumRange/2.0)) ||
+ (IsFuzzyEquivalencePixelInfo(&source,&destination) != MagickFalse))
+ composite.alpha=(MagickRealType) TransparentAlpha;
+ else
+ composite.alpha=(MagickRealType) OpaqueAlpha;
+ break;
+ }
+ case BumpmapCompositeOp:
+ {
+ if (source.alpha == TransparentAlpha)
break;
- }
- CompositeHSB(destination.red,destination.green,destination.blue,&hue,
- &saturation,&brightness);
- CompositeHSB(source.red,source.green,source.blue,&hue,&sans,&sans);
- HSBComposite(hue,saturation,brightness,&composite.red,
- &composite.green,&composite.blue);
- if (source.alpha < destination.alpha)
- composite.alpha=source.alpha;
- break;
- }
- case SaturateCompositeOp:
- {
- if (source.alpha == TransparentAlpha)
+ CompositeBumpmap(&source,&destination,&composite);
break;
- if (destination.alpha == TransparentAlpha)
- {
- composite=source;
+ }
+ case DissolveCompositeOp:
+ {
+ CompositePixelInfoOver(&source,source_dissolve*source.alpha,
+ &destination,(MagickRealType) (destination_dissolve*
+ destination.alpha),&composite);
+ break;
+ }
+ case BlendCompositeOp:
+ {
+ CompositePixelInfoBlend(&source,source_dissolve,&destination,
+ destination_dissolve,&composite);
+ break;
+ }
+ case ThresholdCompositeOp:
+ {
+ CompositeThreshold(&source,&destination,threshold,amount,&composite);
+ break;
+ }
+ case ModulateCompositeOp:
+ {
+ double
+ blue,
+ green,
+ red;
+
+ ssize_t
+ offset;
+
+ if (source.alpha == TransparentAlpha)
break;
- }
- CompositeHSB(destination.red,destination.green,destination.blue,&hue,
- &saturation,&brightness);
- CompositeHSB(source.red,source.green,source.blue,&sans,&saturation,
- &sans);
- HSBComposite(hue,saturation,brightness,&composite.red,
- &composite.green,&composite.blue);
- if (source.alpha < destination.alpha)
- composite.alpha=source.alpha;
- break;
- }
- case LuminizeCompositeOp:
- {
- if (source.alpha == TransparentAlpha)
+ offset=(ssize_t) (GetPixelInfoIntensity(&source)-midpoint);
+ if (offset == 0)
+ break;
+ CompositeHSB(destination.red,destination.green,destination.blue,&hue,
+ &saturation,&brightness);
+ brightness+=(0.01*percent_brightness*offset)/midpoint;
+ saturation*=0.01*percent_saturation;
+ HSBComposite(hue,saturation,brightness,&red,&green,&blue);
+ composite.red=red;
+ composite.green=green;
+ composite.blue=blue;
break;
- if (destination.alpha == TransparentAlpha)
- {
- composite=source;
+ }
+ case HueCompositeOp:
+ {
+ if (source.alpha == TransparentAlpha)
break;
- }
- CompositeHSB(destination.red,destination.green,destination.blue,&hue,
- &saturation,&brightness);
- CompositeHSB(source.red,source.green,source.blue,&sans,&sans,
- &brightness);
- HSBComposite(hue,saturation,brightness,&composite.red,
- &composite.green,&composite.blue);
- if (source.alpha < destination.alpha)
- composite.alpha=source.alpha;
- break;
- }
- case ColorizeCompositeOp:
- {
- if (source.alpha == TransparentAlpha)
+ if (destination.alpha == TransparentAlpha)
+ {
+ composite=source;
+ break;
+ }
+ CompositeHSB(destination.red,destination.green,destination.blue,&hue,
+ &saturation,&brightness);
+ CompositeHSB(source.red,source.green,source.blue,&hue,&sans,&sans);
+ HSBComposite(hue,saturation,brightness,&composite.red,
+ &composite.green,&composite.blue);
+ if (source.alpha < destination.alpha)
+ composite.alpha=source.alpha;
break;
- if (destination.alpha == TransparentAlpha)
- {
- composite=source;
+ }
+ case SaturateCompositeOp:
+ {
+ if (source.alpha == TransparentAlpha)
break;
- }
- CompositeHSB(destination.red,destination.green,destination.blue,&sans,
- &sans,&brightness);
- CompositeHSB(source.red,source.green,source.blue,&hue,&saturation,
- &sans);
- HSBComposite(hue,saturation,brightness,&composite.red,
- &composite.green,&composite.blue);
- if (source.alpha < destination.alpha)
- composite.alpha=source.alpha;
- break;
- }
- case CopyRedCompositeOp:
- case CopyCyanCompositeOp:
- {
- composite.red=source.red;
- break;
- }
- case CopyGreenCompositeOp:
- case CopyMagentaCompositeOp:
- {
- composite.green=source.green;
- break;
- }
- case CopyBlueCompositeOp:
- case CopyYellowCompositeOp:
- {
- composite.blue=source.blue;
- break;
- }
- case CopyOpacityCompositeOp:
- {
- if (source.matte == MagickFalse)
- {
- composite.alpha=(MagickRealType) GetPixelInfoIntensity(&source);
+ if (destination.alpha == TransparentAlpha)
+ {
+ composite=source;
+ break;
+ }
+ CompositeHSB(destination.red,destination.green,destination.blue,&hue,
+ &saturation,&brightness);
+ CompositeHSB(source.red,source.green,source.blue,&sans,&saturation,
+ &sans);
+ HSBComposite(hue,saturation,brightness,&composite.red,
+ &composite.green,&composite.blue);
+ if (source.alpha < destination.alpha)
+ composite.alpha=source.alpha;
+ break;
+ }
+ case LuminizeCompositeOp:
+ {
+ if (source.alpha == TransparentAlpha)
break;
- }
- composite.alpha=source.alpha;
- break;
- }
- case CopyBlackCompositeOp:
- {
- if (source.colorspace != CMYKColorspace)
- ConvertRGBToCMYK(&source);
- composite.black=source.black;
- break;
- }
- case BlurCompositeOp:
- case DisplaceCompositeOp:
- case DistortCompositeOp:
- {
- composite=source;
- break;
+ if (destination.alpha == TransparentAlpha)
+ {
+ composite=source;
+ break;
+ }
+ CompositeHSB(destination.red,destination.green,destination.blue,&hue,
+ &saturation,&brightness);
+ CompositeHSB(source.red,source.green,source.blue,&sans,&sans,
+ &brightness);
+ HSBComposite(hue,saturation,brightness,&composite.red,
+ &composite.green,&composite.blue);
+ if (source.alpha < destination.alpha)
+ composite.alpha=source.alpha;
+ break;
+ }
+ case ColorizeCompositeOp:
+ {
+ if (source.alpha == TransparentAlpha)
+ break;
+ if (destination.alpha == TransparentAlpha)
+ {
+ composite=source;
+ break;
+ }
+ CompositeHSB(destination.red,destination.green,destination.blue,&sans,
+ &sans,&brightness);
+ CompositeHSB(source.red,source.green,source.blue,&hue,&saturation,
+ &sans);
+ HSBComposite(hue,saturation,brightness,&composite.red,
+ &composite.green,&composite.blue);
+ if (source.alpha < destination.alpha)
+ composite.alpha=source.alpha;
+ break;
+ }
+ case CopyRedCompositeOp:
+ case CopyCyanCompositeOp:
+ {
+ composite.red=source.red;
+ break;
+ }
+ case CopyGreenCompositeOp:
+ case CopyMagentaCompositeOp:
+ {
+ composite.green=source.green;
+ break;
+ }
+ case CopyBlueCompositeOp:
+ case CopyYellowCompositeOp:
+ {
+ composite.blue=source.blue;
+ break;
+ }
+ case CopyOpacityCompositeOp:
+ {
+ if (source.matte == MagickFalse)
+ {
+ composite.alpha=(MagickRealType) GetPixelInfoIntensity(&source);
+ break;
+ }
+ composite.alpha=source.alpha;
+ break;
+ }
+ case CopyBlackCompositeOp:
+ {
+ if (source.colorspace != CMYKColorspace)
+ ConvertRGBToCMYK(&source);
+ composite.black=source.black;
+ break;
+ }
+ case BlurCompositeOp:
+ case DisplaceCompositeOp:
+ case DistortCompositeOp:
+ {
+ composite=source;
+ break;
+ }
+ default:
+ break;
}
- default:
- break;
+ if (image->colorspace == CMYKColorspace)
+ {
+ composite.red=(MagickRealType) QuantumRange-composite.red;
+ composite.green=(MagickRealType) QuantumRange-composite.green;
+ composite.blue=(MagickRealType) QuantumRange-composite.blue;
+ composite.black=(MagickRealType) QuantumRange-composite.black;
+ }
+ SetPixelRed(image,ClampToQuantum(composite.red),q);
+ SetPixelGreen(image,ClampToQuantum(composite.green),q);
+ SetPixelBlue(image,ClampToQuantum(composite.blue),q);
+ if (image->colorspace == CMYKColorspace)
+ SetPixelBlack(image,ClampToQuantum(composite.black),q);
+ SetPixelAlpha(image,ClampToQuantum(composite.alpha),q);
}
- if (image->colorspace == CMYKColorspace)
- {
- composite.red=(MagickRealType) QuantumRange-composite.red;
- composite.green=(MagickRealType) QuantumRange-composite.green;
- composite.blue=(MagickRealType) QuantumRange-composite.blue;
- composite.black=(MagickRealType) QuantumRange-composite.black;
- }
- SetPixelRed(image,ClampToQuantum(composite.red),q);
- SetPixelGreen(image,ClampToQuantum(composite.green),q);
- SetPixelBlue(image,ClampToQuantum(composite.blue),q);
- if (image->colorspace == CMYKColorspace)
- SetPixelBlack(image,ClampToQuantum(composite.black),q);
- SetPixelAlpha(image,ClampToQuantum(composite.alpha),q);
p+=GetPixelChannels(composite_image);
if (p >= (pixels+composite_image->columns*GetPixelChannels(composite_image)))
p=pixels;