X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=MagickCore%2Fcomposite.c;h=c3ead4784dc308d0d2f73d1cef523155dc3d5d2a;hb=f6ff9eaa865134189fce2cf73b109da589178bde;hp=faf31757756f4484c67260c8d3fcf7ce8cff37cb;hpb=b20bac4702eacfb5e42698733656d0d1aee9ab86;p=imagemagick diff --git a/MagickCore/composite.c b/MagickCore/composite.c index faf317577..c3ead4784 100644 --- a/MagickCore/composite.c +++ b/MagickCore/composite.c @@ -17,7 +17,7 @@ % July 1992 % % % % % -% Copyright 1999-2015 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 % @@ -291,10 +291,14 @@ static MagickBooleanType CompositeOverImage(Image *image, #define CompositeImageTag "Composite/Image" CacheView - *source_view, - *image_view; + *image_view, + *source_view; + + const char + *value; MagickBooleanType + clamp, status; MagickOffsetType @@ -308,6 +312,10 @@ static MagickBooleanType CompositeOverImage(Image *image, */ status=MagickTrue; progress=0; + 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) @@ -320,10 +328,10 @@ static MagickBooleanType CompositeOverImage(Image *image, *pixels; register const Quantum - *restrict p; + *magick_restrict p; register Quantum - *restrict q; + *magick_restrict q; register ssize_t x; @@ -370,6 +378,7 @@ static MagickBooleanType CompositeOverImage(Image *image, Da, Dc, Dca, + gamma, Sa, Sc, Sca; @@ -398,7 +407,7 @@ static MagickBooleanType CompositeOverImage(Image *image, Sc: source color. Dc: canvas color. */ - if (GetPixelReadMask(image,q) == 0) + if (GetPixelWriteMask(image,q) == 0) { q+=GetPixelChannels(image); continue; @@ -424,7 +433,7 @@ static MagickBooleanType CompositeOverImage(Image *image, Sa: normalized source alpha. Da: normalized canvas alpha. */ - if (GetPixelReadMask(source_image,p) == 0) + if (GetPixelWriteMask(source_image,p) == 0) { p+=GetPixelChannels(source_image); channels=GetPixelChannels(source_image); @@ -435,6 +444,8 @@ static MagickBooleanType CompositeOverImage(Image *image, } Sa=QuantumScale*GetPixelAlpha(source_image,p); Da=QuantumScale*GetPixelAlpha(image,q); + gamma=Sa+Da-Sa*Da; + gamma=PerceptibleReciprocal(gamma); for (i=0; i < (ssize_t) GetPixelChannels(image); i++) { PixelChannel channel=GetPixelChannelChannel(image,i); @@ -457,7 +468,9 @@ static MagickBooleanType CompositeOverImage(Image *image, /* Set alpha channel. */ - q[i]=ClampToQuantum(QuantumRange*(Sa+Da-Sa*Da)); + q[i]=clamp != MagickFalse ? + ClampPixel(QuantumRange*(Sa+Da-Sa*Da)) : + ClampToQuantum(QuantumRange*(Sa+Da-Sa*Da)); continue; } /* @@ -468,7 +481,9 @@ static MagickBooleanType CompositeOverImage(Image *image, Dc=(MagickRealType) q[i]; Sca=QuantumScale*Sa*Sc; Dca=QuantumScale*Da*Dc; - q[i]=ClampToQuantum(QuantumRange*(Sca+Dca*(1.0-Sa))); + q[i]=clamp != MagickFalse ? + ClampPixel(gamma*QuantumRange*(Sca+Dca*(1.0-Sa))) : + ClampToQuantum(gamma*QuantumRange*(Sca+Dca*(1.0-Sa))); } p+=GetPixelChannels(source_image); channels=GetPixelChannels(source_image); @@ -508,6 +523,9 @@ MagickExport MagickBooleanType CompositeImage(Image *image, *source_view, *image_view; + const char + *value; + GeometryInfo geometry_info; @@ -516,6 +534,7 @@ MagickExport MagickBooleanType CompositeImage(Image *image, *source_image; MagickBooleanType + clamp, status; MagickOffsetType @@ -537,11 +556,11 @@ MagickExport MagickBooleanType CompositeImage(Image *image, 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); source_image=CloneImage(composite,0,0,MagickTrue,exception); @@ -550,10 +569,6 @@ MagickExport MagickBooleanType CompositeImage(Image *image, if (IsGrayColorspace(image->colorspace) != MagickFalse) (void) SetImageColorspace(image,sRGBColorspace,exception); (void) SetImageColorspace(source_image,image->colorspace,exception); - if ((image->alpha_trait != UndefinedPixelTrait) && - (source_image->alpha_trait == UndefinedPixelTrait)) - (void) SetImageAlphaChannel(source_image,SetAlphaChannel,exception); -if (0) if ((compose == OverCompositeOp) || (compose == SrcOverCompositeOp)) { status=CompositeOverImage(image,source_image,clip_to_self,x_offset, @@ -561,9 +576,14 @@ if (0) source_image=DestroyImage(source_image); return(status); } - canvas_image=(Image *) NULL; amount=0.5; + 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; @@ -601,8 +621,8 @@ if (0) if (status == MagickFalse) continue; - p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns, - 1,exception); + 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)) @@ -615,22 +635,24 @@ if (0) register ssize_t i; - if (GetPixelReadMask(source_image,p) == 0) + if (GetPixelWriteMask(source_image,p) == 0) { p+=GetPixelChannels(source_image); q+=GetPixelChannels(image); continue; } - for (i=0; i < (ssize_t) GetPixelChannels(source_image); i++) + for (i=0; i < (ssize_t) GetPixelChannels(image); i++) { - PixelChannel channel=GetPixelChannelChannel(source_image,i); + PixelChannel channel=GetPixelChannelChannel(image,i); + PixelTrait traits=GetPixelChannelTraits(image,channel); PixelTrait source_traits=GetPixelChannelTraits(source_image, channel); - PixelTrait traits=GetPixelChannelTraits(image,channel); - if ((traits == UndefinedPixelTrait) || - (source_traits == UndefinedPixelTrait)) + 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); @@ -688,8 +710,8 @@ if (0) if (status == MagickFalse) continue; - p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns, - 1,exception); + 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)) @@ -699,14 +721,15 @@ if (0) } for (x=0; x < (ssize_t) source_image->columns; x++) { - if (GetPixelReadMask(source_image,p) == 0) + if (GetPixelWriteMask(source_image,p) == 0) { p+=GetPixelChannels(source_image); q+=GetPixelChannels(image); continue; } - SetPixelAlpha(image,ClampToQuantum(GetPixelIntensity(source_image, - p)),q); + SetPixelAlpha(image,clamp != MagickFalse ? + ClampPixel(GetPixelIntensity(source_image,p)) : + ClampToQuantum(GetPixelIntensity(source_image,p)),q); p+=GetPixelChannels(source_image); q+=GetPixelChannels(image); } @@ -746,11 +769,7 @@ if (0) case BlurCompositeOp: { CacheView - *canvas_view, - *source_view; - - const char - *value; + *canvas_view; MagickRealType angle_range, @@ -783,7 +802,6 @@ if (0) /* Gather the maximum blur sigma values from user. */ - SetGeometryInfo(&geometry_info); flags=NoValue; value=GetImageArtifact(image,"compose:args"); if (value != (const char *) NULL) @@ -855,20 +873,20 @@ if (0) 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(source_view,0,y,source_image->columns, - 1,exception); - q=QueueCacheViewAuthenticPixels(canvas_view,0,y, - canvas_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) source_image->columns; x++) @@ -923,12 +941,7 @@ if (0) case DistortCompositeOp: { CacheView - *source_view, - *canvas_view, - *image_view; - - const char - *value; + *canvas_view; MagickRealType horizontal_scale, @@ -1039,10 +1052,10 @@ if (0) sync; register const Quantum - *restrict p; + *magick_restrict p; register Quantum - *restrict q; + *magick_restrict q; register ssize_t x; @@ -1098,9 +1111,6 @@ if (0) } case DissolveCompositeOp: { - const char - *value; - /* Geometry arguments to dissolve factors. */ @@ -1126,9 +1136,6 @@ if (0) } case BlendCompositeOp: { - const char - *value; - value=GetImageArtifact(image,"compose:args"); if (value != (char *) NULL) { @@ -1142,9 +1149,6 @@ if (0) } case MathematicsCompositeOp: { - const char - *value; - /* Just collect the values from "compose:args", setting. Unused values are set to zero automagically. @@ -1161,9 +1165,6 @@ if (0) } case ModulateCompositeOp: { - const char - *value; - /* Determine the luma and chroma scale. */ @@ -1179,9 +1180,6 @@ if (0) } case ThresholdCompositeOp: { - const char - *value; - /* Determine the amount and threshold. */ @@ -1230,10 +1228,10 @@ if (0) source_pixel; register const Quantum - *restrict p; + *magick_restrict p; register Quantum - *restrict q; + *magick_restrict q; register ssize_t x; @@ -1317,9 +1315,9 @@ if (0) Sc: source color. Dc: canvas color. */ - (void) GetOneVirtualPixel(source_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; @@ -1380,7 +1378,8 @@ if (0) break; } } - q[i]=ClampToQuantum(pixel); + q[i]=clamp != MagickFalse ? ClampPixel(pixel) : + ClampToQuantum(pixel); } q+=GetPixelChannels(image); continue; @@ -1438,11 +1437,13 @@ if (0) } case DissolveCompositeOp: { - alpha=source_dissolve*Sa*(-canvas_dissolve*Da)+source_dissolve* - Sa+canvas_dissolve*Da; + alpha=source_dissolve*Sa*(-canvas_dissolve*Da)+source_dissolve*Sa+ + canvas_dissolve*Da; break; } case DstOverCompositeOp: + case OverCompositeOp: + case SrcOverCompositeOp: { alpha=Sa+Da-Sa*Da; break; @@ -1458,16 +1459,10 @@ if (0) 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: @@ -1481,7 +1476,7 @@ if (0) break; } } - if (GetPixelReadMask(image,q) == 0) + if (GetPixelWriteMask(image,q) == 0) { p+=GetPixelChannels(source_image); q+=GetPixelChannels(image); @@ -1510,29 +1505,12 @@ if (0) PixelChannel channel=GetPixelChannelChannel(image,i); PixelTrait traits=GetPixelChannelTraits(image,channel); - PixelTrait source_traits=GetPixelChannelTraits(source_image, - channel); + PixelTrait source_traits=GetPixelChannelTraits(source_image,channel); if (traits == UndefinedPixelTrait) continue; if ((source_traits == UndefinedPixelTrait) && - (((compose != CopyAlphaCompositeOp) && - (compose != ChangeMaskCompositeOp)) || - (channel != AlphaPixelChannel))) + (channel != AlphaPixelChannel)) 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]=ClampToQuantum(Sc); - continue; - } if (channel == AlphaPixelChannel) { /* @@ -1565,7 +1543,7 @@ if (0) MagickBooleanType equivalent; - if (Da > ((MagickRealType) QuantumRange/2.0)) + if (Da < 0.5) { pixel=(MagickRealType) TransparentAlpha; break; @@ -1607,7 +1585,7 @@ if (0) } case CopyAlphaCompositeOp: { - if (source_traits == UndefinedPixelTrait) + if (source_image->alpha_trait == UndefinedPixelTrait) pixel=GetPixelIntensity(source_image,p); else pixel=QuantumRange*Sa; @@ -1637,11 +1615,6 @@ if (0) } case ModulateCompositeOp: { - if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon) - { - pixel=QuantumRange*Da; - break; - } pixel=QuantumRange*Da; break; } @@ -1651,7 +1624,22 @@ if (0) 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; } /* @@ -1667,13 +1655,15 @@ if (0) 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) { @@ -1731,31 +1721,25 @@ if (0) { if ((Sca == 0.0) && (Dca == Da)) { - pixel=QuantumRange*(Sa*Da+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Sa*Da+Dca*(1.0-Sa)); break; } if (Sca == 0.0) { - pixel=QuantumRange*(Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Dca*(1.0-Sa)); break; } - pixel=QuantumRange*(Sa*Da-Sa*Da*MagickMin(1.0,(1.0-Dca/Da)*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 == Sa) && (Dca == 0.0)) - { - pixel=QuantumRange*(Sca*(1.0-Da)); - break; - } - if (Sca == Sa) - { - pixel=QuantumRange*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa)); - break; - } - pixel=QuantumRange*(Sa*Da*MagickMin(1.0,Dca/Da*Sa/(Sa-Sca))); + if ((Sca*Da+Dca*Sa) >= Sa*Da) + 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: @@ -1770,8 +1754,8 @@ if (0) pixel=Sc; break; } - CompositeHCL(canvas_pixel.red,canvas_pixel.green, - canvas_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); @@ -1840,7 +1824,7 @@ if (0) } case DifferenceCompositeOp: { - pixel=QuantumRange*(Sca+Dca-2.0*MagickMin(Sca*Da,Dca*Sa)); + pixel=QuantumRange*gamma*(Sca+Dca-2.0*MagickMin(Sca*Da,Dca*Sa)); break; } case DissolveCompositeOp: @@ -1854,15 +1838,15 @@ if (0) if ((fabs((double) Sca) < MagickEpsilon) && (fabs((double) Dca) < MagickEpsilon)) { - pixel=QuantumRange*(Sca*(1.0-Da)+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Sca*(1.0-Da)+Dca*(1.0-Sa)); break; } if (fabs((double) Dca) < MagickEpsilon) { - pixel=QuantumRange*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa)); break; } - pixel=QuantumRange*(Sca*Da*Da/Dca+Sca*(1.0-Da)+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Sca*Da*Da/Dca+Sca*(1.0-Da)+Dca*(1.0-Sa)); break; } case DivideSrcCompositeOp: @@ -1870,15 +1854,15 @@ if (0) if ((fabs((double) Dca) < MagickEpsilon) && (fabs((double) Sca) < MagickEpsilon)) { - pixel=QuantumRange*(Dca*(1.0-Sa)+Sca*(1.0-Da)); + pixel=QuantumRange*gamma*(Dca*(1.0-Sa)+Sca*(1.0-Da)); break; } if (fabs((double) Sca) < MagickEpsilon) { - pixel=QuantumRange*(Da*Sa+Dca*(1.0-Sa)+Sca*(1.0-Da)); + pixel=QuantumRange*gamma*(Da*Sa+Dca*(1.0-Sa)+Sca*(1.0-Da)); break; } - pixel=QuantumRange*(Dca*Sa*Sa/Sca+Dca*(1.0-Sa)+Sca*(1.0-Da)); + pixel=QuantumRange*gamma*(Dca*Sa*Sa/Sca+Dca*(1.0-Sa)+Sca*(1.0-Da)); break; } case DstAtopCompositeOp: @@ -1904,36 +1888,30 @@ if (0) } case DstOverCompositeOp: { - pixel=QuantumRange*(Dca+Sca*(1.0-Da)); + pixel=QuantumRange*gamma*(Dca+Sca*(1.0-Da)); break; } case ExclusionCompositeOp: { - pixel=QuantumRange*(Sca*Da+Dca*Sa-2.0*Sca*Dca+Sca*(1.0-Da)+Dca* - (1.0-Sa)); + pixel=QuantumRange*gamma*(Sca*Da+Dca*Sa-2.0*Sca*Dca+Sca*(1.0-Da)+ + Dca*(1.0-Sa)); break; } case HardLightCompositeOp: { if ((2.0*Sca) < Sa) { - pixel=QuantumRange*(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*(Sa*Da-2.0*(Da-Dca)*(Sa-Sca)+Sca*(1.0-Da)+Dca* - (1.0-Sa)); + pixel=QuantumRange*gamma*(Sa*Da-2.0*(Da-Dca)*(Sa-Sca)+Sca*(1.0-Da)+ + Dca*(1.0-Sa)); break; } case HardMixCompositeOp: { - double - gamma; - - if ((Sa+Da) < 1.0) - gamma=0.0; - else - gamma=1.0; - pixel=(gamma*(1.0-Sca)*(1.0-Dca))+Sa*(1.0-Sca)*Dca+Da*(1.0-Dca)*Sca; + pixel=gamma*(((Sca+Dca) < 1.0) ? 0.0 : QuantumRange); break; } case HueCompositeOp: @@ -1948,8 +1926,8 @@ if (0) pixel=Sc; break; } - CompositeHCL(canvas_pixel.red,canvas_pixel.green, - canvas_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); @@ -1976,12 +1954,12 @@ if (0) f(Sc,Dc) = Sc + Dc - 1 */ - pixel=QuantumRange*(Sca+Dca-Sa*Da); + pixel=QuantumRange*gamma*(Sca+Dca-Sa*Da); break; } case LinearDodgeCompositeOp: { - pixel=(Sa*Sc+Da*Dc); + pixel=gamma*(Sa*Sc+Da*Dc); break; } case LinearLightCompositeOp: @@ -1992,7 +1970,7 @@ if (0) f(Sc,Dc) = Dc + 2*Sc - 1 */ - pixel=QuantumRange*((Sca-Sa)*Da+Sca+Dca); + pixel=QuantumRange*gamma*((Sca-Sa)*Da+Sca+Dca); break; } case LightenCompositeOp: @@ -2028,8 +2006,8 @@ if (0) pixel=Sc; break; } - CompositeHCL(canvas_pixel.red,canvas_pixel.green, - canvas_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); @@ -2063,7 +2041,7 @@ if (0) Dca' = A*Sca*Dca + B*Sca*Da + C*Dca*Sa + D*Sa*Da + Sca*(1.0-Da) + Dca*(1.0-Sa) */ - pixel=gamma*QuantumRange*(geometry_info.rho*Sca*Dca+ + 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; @@ -2080,7 +2058,7 @@ if (0) f(Sc,Dc) = Sc - Dc */ - pixel=QuantumRange*(Da*Dc+Sa*Sc-2.0*Sa*Sc*Da); + pixel=gamma*(Da*Dc+Sa*Sc-2.0*Sa*Sc*Da); break; } case ModulateCompositeOp: @@ -2099,8 +2077,8 @@ if (0) pixel=Dc; break; } - CompositeHCL(canvas_pixel.red,canvas_pixel.green, - canvas_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); @@ -2116,22 +2094,26 @@ if (0) 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: { - pixel=QuantumRange*(Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-Sa)); break; } case OutCompositeOp: @@ -2143,18 +2125,19 @@ if (0) case OverCompositeOp: case SrcOverCompositeOp: { - pixel=QuantumRange*(Sca+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Sca+Dca*(1.0-Sa)); break; } case OverlayCompositeOp: { - if ((2.0*Dca) <= Da) + if ((2.0*Dca) < Da) { - pixel=QuantumRange*(2.0*Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(2.0*Dca*Sca+Dca*(1.0-Sa)+Sca*(1.0- + Da)); break; } - pixel=QuantumRange*(Sa*Da-2.0*(Da-Dca)*(Sa-Sca)+Sca*(1.0-Da)+Dca* - (1.0-Sa)); + pixel=QuantumRange*gamma*(Da*Sa-2.0*(Sa-Sca)*(Da-Dca)+Dca*(1.0-Sa)+ + Sca*(1.0-Da)); break; } case PegtopLightCompositeOp: @@ -2169,11 +2152,11 @@ if (0) */ if (fabs((double) Da) < MagickEpsilon) { - pixel=QuantumRange*(Sca); + pixel=QuantumRange*gamma*(Sca); break; } - pixel=QuantumRange*(Dca*Dca*(Sa-2.0*Sca)/Da+Sca*(2.0*Dca+1.0-Da)+ - Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Dca*Dca*(Sa-2.0*Sca)/Da+Sca*(2.0*Dca+1.0- + Da)+Dca*(1.0-Sa)); break; } case PinLightCompositeOp: @@ -2186,15 +2169,15 @@ if (0) */ if ((Dca*Sa) < (Da*(2.0*Sca-Sa))) { - pixel=QuantumRange*(Sca*(Da+1.0)-Sa*Da+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Sca*(Da+1.0)-Sa*Da+Dca*(1.0-Sa)); break; } if ((Dca*Sa) > (2.0*Sca*Da)) { - pixel=QuantumRange*(Sca*Da+Sca+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Sca*Da+Sca+Dca*(1.0-Sa)); break; } - pixel=QuantumRange*(Sca*(1.0-Da)+Dca); + pixel=QuantumRange*gamma*(Sca*(1.0-Da)+Dca); break; } case PlusCompositeOp: @@ -2214,8 +2197,8 @@ if (0) pixel=Sc; break; } - CompositeHCL(canvas_pixel.red,canvas_pixel.green, - canvas_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); @@ -2235,26 +2218,26 @@ if (0) f(Sc,Dc) = 1.0-(1.0-Sc)*(1.0-Dc) */ - pixel=QuantumRange*(Sca+Dca-Sca*Dca); + pixel=QuantumRange*gamma*(Sca+Dca-Sca*Dca); break; } case SoftLightCompositeOp: { if ((2.0*Sca) < Sa) { - pixel=QuantumRange*(Dca*(Sa+(2.0*Sca-Sa)*(1.0-(Dca/Da)))+Sca* - (1.0-Da)+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Dca*(Sa+(2.0*Sca-Sa)*(1.0-(Dca/Da)))+ + Sca*(1.0-Da)+Dca*(1.0-Sa)); break; } if (((2.0*Sca) > Sa) && ((4.0*Dca) <= Da)) { - pixel=QuantumRange*(Dca*Sa+Da*(2.0*Sca-Sa)*(4.0*(Dca/Da)*(4.0* - (Dca/Da)+1.0)*((Dca/Da)-1.0)+7.0*(Dca/Da))+Sca*(1.0-Da)+Dca* - (1.0-Sa)); + pixel=QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)*(4.0*(Dca/Da)* + (4.0*(Dca/Da)+1.0)*((Dca/Da)-1.0)+7.0*(Dca/Da))+Sca*(1.0-Da)+ + Dca*(1.0-Sa)); break; } - pixel=QuantumRange*(Dca*Sa+Da*(2.0*Sca-Sa)*(pow((Dca/Da),0.5)-(Dca/ - Da))+Sca*(1.0-Da)+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)*(pow((Dca/Da),0.5)- + (Dca/Da))+Sca*(1.0-Da)+Dca*(1.0-Sa)); break; } case ThresholdCompositeOp: @@ -2282,16 +2265,16 @@ if (0) if ((fabs((double) Sa) < MagickEpsilon) || (fabs((double) (Sca-Sa)) < MagickEpsilon)) { - pixel=QuantumRange*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa)); break; } if ((2.0*Sca) <= Sa) { - pixel=QuantumRange*(Sa*(Da+Sa*(Dca-Da)/(2.0*Sca))+Sca*(1.0-Da)+ - Dca*(1.0-Sa)); + pixel=QuantumRange*gamma*(Sa*(Da+Sa*(Dca-Da)/(2.0*Sca))+Sca* + (1.0-Da)+Dca*(1.0-Sa)); break; } - pixel=QuantumRange*(Dca*Sa*Sa/(2.0*(Sa-Sca))+Sca*(1.0-Da)+Dca* + pixel=QuantumRange*gamma*(Dca*Sa*Sa/(2.0*(Sa-Sca))+Sca*(1.0-Da)+Dca* (1.0-Sa)); break; } @@ -2306,7 +2289,7 @@ if (0) break; } } - q[i]=ClampToQuantum(pixel); + q[i]=clamp != MagickFalse ? ClampPixel(pixel) : ClampToQuantum(pixel); } p+=GetPixelChannels(source_image); channels=GetPixelChannels(source_image); @@ -2386,7 +2369,7 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture, 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) @@ -2419,7 +2402,7 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture, 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) { @@ -2432,8 +2415,8 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture, MagickBooleanType proceed; - proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) - y,image->rows); + proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y, + image->rows); if (proceed == MagickFalse) status=MagickFalse; } @@ -2496,7 +2479,7 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture, register ssize_t i; - if (GetPixelReadMask(image,q) == 0) + if (GetPixelWriteMask(image,q) == 0) { p+=GetPixelChannels(texture_image); q+=GetPixelChannels(image);