43#include "magick/studio.h"
44#include "magick/accelerate-private.h"
45#include "magick/artifact.h"
46#include "magick/cache-view.h"
47#include "magick/channel.h"
48#include "magick/client.h"
49#include "magick/color.h"
50#include "magick/color-private.h"
51#include "magick/colorspace.h"
52#include "magick/colorspace-private.h"
53#include "magick/composite.h"
54#include "magick/composite-private.h"
55#include "magick/constitute.h"
56#include "magick/draw.h"
58#include "magick/gem.h"
59#include "magick/geometry.h"
60#include "magick/image.h"
61#include "magick/image-private.h"
62#include "magick/list.h"
63#include "magick/log.h"
64#include "magick/monitor.h"
65#include "magick/monitor-private.h"
66#include "magick/memory_.h"
67#include "magick/option.h"
68#include "magick/pixel-private.h"
69#include "magick/property.h"
70#include "magick/quantum.h"
71#include "magick/resample.h"
72#include "magick/resource_.h"
73#include "magick/string_.h"
74#include "magick/thread-private.h"
75#include "magick/threshold.h"
76#include "magick/token.h"
77#include "magick/utility.h"
78#include "magick/version.h"
192static inline MagickRealType Atop(
const MagickRealType p,
193 const MagickRealType Sa,
const MagickRealType q,
194 const MagickRealType magick_unused(Da))
196 magick_unreferenced(Da);
198 return(p*Sa+q*(1.0-Sa));
207 Sa=1.0-QuantumScale*p->opacity;
208 composite->opacity=q->opacity;
209 composite->red=Atop(p->red,Sa,q->red,1.0);
210 composite->green=Atop(p->green,Sa,q->green,1.0);
211 composite->blue=Atop(p->blue,Sa,q->blue,1.0);
212 if (q->colorspace == CMYKColorspace)
213 composite->index=Atop(p->index,Sa,q->index,1.0);
226 intensity=MagickPixelIntensity(p);
227 composite->red=QuantumScale*intensity*q->red;
228 composite->green=QuantumScale*intensity*q->green;
229 composite->blue=QuantumScale*intensity*q->blue;
230 composite->opacity=(MagickRealType) QuantumScale*intensity*p->opacity;
231 if (q->colorspace == CMYKColorspace)
232 composite->index=QuantumScale*intensity*q->index;
238 composite->opacity=(MagickRealType) TransparentOpacity;
240 composite->green=0.0;
242 if (q->colorspace == CMYKColorspace)
243 composite->index=0.0;
246static MagickRealType ColorBurn(
const MagickRealType Sca,
247 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
252 if ((fabs((
double) Sca) < MagickEpsilon) &&
253 (fabs((
double) (Dca-Da)) < MagickEpsilon))
254 return(Sa*Da+Dca*(1.0-Sa));
255 if (Sca < MagickEpsilon)
256 return(Dca*(1.0-Sa));
257 SaSca=Sa*PerceptibleReciprocal(Sca);
258 return(Sa*Da-Sa*MagickMin(Da,(Da-Dca)*SaSca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
269 Sa=1.0-QuantumScale*p->opacity;
270 Da=1.0-QuantumScale*q->opacity;
271 gamma=RoundToUnity(Sa+Da-Sa*Da);
272 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
273 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
274 MagickEpsilon : gamma);
275 composite->red=gamma*ColorBurn(QuantumScale*p->red*Sa,Sa,QuantumScale*
277 composite->green=gamma*ColorBurn(QuantumScale*p->green*Sa,Sa,QuantumScale*
279 composite->blue=gamma*ColorBurn(QuantumScale*p->blue*Sa,Sa,QuantumScale*
281 if (q->colorspace == CMYKColorspace)
282 composite->index=gamma*ColorBurn(QuantumScale*p->index*Sa,Sa,QuantumScale*
287static MagickRealType ColorDodge(
const MagickRealType Sca,
288 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
293 if ((Sca*Da+Dca*Sa) >= Sa*Da)
294 return(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
295 return(Dca*Sa*Sa*PerceptibleReciprocal(Sa-Sca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
301 if ((fabs(Sca-Sa) < MagickEpsilon) && (fabs(Dca) < MagickEpsilon))
302 return(Sca*(1.0-Da));
303 if (fabs(Sca-Sa) < MagickEpsilon)
304 return(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
305 return(Sa*MagickMin(Da,Dca*Sa/(Sa-Sca)));
316 if ((fabs(Sca-Sa) < MagickEpsilon) && (fabs(Dca) < MagickEpsilon))
317 return(Sca*(1.0-Da)+Dca*(1.0-Sa));
318 if (fabs(Sca-Sa) < MagickEpsilon)
319 return(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
320 return(Dca*Sa*Sa/(Sa-Sca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
332 Sa=1.0-QuantumScale*p->opacity;
333 Da=1.0-QuantumScale*q->opacity;
334 gamma=RoundToUnity(Sa+Da-Sa*Da);
335 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
336 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
337 MagickEpsilon : gamma);
338 composite->red=gamma*ColorDodge(QuantumScale*p->red*Sa,Sa,QuantumScale*
340 composite->green=gamma*ColorDodge(QuantumScale*p->green*Sa,Sa,QuantumScale*
342 composite->blue=gamma*ColorDodge(QuantumScale*p->blue*Sa,Sa,QuantumScale*
344 if (q->colorspace == CMYKColorspace)
345 composite->index=gamma*ColorDodge(QuantumScale*p->index*Sa,Sa,QuantumScale*
349static inline MagickRealType Darken(
const MagickRealType p,
350 const MagickRealType alpha,
const MagickRealType q,
const MagickRealType beta)
353 return(MagickOver_(p,alpha,q,beta));
354 return(MagickOver_(q,beta,p,alpha));
369 if ( (channel & SyncChannels) != 0 ) {
370 composite->opacity=QuantumScale*p->opacity*q->opacity;
371 gamma=1.0-QuantumScale*composite->opacity;
372 gamma=PerceptibleReciprocal(gamma);
373 composite->red=gamma*Darken(p->red,p->opacity,q->red,q->opacity);
374 composite->green=gamma*Darken(p->green,p->opacity,q->green,q->opacity);
375 composite->blue=gamma*Darken(p->blue,p->opacity,q->blue,q->opacity);
376 if (q->colorspace == CMYKColorspace)
377 composite->index=gamma*Darken(p->index,p->opacity,q->index,q->opacity);
380 if ( (channel & AlphaChannel) != 0 )
381 composite->opacity=MagickMax(p->opacity,q->opacity);
382 if ( (channel & RedChannel) != 0 )
383 composite->red=MagickMin(p->red,q->red);
384 if ( (channel & GreenChannel) != 0 )
385 composite->green=MagickMin(p->green,q->green);
386 if ( (channel & BlueChannel) != 0 )
387 composite->blue=MagickMin(p->blue,q->blue);
388 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
389 composite->index=MagickMin(p->index,q->index);
402 if ( (channel & SyncChannels) != 0 ) {
407 Sa=1.0-QuantumScale*p->opacity;
408 Da=1.0-QuantumScale*q->opacity;
409 *composite = (Sa*MagickPixelIntensity(p) < Da*MagickPixelIntensity(q))
413 int from_p = (MagickPixelIntensity(p) < MagickPixelIntensity(q));
414 if ( (channel & AlphaChannel) != 0 )
415 composite->opacity = from_p ? p->opacity : q->opacity;
416 if ( (channel & RedChannel) != 0 )
417 composite->red = from_p ? p->red : q->red;
418 if ( (channel & GreenChannel) != 0 )
419 composite->green = from_p ? p->green : q->green;
420 if ( (channel & BlueChannel) != 0 )
421 composite->blue = from_p ? p->blue : q->blue;
422 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
423 composite->index = from_p ? p->index : q->index;
427static inline MagickRealType Difference(
const MagickRealType p,
428 const MagickRealType Sa,
const MagickRealType q,
const MagickRealType Da)
431 return(Sa*p+Da*q-Sa*Da*2.0*MagickMin(p,q));
445 Sa=1.0-QuantumScale*p->opacity;
446 Da=1.0-QuantumScale*q->opacity;
447 if ( (channel & SyncChannels) != 0 ) {
448 gamma=RoundToUnity(Sa+Da-Sa*Da);
449 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
450 gamma=PerceptibleReciprocal(gamma);
452 composite->red=gamma*Difference(p->red,Sa,q->red,Da);
453 composite->green=gamma*Difference(p->green,Sa,q->green,Da);
454 composite->blue=gamma*Difference(p->blue,Sa,q->blue,Da);
455 if (q->colorspace == CMYKColorspace)
456 composite->index=gamma*Difference(p->index,Sa,q->index,Da);
459 if ( (channel & AlphaChannel) != 0 )
460 composite->opacity=(MagickRealType) QuantumRange-
461 fabs((
double) (p->opacity-q->opacity));
462 if ( (channel & RedChannel) != 0 )
463 composite->red=fabs((
double) (p->red-q->red));
464 if ( (channel & GreenChannel) != 0 )
465 composite->green=fabs((
double) (p->green-q->green));
466 if ( (channel & BlueChannel) != 0 )
467 composite->blue=fabs((
double) (p->blue-q->blue));
468 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
469 composite->index=fabs((
double) (p->index-q->index));
473static MagickRealType Divide(
const MagickRealType Sca,
const MagickRealType Sa,
474 const MagickRealType Dca,
const MagickRealType Da)
486 if ((fabs((
double) Sca) < MagickEpsilon) &&
487 (fabs((
double) Dca) < MagickEpsilon))
488 return(Sca*(1.0-Da)+Dca*(1.0-Sa));
489 if (fabs((
double) Dca) < MagickEpsilon)
490 return(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
491 return(Sca*Da*Da*PerceptibleReciprocal(Dca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
503 Sa=1.0-QuantumScale*p->opacity;
504 Da=1.0-QuantumScale*q->opacity;
505 if ( (channel & SyncChannels) != 0 ) {
506 gamma=RoundToUnity(Sa+Da-Sa*Da);
507 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
508 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
509 MagickEpsilon : gamma);
510 composite->red=gamma*Divide(QuantumScale*p->red*Sa,Sa,QuantumScale*
512 composite->green=gamma*Divide(QuantumScale*p->green*Sa,Sa,QuantumScale*
514 composite->blue=gamma*Divide(QuantumScale*p->blue*Sa,Sa,QuantumScale*
516 if (q->colorspace == CMYKColorspace)
517 composite->index=gamma*Divide(QuantumScale*p->index*Sa,Sa,QuantumScale*
521 if ( (channel & AlphaChannel) != 0 )
522 composite->opacity=(MagickRealType) QuantumRange*(1.0-Divide(Sa,1.0,Da,1.0));
523 if ( (channel & RedChannel) != 0 )
524 composite->red=(MagickRealType) QuantumRange*
525 Divide(QuantumScale*p->red,1.0,QuantumScale*q->red,1.0);
526 if ( (channel & GreenChannel) != 0 )
527 composite->green=(MagickRealType) QuantumRange*
528 Divide(QuantumScale*p->green,1.0,QuantumScale*q->green,1.0);
529 if ( (channel & BlueChannel) != 0 )
530 composite->blue=(MagickRealType) QuantumRange*
531 Divide(QuantumScale*p->blue,1.0,QuantumScale*q->blue,1.0);
532 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
533 composite->index=(MagickRealType) QuantumRange*
534 Divide(QuantumScale*p->index,1.0,QuantumScale*q->index,1.0);
538static MagickRealType Exclusion(
const MagickRealType Sca,
539 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
541 return(Sca*Da+Dca*Sa-2.0*Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-Sa));
553 Sa=1.0-QuantumScale*p->opacity;
554 Da=1.0-QuantumScale*q->opacity;
555 if ( (channel & SyncChannels) != 0 ) {
556 gamma=RoundToUnity(Sa+Da-Sa*Da);
557 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
558 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
559 MagickEpsilon : gamma);
560 composite->red=gamma*Exclusion(QuantumScale*p->red*Sa,Sa,QuantumScale*
562 composite->green=gamma*Exclusion(QuantumScale*p->green*Sa,Sa,QuantumScale*
564 composite->blue=gamma*Exclusion(QuantumScale*p->blue*Sa,Sa,QuantumScale*
566 if (q->colorspace == CMYKColorspace)
567 composite->index=gamma*Exclusion(QuantumScale*p->index*Sa,Sa,QuantumScale*
571 if ((channel & AlphaChannel) != 0)
572 composite->opacity=(MagickRealType) QuantumRange*(1.0-Exclusion(Sa,1.0,Da,1.0));
573 if ((channel & RedChannel) != 0)
574 composite->red=(MagickRealType) QuantumRange*Exclusion(QuantumScale*p->red,1.0,
575 QuantumScale*q->red,1.0);
576 if ((channel & GreenChannel) != 0)
577 composite->green=(MagickRealType) QuantumRange*Exclusion(QuantumScale*p->green,
578 1.0,QuantumScale*q->green,1.0);
579 if ((channel & BlueChannel) != 0)
580 composite->blue=(MagickRealType) QuantumRange*Exclusion(QuantumScale*p->blue,1.0,
581 QuantumScale*q->blue,1.0);
582 if (((channel & IndexChannel) != 0) && (q->colorspace == CMYKColorspace))
583 composite->index=(MagickRealType) QuantumRange*Exclusion(QuantumScale*p->index,
584 1.0,QuantumScale*q->index,1.0);
588static MagickRealType HardLight(
const MagickRealType Sca,
589 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
592 return(2.0*Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-Sa));
593 return(Sa*Da-2.0*(Da-Dca)*(Sa-Sca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
604 Sa=1.0-QuantumScale*p->opacity;
605 Da=1.0-QuantumScale*q->opacity;
606 gamma=RoundToUnity(Sa+Da-Sa*Da);
607 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
608 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
609 MagickEpsilon : gamma);
610 composite->red=gamma*HardLight(QuantumScale*p->red*Sa,Sa,QuantumScale*
612 composite->green=gamma*HardLight(QuantumScale*p->green*Sa,Sa,QuantumScale*
614 composite->blue=gamma*HardLight(QuantumScale*p->blue*Sa,Sa,QuantumScale*
616 if (q->colorspace == CMYKColorspace)
617 composite->index=gamma*HardLight(QuantumScale*p->index*Sa,Sa,QuantumScale*
621static MagickRealType HardMix(
const MagickRealType Sca,
622 const MagickRealType Dca)
624 if ((Sca+Dca) < (MagickRealType) QuantumRange)
638 Sa=1.0-QuantumScale*p->opacity;
639 Da=1.0-QuantumScale*q->opacity;
640 gamma=RoundToUnity(Sa+Da-Sa*Da);
641 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
642 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
643 MagickEpsilon : gamma);
644 composite->red=gamma*HardMix(p->red*Sa,q->red*Da);
645 composite->green=gamma*HardMix(p->green*Sa,q->green*Da);
646 composite->blue=gamma*HardMix(p->blue*Sa,q->blue*Da);
647 if (q->colorspace == CMYKColorspace)
648 composite->index=gamma*HardMix(p->index*Sa,q->index*Da);
651static void HCLComposite(
const double hue,
const double chroma,
const double luma,
652 MagickRealType *red,MagickRealType *green,MagickRealType *blue)
666 assert(red != (MagickRealType *) NULL);
667 assert(green != (MagickRealType *) NULL);
668 assert(blue != (MagickRealType *) NULL);
671 x=c*(1.0-fabs(fmod(h,2.0)-1.0));
675 if ((0.0 <= h) && (h < 1.0))
681 if ((1.0 <= h) && (h < 2.0))
687 if ((2.0 <= h) && (h < 3.0))
693 if ((3.0 <= h) && (h < 4.0))
699 if ((4.0 <= h) && (h < 5.0))
705 if ((5.0 <= h) && (h < 6.0))
710 m=luma-(0.298839*r+0.586811*g+0.114350*b);
711 *red=(MagickRealType) QuantumRange*(r+m);
712 *green=(MagickRealType) QuantumRange*(g+m);
713 *blue=(MagickRealType) QuantumRange*(b+m);
716static void CompositeHCL(
const MagickRealType red,
const MagickRealType green,
717 const MagickRealType blue,
double *hue,
double *chroma,
double *luma)
730 assert(hue != (
double *) NULL);
731 assert(chroma != (
double *) NULL);
732 assert(luma != (
double *) NULL);
736 max=MagickMax(r,MagickMax(g,b));
737 c=max-(double) MagickMin(r,MagickMin(g,b));
742 if (red == (MagickRealType) max)
743 h=fmod((g-b)/c+6.0,6.0);
745 if (green == (MagickRealType) max)
748 if (blue == (MagickRealType) max)
751 *chroma=QuantumScale*c;
752 *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
755static inline MagickRealType In(
const MagickRealType p,
const MagickRealType Sa,
756 const MagickRealType magick_unused(q),
const MagickRealType Da)
758 magick_unreferenced(q);
773 Sa=1.0-QuantumScale*p->opacity;
774 Da=1.0-QuantumScale*q->opacity;
776 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
777 gamma=PerceptibleReciprocal(gamma);
778 composite->red=gamma*In(p->red,Sa,q->red,Da);
779 composite->green=gamma*In(p->green,Sa,q->green,Da);
780 composite->blue=gamma*In(p->blue,Sa,q->blue,Da);
781 if (q->colorspace == CMYKColorspace)
782 composite->index=gamma*In(p->index,Sa,q->index,Da);
785static inline MagickRealType Lighten(
const MagickRealType p,
786 const MagickRealType alpha,
const MagickRealType q,
const MagickRealType beta)
789 return(MagickOver_(p,alpha,q,beta));
790 return(MagickOver_(q,beta,p,alpha));
805 if ( (channel & SyncChannels) != 0 ) {
806 composite->opacity=QuantumScale*p->opacity*q->opacity;
807 gamma=1.0-QuantumScale*composite->opacity;
808 gamma=PerceptibleReciprocal(gamma);
809 composite->red=gamma*Lighten(p->red,p->opacity,q->red,q->opacity);
810 composite->green=gamma*Lighten(p->green,p->opacity,q->green,q->opacity);
811 composite->blue=gamma*Lighten(p->blue,p->opacity,q->blue,q->opacity);
812 if (q->colorspace == CMYKColorspace)
813 composite->index=gamma*Lighten(p->index,p->opacity,q->index,q->opacity);
816 if ( (channel & AlphaChannel) != 0 )
817 composite->opacity=MagickMin(p->opacity,q->opacity);
818 if ( (channel & RedChannel) != 0 )
819 composite->red=MagickMax(p->red,q->red);
820 if ( (channel & GreenChannel) != 0 )
821 composite->green=MagickMax(p->green,q->green);
822 if ( (channel & BlueChannel) != 0 )
823 composite->blue=MagickMax(p->blue,q->blue);
824 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
825 composite->index=MagickMax(p->index,q->index);
838 if ( (channel & SyncChannels) != 0 ) {
843 Sa=1.0-QuantumScale*p->opacity;
844 Da=1.0-QuantumScale*q->opacity;
845 *composite = (Sa*MagickPixelIntensity(p) > Da*MagickPixelIntensity(q))
849 int from_p = (MagickPixelIntensity(p) > MagickPixelIntensity(q));
850 if ( (channel & AlphaChannel) != 0 )
851 composite->opacity = from_p ? p->opacity : q->opacity;
852 if ( (channel & RedChannel) != 0 )
853 composite->red = from_p ? p->red : q->red;
854 if ( (channel & GreenChannel) != 0 )
855 composite->green = from_p ? p->green : q->green;
856 if ( (channel & BlueChannel) != 0 )
857 composite->blue = from_p ? p->blue : q->blue;
858 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
859 composite->index = from_p ? p->index : q->index;
864static inline MagickRealType LinearDodge(
const MagickRealType Sca,
865 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
886 Sa=1.0-QuantumScale*p->opacity;
887 Da=1.0-QuantumScale*q->opacity;
888 gamma=RoundToUnity(Sa+Da-Sa*Da);
889 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
890 gamma=PerceptibleReciprocal(gamma);
891 composite->red=gamma*(p->red*Sa+q->red*Da);
892 composite->green=gamma*(p->green*Sa+q->green*Da);
893 composite->blue=gamma*(p->blue*Sa+q->blue*Da);
894 if (q->colorspace == CMYKColorspace)
895 composite->index=gamma*(p->index*Sa+q->index*Da);
899static inline MagickRealType LinearBurn(
const MagickRealType Sca,
900 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
908 return(Sca+Dca-Sa*Da);
919 Sa=1.0-QuantumScale*p->opacity;
920 Da=1.0-QuantumScale*q->opacity;
921 gamma=RoundToUnity(Sa+Da-Sa*Da);
922 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
923 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
924 MagickEpsilon : gamma);
925 composite->red=gamma*LinearBurn(QuantumScale*p->red*Sa,Sa,QuantumScale*
927 composite->green=gamma*LinearBurn(QuantumScale*p->green*Sa,Sa,QuantumScale*
929 composite->blue=gamma*LinearBurn(QuantumScale*p->blue*Sa,Sa,QuantumScale*
931 if (q->colorspace == CMYKColorspace)
932 composite->index=gamma*LinearBurn(QuantumScale*p->index*Sa,Sa,QuantumScale*
936static inline MagickRealType LinearLight(
const MagickRealType Sca,
937 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
943 return(Dca+2*Sca-1.0);
951 return((Sca-Sa)*Da+Sca+Dca);
963 Sa=1.0-QuantumScale*p->opacity;
964 Da=1.0-QuantumScale*q->opacity;
965 gamma=RoundToUnity(Sa+Da-Sa*Da);
966 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
967 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
968 MagickEpsilon : gamma);
969 composite->red=gamma*LinearLight(QuantumScale*p->red*Sa,Sa,QuantumScale*
971 composite->green=gamma*LinearLight(QuantumScale*p->green*Sa,Sa,QuantumScale*
973 composite->blue=gamma*LinearLight(QuantumScale*p->blue*Sa,Sa,QuantumScale*
975 if (q->colorspace == CMYKColorspace)
976 composite->index=gamma*LinearLight(QuantumScale*p->index*Sa,Sa,QuantumScale*
980static inline MagickRealType Mathematics(
const MagickRealType Sca,
981 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da,
1002 return(geometry_info->rho*Sca*Dca+geometry_info->sigma*Sca*Da+
1003 geometry_info->xi*Dca*Sa+geometry_info->psi*Sa*Da+Sca*(1.0-Da)+
1018 Sa=1.0-QuantumScale*p->opacity;
1019 Da=1.0-QuantumScale*q->opacity;
1020 if ( (channel & SyncChannels) != 0 ) {
1021 gamma=RoundToUnity(Sa+Da-Sa*Da);
1022 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1023 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
1024 MagickEpsilon : gamma);
1025 composite->red=gamma*Mathematics(QuantumScale*p->red*Sa,Sa,QuantumScale*
1027 composite->green=gamma*Mathematics(QuantumScale*p->green*Sa,Sa,QuantumScale*
1028 q->green*Da,Da,args);
1029 composite->blue=gamma*Mathematics(QuantumScale*p->blue*Sa,Sa,QuantumScale*
1030 q->blue*Da,Da,args);
1031 if (q->colorspace == CMYKColorspace)
1032 composite->index=gamma*Mathematics(QuantumScale*p->index*Sa,Sa,
1033 QuantumScale*q->index*Da,Da,args);
1036 if ( (channel & AlphaChannel) != 0 )
1037 composite->opacity=(MagickRealType) QuantumRange*(1.0-
1038 Mathematics(Sa,1.0,Da,1.0,args));
1039 if ( (channel & RedChannel) != 0 )
1040 composite->red=(MagickRealType) QuantumRange*
1041 Mathematics(QuantumScale*p->red,1.0,QuantumScale*q->red,1.0,args);
1042 if ( (channel & GreenChannel) != 0 )
1043 composite->green=(MagickRealType) QuantumRange*
1044 Mathematics(QuantumScale*p->green,1.0,QuantumScale*q->green,1.0,args);
1045 if ( (channel & BlueChannel) != 0 )
1046 composite->blue=(MagickRealType) QuantumRange*
1047 Mathematics(QuantumScale*p->blue,1.0,QuantumScale*q->blue,1.0,args);
1048 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
1049 composite->index=(MagickRealType) QuantumRange*
1050 Mathematics(QuantumScale*p->index,1.0,QuantumScale*q->index,1.0,args);
1059 if ( (channel & SyncChannels) != 0 ) {
1075 MagickPixelCompositePlus(p,p->opacity,q,q->opacity,composite);
1078 if ( (channel & AlphaChannel) != 0 )
1079 composite->opacity=p->opacity+q->opacity-(MagickRealType) QuantumRange;
1080 if ( (channel & RedChannel) != 0 )
1081 composite->red=p->red+q->red;
1082 if ( (channel & GreenChannel) != 0 )
1083 composite->green=p->green+q->green;
1084 if ( (channel & BlueChannel) != 0 )
1085 composite->blue=p->blue+q->blue;
1086 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
1087 composite->index=p->index+q->index;
1091static inline MagickRealType Minus(
const MagickRealType Sca,
1092 const MagickRealType Sa,
const MagickRealType Dca,
1093 const MagickRealType magick_unused(Da))
1101 magick_unreferenced(Da);
1103 return(Sca+Dca-2*Dca*Sa);
1117 Sa=1.0-QuantumScale*p->opacity;
1118 Da=1.0-QuantumScale*q->opacity;
1119 if ( (channel & SyncChannels) != 0 ) {
1120 gamma=RoundToUnity(Sa+Da-Sa*Da);
1121 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1122 gamma=PerceptibleReciprocal(gamma);
1123 composite->red=gamma*Minus(p->red*Sa,Sa,q->red*Da,Da);
1124 composite->green=gamma*Minus(p->green*Sa,Sa,q->green*Da,Da);
1125 composite->blue=gamma*Minus(p->blue*Sa,Sa,q->blue*Da,Da);
1126 if (q->colorspace == CMYKColorspace)
1127 composite->index=gamma*Minus(p->index*Sa,Sa,q->index*Da,Da);
1130 if ( (channel & AlphaChannel) != 0 )
1131 composite->opacity=(MagickRealType) QuantumRange*(1.0-(Sa-Da));
1132 if ( (channel & RedChannel) != 0 )
1133 composite->red=p->red-q->red;
1134 if ( (channel & GreenChannel) != 0 )
1135 composite->green=p->green-q->green;
1136 if ( (channel & BlueChannel) != 0 )
1137 composite->blue=p->blue-q->blue;
1138 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
1139 composite->index=p->index-q->index;
1143static inline MagickRealType ModulusAdd(
const MagickRealType Sc,
1144 const MagickRealType Sa,
const MagickRealType Dc,
const MagickRealType Da)
1146 if (((Sc*Sa)+(Dc*Da)) <= (MagickRealType) QuantumRange)
1147 return((Sc*Sa)+Dc*Da);
1148 return(((Sc*Sa)+Dc*Da)-(MagickRealType) QuantumRange);
1155 if ( (channel & SyncChannels) != 0 ) {
1163 Sa=1.0-QuantumScale*p->opacity;
1164 Da=1.0-QuantumScale*q->opacity;
1165 gamma=RoundToUnity(Sa+Da-Sa*Da);
1166 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1167 gamma=PerceptibleReciprocal(gamma);
1168 composite->red=ModulusAdd(p->red,Sa,q->red,Da);
1169 composite->green=ModulusAdd(p->green,Sa,q->green,Da);
1170 composite->blue=ModulusAdd(p->blue,Sa,q->blue,Da);
1171 if (q->colorspace == CMYKColorspace)
1172 composite->index=ModulusAdd(p->index,Sa,q->index,Da);
1175 if ( (channel & AlphaChannel) != 0 )
1176 composite->opacity=(MagickRealType) QuantumRange-ModulusAdd(
1177 (MagickRealType) QuantumRange-p->opacity,1.0,(MagickRealType)
1178 QuantumRange-q->opacity,1.0);
1179 if ( (channel & RedChannel) != 0 )
1180 composite->red=ModulusAdd(p->red,1.0,q->red,1.0);
1181 if ( (channel & GreenChannel) != 0 )
1182 composite->green=ModulusAdd(p->green,1.0,q->green,1.0);
1183 if ( (channel & BlueChannel) != 0 )
1184 composite->blue=ModulusAdd(p->blue,1.0,q->blue,1.0);
1185 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
1186 composite->index=ModulusAdd(p->index,1.0,q->index,1.0);
1190static inline MagickRealType ModulusSubtract(
const MagickRealType Sc,
1191 const MagickRealType Sa,
const MagickRealType Dc,
const MagickRealType Da)
1193 if (((Sc*Sa)-(Dc*Da)) <= 0.0)
1194 return((Sc*Sa)-Dc*Da);
1195 return(((Sc*Sa)-Dc*Da)+(MagickRealType) QuantumRange);
1202 if ( (channel & SyncChannels) != 0 ) {
1210 Sa=1.0-QuantumScale*p->opacity;
1211 Da=1.0-QuantumScale*q->opacity;
1212 gamma = RoundToUnity(Sa+Da-Sa*Da);
1213 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1214 gamma=PerceptibleReciprocal(gamma);
1215 composite->red=ModulusSubtract(p->red,Sa,q->red,Da);
1216 composite->green=ModulusSubtract(p->green,Sa,q->green,Da);
1217 composite->blue=ModulusSubtract(p->blue,Sa,q->blue,Da);
1218 if (q->colorspace == CMYKColorspace)
1219 composite->index=ModulusSubtract(p->index,Sa,q->index,Da);
1222 if ( (channel & AlphaChannel) != 0 )
1223 composite->opacity=(MagickRealType) QuantumRange-ModulusSubtract((
double)
1224 QuantumRange-p->opacity,1.0,(MagickRealType) QuantumRange-q->opacity,1.0);
1225 if ( (channel & RedChannel) != 0 )
1226 composite->red=ModulusSubtract(p->red,1.0,q->red,1.0);
1227 if ( (channel & GreenChannel) != 0 )
1228 composite->green=ModulusSubtract(p->green,1.0,q->green,1.0);
1229 if ( (channel & BlueChannel) != 0 )
1230 composite->blue=ModulusSubtract(p->blue,1.0,q->blue,1.0);
1231 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
1232 composite->index=ModulusSubtract(p->index,1.0,q->index,1.0);
1236static inline MagickRealType Multiply(
const MagickRealType Sca,
1237 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
1239 return(Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-Sa));
1251 Sa=1.0-QuantumScale*p->opacity;
1252 Da=1.0-QuantumScale*q->opacity;
1253 if ( (channel & SyncChannels) != 0 ) {
1254 gamma=RoundToUnity(Sa+Da-Sa*Da);
1255 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1256 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
1257 MagickEpsilon : gamma);
1258 composite->red=gamma*Multiply(QuantumScale*p->red*Sa,Sa,QuantumScale*
1260 composite->green=gamma*Multiply(QuantumScale*p->green*Sa,Sa,QuantumScale*
1262 composite->blue=gamma*Multiply(QuantumScale*p->blue*Sa,Sa,QuantumScale*
1264 if (q->colorspace == CMYKColorspace)
1265 composite->index=gamma*Multiply(QuantumScale*p->index*Sa,Sa,QuantumScale*
1269 if ( (channel & AlphaChannel) != 0 )
1270 composite->opacity=(MagickRealType) QuantumRange*(1.0-Sa*Da);
1271 if ( (channel & RedChannel) != 0 )
1272 composite->red=QuantumScale*p->red*q->red;
1273 if ( (channel & GreenChannel) != 0 )
1274 composite->green=QuantumScale*p->green*q->green;
1275 if ( (channel & BlueChannel) != 0 )
1276 composite->blue=QuantumScale*p->blue*q->blue;
1277 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
1278 composite->index=QuantumScale*p->index*q->index;
1282static inline MagickRealType Out(
const MagickRealType p,
1283 const MagickRealType Sa,
const MagickRealType magick_unused(q),
1284 const MagickRealType Da)
1286 magick_unreferenced(q);
1288 return(Sa*p*(1.0-Da));
1301 Sa=1.0-QuantumScale*p->opacity;
1302 Da=1.0-QuantumScale*q->opacity;
1304 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1305 gamma=PerceptibleReciprocal(gamma);
1306 composite->red=gamma*Out(p->red,Sa,q->red,Da);
1307 composite->green=gamma*Out(p->green,Sa,q->green,Da);
1308 composite->blue=gamma*Out(p->blue,Sa,q->blue,Da);
1309 if (q->colorspace == CMYKColorspace)
1310 composite->index=gamma*Out(p->index,Sa,q->index,Da);
1313static MagickRealType PegtopLight(
const MagickRealType Sca,
1314 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
1324 if (fabs((
double) Da) < MagickEpsilon)
1326 return(Dca*Dca*(Sa-2.0*Sca)*PerceptibleReciprocal(Da)+Sca*(2.0*Dca+1.0-Da)+Dca*(1.0-Sa));
1337 Sa=1.0-QuantumScale*p->opacity;
1338 Da=1.0-QuantumScale*q->opacity;
1339 gamma=RoundToUnity(Sa+Da-Sa*Da);
1340 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1341 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
1342 MagickEpsilon : gamma);
1343 composite->red=gamma*PegtopLight(QuantumScale*p->red*Sa,Sa,QuantumScale*
1345 composite->green=gamma*PegtopLight(QuantumScale*p->green*Sa,Sa,QuantumScale*
1347 composite->blue=gamma*PegtopLight(QuantumScale*p->blue*Sa,Sa,QuantumScale*
1349 if (q->colorspace == CMYKColorspace)
1350 composite->index=gamma*PegtopLight(QuantumScale*p->index*Sa,Sa,QuantumScale*
1354static MagickRealType PinLight(
const MagickRealType Sca,
1355 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
1363 if (Dca*Sa < Da*(2*Sca-Sa))
1364 return(Sca*(Da+1.0)-Sa*Da+Dca*(1.0-Sa));
1365 if ((Dca*Sa) > (2*Sca*Da))
1366 return(Sca*Da+Sca+Dca*(1.0-Sa));
1367 return(Sca*(1.0-Da)+Dca);
1378 Sa=1.0-QuantumScale*p->opacity;
1379 Da=1.0-QuantumScale*q->opacity;
1380 gamma=RoundToUnity(Sa+Da-Sa*Da);
1381 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1382 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
1383 MagickEpsilon : gamma);
1384 composite->red=gamma*PinLight(QuantumScale*p->red*Sa,Sa,QuantumScale*
1386 composite->green=gamma*PinLight(QuantumScale*p->green*Sa,Sa,QuantumScale*
1388 composite->blue=gamma*PinLight(QuantumScale*p->blue*Sa,Sa,QuantumScale*
1390 if (q->colorspace == CMYKColorspace)
1391 composite->index=gamma*PinLight(QuantumScale*p->index*Sa,Sa,QuantumScale*
1395static inline MagickRealType Screen(
const MagickRealType Sca,
1396 const MagickRealType Dca)
1401 return(Sca+Dca-Sca*Dca);
1415 Sa=1.0-QuantumScale*p->opacity;
1416 Da=1.0-QuantumScale*q->opacity;
1417 if ( (channel & SyncChannels) != 0 ) {
1418 gamma=RoundToUnity(Sa+Da-Sa*Da);
1419 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1420 Sa*=(MagickRealType) QuantumScale;
1421 Da*=(MagickRealType) QuantumScale;
1422 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
1423 MagickEpsilon : gamma);
1424 composite->red=gamma*Screen(p->red*Sa,q->red*Da);
1425 composite->green=gamma*Screen(p->green*Sa,q->green*Da);
1426 composite->blue=gamma*Screen(p->blue*Sa,q->blue*Da);
1427 if (q->colorspace == CMYKColorspace)
1428 composite->index=gamma*Screen(p->index*Sa,q->index*Da);
1431 if ( (channel & AlphaChannel) != 0 )
1432 composite->opacity=(MagickRealType) QuantumRange*(1.0-Screen(Sa,Da));
1433 if ( (channel & RedChannel) != 0 )
1434 composite->red=(MagickRealType) QuantumRange*Screen(QuantumScale*p->red,
1435 QuantumScale*q->red);
1436 if ( (channel & GreenChannel) != 0 )
1437 composite->green=(MagickRealType) QuantumRange*Screen(QuantumScale*p->green,
1438 QuantumScale*q->green);
1439 if ( (channel & BlueChannel) != 0 )
1440 composite->blue=(MagickRealType) QuantumRange*Screen(QuantumScale*p->blue,
1441 QuantumScale*q->blue);
1442 if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
1443 composite->index=(MagickRealType) QuantumRange*Screen(QuantumScale*p->index,
1444 QuantumScale*q->index);
1448static MagickRealType SoftLight(
const MagickRealType Sca,
1449 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
1455 alpha=Dca*PerceptibleReciprocal(Da);
1457 return(Dca*(Sa+(2.0*Sca-Sa)*(1.0-alpha))+Sca*(1.0-Da)+Dca*(1.0-Sa));
1458 if (((2.0*Sca) > Sa) && ((4.0*Dca) <= Da))
1460 beta=Dca*Sa+Da*(2.0*Sca-Sa)*(4.0*alpha*(4.0*alpha+1.0)*(alpha-1.0)+7.0*
1461 alpha)+Sca*(1.0-Da)+Dca*(1.0-Sa);
1464 beta=Dca*Sa+Da*(2.0*Sca-Sa)*(pow(alpha,0.5)-alpha)+Sca*(1.0-Da)+Dca*(1.0-Sa);
1476 Sa=1.0-QuantumScale*p->opacity;
1477 Da=1.0-QuantumScale*q->opacity;
1478 gamma=RoundToUnity(Sa+Da-Sa*Da);
1479 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1480 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
1481 MagickEpsilon : gamma);
1482 composite->red=gamma*SoftLight(QuantumScale*p->red*Sa,Sa,QuantumScale*
1484 composite->green=gamma*SoftLight(QuantumScale*p->green*Sa,Sa,QuantumScale*
1486 composite->blue=gamma*SoftLight(QuantumScale*p->blue*Sa,Sa,QuantumScale*
1488 if (q->colorspace == CMYKColorspace)
1489 composite->index=gamma*SoftLight(QuantumScale*p->index*Sa,Sa,QuantumScale*
1499static inline MagickRealType Threshold(
const MagickRealType p,
1500 const MagickRealType q,
const MagickRealType threshold,
1501 const MagickRealType amount)
1507 if ((MagickRealType) fabs((
double) (2.0*delta)) < threshold)
1509 return(q+delta*amount);
1516 composite->red=Threshold(p->red,q->red,threshold,amount);
1517 composite->green=Threshold(p->green,q->green,threshold,amount);
1518 composite->blue=Threshold(p->blue,q->blue,threshold,amount);
1519 composite->opacity=(MagickRealType) QuantumRange-Threshold(p->opacity,
1520 q->opacity,threshold,amount);
1521 if (q->colorspace == CMYKColorspace)
1522 composite->index=Threshold(p->index,q->index,threshold,amount);
1525static MagickRealType VividLight(
const MagickRealType Sca,
1526 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
1534 if ((fabs((
double) Sa) < MagickEpsilon) ||
1535 (fabs((
double) (Sca-Sa)) < MagickEpsilon))
1536 return(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
1538 return(Sa*(Da+Sa*(Dca-Da)*PerceptibleReciprocal(2.0*Sca))+Sca*(1.0-Da)+
1540 return(Dca*Sa*Sa*PerceptibleReciprocal(2.0*(Sa-Sca))+Sca*(1.0-Da)+Dca*
1552 Sa=1.0-QuantumScale*p->opacity;
1553 Da=1.0-QuantumScale*q->opacity;
1554 gamma=RoundToUnity(Sa+Da-Sa*Da);
1555 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1556 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
1557 MagickEpsilon : gamma);
1558 composite->red=gamma*VividLight(QuantumScale*p->red*Sa,Sa,QuantumScale*
1560 composite->green=gamma*VividLight(QuantumScale*p->green*Sa,Sa,QuantumScale*
1562 composite->blue=gamma*VividLight(QuantumScale*p->blue*Sa,Sa,QuantumScale*
1564 if (q->colorspace == CMYKColorspace)
1565 composite->index=gamma*VividLight(QuantumScale*p->index*Sa,Sa,QuantumScale*
1569static MagickRealType Xor(
const MagickRealType Sca,
const MagickRealType Sa,
1570 const MagickRealType Dca,
const MagickRealType Da)
1572 return(Sca*(1.0-Da)+Dca*(1.0-Sa));
1583 Sa=1.0-QuantumScale*p->opacity;
1584 Da=1.0-QuantumScale*q->opacity;
1585 gamma=Sa+Da-2*Sa*Da;
1586 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1587 gamma=PerceptibleReciprocal(gamma);
1588 composite->red=gamma*Xor(p->red*Sa,Sa,q->red*Da,Da);
1589 composite->green=gamma*Xor(p->green*Sa,Sa,q->green*Da,Da);
1590 composite->blue=gamma*Xor(p->blue*Sa,Sa,q->blue*Da,Da);
1591 if (q->colorspace == CMYKColorspace)
1592 composite->index=gamma*Xor(p->index*Sa,Sa,q->index*Da,Da);
1595MagickExport MagickBooleanType CompositeImage(
Image *image,
1596 const CompositeOperator compose,
const Image *source_image,
1597 const ssize_t x_offset,
const ssize_t y_offset)
1602 status=CompositeImageChannel(image,DefaultChannels,compose,source_image,
1607MagickExport MagickBooleanType CompositeImageChannel(
Image *image,
1608 const ChannelType channel,
const CompositeOperator compose,
1609 const Image *composite,
const ssize_t x_offset,
const ssize_t y_offset)
1611#define CompositeImageTag "Composite/Image"
1659 assert(image != (
Image *) NULL);
1660 assert(image->signature == MagickCoreSignature);
1661 assert(composite != (
Image *) NULL);
1662 assert(composite->signature == MagickCoreSignature);
1663 if (IsEventLogging() != MagickFalse)
1664 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1665 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1666 return(MagickFalse);
1667 exception=(&image->exception);
1668 source_image=CloneImage(composite,0,0,MagickTrue,exception);
1669 if (source_image == (
const Image *) NULL)
1670 return(MagickFalse);
1671 (void) SetImageColorspace(source_image,image->colorspace);
1672 GetMagickPixelPacket(image,&zero);
1673 canvas_image=(
Image *) NULL;
1675 canvas_dissolve=1.0;
1676 clip_to_self=MagickTrue;
1678 percent_chroma=100.0;
1679 source_dissolve=1.0;
1683 case ClearCompositeOp:
1684 case SrcCompositeOp:
1686 case SrcInCompositeOp:
1687 case OutCompositeOp:
1688 case SrcOutCompositeOp:
1689 case DstInCompositeOp:
1690 case DstAtopCompositeOp:
1695 clip_to_self=MagickFalse;
1698 case OverCompositeOp:
1700 if (image->matte != MagickFalse)
1702 if (source_image->matte != MagickFalse)
1706 case CopyCompositeOp:
1708 if ((x_offset < 0) || (y_offset < 0))
1710 if ((x_offset+(ssize_t) source_image->columns) >= (ssize_t) image->columns)
1712 if ((y_offset+(ssize_t) source_image->rows) >= (ssize_t) image->rows)
1715 source_view=AcquireVirtualCacheView(source_image,exception);
1716 image_view=AcquireAuthenticCacheView(image,exception);
1717#if defined(MAGICKCORE_OPENMP_SUPPORT)
1718 #pragma omp parallel for schedule(static) shared(status) \
1719 magick_number_threads(source_image,image,source_image->rows,4)
1721 for (y=0; y < (ssize_t) source_image->rows; y++)
1738 if (status == MagickFalse)
1740 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,
1742 q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
1743 source_image->columns,1,exception);
1749 source_indexes=GetCacheViewVirtualIndexQueue(source_view);
1750 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1751 (void) memcpy(q,p,source_image->columns*
sizeof(*p));
1752 if ((indexes != (IndexPacket *) NULL) &&
1753 (source_indexes != (
const IndexPacket *) NULL))
1754 (void) memcpy(indexes,source_indexes,
1755 source_image->columns*
sizeof(*indexes));
1756 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1757 if (sync == MagickFalse)
1759 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1764 proceed=SetImageProgress(image,CompositeImageTag,(MagickOffsetType)
1766 if (proceed == MagickFalse)
1770 source_view=DestroyCacheView(source_view);
1771 image_view=DestroyCacheView(image_view);
1772 source_image=DestroyImage(source_image);
1775 case CopyOpacityCompositeOp:
1776 case ChangeMaskCompositeOp:
1782 if (image->matte == MagickFalse)
1783 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1784 clip_to_self=MagickFalse;
1787 case BlurCompositeOp:
1814 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1815 if (canvas_image == (
Image *) NULL)
1817 source_image=DestroyImage(source_image);
1818 return(MagickFalse);
1823 SetGeometryInfo(&geometry_info);
1825 value=GetImageArtifact(image,
"compose:args");
1826 if (value != (
char *) NULL)
1827 flags=ParseGeometry(value,&geometry_info);
1828 if ((flags & WidthValue) == 0)
1830 (void) ThrowMagickException(exception,GetMagickModule(),
1831 OptionWarning,
"InvalidGeometry",
"'%s' '%s'",
"compose:args",value);
1832 source_image=DestroyImage(source_image);
1833 canvas_image=DestroyImage(canvas_image);
1834 return(MagickFalse);
1841 width=height=geometry_info.rho*2.0;
1842 if ((flags & HeightValue) != 0 )
1843 height=geometry_info.sigma*2.0;
1851 if ((flags & XValue) != 0 )
1856 angle=DegreesToRadians(geometry_info.xi);
1857 blur.x1=width*cos(angle);
1858 blur.x2=width*sin(angle);
1859 blur.y1=(-height*sin(angle));
1860 blur.y2=height*cos(angle);
1865 if ((flags & YValue) != 0 )
1867 angle_start=DegreesToRadians(geometry_info.xi);
1868 angle_range=DegreesToRadians(geometry_info.psi)-angle_start;
1881 resample_filter=AcquireResampleFilter(image,exception);
1882 SetResampleFilter(resample_filter,GaussianFilter,1.0);
1886 source_view=AcquireVirtualCacheView(source_image,exception);
1887 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
1888 for (y=0; y < (ssize_t) source_image->rows; y++)
1900 *magick_restrict canvas_indexes;
1905 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
1907 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,
1909 r=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,
1913 canvas_indexes=GetCacheViewAuthenticIndexQueue(canvas_view);
1914 for (x=0; x < (ssize_t) source_image->columns; x++)
1916 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
1921 if (fabs((
double) angle_range) > MagickEpsilon)
1926 angle=angle_start+angle_range*QuantumScale*(double)
1928 blur.x1=width*cos(angle);
1929 blur.x2=width*sin(angle);
1930 blur.y1=(-height*sin(angle));
1931 blur.y2=height*cos(angle);
1934 if ( x == 10 && y == 60 ) {
1935 fprintf(stderr,
"blur.x=%lf,%lf, blur.y=%lf,%lf\n",
1936 blur.x1, blur.x2, blur.y1, blur.y2);
1937 fprintf(stderr,
"scaled by=%lf,%lf\n",
1938 QuantumScale*GetPixelRed(p), QuantumScale*GetPixelGreen(p));
1941 ScaleResampleFilter(resample_filter,
1942 blur.x1*QuantumScale*(
double) GetPixelRed(p),
1943 blur.y1*QuantumScale*(
double) GetPixelGreen(p),
1944 blur.x2*QuantumScale*(
double) GetPixelRed(p),
1945 blur.y2*QuantumScale*(
double) GetPixelGreen(p));
1946 (void) ResamplePixelColor(resample_filter,(
double) x_offset+x,(
double)
1948 SetPixelPacket(canvas_image,&pixel,r,canvas_indexes+x);
1952 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
1953 if (sync == MagickFalse)
1956 resample_filter=DestroyResampleFilter(resample_filter);
1957 source_view=DestroyCacheView(source_view);
1958 canvas_view=DestroyCacheView(canvas_view);
1959 source_image=DestroyImage(source_image);
1960 source_image=canvas_image;
1963 case DisplaceCompositeOp:
1964 case DistortCompositeOp:
1983 *magick_restrict canvas_indexes;
1993 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1994 if (canvas_image == (
Image *) NULL)
1996 source_image=DestroyImage(source_image);
1997 return(MagickFalse);
1999 SetGeometryInfo(&geometry_info);
2001 value=GetImageArtifact(image,
"compose:args");
2002 if (value != (
char *) NULL)
2003 flags=ParseGeometry(value,&geometry_info);
2004 if ((flags & (WidthValue | HeightValue)) == 0 )
2006 if ((flags & AspectValue) == 0)
2008 horizontal_scale=(MagickRealType) (source_image->columns-1)/2.0;
2009 vertical_scale=(MagickRealType) (source_image->rows-1)/2.0;
2013 horizontal_scale=(MagickRealType) (image->columns-1)/2.0;
2014 vertical_scale=(MagickRealType) (image->rows-1)/2.0;
2019 horizontal_scale=geometry_info.rho;
2020 vertical_scale=geometry_info.sigma;
2021 if ((flags & PercentValue) != 0)
2023 if ((flags & AspectValue) == 0)
2025 horizontal_scale*=(source_image->columns-1)/200.0;
2026 vertical_scale*=(source_image->rows-1)/200.0;
2030 horizontal_scale*=(image->columns-1)/200.0;
2031 vertical_scale*=(image->rows-1)/200.0;
2034 if ((flags & HeightValue) == 0)
2035 vertical_scale=horizontal_scale;
2045 center.x=(MagickRealType) x_offset;
2046 center.y=(MagickRealType) y_offset;
2047 if (compose == DistortCompositeOp)
2049 if ((flags & XValue) == 0)
2050 if ((flags & AspectValue) != 0)
2051 center.x=((MagickRealType) image->columns-1)/2.0;
2053 center.x=(MagickRealType) (x_offset+(source_image->columns-1)/
2056 if ((flags & AspectValue) == 0)
2057 center.x=(MagickRealType) (x_offset+geometry_info.xi);
2059 center.x=geometry_info.xi;
2060 if ((flags & YValue) == 0)
2061 if ((flags & AspectValue) != 0)
2062 center.y=((MagickRealType) image->rows-1)/2.0;
2064 center.y=(MagickRealType) (y_offset+(source_image->rows-1)/2.0);
2066 if ((flags & AspectValue) != 0)
2067 center.y=geometry_info.psi;
2069 center.y=(MagickRealType) (y_offset+geometry_info.psi);
2076 image_view=AcquireVirtualCacheView(image,exception);
2077 source_view=AcquireVirtualCacheView(source_image,exception);
2078 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
2079 for (y=0; y < (ssize_t) source_image->rows; y++)
2090 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
2092 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,
2094 r=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,
2098 canvas_indexes=GetCacheViewAuthenticIndexQueue(canvas_view);
2099 for (x=0; x < (ssize_t) source_image->columns; x++)
2101 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
2109 offset.x=(double) ((horizontal_scale*((MagickRealType) GetPixelRed(p)-
2110 (((MagickRealType) QuantumRange+1.0)/2.0)))/(((MagickRealType)
2111 QuantumRange+1.0)/2.0)+center.x+((compose == DisplaceCompositeOp) ?
2113 offset.y=(double) ((vertical_scale*((MagickRealType) GetPixelGreen(p)-
2114 (((MagickRealType) QuantumRange+1.0)/2.0)))/(((MagickRealType)
2115 QuantumRange+1.0)/2.0)+center.y+((compose == DisplaceCompositeOp) ?
2117 status=InterpolateMagickPixelPacket(image,image_view,
2118 UndefinedInterpolatePixel,(
double) offset.x,(
double) offset.y,
2120 if (status == MagickFalse)
2125 pixel.opacity=(MagickRealType) QuantumRange*(1.0-(1.0-QuantumScale*
2126 pixel.opacity)*(1.0-QuantumScale*(
double) GetPixelOpacity(p)));
2127 SetPixelPacket(canvas_image,&pixel,r,canvas_indexes+x);
2131 if (x < (ssize_t) source_image->columns)
2133 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
2134 if (sync == MagickFalse)
2137 canvas_view=DestroyCacheView(canvas_view);
2138 source_view=DestroyCacheView(source_view);
2139 image_view=DestroyCacheView(image_view);
2140 source_image=DestroyImage(source_image);
2141 source_image=canvas_image;
2144 case DissolveCompositeOp:
2149 value=GetImageArtifact(image,
"compose:args");
2150 if (value != (
char *) NULL)
2152 flags=ParseGeometry(value,&geometry_info);
2153 source_dissolve=geometry_info.rho/100.0;
2154 canvas_dissolve=1.0;
2155 if ((source_dissolve-MagickEpsilon) < 0.0)
2156 source_dissolve=0.0;
2157 if ((source_dissolve+MagickEpsilon) > 1.0)
2159 canvas_dissolve=2.0-source_dissolve;
2160 source_dissolve=1.0;
2162 if ((flags & SigmaValue) != 0)
2163 canvas_dissolve=geometry_info.sigma/100.0;
2164 if ((canvas_dissolve-MagickEpsilon) < 0.0)
2165 canvas_dissolve=0.0;
2166 clip_to_self=MagickFalse;
2167 if ((canvas_dissolve+MagickEpsilon) > 1.0 )
2169 canvas_dissolve=1.0;
2170 clip_to_self=MagickTrue;
2175 case BlendCompositeOp:
2177 value=GetImageArtifact(image,
"compose:args");
2178 if (value != (
char *) NULL)
2180 flags=ParseGeometry(value,&geometry_info);
2181 source_dissolve=geometry_info.rho/100.0;
2182 canvas_dissolve=1.0-source_dissolve;
2183 if ((flags & SigmaValue) != 0)
2184 canvas_dissolve=geometry_info.sigma/100.0;
2185 clip_to_self=MagickFalse;
2186 if ((canvas_dissolve+MagickEpsilon) > 1.0)
2187 clip_to_self=MagickTrue;
2191 case MathematicsCompositeOp:
2201 SetGeometryInfo(&geometry_info);
2202 value=GetImageArtifact(image,
"compose:args");
2203 if (value != (
char *) NULL)
2205 flags=ParseGeometry(value,&geometry_info);
2206 if (flags == NoValue)
2207 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2208 "InvalidGeometry",
"`%s'",value);
2212 case ModulateCompositeOp:
2217 value=GetImageArtifact(image,
"compose:args");
2218 if (value != (
char *) NULL)
2220 flags=ParseGeometry(value,&geometry_info);
2221 percent_luma=geometry_info.rho;
2222 if ((flags & SigmaValue) != 0)
2223 percent_chroma=geometry_info.sigma;
2227 case ThresholdCompositeOp:
2233 value=GetImageArtifact(image,
"compose:args");
2234 if (value != (
char *) NULL)
2236 flags=ParseGeometry(value,&geometry_info);
2237 amount=geometry_info.rho;
2238 threshold=geometry_info.sigma;
2239 if ((flags & SigmaValue) == 0)
2242 threshold*=(double) QuantumRange;
2248 value=GetImageArtifact(image,
"compose:outside-overlay");
2249 if (value != (
const char *) NULL)
2250 clip_to_self=IsMagickTrue(value) == MagickFalse ? MagickTrue : MagickFalse;
2251 value=GetImageArtifact(image,
"compose:clip-to-self");
2252 if (value != (
const char *) NULL)
2253 clip_to_self=IsMagickTrue(value) != MagickFalse ? MagickTrue : MagickFalse;
2255 value=GetImageArtifact(image,
"compose:clamp");
2256 if (value != (
const char *) NULL)
2257 clamp=IsMagickTrue(value);
2261#if defined(MAGICKCORE_OPENCL_SUPPORT)
2262 status=AccelerateCompositeImage(image,channel,compose,source_image,
2263 x_offset,y_offset,canvas_dissolve,source_dissolve,exception);
2264 if (status != MagickFalse)
2269 midpoint=((MagickRealType) QuantumRange+1.0)/2;
2270 GetMagickPixelPacket(source_image,&zero);
2271 source_view=AcquireVirtualCacheView(source_image,exception);
2272 image_view=AcquireAuthenticCacheView(image,exception);
2273#if defined(MAGICKCORE_OPENMP_SUPPORT)
2274 #pragma omp parallel for schedule(static) shared(progress,status) \
2275 magick_number_threads(source_image,image,image->rows,1)
2277 for (y=0; y < (ssize_t) image->rows; y++)
2294 *magick_restrict source_indexes;
2300 *magick_restrict indexes;
2308 if (status == MagickFalse)
2310 if (clip_to_self != MagickFalse)
2314 if ((y-(
double) y_offset) >= (
double) source_image->rows)
2322 if ((y >= y_offset) &&
2323 ((y-(
double) y_offset) < (
double) source_image->rows))
2325 p=GetCacheViewVirtualPixels(source_view,0,
2326 CastDoubleToLong(y-(
double) y_offset),source_image->columns,1,
2335 p-=(ptrdiff_t)x_offset;
2337 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2343 indexes=GetCacheViewAuthenticIndexQueue(image_view);
2344 source_indexes=GetCacheViewVirtualIndexQueue(source_view);
2345 GetMagickPixelPacket(source_image,&source);
2346 GetMagickPixelPacket(image,&canvas);
2350 for (x=0; x < (ssize_t) image->columns; x++)
2352 if (clip_to_self != MagickFalse)
2359 if ((x-(
double) x_offset) >= (
double) source_image->columns)
2362 canvas.red=(MagickRealType) GetPixelRed(q);
2363 canvas.green=(MagickRealType) GetPixelGreen(q);
2364 canvas.blue=(MagickRealType) GetPixelBlue(q);
2365 if (image->matte != MagickFalse)
2366 canvas.opacity=(MagickRealType) GetPixelOpacity(q);
2367 if (image->colorspace == CMYKColorspace)
2368 canvas.index=(MagickRealType) GetPixelIndex(indexes+x);
2369 if (image->colorspace == CMYKColorspace)
2371 canvas.red=(MagickRealType) QuantumRange-canvas.red;
2372 canvas.green=(MagickRealType) QuantumRange-canvas.green;
2373 canvas.blue=(MagickRealType) QuantumRange-canvas.blue;
2374 canvas.index=(MagickRealType) QuantumRange-canvas.index;
2380 if ((pixels == (
PixelPacket *) NULL) || (x < x_offset) ||
2381 ((x-(
double) x_offset) >= (
double) source_image->columns))
2385 case DissolveCompositeOp:
2386 case BlendCompositeOp:
2388 composite.opacity=(MagickRealType) ((MagickRealType) QuantumRange-
2389 canvas_dissolve*((MagickRealType) QuantumRange-
2390 composite.opacity));
2393 case ClearCompositeOp:
2394 case SrcCompositeOp:
2396 CompositeClear(&canvas,&composite);
2400 case SrcInCompositeOp:
2401 case OutCompositeOp:
2402 case SrcOutCompositeOp:
2403 case DstInCompositeOp:
2404 case DstAtopCompositeOp:
2405 case CopyOpacityCompositeOp:
2406 case ChangeMaskCompositeOp:
2408 composite.opacity=(MagickRealType) TransparentOpacity;
2413 (void) GetOneVirtualMagickPixel(source_image,
2414 CastDoubleToLong(x-(
double) x_offset),
2415 CastDoubleToLong(y-(
double) y_offset),&composite,exception);
2419 if (image->colorspace == CMYKColorspace)
2421 composite.red=(MagickRealType) QuantumRange-composite.red;
2422 composite.green=(MagickRealType) QuantumRange-composite.green;
2423 composite.blue=(MagickRealType) QuantumRange-composite.blue;
2424 composite.index=(MagickRealType) QuantumRange-composite.index;
2426 SetPixelRed(q,clamp != MagickFalse ?
2427 ClampPixel(composite.red) : ClampToQuantum(composite.red));
2428 SetPixelGreen(q,clamp != MagickFalse ?
2429 ClampPixel(composite.green) : ClampToQuantum(composite.green));
2430 SetPixelBlue(q,clamp != MagickFalse ?
2431 ClampPixel(composite.blue) : ClampToQuantum(composite.blue));
2432 if (image->matte != MagickFalse)
2433 SetPixelOpacity(q,clamp != MagickFalse ?
2434 ClampPixel(composite.opacity) :
2435 ClampToQuantum(composite.opacity));
2436 if (image->colorspace == CMYKColorspace)
2437 SetPixelIndex(indexes+x,clamp != MagickFalse ?
2438 ClampPixel(composite.index) : ClampToQuantum(composite.index));
2445 source.red=(MagickRealType) GetPixelRed(p);
2446 source.green=(MagickRealType) GetPixelGreen(p);
2447 source.blue=(MagickRealType) GetPixelBlue(p);
2448 if (source_image->matte != MagickFalse)
2449 source.opacity=(MagickRealType) GetPixelOpacity(p);
2450 if (source_image->colorspace == CMYKColorspace)
2451 source.index=(MagickRealType) GetPixelIndex(source_indexes+
2452 CastDoubleToLong(x-(
double) x_offset));
2453 if (source_image->colorspace == CMYKColorspace)
2455 source.red=(MagickRealType) QuantumRange-source.red;
2456 source.green=(MagickRealType) QuantumRange-source.green;
2457 source.blue=(MagickRealType) QuantumRange-source.blue;
2458 source.index=(MagickRealType) QuantumRange-source.index;
2463 case ClearCompositeOp:
2465 CompositeClear(&canvas,&composite);
2468 case SrcCompositeOp:
2469 case CopyCompositeOp:
2470 case ReplaceCompositeOp:
2476 case DstCompositeOp:
2478 case OverCompositeOp:
2479 case SrcOverCompositeOp:
2481 MagickPixelCompositeOver(&source,source.opacity,&canvas,
2482 canvas.opacity,&composite);
2485 case DstOverCompositeOp:
2487 MagickPixelCompositeOver(&canvas,canvas.opacity,&source,
2488 source.opacity,&composite);
2491 case SrcInCompositeOp:
2494 CompositeIn(&source,&canvas,&composite);
2497 case DstInCompositeOp:
2499 CompositeIn(&canvas,&source,&composite);
2502 case OutCompositeOp:
2503 case SrcOutCompositeOp:
2505 CompositeOut(&source,&canvas,&composite);
2508 case DstOutCompositeOp:
2510 CompositeOut(&canvas,&source,&composite);
2513 case AtopCompositeOp:
2514 case SrcAtopCompositeOp:
2516 CompositeAtop(&source,&canvas,&composite);
2519 case DstAtopCompositeOp:
2521 CompositeAtop(&canvas,&source,&composite);
2524 case XorCompositeOp:
2526 CompositeXor(&source,&canvas,&composite);
2530 case PlusCompositeOp:
2532 CompositePlus(&source,&canvas,channel,&composite);
2535 case MinusDstCompositeOp:
2537 CompositeMinus(&source,&canvas,channel,&composite);
2540 case MinusSrcCompositeOp:
2542 CompositeMinus(&canvas,&source,channel,&composite);
2545 case ModulusAddCompositeOp:
2547 CompositeModulusAdd(&source,&canvas,channel,&composite);
2550 case ModulusSubtractCompositeOp:
2552 CompositeModulusSubtract(&source,&canvas,channel,&composite);
2555 case DifferenceCompositeOp:
2557 CompositeDifference(&source,&canvas,channel,&composite);
2560 case ExclusionCompositeOp:
2562 CompositeExclusion(&source,&canvas,channel,&composite);
2565 case MultiplyCompositeOp:
2567 CompositeMultiply(&source,&canvas,channel,&composite);
2570 case ScreenCompositeOp:
2572 CompositeScreen(&source,&canvas,channel,&composite);
2575 case DivideDstCompositeOp:
2577 CompositeDivide(&source,&canvas,channel,&composite);
2580 case DivideSrcCompositeOp:
2582 CompositeDivide(&canvas,&source,channel,&composite);
2585 case DarkenCompositeOp:
2587 CompositeDarken(&source,&canvas,channel,&composite);
2590 case LightenCompositeOp:
2592 CompositeLighten(&source,&canvas,channel,&composite);
2595 case DarkenIntensityCompositeOp:
2597 CompositeDarkenIntensity(&source,&canvas,channel,&composite);
2600 case LightenIntensityCompositeOp:
2602 CompositeLightenIntensity(&source,&canvas,channel,&composite);
2605 case MathematicsCompositeOp:
2607 CompositeMathematics(&source,&canvas,channel,&geometry_info,
2612 case ColorDodgeCompositeOp:
2614 CompositeColorDodge(&source,&canvas,&composite);
2617 case ColorBurnCompositeOp:
2619 CompositeColorBurn(&source,&canvas,&composite);
2622 case LinearDodgeCompositeOp:
2624 CompositeLinearDodge(&source,&canvas,&composite);
2627 case LinearBurnCompositeOp:
2629 CompositeLinearBurn(&source,&canvas,&composite);
2632 case HardLightCompositeOp:
2634 CompositeHardLight(&source,&canvas,&composite);
2637 case HardMixCompositeOp:
2639 CompositeHardMix(&source,&canvas,&composite);
2642 case OverlayCompositeOp:
2645 CompositeHardLight(&canvas,&source,&composite);
2648 case SoftLightCompositeOp:
2650 CompositeSoftLight(&source,&canvas,&composite);
2653 case LinearLightCompositeOp:
2655 CompositeLinearLight(&source,&canvas,&composite);
2658 case PegtopLightCompositeOp:
2660 CompositePegtopLight(&source,&canvas,&composite);
2663 case VividLightCompositeOp:
2665 CompositeVividLight(&source,&canvas,&composite);
2668 case PinLightCompositeOp:
2670 CompositePinLight(&source,&canvas,&composite);
2674 case ChangeMaskCompositeOp:
2676 if ((composite.opacity > ((MagickRealType) QuantumRange/2.0)) ||
2677 (IsMagickColorSimilar(&source,&canvas) != MagickFalse))
2678 composite.opacity=(MagickRealType) TransparentOpacity;
2680 composite.opacity=(MagickRealType) OpaqueOpacity;
2683 case BumpmapCompositeOp:
2685 if (source.opacity == (MagickRealType) TransparentOpacity)
2687 CompositeBumpmap(&source,&canvas,&composite);
2690 case DissolveCompositeOp:
2692 MagickPixelCompositeOver(&source,(MagickRealType) QuantumRange-
2693 source_dissolve*((MagickRealType) QuantumRange-source.opacity),
2694 &canvas,(MagickRealType) QuantumRange-canvas_dissolve*
2695 ((MagickRealType) QuantumRange-canvas.opacity),&composite);
2698 case BlendCompositeOp:
2700 MagickPixelCompositeBlend(&source,source_dissolve,&canvas,
2701 canvas_dissolve,&composite);
2704 case StereoCompositeOp:
2706 composite.red=(MagickRealType) GetPixelRed(p);
2707 composite.opacity=(composite.opacity+canvas.opacity/2);
2710 case ThresholdCompositeOp:
2712 CompositeThreshold(&source,&canvas,threshold,amount,&composite);
2715 case ModulateCompositeOp:
2720 if (source.opacity == (MagickRealType) TransparentOpacity)
2722 offset=(ssize_t) ((MagickRealType) MagickPixelIntensityToQuantum(
2723 &source)-(MagickRealType) midpoint);
2726 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2728 luma+=(0.01*percent_luma*offset)/midpoint;
2729 chroma*=0.01*percent_chroma;
2730 HCLComposite(hue,chroma,luma,&composite.red,&composite.green,
2734 case HueCompositeOp:
2736 if (source.opacity == (MagickRealType) TransparentOpacity)
2738 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2743 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2745 CompositeHCL(source.red,source.green,source.blue,&hue,&sans,&sans);
2746 HCLComposite(hue,chroma,luma,&composite.red,
2747 &composite.green,&composite.blue);
2748 if (source.opacity < canvas.opacity)
2749 composite.opacity=source.opacity;
2752 case SaturateCompositeOp:
2754 if (source.opacity == (MagickRealType) TransparentOpacity)
2756 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2761 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2763 CompositeHCL(source.red,source.green,source.blue,&sans,&chroma,
2765 HCLComposite(hue,chroma,luma,&composite.red,
2766 &composite.green,&composite.blue);
2767 if (source.opacity < canvas.opacity)
2768 composite.opacity=source.opacity;
2771 case LuminizeCompositeOp:
2773 if (source.opacity == (MagickRealType) TransparentOpacity)
2775 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2780 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2782 CompositeHCL(source.red,source.green,source.blue,&sans,&sans,
2784 HCLComposite(hue,chroma,luma,&composite.red,
2785 &composite.green,&composite.blue);
2786 if (source.opacity < canvas.opacity)
2787 composite.opacity=source.opacity;
2790 case ColorizeCompositeOp:
2792 if (source.opacity == (MagickRealType) TransparentOpacity)
2794 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2799 CompositeHCL(canvas.red,canvas.green,canvas.blue,&sans,
2801 CompositeHCL(source.red,source.green,source.blue,&hue,&chroma,&sans);
2802 HCLComposite(hue,chroma,luma,&composite.red,
2803 &composite.green,&composite.blue);
2804 if (source.opacity < canvas.opacity)
2805 composite.opacity=source.opacity;
2808 case CopyRedCompositeOp:
2809 case CopyCyanCompositeOp:
2811 composite.red=source.red;
2814 case CopyGreenCompositeOp:
2815 case CopyMagentaCompositeOp:
2817 composite.green=source.green;
2820 case CopyBlueCompositeOp:
2821 case CopyYellowCompositeOp:
2823 composite.blue=source.blue;
2826 case CopyOpacityCompositeOp:
2828 if (source.matte == MagickFalse)
2829 composite.opacity=(MagickRealType) (QuantumRange-
2830 MagickPixelIntensityToQuantum(&source));
2832 composite.opacity=source.opacity;
2835 case CopyBlackCompositeOp:
2837 if (source.colorspace != CMYKColorspace)
2838 ConvertRGBToCMYK(&source);
2839 composite.index=source.index;
2843 case BlurCompositeOp:
2844 case DisplaceCompositeOp:
2845 case DistortCompositeOp:
2853 if (image->colorspace == CMYKColorspace)
2855 composite.red=(MagickRealType) QuantumRange-composite.red;
2856 composite.green=(MagickRealType) QuantumRange-composite.green;
2857 composite.blue=(MagickRealType) QuantumRange-composite.blue;
2858 composite.index=(MagickRealType) QuantumRange-composite.index;
2860 SetPixelRed(q,clamp != MagickFalse ?
2861 ClampPixel(composite.red) : ClampToQuantum(composite.red));
2862 SetPixelGreen(q,clamp != MagickFalse ?
2863 ClampPixel(composite.green) : ClampToQuantum(composite.green));
2864 SetPixelBlue(q,clamp != MagickFalse ?
2865 ClampPixel(composite.blue) : ClampToQuantum(composite.blue));
2866 SetPixelOpacity(q,clamp != MagickFalse ?
2867 ClampPixel(composite.opacity) : ClampToQuantum(composite.opacity));
2868 if (image->colorspace == CMYKColorspace)
2869 SetPixelIndex(indexes+x,clamp != MagickFalse ?
2870 ClampPixel(composite.index) : ClampToQuantum(composite.index));
2872 if (p >= (pixels+source_image->columns))
2876 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2878 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2883#if defined(MAGICKCORE_OPENMP_SUPPORT)
2887 proceed=SetImageProgress(image,CompositeImageTag,progress,image->rows);
2888 if (proceed == MagickFalse)
2892 source_view=DestroyCacheView(source_view);
2893 image_view=DestroyCacheView(image_view);
2894 if (canvas_image != (
Image * ) NULL)
2895 canvas_image=DestroyImage(canvas_image);
2897 source_image=DestroyImage(source_image);
2926MagickExport MagickBooleanType TextureImage(
Image *image,
const Image *texture)
2928#define TextureImageTag "Texture/Image"
2946 assert(image != (
Image *) NULL);
2947 assert(image->signature == MagickCoreSignature);
2948 if (IsEventLogging() != MagickFalse)
2949 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
2950 if (texture == (
const Image *) NULL)
2951 return(MagickFalse);
2952 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2953 return(MagickFalse);
2954 exception=(&image->exception);
2955 texture_image=CloneImage(texture,0,0,MagickTrue,exception);
2956 if (texture_image == (
const Image *) NULL)
2957 return(MagickFalse);
2958 (void) TransformImageColorspace(texture_image,image->colorspace);
2959 (void) SetImageVirtualPixelMethod(texture_image,TileVirtualPixelMethod);
2961 if ((image->compose != CopyCompositeOp) &&
2962 ((image->compose != OverCompositeOp) || (image->matte != MagickFalse) ||
2963 (texture_image->matte != MagickFalse)))
2968 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) texture_image->rows)
2973 if (status == MagickFalse)
2975 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
2980 thread_status=CompositeImage(image,image->compose,texture_image,x+
2981 texture_image->tile_offset.x,y+texture_image->tile_offset.y);
2982 if (thread_status == MagickFalse)
2984 status=thread_status;
2988 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2993 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType)
2995 if (proceed == MagickFalse)
2999 (void) SetImageProgress(image,TextureImageTag,(MagickOffsetType)
3000 image->rows,image->rows);
3001 texture_image=DestroyImage(texture_image);
3008 texture_view=AcquireVirtualCacheView(texture_image,exception);
3009 image_view=AcquireAuthenticCacheView(image,exception);
3010#if defined(MAGICKCORE_OPENMP_SUPPORT)
3011 #pragma omp parallel for schedule(static) shared(status) \
3012 magick_number_threads(image,texture_image,image->rows,2)
3014 for (y=0; y < (ssize_t) image->rows; y++)
3037 if (status == MagickFalse)
3039 p=GetCacheViewVirtualPixels(texture_view,texture_image->tile_offset.x,(y+
3040 texture_image->tile_offset.y) % texture_image->rows,
3041 texture_image->columns,1,exception);
3042 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3049 texture_indexes=GetCacheViewVirtualIndexQueue(texture_view);
3050 indexes=GetCacheViewAuthenticIndexQueue(image_view);
3051 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
3053 width=texture_image->columns;
3054 if ((x+(ssize_t) width) > (ssize_t) image->columns)
3055 width=image->columns-x;
3056 (void) memcpy(q,p,width*
sizeof(*p));
3057 if ((image->colorspace == CMYKColorspace) &&
3058 (texture_image->colorspace == CMYKColorspace))
3060 (void) memcpy(indexes,texture_indexes,width*
3064 q+=(ptrdiff_t) width;
3066 sync=SyncCacheViewAuthenticPixels(image_view,exception);
3067 if (sync == MagickFalse)
3069 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3074 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
3076 if (proceed == MagickFalse)
3080 texture_view=DestroyCacheView(texture_view);
3081 image_view=DestroyCacheView(image_view);
3082 texture_image=DestroyImage(texture_image);