% MagickCore Image Composite Methods %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% July 1992 %
% %
% %
-% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2014 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 %
#include "MagickCore/cache.h"
#include "MagickCore/cache-private.h"
#include "MagickCore/cache-view.h"
+#include "MagickCore/channel.h"
#include "MagickCore/client.h"
#include "MagickCore/color.h"
#include "MagickCore/color-private.h"
#include "MagickCore/resource_.h"
#include "MagickCore/string_.h"
#include "MagickCore/thread-private.h"
+#include "MagickCore/threshold.h"
#include "MagickCore/token.h"
#include "MagickCore/utility.h"
#include "MagickCore/utility-private.h"
performed as 'pure' mathematical operations, rather than as image
operations.
*/
-static void CompositeHSB(const double red,const double green,
- const double blue,double *hue,double *saturation,double *brightness)
+
+static inline MagickRealType MagickMin(const MagickRealType x,
+ const MagickRealType y)
{
- double
- delta,
- max,
- min;
+ if (x < y)
+ return(x);
+ return(y);
+}
- /*
- Convert RGB to HSB colorspace.
- */
- assert(hue != (double *) NULL);
- assert(saturation != (double *) NULL);
- assert(brightness != (double *) NULL);
- max=(red > green ? red : green);
- if (blue > max)
- max=blue;
- min=(red < green ? red : green);
- if (blue < min)
- min=blue;
- *hue=0.0;
- *saturation=0.0;
- *brightness=(double) (QuantumScale*max);
- if (fabs((double) max) < MagickEpsilon)
- return;
- *saturation=(double) (1.0-min/max);
- delta=(MagickRealType) max-min;
- if (fabs(delta) < MagickEpsilon)
- return;
- if (fabs((double) red-max) < MagickEpsilon)
- *hue=(double) ((green-blue)/delta);
- else
- if (fabs((double) green-max) < MagickEpsilon)
- *hue=(double) (2.0+(blue-red)/delta);
- else
- if (fabs((double) blue-max) < MagickEpsilon)
- *hue=(double) (4.0+(red-green)/delta);
- *hue/=6.0;
- if (*hue < 0.0)
- *hue+=1.0;
+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 HSBComposite(const double hue,const double saturation,
- const double brightness,double *red,double *green,double *blue)
+static void HCLComposite(const MagickRealType hue,const MagickRealType chroma,
+ const MagickRealType luma,MagickRealType *red,MagickRealType *green,
+ MagickRealType *blue)
{
- double
- f,
+ MagickRealType
+ b,
+ c,
+ g,
h,
- p,
- q,
- t;
+ m,
+ r,
+ x;
/*
- Convert HSB to RGB colorspace.
+ Convert HCL to RGB colorspace.
*/
- assert(red != (double *) NULL);
- assert(green != (double *) NULL);
- assert(blue != (double *) NULL);
- if (saturation == 0.0)
- {
- *red=(double) QuantumRange*brightness;
- *green=(*red);
- *blue=(*red);
- return;
- }
- h=6.0*(hue-floor(hue));
- f=h-floor((double) h);
- p=brightness*(1.0-saturation);
- q=brightness*(1.0-saturation*f);
- t=brightness*(1.0-saturation*(1.0-f));
- switch ((int) h)
- {
- case 0:
- default:
- {
- *red=(double) QuantumRange*brightness;
- *green=(double) QuantumRange*t;
- *blue=(double) QuantumRange*p;
- break;
- }
- case 1:
- {
- *red=(double) QuantumRange*q;
- *green=(double) QuantumRange*brightness;
- *blue=(double) QuantumRange*p;
- break;
- }
- case 2:
- {
- *red=(double) QuantumRange*p;
- *green=(double) QuantumRange*brightness;
- *blue=(double) QuantumRange*t;
- break;
- }
- case 3:
- {
- *red=(double) QuantumRange*p;
- *green=(double) QuantumRange*q;
- *blue=(double) QuantumRange*brightness;
- break;
- }
- case 4:
- {
- *red=(double) QuantumRange*t;
- *green=(double) QuantumRange*p;
- *blue=(double) QuantumRange*brightness;
- break;
- }
- case 5:
+ assert(red != (MagickRealType *) NULL);
+ assert(green != (MagickRealType *) NULL);
+ assert(blue != (MagickRealType *) NULL);
+ h=6.0*hue;
+ c=chroma;
+ x=c*(1.0-fabs(fmod(h,2.0)-1.0));
+ r=0.0;
+ g=0.0;
+ b=0.0;
+ if ((0.0 <= h) && (h < 1.0))
{
- *red=(double) QuantumRange*brightness;
- *green=(double) QuantumRange*p;
- *blue=(double) QuantumRange*q;
- break;
+ r=c;
+ g=x;
}
- }
+ else
+ if ((1.0 <= h) && (h < 2.0))
+ {
+ r=x;
+ g=c;
+ }
+ else
+ if ((2.0 <= h) && (h < 3.0))
+ {
+ g=c;
+ b=x;
+ }
+ else
+ if ((3.0 <= h) && (h < 4.0))
+ {
+ g=x;
+ b=c;
+ }
+ else
+ if ((4.0 <= h) && (h < 5.0))
+ {
+ r=x;
+ b=c;
+ }
+ else
+ if ((5.0 <= h) && (h < 6.0))
+ {
+ r=c;
+ b=x;
+ }
+ m=luma-(0.298839*r+0.586811*g+0.114350*b);
+ *red=QuantumRange*(r+m);
+ *green=QuantumRange*(g+m);
+ *blue=QuantumRange*(b+m);
}
-static inline double MagickMin(const double x,const double y)
+static void CompositeHCL(const MagickRealType red,const MagickRealType green,
+ const MagickRealType blue,MagickRealType *hue,MagickRealType *chroma,
+ MagickRealType *luma)
{
- if (x < y)
- return(x);
- return(y);
-}
+ MagickRealType
+ b,
+ c,
+ g,
+ h,
+ max,
+ r;
-static inline double MagickMax(const double x,const double y)
-{
- if (x > y)
- return(x);
- return(y);
+ /*
+ Convert RGB to HCL colorspace.
+ */
+ assert(hue != (MagickRealType *) NULL);
+ assert(chroma != (MagickRealType *) NULL);
+ assert(luma != (MagickRealType *) NULL);
+ r=red;
+ g=green;
+ b=blue;
+ max=MagickMax(r,MagickMax(g,b));
+ c=max-(MagickRealType) MagickMin(r,MagickMin(g,b));
+ h=0.0;
+ if (c == 0)
+ h=0.0;
+ else
+ if (red == max)
+ h=fmod((g-b)/c+6.0,6.0);
+ else
+ if (green == max)
+ h=((b-r)/c)+2.0;
+ else
+ if (blue == max)
+ h=((r-g)/c)+4.0;
+ *hue=(h/6.0);
+ *chroma=QuantumScale*c;
+ *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
}
static MagickBooleanType CompositeOverImage(Image *image,
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static,4) shared(progress,status) \
- if ((image->rows*image->columns) > 8192) \
- num_threads(GetMagickResourceLimit(ThreadResource))
+ magick_threads(composite_image,image,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
}
for (x=0; x < (ssize_t) image->columns; x++)
{
+ double
+ gamma;
+
MagickRealType
alpha,
Da,
Dc,
- gamma,
Sa,
Sc;
Sc: source color.
Dc: destination color.
*/
- if (GetPixelMask(image,q) != 0)
+ if (GetPixelReadMask(image,q) == 0)
{
q+=GetPixelChannels(image);
continue;
source,exception);
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- PixelChannel
- channel;
-
- PixelTrait
- composite_traits,
- traits;
-
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- composite_traits=GetPixelChannelMapTraits(composite_image,channel);
+ PixelChannel channel=GetPixelChannelChannel(image,i);
+ PixelTrait traits=GetPixelChannelTraits(image,channel);
+ PixelTrait composite_traits=GetPixelChannelTraits(composite_image,
+ channel);
if ((traits == UndefinedPixelTrait) ||
(composite_traits == UndefinedPixelTrait))
continue;
Sa: normalized source alpha.
Da: normalized destination alpha.
*/
- if (GetPixelMask(composite_image,p) != 0)
+ if (GetPixelReadMask(composite_image,p) == 0)
{
p+=GetPixelChannels(composite_image);
channels=GetPixelChannels(composite_image);
alpha=Sa*(-Da)+Sa+Da;
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- PixelChannel
- channel;
-
- PixelTrait
- composite_traits,
- traits;
-
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- composite_traits=GetPixelChannelMapTraits(composite_image,channel);
+ PixelChannel channel=GetPixelChannelChannel(image,i);
+ PixelTrait traits=GetPixelChannelTraits(image,channel);
+ PixelTrait composite_traits=GetPixelChannelTraits(composite_image,
+ channel);
if ((traits == UndefinedPixelTrait) ||
(composite_traits == UndefinedPixelTrait))
continue;
*/
Sc=(MagickRealType) GetPixelChannel(composite_image,channel,p);
Dc=(MagickRealType) q[i];
- gamma=1.0/(fabs(alpha) <= MagickEpsilon ? 1.0 : alpha);
+ gamma=PerceptibleReciprocal(alpha);
q[i]=ClampToQuantum(gamma*(Sa*Sc-Sa*Da*Dc+Da*Dc));
}
p+=GetPixelChannels(composite_image);
}
MagickExport MagickBooleanType CompositeImage(Image *image,
- const Image *composite_image,const CompositeOperator compose,
+ const Image *composite,const CompositeOperator compose,
const MagickBooleanType clip_to_self,const ssize_t x_offset,
const ssize_t y_offset,ExceptionInfo *exception)
{
geometry_info;
Image
+ *composite_image,
*destination_image;
MagickBooleanType
amount,
destination_dissolve,
midpoint,
- percent_brightness,
- percent_saturation,
+ percent_luma,
+ percent_chroma,
source_dissolve,
threshold;
assert(image->signature == MagickSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- assert(composite_image != (Image *) NULL);
- assert(composite_image->signature == MagickSignature);
+ assert(composite!= (Image *) NULL);
+ assert(composite->signature == MagickSignature);
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
return(MagickFalse);
- if ((IsGrayColorspace(image->colorspace) != MagickFalse) &&
- (IsGrayColorspace(composite_image->colorspace) == MagickFalse))
- (void) TransformImageColorspace(image,sRGBColorspace,exception);
+ composite_image=CloneImage(composite,0,0,MagickTrue,exception);
+ if (composite_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);
if ((compose == OverCompositeOp) || (compose == SrcOverCompositeOp))
{
status=CompositeOverImage(image,composite_image,clip_to_self,x_offset,
y_offset,exception);
+ composite_image=DestroyImage(composite_image);
return(status);
}
destination_image=(Image *) NULL;
amount=0.5;
destination_dissolve=1.0;
- percent_brightness=100.0;
- percent_saturation=100.0;
+ percent_luma=100.0;
+ percent_chroma=100.0;
source_dissolve=1.0;
threshold=0.05f;
switch (compose)
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static,4) shared(status) \
- if ((composite_image->rows*composite_image->columns) > 8192) \
- num_threads(GetMagickResourceLimit(ThreadResource))
+ magick_threads(composite_image,image,composite_image->rows,1)
#endif
for (y=0; y < (ssize_t) composite_image->rows; y++)
{
register ssize_t
i;
- if (GetPixelMask(image,p) != 0)
+ if (GetPixelReadMask(composite_image,p) == 0)
{
p+=GetPixelChannels(composite_image);
q+=GetPixelChannels(image);
}
for (i=0; i < (ssize_t) GetPixelChannels(composite_image); i++)
{
- PixelChannel
- channel;
-
- PixelTrait
- composite_traits,
- traits;
-
- channel=GetPixelChannelMapChannel(composite_image,i);
- composite_traits=GetPixelChannelMapTraits(composite_image,channel);
- traits=GetPixelChannelMapTraits(image,channel);
+ PixelChannel channel=GetPixelChannelChannel(composite_image,i);
+ PixelTrait composite_traits=GetPixelChannelTraits(composite_image,
+ channel);
+ PixelTrait traits=GetPixelChannelTraits(image,channel);
if ((traits == UndefinedPixelTrait) ||
(composite_traits == UndefinedPixelTrait))
continue;
}
composite_view=DestroyCacheView(composite_view);
image_view=DestroyCacheView(image_view);
+ composite_image=DestroyImage(composite_image);
return(status);
}
case CopyAlphaCompositeOp:
Modify destination outside the overlaid region and require an alpha
channel to exist, to add transparency.
*/
- if (image->matte == MagickFalse)
+ if (image->alpha_trait != BlendPixelTrait)
(void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
break;
}
const char
*value;
- PixelInfo
- pixel;
-
MagickRealType
angle_range,
angle_start,
height,
width;
+ PixelInfo
+ pixel;
+
ResampleFilter
*resample_filter;
destination_image=CloneImage(image,image->columns,image->rows,MagickTrue,
exception);
if (destination_image == (Image *) NULL)
- return(MagickFalse);
+ {
+ composite_image=DestroyImage(composite_image);
+ return(MagickFalse);
+ }
/*
Gather the maximum blur sigma values from user.
*/
SetGeometryInfo(&geometry_info);
flags=NoValue;
- value=GetImageArtifact(composite_image,"compose:args");
- if (value != (char *) NULL)
+ value=GetImageArtifact(image,"compose:args");
+ if (value != (const char *) NULL)
flags=ParseGeometry(value,&geometry_info);
- if ((flags & WidthValue) == 0 ) {
- (void) ThrowMagickException(exception,GetMagickModule(),
- OptionWarning,"InvalidSetting","'%s' '%s'",
- "compose:args",value);
+ if ((flags & WidthValue) == 0)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
+ "InvalidSetting","'%s' '%s'","compose:args",value);
+ composite_image=DestroyImage(composite_image);
destination_image=DestroyImage(destination_image);
return(MagickFalse);
}
width=height=geometry_info.rho*2.0;
if ((flags & HeightValue) != 0 )
height=geometry_info.sigma*2.0;
-
- /* default the unrotated ellipse width and height axis vectors */
+ /*
+ Default the unrotated ellipse width and height axis vectors.
+ */
blur.x1=width;
blur.x2=0.0;
blur.y1=0.0;
}
#if 0
if ( x == 10 && y == 60 ) {
- fprintf(stderr, "blur.x=%lf,%lf, blur.y=%lf,%lf\n",
- blur.x1, blur.x2, blur.y1, blur.y2);
- fprintf(stderr, "scaled by=%lf,%lf\n",
- QuantumScale*GetPixelRed(p), QuantumScale*GetPixelGreen(p));
+ (void) fprintf(stderr, "blur.x=%lf,%lf, blur.y=%lf,%lf\n",blur.x1,
+ blur.x2,blur.y1, blur.y2);
+ (void) fprintf(stderr, "scaled by=%lf,%lf\n",QuantumScale*
+ GetPixelRed(p),QuantumScale*GetPixelGreen(p));
#endif
ScaleResampleFilter(resample_filter,
blur.x1*QuantumScale*GetPixelRed(composite_image,p),
resample_filter=DestroyResampleFilter(resample_filter);
composite_view=DestroyCacheView(composite_view);
destination_view=DestroyCacheView(destination_view);
+ composite_image=DestroyImage(composite_image);
composite_image=destination_image;
break;
}
destination_image=CloneImage(image,image->columns,image->rows,MagickTrue,
exception);
if (destination_image == (Image *) NULL)
- return(MagickFalse);
+ {
+ composite_image=DestroyImage(composite_image);
+ return(MagickFalse);
+ }
SetGeometryInfo(&geometry_info);
flags=NoValue;
value=GetImageArtifact(composite_image,"compose:args");
{
if ((flags & XValue) == 0)
if ((flags & AspectValue) == 0)
- center.x=(MagickRealType) x_offset+(composite_image->columns-1)/
- 2.0;
+ center.x=(MagickRealType) (x_offset+(composite_image->columns-1)/
+ 2.0);
else
- center.x=((MagickRealType) image->columns-1)/2.0;
+ center.x=(MagickRealType) ((image->columns-1)/2);
else
if ((flags & AspectValue) == 0)
center.x=(MagickRealType) x_offset+geometry_info.xi;
center.x=geometry_info.xi;
if ((flags & YValue) == 0)
if ((flags & AspectValue) == 0)
- center.y=(MagickRealType) y_offset+(composite_image->rows-1)/2.0;
+ center.y=(MagickRealType) (y_offset+(composite_image->rows-1)/
+ 2.0);
else
- center.y=((MagickRealType) image->rows-1)/2.0;
+ center.y=(MagickRealType) ((image->rows-1)/2);
else
if ((flags & AspectValue) == 0)
center.y=(MagickRealType) y_offset+geometry_info.psi;
/*
Displace the offset.
*/
- offset.x=(horizontal_scale*(GetPixelRed(composite_image,p)-
+ offset.x=(double) (horizontal_scale*(GetPixelRed(composite_image,p)-
(((MagickRealType) QuantumRange+1.0)/2.0)))/(((MagickRealType)
QuantumRange+1.0)/2.0)+center.x+((compose == DisplaceCompositeOp) ?
x : 0);
- offset.y=(vertical_scale*(GetPixelGreen(composite_image,p)-
+ offset.y=(double) (vertical_scale*(GetPixelGreen(composite_image,p)-
(((MagickRealType) QuantumRange+1.0)/2.0)))/(((MagickRealType)
QuantumRange+1.0)/2.0)+center.y+((compose == DisplaceCompositeOp) ?
y : 0);
destination_view=DestroyCacheView(destination_view);
composite_view=DestroyCacheView(composite_view);
image_view=DestroyCacheView(image_view);
+ composite_image=DestroyImage(composite_image);
composite_image=destination_image;
break;
}
*value;
/*
- Determine the brightness and saturation scale.
+ Determine the luma and chroma scale.
*/
value=GetImageArtifact(composite_image,"compose:args");
if (value != (char *) NULL)
{
flags=ParseGeometry(value,&geometry_info);
- percent_brightness=geometry_info.rho;
+ percent_luma=geometry_info.rho;
if ((flags & SigmaValue) != 0)
- percent_saturation=geometry_info.sigma;
+ percent_chroma=geometry_info.sigma;
}
break;
}
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static,4) shared(progress,status) \
- if ((image->rows*image->columns) > 8192) \
- num_threads(GetMagickResourceLimit(ThreadResource))
+ magick_threads(composite_image,image,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
const Quantum
*pixels;
- double
+ MagickRealType
blue,
- brightness,
+ luma,
green,
hue,
red,
- saturation;
+ chroma;
PixelInfo
destination_pixel,
continue;
}
hue=0.0;
- saturation=0.0;
- brightness=0.0;
+ chroma=0.0;
+ luma=0.0;
GetPixelInfo(image,&destination_pixel);
GetPixelInfo(composite_image,&source_pixel);
for (x=0; x < (ssize_t) image->columns; x++)
{
+ double
+ gamma;
+
MagickRealType
alpha,
Da,
Dc,
Dca,
- gamma,
Sa,
Sc,
Sca;
*/
(void) GetOneVirtualPixel(composite_image,x-x_offset,y-y_offset,
source,exception);
- if (GetPixelMask(image,q) != 0)
+ if (GetPixelReadMask(image,q) == 0)
{
q+=GetPixelChannels(image);
continue;
MagickRealType
pixel;
- PixelChannel
- channel;
-
- PixelTrait
- composite_traits,
- traits;
-
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- composite_traits=GetPixelChannelMapTraits(composite_image,channel);
+ PixelChannel channel=GetPixelChannelChannel(image,i);
+ PixelTrait traits=GetPixelChannelTraits(image,channel);
+ PixelTrait composite_traits=GetPixelChannelTraits(composite_image,
+ channel);
if ((traits == UndefinedPixelTrait) ||
(composite_traits == UndefinedPixelTrait))
continue;
break;
}
}
- if (GetPixelMask(image,p) != 0)
+ if (GetPixelReadMask(image,q) == 0)
{
p+=GetPixelChannels(composite_image);
q+=GetPixelChannels(image);
}
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- double
- sans;
-
MagickRealType
- pixel;
-
- PixelChannel
- channel;
-
- PixelTrait
- composite_traits,
- traits;
+ pixel,
+ sans;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- composite_traits=GetPixelChannelMapTraits(composite_image,channel);
+ PixelChannel channel=GetPixelChannelChannel(image,i);
+ PixelTrait traits=GetPixelChannelTraits(image,channel);
+ PixelTrait composite_traits=GetPixelChannelTraits(composite_image,
+ channel);
if (traits == UndefinedPixelTrait)
continue;
if ((compose != IntensityCompositeOp) &&
pixel=QuantumRange*Sa;
break;
}
- case CopyCompositeOp:
case CopyAlphaCompositeOp:
+ {
+ pixel=QuantumRange*Sa;
+ if (composite_image->alpha_trait == BlendPixelTrait)
+ pixel=GetPixelIntensity(composite_image,p);
+ break;
+ }
+ case CopyCompositeOp:
case DisplaceCompositeOp:
case DistortCompositeOp:
case DstAtopCompositeOp:
}
case IntensityCompositeOp:
{
- pixel=(MagickRealType) GetPixelIntensity(composite_image,p);
+ pixel=GetPixelIntensity(composite_image,p);
break;
}
case LightenIntensityCompositeOp:
default:
break;
}
- gamma=1.0/(fabs(alpha) <= MagickEpsilon ? 1.0 : alpha);
+ gamma=PerceptibleReciprocal(alpha);
pixel=Dc;
switch (compose)
{
}
case ColorDodgeCompositeOp:
{
- if ((fabs(Sca-Sa) < MagickEpsilon) && (fabs(Dca) < MagickEpsilon))
- {
- pixel=QuantumRange*gamma*(Sca*(1.0-Da)+Dca*(1.0-Sa));
- break;
- }
- if (fabs(Sca-Sa) < MagickEpsilon)
+ if ((Sca*Da+Dca*Sa) >= Sa*Da)
{
pixel=QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
break;
pixel=Sc;
break;
}
- CompositeHSB(destination_pixel.red,destination_pixel.green,
- destination_pixel.blue,&sans,&sans,&brightness);
- CompositeHSB(source_pixel.red,source_pixel.green,source_pixel.blue,
- &hue,&saturation,&sans);
- HSBComposite(hue,saturation,brightness,&red,&green,&blue);
+ CompositeHCL(destination_pixel.red,destination_pixel.green,
+ destination_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);
switch (channel)
{
case RedPixelChannel: pixel=red; break;
case CopyAlphaCompositeOp:
case IntensityCompositeOp:
{
- if (channel == AlphaPixelChannel)
- pixel=(MagickRealType) GetPixelAlpha(composite_image,p);
+ pixel=Dc;
break;
}
case CopyBlackCompositeOp:
{
if (channel == BlackPixelChannel)
- pixel=(MagickRealType) GetPixelBlack(composite_image,p);
+ pixel=(MagickRealType) (QuantumRange-
+ GetPixelBlack(composite_image,p));
break;
}
case CopyBlueCompositeOp:
pixel=Sc;
break;
}
- CompositeHSB(destination_pixel.red,destination_pixel.green,
- destination_pixel.blue,&hue,&saturation,&brightness);
- CompositeHSB(source_pixel.red,source_pixel.green,source_pixel.blue,
+ CompositeHCL(destination_pixel.red,destination_pixel.green,
+ destination_pixel.blue,&hue,&chroma,&luma);
+ CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
&hue,&sans,&sans);
- HSBComposite(hue,saturation,brightness,&red,&green,&blue);
+ HCLComposite(hue,chroma,luma,&red,&green,&blue);
switch (channel)
{
case RedPixelChannel: pixel=red; break;
{
if (Sc > Dc)
{
- pixel=QuantumRange*gamma*(Sa*Sc-Sa*Da*Dc+Da*Dc);
+ pixel=gamma*(Sa*Sc-Sa*Da*Dc+Da*Dc);
break;
}
- pixel=QuantumRange*gamma*(Da*Dc-Da*Sa*Sc+Sa*Sc);
+ pixel=gamma*(Da*Dc-Da*Sa*Sc+Sa*Sc);
break;
}
case LightenIntensityCompositeOp:
pixel=Sc;
break;
}
- CompositeHSB(destination_pixel.red,destination_pixel.green,
- destination_pixel.blue,&hue,&saturation,&brightness);
- CompositeHSB(source_pixel.red,source_pixel.green,source_pixel.blue,
- &sans,&sans,&brightness);
- HSBComposite(hue,saturation,brightness,&red,&green,&blue);
+ CompositeHCL(destination_pixel.red,destination_pixel.green,
+ destination_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);
switch (channel)
{
case RedPixelChannel: pixel=red; break;
pixel=Dc;
break;
}
- CompositeHSB(destination_pixel.red,destination_pixel.green,
- destination_pixel.blue,&hue,&saturation,&brightness);
- brightness+=(0.01*percent_brightness*offset)/midpoint;
- saturation*=0.01*percent_saturation;
- HSBComposite(hue,saturation,brightness,&red,&green,&blue);
+ CompositeHCL(destination_pixel.red,destination_pixel.green,
+ destination_pixel.blue,&hue,&chroma,&luma);
+ luma+=(0.01*percent_luma*offset)/midpoint;
+ chroma*=0.01*percent_chroma;
+ HCLComposite(hue,chroma,luma,&red,&green,&blue);
switch (channel)
{
case RedPixelChannel: pixel=red; break;
{
pixel=Sc+Dc;
if (pixel > QuantumRange)
- pixel-=(QuantumRange+1.0);
- pixel=gamma*(pixel*Sa*Da+Sa*Sc*(1.0-Da)+Da*Dc*(1.0-Sa));
+ pixel-=QuantumRange;
+ pixel=gamma*(Sa*Da*pixel+Sa*Sc*(1.0-Da)+Da*Dc*(1.0-Sa));
break;
}
case ModulusSubtractCompositeOp:
{
pixel=Sc-Dc;
if (pixel < 0.0)
- pixel+=(QuantumRange+1.0);
- pixel=gamma*(pixel*Sa*Da+Sa*Sc*(1.0-Da)+Da*Dc*(1.0-Sa));
+ pixel+=QuantumRange;
+ pixel=gamma*(Sa*Da*pixel+Sa*Sc*(1.0-Da)+Da*Dc*(1.0-Sa));
break;
}
case MultiplyCompositeOp:
}
case PlusCompositeOp:
{
- pixel=QuantumRange*gamma*(Sa*Sc+Da*Dc);
+ pixel=gamma*(Sa*Sc+Da*Dc);
break;
}
case SaturateCompositeOp:
pixel=Sc;
break;
}
- CompositeHSB(destination_pixel.red,destination_pixel.green,
- destination_pixel.blue,&hue,&saturation,&brightness);
- CompositeHSB(source_pixel.red,source_pixel.green,source_pixel.blue,
- &sans,&saturation,&sans);
- HSBComposite(hue,saturation,brightness,&red,&green,&blue);
+ CompositeHCL(destination_pixel.red,destination_pixel.green,
+ destination_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);
switch (channel)
{
case RedPixelChannel: pixel=red; break;
image_view=DestroyCacheView(image_view);
if (destination_image != (Image * ) NULL)
destination_image=DestroyImage(destination_image);
+ else
+ composite_image=DestroyImage(composite_image);
return(status);
}
\f
texture_image=CloneImage(texture,0,0,MagickTrue,exception);
if (texture_image == (const Image *) NULL)
return(MagickFalse);
+ (void) TransformImageColorspace(texture_image,image->colorspace,exception);
(void) SetImageVirtualPixelMethod(texture_image,TileVirtualPixelMethod,
exception);
status=MagickTrue;
if ((image->compose != CopyCompositeOp) &&
- ((image->compose != OverCompositeOp) || (image->matte != MagickFalse) ||
- (texture_image->matte != MagickFalse)))
+ ((image->compose != OverCompositeOp) ||
+ (image->alpha_trait == BlendPixelTrait) ||
+ (texture_image->alpha_trait == BlendPixelTrait)))
{
/*
Tile texture onto the image background.
*/
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(static) shared(status) \
- if ((image->rows*image->columns) > 8192) \
- num_threads(GetMagickResourceLimit(ThreadResource))
-#endif
for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) texture_image->rows)
{
register ssize_t
MagickBooleanType
proceed;
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_TextureImage)
-#endif
proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType)
y,image->rows);
if (proceed == MagickFalse)
texture_view=AcquireVirtualCacheView(texture_image,exception);
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(static) shared(status) \
- if ((image->rows*image->columns) > 8192) \
- num_threads(GetMagickResourceLimit(ThreadResource))
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ magick_threads(texture_image,image,1,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
register ssize_t
i;
- if (GetPixelMask(image,p) != 0)
+ if (GetPixelReadMask(image,q) == 0)
{
p+=GetPixelChannels(texture_image);
q+=GetPixelChannels(image);
}
for (i=0; i < (ssize_t) GetPixelChannels(texture_image); i++)
{
- PixelChannel
- channel;
-
- PixelTrait
- texture_traits,
- traits;
-
- channel=GetPixelChannelMapChannel(texture_image,i);
- texture_traits=GetPixelChannelMapTraits(texture_image,channel);
- traits=GetPixelChannelMapTraits(image,channel);
+ PixelChannel channel=GetPixelChannelChannel(texture_image,i);
+ PixelTrait traits=GetPixelChannelTraits(image,channel);
+ PixelTrait texture_traits=GetPixelChannelTraits(texture_image,
+ channel);
if ((traits == UndefinedPixelTrait) ||
(texture_traits == UndefinedPixelTrait))
continue;
MagickBooleanType
proceed;
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_TextureImage)
-#endif
proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
image->rows);
if (proceed == MagickFalse)