% MagickCore Image Composite Methods %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% July 1992 %
% %
% %
-% Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% The format of the CompositeImage method is:
%
% MagickBooleanType CompositeImage(Image *image,
-% const Image *composite_image,const CompositeOperator compose,
+% const Image *source_image,const CompositeOperator compose,
% const MagickBooleanType clip_to_self,const ssize_t x_offset,
% const ssize_t y_offset,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
-% o image: the destination image, modified by he composition
+% o image: the canvas image, modified by he composition
%
-% o composite_image: the composite (source) image.
+% o source_image: the source image.
%
% o compose: This operator affects how the composite is applied to
% the image. The operators and how they are utilized are listed here
%
% o y_offset: the row offset of the composited image.
%
-% Extra Controls from Image meta-data in 'composite_image' (artifacts)
+% Extra Controls from Image meta-data in 'image' (artifacts)
%
% o "compose:args"
% A string containing extra numerical arguments for specific compose
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
+ Z = 1 for canvas preserved
Conversion to transparency (then optimized)
Dca' = f(Sc, Dc)*Sa*Da + Y*Sca*(1-Da) + Z*Dca*(1-Sa)
operations.
*/
-static inline MagickRealType MagickMin(const MagickRealType x,
- const MagickRealType y)
-{
- if (x < y)
- return(x);
- return(y);
-}
-
-static inline MagickRealType MagickMax(const MagickRealType x,
- const MagickRealType y)
-{
- if (x > y)
- return(x);
- return(y);
-}
-
-static inline MagickRealType ConvertHueToRGB(MagickRealType m1,
- MagickRealType m2,MagickRealType hue)
-{
- if (hue < 0.0)
- hue+=1.0;
- if (hue > 1.0)
- hue-=1.0;
- if ((6.0*hue) < 1.0)
- return(m1+6.0*(m2-m1)*hue);
- if ((2.0*hue) < 1.0)
- return(m2);
- if ((3.0*hue) < 2.0)
- return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
- return(m1);
-}
-
static void HCLComposite(const MagickRealType hue,const MagickRealType chroma,
const MagickRealType luma,MagickRealType *red,MagickRealType *green,
MagickRealType *blue)
}
static MagickBooleanType CompositeOverImage(Image *image,
- const Image *composite_image,const MagickBooleanType clip_to_self,
+ const Image *source_image,const MagickBooleanType clip_to_self,
const ssize_t x_offset,const ssize_t y_offset,ExceptionInfo *exception)
{
#define CompositeImageTag "Composite/Image"
CacheView
- *composite_view,
- *image_view;
+ *image_view,
+ *source_view;
+
+ const char
+ *value;
MagickBooleanType
+ clamp,
status;
MagickOffsetType
*/
status=MagickTrue;
progress=0;
- composite_view=AcquireVirtualCacheView(composite_image,exception);
+ clamp=MagickTrue;
+ value=GetImageArtifact(image,"compose:clamp");
+ if (value != (const char *) NULL)
+ clamp=IsStringTrue(value);
+ source_view=AcquireVirtualCacheView(source_image,exception);
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static,4) shared(progress,status) \
- magick_threads(composite_image,image,image->rows,1)
+ magick_threads(source_image,image,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
*pixels;
register const Quantum
- *restrict p;
+ *magick_restrict p;
register Quantum
- *restrict q;
+ *magick_restrict q;
register ssize_t
x;
{
if (y < y_offset)
continue;
- if ((y-y_offset) >= (ssize_t) composite_image->rows)
+ if ((y-y_offset) >= (ssize_t) source_image->rows)
continue;
}
/*
*/
pixels=(Quantum *) NULL;
p=(Quantum *) NULL;
- if ((y >= y_offset) && ((y-y_offset) < (ssize_t) composite_image->rows))
+ if ((y >= y_offset) && ((y-y_offset) < (ssize_t) source_image->rows))
{
- p=GetCacheViewVirtualPixels(composite_view,0,y-y_offset,
- composite_image->columns,1,exception);
+ p=GetCacheViewVirtualPixels(source_view,0,y-y_offset,
+ source_image->columns,1,exception);
if (p == (const Quantum *) NULL)
{
status=MagickFalse;
}
pixels=p;
if (x_offset < 0)
- p-=x_offset*GetPixelChannels(composite_image);
+ p-=x_offset*GetPixelChannels(source_image);
}
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- double
- gamma;
-
MagickRealType
- alpha,
Da,
Dc,
+ Dca,
+ gamma,
Sa,
- Sc;
+ Sc,
+ Sca;
register ssize_t
i;
q+=GetPixelChannels(image);
continue;
}
- if ((x-x_offset) >= (ssize_t) composite_image->columns)
+ if ((x-x_offset) >= (ssize_t) source_image->columns)
break;
}
if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
- ((x-x_offset) >= (ssize_t) composite_image->columns))
+ ((x-x_offset) >= (ssize_t) source_image->columns))
{
Quantum
source[MaxPixelChannels];
/*
Virtual composite:
Sc: source color.
- Dc: destination color.
+ Dc: canvas color.
*/
- if (GetPixelReadMask(image,q) == 0)
+ if (GetPixelWriteMask(image,q) == 0)
{
q+=GetPixelChannels(image);
continue;
}
- (void) GetOneVirtualPixel(composite_image,x-x_offset,y-y_offset,
+ (void) GetOneVirtualPixel(source_image,x-x_offset,y-y_offset,
source,exception);
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
PixelChannel channel=GetPixelChannelChannel(image,i);
PixelTrait traits=GetPixelChannelTraits(image,channel);
- PixelTrait composite_traits=GetPixelChannelTraits(composite_image,
+ PixelTrait source_traits=GetPixelChannelTraits(source_image,
channel);
if ((traits == UndefinedPixelTrait) ||
- (composite_traits == UndefinedPixelTrait))
+ (source_traits == UndefinedPixelTrait))
continue;
q[i]=source[channel];
}
/*
Authentic composite:
Sa: normalized source alpha.
- Da: normalized destination alpha.
+ Da: normalized canvas alpha.
*/
- if (GetPixelReadMask(composite_image,p) == 0)
+ if (GetPixelWriteMask(source_image,p) == 0)
{
- p+=GetPixelChannels(composite_image);
- channels=GetPixelChannels(composite_image);
- if (p >= (pixels+channels*composite_image->columns))
+ p+=GetPixelChannels(source_image);
+ channels=GetPixelChannels(source_image);
+ if (p >= (pixels+channels*source_image->columns))
p=pixels;
q+=GetPixelChannels(image);
continue;
}
- Sa=QuantumScale*GetPixelAlpha(composite_image,p);
+ Sa=QuantumScale*GetPixelAlpha(source_image,p);
Da=QuantumScale*GetPixelAlpha(image,q);
- alpha=Sa*(-Da)+Sa+Da;
+ gamma=Sa+Da-Sa*Da;
+ gamma=PerceptibleReciprocal(gamma);
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
PixelChannel channel=GetPixelChannelChannel(image,i);
PixelTrait traits=GetPixelChannelTraits(image,channel);
- PixelTrait composite_traits=GetPixelChannelTraits(composite_image,
+ PixelTrait source_traits=GetPixelChannelTraits(source_image,
channel);
if ((traits == UndefinedPixelTrait) ||
- (composite_traits == UndefinedPixelTrait))
+ (source_traits == UndefinedPixelTrait))
continue;
if ((traits & CopyPixelTrait) != 0)
{
- if (channel != AlphaPixelChannel)
- {
- /*
- Copy channel.
- */
- q[i]=GetPixelChannel(composite_image,channel,p);
- continue;
- }
+ /*
+ Copy channel.
+ */
+ q[i]=GetPixelChannel(source_image,channel,p);
+ continue;
+ }
+ if (channel == AlphaPixelChannel)
+ {
/*
Set alpha channel.
*/
- q[i]=ClampToQuantum(QuantumRange*alpha);
+ q[i]=clamp != MagickFalse ?
+ ClampPixel(QuantumRange*(Sa+Da-Sa*Da)) :
+ ClampToQuantum(QuantumRange*(Sa+Da-Sa*Da));
continue;
}
/*
Sc: source color.
- Dc: destination color.
+ Dc: canvas color.
*/
- Sc=(MagickRealType) GetPixelChannel(composite_image,channel,p);
+ Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
Dc=(MagickRealType) q[i];
- gamma=PerceptibleReciprocal(alpha);
- q[i]=ClampToQuantum(gamma*(Sa*Sc-Sa*Da*Dc+Da*Dc));
+ Sca=QuantumScale*Sa*Sc;
+ Dca=QuantumScale*Da*Dc;
+ q[i]=clamp != MagickFalse ?
+ ClampPixel(gamma*QuantumRange*(Sca+Dca*(1.0-Sa))) :
+ ClampToQuantum(gamma*QuantumRange*(Sca+Dca*(1.0-Sa)));
}
- p+=GetPixelChannels(composite_image);
- channels=GetPixelChannels(composite_image);
- if (p >= (pixels+channels*composite_image->columns))
+ p+=GetPixelChannels(source_image);
+ channels=GetPixelChannels(source_image);
+ if (p >= (pixels+channels*source_image->columns))
p=pixels;
q+=GetPixelChannels(image);
}
status=MagickFalse;
}
}
- composite_view=DestroyCacheView(composite_view);
+ source_view=DestroyCacheView(source_view);
image_view=DestroyCacheView(image_view);
return(status);
}
#define CompositeImageTag "Composite/Image"
CacheView
- *composite_view,
+ *source_view,
*image_view;
+ const char
+ *value;
+
GeometryInfo
geometry_info;
Image
- *composite_image,
- *destination_image;
+ *canvas_image,
+ *source_image;
MagickBooleanType
+ clamp,
status;
MagickOffsetType
MagickRealType
amount,
- destination_dissolve,
+ canvas_dissolve,
midpoint,
percent_luma,
percent_chroma,
y;
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- assert(composite!= (Image *) NULL);
- assert(composite->signature == MagickSignature);
+ assert(composite != (Image *) NULL);
+ assert(composite->signature == MagickCoreSignature);
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
return(MagickFalse);
- composite_image=CloneImage(composite,0,0,MagickTrue,exception);
- if (composite_image == (const Image *) NULL)
+ source_image=CloneImage(composite,0,0,MagickTrue,exception);
+ if (source_image == (const Image *) NULL)
return(MagickFalse);
if (IsGrayColorspace(image->colorspace) != MagickFalse)
(void) SetImageColorspace(image,sRGBColorspace,exception);
- (void) SetImageColorspace(composite_image,image->colorspace,exception);
- if ((image->alpha_trait == BlendPixelTrait) &&
- (composite_image->alpha_trait != BlendPixelTrait))
- (void) SetImageAlphaChannel(composite_image,SetAlphaChannel,exception);
+ (void) SetImageColorspace(source_image,image->colorspace,exception);
if ((compose == OverCompositeOp) || (compose == SrcOverCompositeOp))
{
- status=CompositeOverImage(image,composite_image,clip_to_self,x_offset,
+ status=CompositeOverImage(image,source_image,clip_to_self,x_offset,
y_offset,exception);
- composite_image=DestroyImage(composite_image);
+ source_image=DestroyImage(source_image);
return(status);
}
- destination_image=(Image *) NULL;
amount=0.5;
- destination_dissolve=1.0;
+ canvas_image=(Image *) NULL;
+ canvas_dissolve=1.0;
+ clamp=MagickTrue;
+ value=GetImageArtifact(image,"compose:clamp");
+ if (value != (const char *) NULL)
+ clamp=IsStringTrue(value);
+ SetGeometryInfo(&geometry_info);
percent_luma=100.0;
percent_chroma=100.0;
source_dissolve=1.0;
{
if ((x_offset < 0) || (y_offset < 0))
break;
- if ((x_offset+(ssize_t) composite_image->columns) >= (ssize_t) image->columns)
+ if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
break;
- if ((y_offset+(ssize_t) composite_image->rows) >= (ssize_t) image->rows)
+ if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
break;
status=MagickTrue;
- composite_view=AcquireVirtualCacheView(composite_image,exception);
+ source_view=AcquireVirtualCacheView(source_image,exception);
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static,4) shared(status) \
- magick_threads(composite_image,image,composite_image->rows,1)
+ magick_threads(source_image,image,source_image->rows,1)
#endif
- for (y=0; y < (ssize_t) composite_image->rows; y++)
+ for (y=0; y < (ssize_t) source_image->rows; y++)
{
MagickBooleanType
sync;
if (status == MagickFalse)
continue;
- p=GetCacheViewVirtualPixels(composite_view,0,y,composite_image->columns,
- 1,exception);
+ p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
+ exception);
q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
- composite_image->columns,1,exception);
+ source_image->columns,1,exception);
if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
{
status=MagickFalse;
continue;
}
- for (x=0; x < (ssize_t) composite_image->columns; x++)
+ for (x=0; x < (ssize_t) source_image->columns; x++)
{
register ssize_t
i;
- if (GetPixelReadMask(composite_image,p) == 0)
+ if (GetPixelWriteMask(source_image,p) == 0)
{
- p+=GetPixelChannels(composite_image);
+ p+=GetPixelChannels(source_image);
q+=GetPixelChannels(image);
continue;
}
- for (i=0; i < (ssize_t) GetPixelChannels(composite_image); i++)
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- PixelChannel channel=GetPixelChannelChannel(composite_image,i);
- PixelTrait composite_traits=GetPixelChannelTraits(composite_image,
- channel);
+ PixelChannel channel=GetPixelChannelChannel(image,i);
PixelTrait traits=GetPixelChannelTraits(image,channel);
- if ((traits == UndefinedPixelTrait) ||
- (composite_traits == UndefinedPixelTrait))
+ PixelTrait source_traits=GetPixelChannelTraits(source_image,
+ channel);
+ if (traits == UndefinedPixelTrait)
continue;
- SetPixelChannel(image,channel,p[i],q);
+ if (source_traits != UndefinedPixelTrait)
+ SetPixelChannel(image,channel,p[i],q);
+ else if (channel == AlphaPixelChannel)
+ SetPixelChannel(image,channel,OpaqueAlpha,q);
+ }
+ p+=GetPixelChannels(source_image);
+ q+=GetPixelChannels(image);
+ }
+ sync=SyncCacheViewAuthenticPixels(image_view,exception);
+ if (sync == MagickFalse)
+ status=MagickFalse;
+ if (image->progress_monitor != (MagickProgressMonitor) NULL)
+ {
+ MagickBooleanType
+ proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp critical (MagickCore_CompositeImage)
+#endif
+ proceed=SetImageProgress(image,CompositeImageTag,
+ (MagickOffsetType) y,image->rows);
+ if (proceed == MagickFalse)
+ status=MagickFalse;
+ }
+ }
+ source_view=DestroyCacheView(source_view);
+ image_view=DestroyCacheView(image_view);
+ source_image=DestroyImage(source_image);
+ return(status);
+ }
+ case IntensityCompositeOp:
+ {
+ if ((x_offset < 0) || (y_offset < 0))
+ break;
+ if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
+ break;
+ if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
+ break;
+ status=MagickTrue;
+ source_view=AcquireVirtualCacheView(source_image,exception);
+ image_view=AcquireAuthenticCacheView(image,exception);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ magick_threads(source_image,image,source_image->rows,1)
+#endif
+ for (y=0; y < (ssize_t) source_image->rows; y++)
+ {
+ MagickBooleanType
+ sync;
+
+ register const Quantum
+ *p;
+
+ register Quantum
+ *q;
+
+ register ssize_t
+ x;
+
+ if (status == MagickFalse)
+ continue;
+ p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
+ exception);
+ q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
+ source_image->columns,1,exception);
+ if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
+ {
+ status=MagickFalse;
+ continue;
}
- p+=GetPixelChannels(composite_image);
+ for (x=0; x < (ssize_t) source_image->columns; x++)
+ {
+ if (GetPixelWriteMask(source_image,p) == 0)
+ {
+ p+=GetPixelChannels(source_image);
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ SetPixelAlpha(image,clamp != MagickFalse ?
+ ClampPixel(GetPixelIntensity(source_image,p)) :
+ ClampToQuantum(GetPixelIntensity(source_image,p)),q);
+ p+=GetPixelChannels(source_image);
q+=GetPixelChannels(image);
}
sync=SyncCacheViewAuthenticPixels(image_view,exception);
status=MagickFalse;
}
}
- composite_view=DestroyCacheView(composite_view);
+ source_view=DestroyCacheView(source_view);
image_view=DestroyCacheView(image_view);
- composite_image=DestroyImage(composite_image);
+ source_image=DestroyImage(source_image);
return(status);
}
case CopyAlphaCompositeOp:
case ChangeMaskCompositeOp:
- case IntensityCompositeOp:
{
/*
- Modify destination outside the overlaid region and require an alpha
+ Modify canvas outside the overlaid region and require an alpha
channel to exist, to add transparency.
*/
- if (image->alpha_trait != BlendPixelTrait)
+ if (image->alpha_trait == UndefinedPixelTrait)
(void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
break;
}
case BlurCompositeOp:
{
CacheView
- *composite_view,
- *destination_view;
-
- const char
- *value;
+ *canvas_view;
MagickRealType
angle_range,
Blur Image dictated by an overlay gradient map: X = red_channel;
Y = green_channel; compose:args = x_scale[,y_scale[,angle]].
*/
- destination_image=CloneImage(image,image->columns,image->rows,MagickTrue,
+ canvas_image=CloneImage(image,image->columns,image->rows,MagickTrue,
exception);
- if (destination_image == (Image *) NULL)
+ if (canvas_image == (Image *) NULL)
{
- composite_image=DestroyImage(composite_image);
+ source_image=DestroyImage(source_image);
return(MagickFalse);
}
/*
Gather the maximum blur sigma values from user.
*/
- SetGeometryInfo(&geometry_info);
flags=NoValue;
value=GetImageArtifact(image,"compose:args");
if (value != (const char *) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
"InvalidSetting","'%s' '%s'","compose:args",value);
- composite_image=DestroyImage(composite_image);
- destination_image=DestroyImage(destination_image);
+ source_image=DestroyImage(source_image);
+ canvas_image=DestroyImage(canvas_image);
return(MagickFalse);
}
/*
/* do the variable blurring of each pixel in image */
GetPixelInfo(image,&pixel);
- composite_view=AcquireVirtualCacheView(composite_image,exception);
- destination_view=AcquireAuthenticCacheView(destination_image,exception);
- for (y=0; y < (ssize_t) composite_image->rows; y++)
+ source_view=AcquireVirtualCacheView(source_image,exception);
+ canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
+ for (y=0; y < (ssize_t) source_image->rows; y++)
{
MagickBooleanType
sync;
register const Quantum
- *restrict p;
+ *magick_restrict p;
register Quantum
- *restrict q;
+ *magick_restrict q;
register ssize_t
x;
if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
continue;
- p=GetCacheViewVirtualPixels(composite_view,0,y,composite_image->columns,
- 1,exception);
- q=QueueCacheViewAuthenticPixels(destination_view,0,y,
- destination_image->columns,1,exception);
+ p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
+ exception);
+ q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
+ exception);
if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
break;
- for (x=0; x < (ssize_t) composite_image->columns; x++)
+ for (x=0; x < (ssize_t) source_image->columns; x++)
{
if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
{
- p+=GetPixelChannels(composite_image);
+ p+=GetPixelChannels(source_image);
continue;
}
- if (fabs(angle_range) > MagickEpsilon)
+ if (fabs((double) angle_range) > MagickEpsilon)
{
MagickRealType
angle;
angle=angle_start+angle_range*QuantumScale*
- GetPixelBlue(composite_image,p);
+ GetPixelBlue(source_image,p);
blur.x1=width*cos(angle);
blur.x2=width*sin(angle);
blur.y1=(-height*sin(angle));
GetPixelRed(p),QuantumScale*GetPixelGreen(p));
#endif
ScaleResampleFilter(resample_filter,
- blur.x1*QuantumScale*GetPixelRed(composite_image,p),
- blur.y1*QuantumScale*GetPixelGreen(composite_image,p),
- blur.x2*QuantumScale*GetPixelRed(composite_image,p),
- blur.y2*QuantumScale*GetPixelGreen(composite_image,p) );
+ blur.x1*QuantumScale*GetPixelRed(source_image,p),
+ blur.y1*QuantumScale*GetPixelGreen(source_image,p),
+ blur.x2*QuantumScale*GetPixelRed(source_image,p),
+ blur.y2*QuantumScale*GetPixelGreen(source_image,p) );
(void) ResamplePixelColor(resample_filter,(double) x_offset+x,
(double) y_offset+y,&pixel,exception);
- SetPixelInfoPixel(destination_image,&pixel,q);
- p+=GetPixelChannels(composite_image);
- q+=GetPixelChannels(destination_image);
+ SetPixelViaPixelInfo(canvas_image,&pixel,q);
+ p+=GetPixelChannels(source_image);
+ q+=GetPixelChannels(canvas_image);
}
- sync=SyncCacheViewAuthenticPixels(destination_view,exception);
+ sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
if (sync == MagickFalse)
break;
}
resample_filter=DestroyResampleFilter(resample_filter);
- composite_view=DestroyCacheView(composite_view);
- destination_view=DestroyCacheView(destination_view);
- composite_image=DestroyImage(composite_image);
- composite_image=destination_image;
+ source_view=DestroyCacheView(source_view);
+ canvas_view=DestroyCacheView(canvas_view);
+ source_image=DestroyImage(source_image);
+ source_image=canvas_image;
break;
}
case DisplaceCompositeOp:
case DistortCompositeOp:
{
CacheView
- *composite_view,
- *destination_view,
- *image_view;
-
- const char
- *value;
-
- PixelInfo
- pixel;
+ *canvas_view;
MagickRealType
horizontal_scale,
vertical_scale;
+ PixelInfo
+ pixel;
+
PointInfo
center,
offset;
X = red_channel; Y = green_channel;
compose:args = x_scale[,y_scale[,center.x,center.y]]
*/
- destination_image=CloneImage(image,image->columns,image->rows,MagickTrue,
+ canvas_image=CloneImage(image,image->columns,image->rows,MagickTrue,
exception);
- if (destination_image == (Image *) NULL)
+ if (canvas_image == (Image *) NULL)
{
- composite_image=DestroyImage(composite_image);
+ source_image=DestroyImage(source_image);
return(MagickFalse);
}
SetGeometryInfo(&geometry_info);
flags=NoValue;
- value=GetImageArtifact(composite_image,"compose:args");
+ value=GetImageArtifact(image,"compose:args");
if (value != (char *) NULL)
flags=ParseGeometry(value,&geometry_info);
- if ((flags & (WidthValue|HeightValue)) == 0 )
+ if ((flags & (WidthValue | HeightValue)) == 0 )
{
if ((flags & AspectValue) == 0)
{
- horizontal_scale=(MagickRealType) (composite_image->columns-1.0)/
- 2.0;
- vertical_scale=(MagickRealType) (composite_image->rows-1.0)/2.0;
+ horizontal_scale=(MagickRealType) (source_image->columns-1)/2.0;
+ vertical_scale=(MagickRealType) (source_image->rows-1)/2.0;
}
else
{
- horizontal_scale=(MagickRealType) (image->columns-1.0)/2.0;
- vertical_scale=(MagickRealType) (image->rows-1.0)/2.0;
+ horizontal_scale=(MagickRealType) (image->columns-1)/2.0;
+ vertical_scale=(MagickRealType) (image->rows-1)/2.0;
}
}
else
{
if ((flags & AspectValue) == 0)
{
- horizontal_scale*=(composite_image->columns-1.0)/200.0;
- vertical_scale*=(composite_image->rows-1.0)/200.0;
+ horizontal_scale*=(source_image->columns-1)/200.0;
+ vertical_scale*=(source_image->rows-1)/200.0;
}
else
{
- horizontal_scale*=(image->columns-1.0)/200.0;
- vertical_scale*=(image->rows-1.0)/200.0;
+ horizontal_scale*=(image->columns-1)/200.0;
+ vertical_scale*=(image->rows-1)/200.0;
}
}
if ((flags & HeightValue) == 0)
if (compose == DistortCompositeOp)
{
if ((flags & XValue) == 0)
- if ((flags & AspectValue) == 0)
- center.x=(MagickRealType) (x_offset+(composite_image->columns-1)/
- 2.0);
+ if ((flags & AspectValue) != 0)
+ center.x=(MagickRealType) ((image->columns-1)/2.0);
else
- center.x=(MagickRealType) ((image->columns-1)/2);
+ center.x=(MagickRealType) (x_offset+(source_image->columns-1)/
+ 2.0);
else
- if ((flags & AspectValue) == 0)
- center.x=(MagickRealType) x_offset+geometry_info.xi;
- else
+ if ((flags & AspectValue) != 0)
center.x=geometry_info.xi;
+ else
+ center.x=(MagickRealType) (x_offset+geometry_info.xi);
if ((flags & YValue) == 0)
- if ((flags & AspectValue) == 0)
- center.y=(MagickRealType) (y_offset+(composite_image->rows-1)/
- 2.0);
+ if ((flags & AspectValue) != 0)
+ center.y=(MagickRealType) ((image->rows-1)/2.0);
else
- center.y=(MagickRealType) ((image->rows-1)/2);
+ center.y=(MagickRealType) (y_offset+(source_image->rows-1)/2.0);
else
- if ((flags & AspectValue) == 0)
- center.y=(MagickRealType) y_offset+geometry_info.psi;
- else
+ if ((flags & AspectValue) != 0)
center.y=geometry_info.psi;
+ else
+ center.y=(MagickRealType) (y_offset+geometry_info.psi);
}
/*
Shift the pixel offset point as defined by the provided,
*/
GetPixelInfo(image,&pixel);
image_view=AcquireVirtualCacheView(image,exception);
- composite_view=AcquireVirtualCacheView(composite_image,exception);
- destination_view=AcquireAuthenticCacheView(destination_image,exception);
- for (y=0; y < (ssize_t) composite_image->rows; y++)
+ source_view=AcquireVirtualCacheView(source_image,exception);
+ canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
+ for (y=0; y < (ssize_t) source_image->rows; y++)
{
MagickBooleanType
sync;
register const Quantum
- *restrict p;
+ *magick_restrict p;
register Quantum
- *restrict q;
+ *magick_restrict q;
register ssize_t
x;
if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
continue;
- p=GetCacheViewVirtualPixels(composite_view,0,y,composite_image->columns,
- 1,exception);
- q=QueueCacheViewAuthenticPixels(destination_view,0,y,
- destination_image->columns,1,exception);
+ p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
+ exception);
+ q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
+ exception);
if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
break;
- for (x=0; x < (ssize_t) composite_image->columns; x++)
+ for (x=0; x < (ssize_t) source_image->columns; x++)
{
if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
{
- p+=GetPixelChannels(composite_image);
+ p+=GetPixelChannels(source_image);
continue;
}
/*
Displace the offset.
*/
- offset.x=(double) (horizontal_scale*(GetPixelRed(composite_image,p)-
+ offset.x=(double) (horizontal_scale*(GetPixelRed(source_image,p)-
(((MagickRealType) QuantumRange+1.0)/2.0)))/(((MagickRealType)
QuantumRange+1.0)/2.0)+center.x+((compose == DisplaceCompositeOp) ?
x : 0);
- offset.y=(double) (vertical_scale*(GetPixelGreen(composite_image,p)-
+ offset.y=(double) (vertical_scale*(GetPixelGreen(source_image,p)-
(((MagickRealType) QuantumRange+1.0)/2.0)))/(((MagickRealType)
QuantumRange+1.0)/2.0)+center.y+((compose == DisplaceCompositeOp) ?
y : 0);
/*
Mask with the 'invalid pixel mask' in alpha channel.
*/
- pixel.alpha=(MagickRealType) QuantumRange*(1.0-(1.0-QuantumScale*
- pixel.alpha)*(1.0-QuantumScale*GetPixelAlpha(composite_image,p)));
- SetPixelInfoPixel(destination_image,&pixel,q);
- p+=GetPixelChannels(composite_image);
- q+=GetPixelChannels(destination_image);
+ pixel.alpha=(MagickRealType) QuantumRange*(QuantumScale*pixel.alpha)*
+ (QuantumScale*GetPixelAlpha(source_image,p));
+ SetPixelViaPixelInfo(canvas_image,&pixel,q);
+ p+=GetPixelChannels(source_image);
+ q+=GetPixelChannels(canvas_image);
}
- sync=SyncCacheViewAuthenticPixels(destination_view,exception);
+ sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
if (sync == MagickFalse)
break;
}
- destination_view=DestroyCacheView(destination_view);
- composite_view=DestroyCacheView(composite_view);
+ canvas_view=DestroyCacheView(canvas_view);
+ source_view=DestroyCacheView(source_view);
image_view=DestroyCacheView(image_view);
- composite_image=DestroyImage(composite_image);
- composite_image=destination_image;
+ source_image=DestroyImage(source_image);
+ source_image=canvas_image;
break;
}
case DissolveCompositeOp:
{
- const char
- *value;
-
/*
Geometry arguments to dissolve factors.
*/
- value=GetImageArtifact(composite_image,"compose:args");
+ value=GetImageArtifact(image,"compose:args");
if (value != (char *) NULL)
{
flags=ParseGeometry(value,&geometry_info);
source_dissolve=geometry_info.rho/100.0;
- destination_dissolve=1.0;
+ canvas_dissolve=1.0;
if ((source_dissolve-MagickEpsilon) < 0.0)
source_dissolve=0.0;
if ((source_dissolve+MagickEpsilon) > 1.0)
{
- destination_dissolve=2.0-source_dissolve;
+ canvas_dissolve=2.0-source_dissolve;
source_dissolve=1.0;
}
if ((flags & SigmaValue) != 0)
- destination_dissolve=geometry_info.sigma/100.0;
- if ((destination_dissolve-MagickEpsilon) < 0.0)
- destination_dissolve=0.0;
- /* posible speed up? -- from IMv6 update
- clip_to_self=MagickFalse;
- if ((destination_dissolve+MagickEpsilon) > 1.0 )
- {
- destination_dissolve=1.0;
- clip_to_self=MagickTrue;
- }
- */
+ canvas_dissolve=geometry_info.sigma/100.0;
+ if ((canvas_dissolve-MagickEpsilon) < 0.0)
+ canvas_dissolve=0.0;
}
break;
}
case BlendCompositeOp:
{
- const char
- *value;
-
- value=GetImageArtifact(composite_image,"compose:args");
+ value=GetImageArtifact(image,"compose:args");
if (value != (char *) NULL)
{
flags=ParseGeometry(value,&geometry_info);
source_dissolve=geometry_info.rho/100.0;
- destination_dissolve=1.0-source_dissolve;
+ canvas_dissolve=1.0-source_dissolve;
if ((flags & SigmaValue) != 0)
- destination_dissolve=geometry_info.sigma/100.0;
+ canvas_dissolve=geometry_info.sigma/100.0;
}
break;
}
case MathematicsCompositeOp:
{
- const char
- *value;
-
/*
Just collect the values from "compose:args", setting.
Unused values are set to zero automagically.
number of values)
*/
SetGeometryInfo(&geometry_info);
- value=GetImageArtifact(composite_image,"compose:args");
+ value=GetImageArtifact(image,"compose:args");
if (value != (char *) NULL)
(void) ParseGeometry(value,&geometry_info);
break;
}
case ModulateCompositeOp:
{
- const char
- *value;
-
/*
Determine the luma and chroma scale.
*/
- value=GetImageArtifact(composite_image,"compose:args");
+ value=GetImageArtifact(image,"compose:args");
if (value != (char *) NULL)
{
flags=ParseGeometry(value,&geometry_info);
}
case ThresholdCompositeOp:
{
- const char
- *value;
-
/*
Determine the amount and threshold.
*/
- value=GetImageArtifact(composite_image,"compose:args");
+ value=GetImageArtifact(image,"compose:args");
if (value != (char *) NULL)
{
flags=ParseGeometry(value,&geometry_info);
status=MagickTrue;
progress=0;
midpoint=((MagickRealType) QuantumRange+1.0)/2;
- composite_view=AcquireVirtualCacheView(composite_image,exception);
+ source_view=AcquireVirtualCacheView(source_image,exception);
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static,4) shared(progress,status) \
- magick_threads(composite_image,image,image->rows,1)
+ magick_threads(source_image,image,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
MagickRealType
blue,
- luma,
+ chroma,
green,
hue,
- red,
- chroma;
+ luma,
+ red;
PixelInfo
- destination_pixel,
+ canvas_pixel,
source_pixel;
register const Quantum
- *restrict p;
+ *magick_restrict p;
register Quantum
- *restrict q;
+ *magick_restrict q;
register ssize_t
x;
{
if (y < y_offset)
continue;
- if ((y-y_offset) >= (ssize_t) composite_image->rows)
+ if ((y-y_offset) >= (ssize_t) source_image->rows)
continue;
}
/*
*/
pixels=(Quantum *) NULL;
p=(Quantum *) NULL;
- if ((y >= y_offset) && ((y-y_offset) < (ssize_t) composite_image->rows))
+ if ((y >= y_offset) && ((y-y_offset) < (ssize_t) source_image->rows))
{
- p=GetCacheViewVirtualPixels(composite_view,0,y-y_offset,
- composite_image->columns,1,exception);
+ p=GetCacheViewVirtualPixels(source_view,0,y-y_offset,
+ source_image->columns,1,exception);
if (p == (const Quantum *) NULL)
{
status=MagickFalse;
}
pixels=p;
if (x_offset < 0)
- p-=x_offset*GetPixelChannels(composite_image);
+ p-=x_offset*GetPixelChannels(source_image);
}
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
hue=0.0;
chroma=0.0;
luma=0.0;
- GetPixelInfo(image,&destination_pixel);
- GetPixelInfo(composite_image,&source_pixel);
+ GetPixelInfo(image,&canvas_pixel);
+ GetPixelInfo(source_image,&source_pixel);
for (x=0; x < (ssize_t) image->columns; x++)
{
double
q+=GetPixelChannels(image);
continue;
}
- if ((x-x_offset) >= (ssize_t) composite_image->columns)
+ if ((x-x_offset) >= (ssize_t) source_image->columns)
break;
}
if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
- ((x-x_offset) >= (ssize_t) composite_image->columns))
+ ((x-x_offset) >= (ssize_t) source_image->columns))
{
Quantum
source[MaxPixelChannels];
/*
Virtual composite:
Sc: source color.
- Dc: destination color.
+ Dc: canvas color.
*/
- (void) GetOneVirtualPixel(composite_image,x-x_offset,y-y_offset,
- source,exception);
- if (GetPixelReadMask(image,q) == 0)
+ (void) GetOneVirtualPixel(source_image,x-x_offset,y-y_offset,source,
+ exception);
+ if (GetPixelWriteMask(image,q) == 0)
{
q+=GetPixelChannels(image);
continue;
PixelChannel channel=GetPixelChannelChannel(image,i);
PixelTrait traits=GetPixelChannelTraits(image,channel);
- PixelTrait composite_traits=GetPixelChannelTraits(composite_image,
+ PixelTrait source_traits=GetPixelChannelTraits(source_image,
channel);
if ((traits == UndefinedPixelTrait) ||
- (composite_traits == UndefinedPixelTrait))
+ (source_traits == UndefinedPixelTrait))
continue;
switch (compose)
{
case DstAtopCompositeOp:
case DstInCompositeOp:
case InCompositeOp:
- case IntensityCompositeOp:
case OutCompositeOp:
case SrcInCompositeOp:
case SrcOutCompositeOp:
{
- pixel=(MagickRealType) q[i];
if (channel == AlphaPixelChannel)
pixel=(MagickRealType) TransparentAlpha;
+ else
+ pixel=(MagickRealType) q[i];
break;
}
case ClearCompositeOp:
case SrcCompositeOp:
{
if (channel == AlphaPixelChannel)
- {
- pixel=(MagickRealType) TransparentAlpha;
- break;
- }
- pixel=0.0;
+ pixel=(MagickRealType) TransparentAlpha;
+ else
+ pixel=0.0;
break;
}
case BlendCompositeOp:
case DissolveCompositeOp:
{
if (channel == AlphaPixelChannel)
- {
- pixel=destination_dissolve*GetPixelAlpha(composite_image,
- source);
- break;
- }
- pixel=(MagickRealType) source[channel];
+ pixel=canvas_dissolve*GetPixelAlpha(source_image,source);
+ else
+ pixel=(MagickRealType) source[channel];
break;
}
default:
break;
}
}
- q[i]=ClampToQuantum(pixel);
+ q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
+ ClampToQuantum(pixel);
}
q+=GetPixelChannels(image);
continue;
/*
Authentic composite:
Sa: normalized source alpha.
- Da: normalized destination alpha.
+ Da: normalized canvas alpha.
*/
- Sa=QuantumScale*GetPixelAlpha(composite_image,p);
+ Sa=QuantumScale*GetPixelAlpha(source_image,p);
Da=QuantumScale*GetPixelAlpha(image,q);
switch (compose)
{
case BumpmapCompositeOp:
{
- alpha=GetPixelIntensity(composite_image,p)*Sa;
+ alpha=GetPixelIntensity(source_image,p)*Sa;
break;
}
case ColorBurnCompositeOp:
case ColorDodgeCompositeOp:
+ case DarkenCompositeOp:
case DifferenceCompositeOp:
case DivideDstCompositeOp:
case DivideSrcCompositeOp:
case ExclusionCompositeOp:
case HardLightCompositeOp:
+ case HardMixCompositeOp:
case LinearBurnCompositeOp:
case LinearDodgeCompositeOp:
case LinearLightCompositeOp:
+ case LightenCompositeOp:
case MathematicsCompositeOp:
case MinusDstCompositeOp:
case MinusSrcCompositeOp:
alpha=RoundToUnity(Sa+Da-Sa*Da);
break;
}
- case DarkenCompositeOp:
case DstAtopCompositeOp:
case DstInCompositeOp:
case InCompositeOp:
- case LightenCompositeOp:
case SrcInCompositeOp:
{
alpha=Sa*Da;
}
case DissolveCompositeOp:
{
- alpha=source_dissolve*Sa*(-destination_dissolve*Da)+source_dissolve*
- Sa+destination_dissolve*Da;
+ alpha=source_dissolve*Sa*(-canvas_dissolve*Da)+source_dissolve*Sa+
+ canvas_dissolve*Da;
break;
}
case DstOverCompositeOp:
+ case OverCompositeOp:
+ case SrcOverCompositeOp:
{
- alpha=Da*(-Sa)+Da+Sa;
+ alpha=Sa+Da-Sa*Da;
break;
}
case DstOutCompositeOp:
alpha=Sa*(1.0-Da);
break;
}
- case OverCompositeOp:
- case SrcOverCompositeOp:
- {
- alpha=Sa*(-Da)+Sa+Da;
- break;
- }
case BlendCompositeOp:
case PlusCompositeOp:
{
- alpha=RoundToUnity(Sa+Da);
+ alpha=RoundToUnity(source_dissolve*Sa+canvas_dissolve*Da);
break;
}
case XorCompositeOp:
break;
}
}
- if (GetPixelReadMask(image,q) == 0)
+ if (GetPixelWriteMask(image,q) == 0)
{
- p+=GetPixelChannels(composite_image);
+ p+=GetPixelChannels(source_image);
q+=GetPixelChannels(image);
continue;
}
case ModulateCompositeOp:
case SaturateCompositeOp:
{
- GetPixelInfoPixel(composite_image,p,&source_pixel);
- GetPixelInfoPixel(image,q,&destination_pixel);
+ GetPixelInfoPixel(source_image,p,&source_pixel);
+ GetPixelInfoPixel(image,q,&canvas_pixel);
break;
}
default:
PixelChannel channel=GetPixelChannelChannel(image,i);
PixelTrait traits=GetPixelChannelTraits(image,channel);
- PixelTrait composite_traits=GetPixelChannelTraits(composite_image,
- channel);
+ PixelTrait source_traits=GetPixelChannelTraits(source_image,channel);
if (traits == UndefinedPixelTrait)
continue;
- if ((compose != IntensityCompositeOp) &&
- (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 ((source_traits == UndefinedPixelTrait) &&
+ (channel != AlphaPixelChannel))
+ continue;
+ if (channel == AlphaPixelChannel)
{
- if (channel != AlphaPixelChannel)
- {
- /*
- Copy channel.
- */
- q[i]=ClampToQuantum(Sc);
- continue;
- }
/*
Set alpha channel.
*/
MagickBooleanType
equivalent;
- if (Da > ((MagickRealType) QuantumRange/2.0))
+ if (Da < 0.5)
{
pixel=(MagickRealType) TransparentAlpha;
break;
}
- equivalent=IsFuzzyEquivalencePixel(composite_image,p,image,q);
+ equivalent=IsFuzzyEquivalencePixel(source_image,p,image,q);
if (equivalent != MagickFalse)
- {
- pixel=(MagickRealType) TransparentAlpha;
- break;
- }
- pixel=(MagickRealType) OpaqueAlpha;
+ pixel=(MagickRealType) TransparentAlpha;
+ else
+ pixel=(MagickRealType) OpaqueAlpha;
break;
}
case ClearCompositeOp:
case LuminizeCompositeOp:
case SaturateCompositeOp:
{
- if (fabs(QuantumRange*Sa-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
{
pixel=QuantumRange*Da;
break;
}
- if (fabs(QuantumRange*Da-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Da-TransparentAlpha)) < MagickEpsilon)
{
pixel=QuantumRange*Sa;
break;
}
case CopyAlphaCompositeOp:
{
- pixel=QuantumRange*Sa;
- if (composite_image->alpha_trait == BlendPixelTrait)
- pixel=GetPixelIntensity(composite_image,p);
+ if (source_image->alpha_trait == UndefinedPixelTrait)
+ pixel=GetPixelIntensity(source_image,p);
+ else
+ pixel=QuantumRange*Sa;
break;
}
case CopyCompositeOp:
}
case DarkenIntensityCompositeOp:
{
- pixel=(1.0-Sa)*GetPixelIntensity(composite_image,p) <
- (1.0-Da)*GetPixelIntensity(image,q) ? Sa : Da;
- break;
- }
- case IntensityCompositeOp:
- {
- pixel=GetPixelIntensity(composite_image,p);
+ pixel=Sa*GetPixelIntensity(source_image,p) <
+ Da*GetPixelIntensity(image,q) ? Sa : Da;
break;
}
case LightenIntensityCompositeOp:
{
- pixel=Sa*GetPixelIntensity(composite_image,p) >
+ pixel=Sa*GetPixelIntensity(source_image,p) >
Da*GetPixelIntensity(image,q) ? Sa : Da;
break;
}
case ModulateCompositeOp:
{
- if (fabs(QuantumRange*Sa-TransparentAlpha) < MagickEpsilon)
- {
- pixel=QuantumRange*Da;
- break;
- }
pixel=QuantumRange*Da;
break;
}
break;
}
}
- q[i]=ClampToQuantum(pixel);
+ q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
+ ClampToQuantum(pixel);
+ continue;
+ }
+ /*
+ Sc: source color.
+ Dc: canvas color.
+ */
+ Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
+ Dc=(MagickRealType) q[i];
+ if ((traits & CopyPixelTrait) != 0)
+ {
+ /*
+ Copy channel.
+ */
+ q[i]=Sc;
continue;
}
/*
Porter-Duff compositions:
Sca: source normalized color multiplied by alpha.
- Dca: normalized destination color multiplied by alpha.
+ Dca: normalized canvas color multiplied by alpha.
*/
Sca=QuantumScale*Sa*Sc;
Dca=QuantumScale*Da*Dc;
case LightenCompositeOp:
case ModulusSubtractCompositeOp:
{
- gamma=1.0-alpha;
+ gamma=PerceptibleReciprocal(1.0-alpha);
break;
}
default:
+ {
+ gamma=PerceptibleReciprocal(alpha);
break;
+ }
}
- gamma=PerceptibleReciprocal(alpha);
pixel=Dc;
switch (compose)
{
case AtopCompositeOp:
case SrcAtopCompositeOp:
{
- pixel=Sc*Sa+Dc*(1.0-Sa);
+ pixel=QuantumRange*(Sca*Da+Dca*(1.0-Sa));
break;
}
case BlendCompositeOp:
{
- pixel=gamma*(source_dissolve*Sa*Sc+destination_dissolve*Da*Dc);
+ pixel=gamma*(source_dissolve*Sa*Sc+canvas_dissolve*Da*Dc);
break;
}
case BlurCompositeOp:
- case DisplaceCompositeOp:
- case DistortCompositeOp:
case CopyCompositeOp:
case ReplaceCompositeOp:
case SrcCompositeOp:
+ {
+ pixel=QuantumRange*Sca;
+ break;
+ }
+ case DisplaceCompositeOp:
+ case DistortCompositeOp:
{
pixel=Sc;
break;
}
case BumpmapCompositeOp:
{
- if (fabs(QuantumRange*Sa-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
{
pixel=Dc;
break;
}
- pixel=QuantumScale*GetPixelIntensity(composite_image,p)*Dc;
+ pixel=QuantumScale*GetPixelIntensity(source_image,p)*Dc;
break;
}
case ChangeMaskCompositeOp:
}
case ColorBurnCompositeOp:
{
- /*
- Refer to the March 2009 SVG specification.
- */
- if ((fabs(Sca) < MagickEpsilon) && (fabs(Dca-Da) < MagickEpsilon))
+ if ((Sca == 0.0) && (Dca == Da))
{
pixel=QuantumRange*gamma*(Sa*Da+Dca*(1.0-Sa));
break;
}
- if (Sca < MagickEpsilon)
+ if (Sca == 0.0)
{
pixel=QuantumRange*gamma*(Dca*(1.0-Sa));
break;
}
- pixel=QuantumRange*gamma*(Sa*Da-Sa*MagickMin(Da,(Da-Dca)*Sa/Sca)+
- Sca*(1.0-Da)+Dca*(1.0-Sa));
+ pixel=QuantumRange*gamma*(Sa*Da-Sa*Da*MagickMin(1.0,(1.0-Dca/Da)*Sa/
+ Sca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
break;
}
case ColorDodgeCompositeOp:
{
if ((Sca*Da+Dca*Sa) >= Sa*Da)
- {
- pixel=QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
- break;
- }
- pixel=QuantumRange*gamma*(Dca*Sa*Sa/(Sa-Sca)+Sca*(1.0-Da)+Dca*
- (1.0-Sa));
+ pixel=QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
+ else
+ pixel=QuantumRange*gamma*(Dca*Sa*Sa/(Sa-Sca)+Sca*(1.0-Da)+Dca*
+ (1.0-Sa));
break;
}
case ColorizeCompositeOp:
{
- if (fabs(QuantumRange*Sa-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
{
pixel=Dc;
break;
}
- if (fabs(QuantumRange*Da-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Da-TransparentAlpha)) < MagickEpsilon)
{
pixel=Sc;
break;
}
- CompositeHCL(destination_pixel.red,destination_pixel.green,
- destination_pixel.blue,&sans,&sans,&luma);
+ CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
+ &sans,&sans,&luma);
CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
&hue,&chroma,&sans);
HCLComposite(hue,chroma,luma,&red,&green,&blue);
break;
}
case CopyAlphaCompositeOp:
- case IntensityCompositeOp:
{
pixel=Dc;
break;
{
if (channel == BlackPixelChannel)
pixel=(MagickRealType) (QuantumRange-
- GetPixelBlack(composite_image,p));
+ GetPixelBlack(source_image,p));
break;
}
case CopyBlueCompositeOp:
case CopyYellowCompositeOp:
{
if (channel == BluePixelChannel)
- pixel=(MagickRealType) GetPixelBlue(composite_image,p);
+ pixel=(MagickRealType) GetPixelBlue(source_image,p);
break;
}
case CopyGreenCompositeOp:
case CopyMagentaCompositeOp:
{
if (channel == GreenPixelChannel)
- pixel=(MagickRealType) GetPixelGreen(composite_image,p);
+ pixel=(MagickRealType) GetPixelGreen(source_image,p);
break;
}
case CopyRedCompositeOp:
case CopyCyanCompositeOp:
{
if (channel == RedPixelChannel)
- pixel=(MagickRealType) GetPixelRed(composite_image,p);
+ pixel=(MagickRealType) GetPixelRed(source_image,p);
break;
}
case DarkenCompositeOp:
OR a greyscale version of a binary 'Or'
OR the 'Intersection' of pixel sets.
*/
- if (Sc < Dc)
+ if ((Sca*Da) < (Dca*Sa))
{
- pixel=gamma*(Sa*Sc-Sa*Da*Dc+Da*Dc);
+ pixel=QuantumRange*(Sca+Dca*(1.0-Sa));
break;
}
- pixel=gamma*(Da*Dc-Da*Sa*Sc+Sa*Sc);
+ pixel=QuantumRange*(Dca+Sca*(1.0-Da));
break;
}
case DarkenIntensityCompositeOp:
{
- pixel=(1.0-Sa)*GetPixelIntensity(composite_image,p) <
- (1.0-Da)*GetPixelIntensity(image,q) ? Sc : Dc;
+ pixel=Sa*GetPixelIntensity(source_image,p) <
+ Da*GetPixelIntensity(image,q) ? Sc : Dc;
break;
}
case DifferenceCompositeOp:
{
- pixel=gamma*(Sa*Sc+Da*Dc-Sa*Da*2.0*MagickMin(Sc,Dc));
+ pixel=QuantumRange*gamma*(Sca+Dca-2.0*MagickMin(Sca*Da,Dca*Sa));
break;
}
case DissolveCompositeOp:
{
pixel=gamma*(source_dissolve*Sa*Sc-source_dissolve*Sa*
- destination_dissolve*Da*Dc+destination_dissolve*Da*Dc);
+ canvas_dissolve*Da*Dc+canvas_dissolve*Da*Dc);
break;
}
case DivideDstCompositeOp:
{
- if ((fabs(Sca) < MagickEpsilon) && (fabs(Dca) < MagickEpsilon))
+ if ((fabs((double) Sca) < MagickEpsilon) &&
+ (fabs((double) Dca) < MagickEpsilon))
{
pixel=QuantumRange*gamma*(Sca*(1.0-Da)+Dca*(1.0-Sa));
break;
}
- if (fabs(Dca) < MagickEpsilon)
+ if (fabs((double) Dca) < MagickEpsilon)
{
pixel=QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
break;
}
case DivideSrcCompositeOp:
{
- if ((fabs(Dca) < MagickEpsilon) && (fabs(Sca) < MagickEpsilon))
+ if ((fabs((double) Dca) < MagickEpsilon) &&
+ (fabs((double) Sca) < MagickEpsilon))
{
pixel=QuantumRange*gamma*(Dca*(1.0-Sa)+Sca*(1.0-Da));
break;
}
- if (fabs(Sca) < MagickEpsilon)
+ if (fabs((double) Sca) < MagickEpsilon)
{
pixel=QuantumRange*gamma*(Da*Sa+Dca*(1.0-Sa)+Sca*(1.0-Da));
break;
}
case DstAtopCompositeOp:
{
- pixel=Dc*Da+Sc*(1.0-Da);
+ pixel=QuantumRange*(Dca*Sa+Sca*(1.0-Da));
break;
}
case DstCompositeOp:
case NoCompositeOp:
{
- pixel=Dc;
+ pixel=QuantumRange*Dca;
break;
}
case DstInCompositeOp:
{
- pixel=gamma*(Sa*Dc*Sa);
+ pixel=QuantumRange*(Dca*Sa);
break;
}
case DstOutCompositeOp:
{
- pixel=gamma*(Da*Dc*(1.0-Sa));
+ pixel=QuantumRange*(Dca*(1.0-Sa));
break;
}
case DstOverCompositeOp:
{
- pixel=gamma*(Da*Dc-Da*Sa*Sc+Sa*Sc);
+ pixel=QuantumRange*gamma*(Dca+Sca*(1.0-Da));
break;
}
case ExclusionCompositeOp:
{
if ((2.0*Sca) < Sa)
{
- pixel=QuantumRange*gamma*(2.0*Sca*Dca+Sca*(1.0-Da)+Dca*
- (1.0-Sa));
+ pixel=QuantumRange*gamma*(2.0*Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-
+ Sa));
break;
}
pixel=QuantumRange*gamma*(Sa*Da-2.0*(Da-Dca)*(Sa-Sca)+Sca*(1.0-Da)+
Dca*(1.0-Sa));
break;
}
+ case HardMixCompositeOp:
+ {
+ pixel=gamma*(((Sca+Dca) < 1.0) ? 0.0 : QuantumRange);
+ break;
+ }
case HueCompositeOp:
{
- if (fabs(QuantumRange*Sa-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
{
pixel=Dc;
break;
}
- if (fabs(QuantumRange*Da-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Da-TransparentAlpha)) < MagickEpsilon)
{
pixel=Sc;
break;
}
- CompositeHCL(destination_pixel.red,destination_pixel.green,
- destination_pixel.blue,&hue,&chroma,&luma);
+ CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
+ &hue,&chroma,&luma);
CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
&hue,&sans,&sans);
HCLComposite(hue,chroma,luma,&red,&green,&blue);
case InCompositeOp:
case SrcInCompositeOp:
{
- pixel=gamma*(Da*Sc*Da);
+ pixel=QuantumRange*(Sca*Da);
break;
}
case LinearBurnCompositeOp:
}
case LinearDodgeCompositeOp:
{
- pixel=QuantumRange*gamma*(Sa*Sc+Da*Dc);
+ pixel=gamma*(Sa*Sc+Da*Dc);
break;
}
case LinearLightCompositeOp:
}
case LightenCompositeOp:
{
- if (Sc > Dc)
+ if ((Sca*Da) > (Dca*Sa))
{
- pixel=gamma*(Sa*Sc-Sa*Da*Dc+Da*Dc);
+ pixel=QuantumRange*(Sca+Dca*(1.0-Sa));
break;
}
- pixel=gamma*(Da*Dc-Da*Sa*Sc+Sa*Sc);
+ pixel=QuantumRange*(Dca+Sca*(1.0-Da));
break;
}
case LightenIntensityCompositeOp:
OR a greyscale version of a binary 'And'
OR the 'Union' of pixel sets.
*/
- pixel=Sa*GetPixelIntensity(composite_image,p) >
+ pixel=Sa*GetPixelIntensity(source_image,p) >
Da*GetPixelIntensity(image,q) ? Sc : Dc;
break;
}
case LuminizeCompositeOp:
{
- if (fabs(QuantumRange*Sa-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
{
pixel=Dc;
break;
}
- if (fabs(QuantumRange*Da-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Da-TransparentAlpha)) < MagickEpsilon)
{
pixel=Sc;
break;
}
- CompositeHCL(destination_pixel.red,destination_pixel.green,
- destination_pixel.blue,&hue,&chroma,&luma);
+ CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
+ &hue,&chroma,&luma);
CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
&sans,&sans,&luma);
HCLComposite(hue,chroma,luma,&red,&green,&blue);
Dca' = A*Sca*Dca + B*Sca*Da + C*Dca*Sa + D*Sa*Da + Sca*(1.0-Da) +
Dca*(1.0-Sa)
*/
- pixel=gamma*geometry_info.rho*Sa*Sc*Da*Dc+geometry_info.sigma*
- Sa*Sc*Da+geometry_info.xi*Da*Dc*Sa+geometry_info.psi*Sa*Da+
- Sa*Sc*(1.0-Da)+Da*Dc*(1.0-Sa);
+ pixel=QuantumRange*gamma*(geometry_info.rho*Sca*Dca+
+ geometry_info.sigma*Sca*Da+geometry_info.xi*Dca*Sa+
+ geometry_info.psi*Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
break;
}
case MinusDstCompositeOp:
case MinusSrcCompositeOp:
{
/*
- Minus source from destination.
+ Minus source from canvas.
f(Sc,Dc) = Sc - Dc
*/
- pixel=QuantumRange*gamma*(Da*Dc+Sa*Sc-2.0*Sa*Sc*Da);
+ pixel=gamma*(Da*Dc+Sa*Sc-2.0*Sa*Sc*Da);
break;
}
case ModulateCompositeOp:
ssize_t
offset;
- if (fabs(QuantumRange*Sa-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
{
pixel=Dc;
break;
}
- offset=(ssize_t) (GetPixelIntensity(composite_image,p)-midpoint);
+ offset=(ssize_t) (GetPixelIntensity(source_image,p)-midpoint);
if (offset == 0)
{
pixel=Dc;
break;
}
- CompositeHCL(destination_pixel.red,destination_pixel.green,
- destination_pixel.blue,&hue,&chroma,&luma);
+ CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
+ &hue,&chroma,&luma);
luma+=(0.01*percent_luma*offset)/midpoint;
chroma*=0.01*percent_chroma;
HCLComposite(hue,chroma,luma,&red,&green,&blue);
case ModulusAddCompositeOp:
{
pixel=Sc+Dc;
- if (pixel > QuantumRange)
+ while (pixel > QuantumRange)
pixel-=QuantumRange;
- pixel=gamma*(Sa*Da*pixel+Sa*Sc*(1.0-Da)+Da*Dc*(1.0-Sa));
+ while (pixel < 0.0)
+ pixel+=QuantumRange;
+ pixel=(Sa*Da*pixel+Sa*Sc*(1.0-Da)+Da*Dc*(1.0-Sa));
break;
}
case ModulusSubtractCompositeOp:
{
pixel=Sc-Dc;
- if (pixel < 0.0)
+ while (pixel > QuantumRange)
+ pixel-=QuantumRange;
+ while (pixel < 0.0)
pixel+=QuantumRange;
- pixel=gamma*(Sa*Da*pixel+Sa*Sc*(1.0-Da)+Da*Dc*(1.0-Sa));
+ pixel=(Sa*Da*pixel+Sa*Sc*(1.0-Da)+Da*Dc*(1.0-Sa));
break;
}
case MultiplyCompositeOp:
case OutCompositeOp:
case SrcOutCompositeOp:
{
- pixel=gamma*(Sa*Sc*(1.0-Da));
+ pixel=QuantumRange*(Sca*(1.0-Da));
break;
}
case OverCompositeOp:
case SrcOverCompositeOp:
{
- pixel=QuantumRange*gamma*(Sa*Sc-Sa*Da*Dc+Da*Dc);
+ pixel=QuantumRange*gamma*(Sca+Dca*(1.0-Sa));
break;
}
case OverlayCompositeOp:
{
if ((2.0*Dca) < Da)
{
- pixel=QuantumRange*gamma*(2.0*Dca*Sca+Dca*(1.0-Sa)+Sca*
- (1.0-Da));
+ pixel=QuantumRange*gamma*(2.0*Dca*Sca+Dca*(1.0-Sa)+Sca*(1.0-
+ Da));
break;
}
pixel=QuantumRange*gamma*(Da*Sa-2.0*(Sa-Sca)*(Da-Dca)+Dca*(1.0-Sa)+
http://www.pegtop.net/delphi/articles/blendmodes/softlight.htm.
*/
- if (fabs(Da) < MagickEpsilon)
+ if (fabs((double) Da) < MagickEpsilon)
{
pixel=QuantumRange*gamma*(Sca);
break;
}
case PlusCompositeOp:
{
- pixel=gamma*(Sa*Sc+Da*Dc);
+ pixel=QuantumRange*(Sca+Dca);
break;
}
case SaturateCompositeOp:
{
- if (fabs(QuantumRange*Sa-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
{
pixel=Dc;
break;
}
- if (fabs(QuantumRange*Da-TransparentAlpha) < MagickEpsilon)
+ if (fabs((double) (QuantumRange*Da-TransparentAlpha)) < MagickEpsilon)
{
pixel=Sc;
break;
}
- CompositeHCL(destination_pixel.red,destination_pixel.green,
- destination_pixel.blue,&hue,&chroma,&luma);
+ CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
+ &hue,&chroma,&luma);
CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
&sans,&chroma,&sans);
HCLComposite(hue,chroma,luma,&red,&green,&blue);
}
case SoftLightCompositeOp:
{
- /*
- Refer to the March 2009 SVG specification.
- */
if ((2.0*Sca) < Sa)
{
pixel=QuantumRange*gamma*(Dca*(Sa+(2.0*Sca-Sa)*(1.0-(Dca/Da)))+
f(Sc,Dc) = (2*Sc < 1) ? 1-(1-Dc)/(2*Sc) : Dc/(2*(1-Sc))
*/
- if ((fabs(Sa) < MagickEpsilon) || (fabs(Sca-Sa) < MagickEpsilon))
+ if ((fabs((double) Sa) < MagickEpsilon) ||
+ (fabs((double) (Sca-Sa)) < MagickEpsilon))
{
pixel=QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
break;
(1.0-Da)+Dca*(1.0-Sa));
break;
}
- pixel=QuantumRange*gamma*(Dca*Sa*Sa/(2.0*(Sa-Sca))+Sca*(1.0-Da)+
- Dca*(1.0-Sa));
+ pixel=QuantumRange*gamma*(Dca*Sa*Sa/(2.0*(Sa-Sca))+Sca*(1.0-Da)+Dca*
+ (1.0-Sa));
break;
}
case XorCompositeOp:
{
- pixel=QuantumRange*gamma*(Sc*Sa*(1.0-Da)+Dc*Da*(1.0-Sa));
+ pixel=QuantumRange*(Sca*(1.0-Da)+Dca*(1.0-Sa));
break;
}
default:
break;
}
}
- q[i]=ClampToQuantum(pixel);
+ q[i]=clamp != MagickFalse ? ClampPixel(pixel) : ClampToQuantum(pixel);
}
- p+=GetPixelChannels(composite_image);
- channels=GetPixelChannels(composite_image);
- if (p >= (pixels+channels*composite_image->columns))
+ p+=GetPixelChannels(source_image);
+ channels=GetPixelChannels(source_image);
+ if (p >= (pixels+channels*source_image->columns))
p=pixels;
q+=GetPixelChannels(image);
}
status=MagickFalse;
}
}
- composite_view=DestroyCacheView(composite_view);
+ source_view=DestroyCacheView(source_view);
image_view=DestroyCacheView(image_view);
- if (destination_image != (Image * ) NULL)
- destination_image=DestroyImage(destination_image);
+ if (canvas_image != (Image * ) NULL)
+ canvas_image=DestroyImage(canvas_image);
else
- composite_image=DestroyImage(composite_image);
+ source_image=DestroyImage(source_image);
return(status);
}
\f
assert(image != (Image *) NULL);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (texture == (const Image *) NULL)
return(MagickFalse);
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
status=MagickTrue;
if ((image->compose != CopyCompositeOp) &&
((image->compose != OverCompositeOp) ||
- (image->alpha_trait == BlendPixelTrait) ||
- (texture_image->alpha_trait == BlendPixelTrait)))
+ (image->alpha_trait != UndefinedPixelTrait) ||
+ (texture_image->alpha_trait != UndefinedPixelTrait)))
{
/*
Tile texture onto the image background.
thread_status;
thread_status=CompositeImage(image,texture_image,image->compose,
- MagickFalse,x+texture_image->tile_offset.x,y+
+ MagickTrue,x+texture_image->tile_offset.x,y+
texture_image->tile_offset.y,exception);
if (thread_status == MagickFalse)
{
MagickBooleanType
proceed;
- proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType)
- y,image->rows);
+ proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
+ image->rows);
if (proceed == MagickFalse)
status=MagickFalse;
}
register ssize_t
i;
- if (GetPixelReadMask(image,q) == 0)
+ if (GetPixelWriteMask(image,q) == 0)
{
p+=GetPixelChannels(texture_image);
q+=GetPixelChannels(image);