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"
57 #include "magick/fx.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"
192 static 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;
246 static 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*
287 static 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*
349 static 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;
427 static 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));
473 static 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);
538 static 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);
588 static 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*
621 static 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);
651 static 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);
716 static 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);
755 static 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);
785 static 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;
864 static 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);
899 static 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*
936 static 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*
980 static 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;
1091 static 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;
1143 static 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);
1190 static 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);
1236 static 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;
1282 static 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);
1313 static 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*
1354 static 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*
1395 static 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);
1448 static 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*
1499 static 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,q->opacity,
1521 if (q->colorspace == CMYKColorspace)
1522 composite->index=Threshold(p->index,q->index,threshold,amount);
1526 static MagickRealType VividLight(
const MagickRealType Sca,
1527 const MagickRealType Sa,
const MagickRealType Dca,
const MagickRealType Da)
1535 if ((fabs((
double) Sa) < MagickEpsilon) ||
1536 (fabs((
double) (Sca-Sa)) < MagickEpsilon))
1537 return(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
1539 return(Sa*(Da+Sa*(Dca-Da)*PerceptibleReciprocal(2.0*Sca))+Sca*(1.0-Da)+
1541 return(Dca*Sa*Sa*PerceptibleReciprocal(2.0*(Sa-Sca))+Sca*(1.0-Da)+Dca*
1553 Sa=1.0-QuantumScale*p->opacity;
1554 Da=1.0-QuantumScale*q->opacity;
1555 gamma=RoundToUnity(Sa+Da-Sa*Da);
1556 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1557 gamma=(MagickRealType) QuantumRange/(fabs((
double) gamma) < MagickEpsilon ?
1558 MagickEpsilon : gamma);
1559 composite->red=gamma*VividLight(QuantumScale*p->red*Sa,Sa,QuantumScale*
1561 composite->green=gamma*VividLight(QuantumScale*p->green*Sa,Sa,QuantumScale*
1563 composite->blue=gamma*VividLight(QuantumScale*p->blue*Sa,Sa,QuantumScale*
1565 if (q->colorspace == CMYKColorspace)
1566 composite->index=gamma*VividLight(QuantumScale*p->index*Sa,Sa,QuantumScale*
1570 static MagickRealType Xor(
const MagickRealType Sca,
const MagickRealType Sa,
1571 const MagickRealType Dca,
const MagickRealType Da)
1573 return(Sca*(1.0-Da)+Dca*(1.0-Sa));
1584 Sa=1.0-QuantumScale*p->opacity;
1585 Da=1.0-QuantumScale*q->opacity;
1586 gamma=Sa+Da-2*Sa*Da;
1587 composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
1588 gamma=PerceptibleReciprocal(gamma);
1589 composite->red=gamma*Xor(p->red*Sa,Sa,q->red*Da,Da);
1590 composite->green=gamma*Xor(p->green*Sa,Sa,q->green*Da,Da);
1591 composite->blue=gamma*Xor(p->blue*Sa,Sa,q->blue*Da,Da);
1592 if (q->colorspace == CMYKColorspace)
1593 composite->index=gamma*Xor(p->index*Sa,Sa,q->index*Da,Da);
1596 MagickExport MagickBooleanType CompositeImage(
Image *image,
1597 const CompositeOperator compose,
const Image *source_image,
1598 const ssize_t x_offset,
const ssize_t y_offset)
1603 status=CompositeImageChannel(image,DefaultChannels,compose,source_image,
1608 MagickExport MagickBooleanType CompositeImageChannel(
Image *image,
1609 const ChannelType channel,
const CompositeOperator compose,
1610 const Image *composite,
const ssize_t x_offset,
const ssize_t y_offset)
1612 #define CompositeImageTag "Composite/Image"
1660 assert(image != (
Image *) NULL);
1661 assert(image->signature == MagickCoreSignature);
1662 assert(composite != (
Image *) NULL);
1663 assert(composite->signature == MagickCoreSignature);
1664 if (IsEventLogging() != MagickFalse)
1665 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1666 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1667 return(MagickFalse);
1668 exception=(&image->exception);
1669 source_image=CloneImage(composite,0,0,MagickTrue,exception);
1670 if (source_image == (
const Image *) NULL)
1671 return(MagickFalse);
1672 (void) SetImageColorspace(source_image,image->colorspace);
1673 GetMagickPixelPacket(image,&zero);
1674 canvas_image=(
Image *) NULL;
1676 canvas_dissolve=1.0;
1677 clip_to_self=MagickTrue;
1679 percent_chroma=100.0;
1680 source_dissolve=1.0;
1684 case ClearCompositeOp:
1685 case SrcCompositeOp:
1687 case SrcInCompositeOp:
1688 case OutCompositeOp:
1689 case SrcOutCompositeOp:
1690 case DstInCompositeOp:
1691 case DstAtopCompositeOp:
1696 clip_to_self=MagickFalse;
1699 case OverCompositeOp:
1701 if (image->matte != MagickFalse)
1703 if (source_image->matte != MagickFalse)
1707 case CopyCompositeOp:
1709 if ((x_offset < 0) || (y_offset < 0))
1711 if ((x_offset+(ssize_t) source_image->columns) >= (ssize_t) image->columns)
1713 if ((y_offset+(ssize_t) source_image->rows) >= (ssize_t) image->rows)
1716 source_view=AcquireVirtualCacheView(source_image,exception);
1717 image_view=AcquireAuthenticCacheView(image,exception);
1718 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1719 #pragma omp parallel for schedule(static) shared(status) \
1720 magick_number_threads(source_image,image,source_image->rows,1)
1722 for (y=0; y < (ssize_t) source_image->rows; y++)
1739 if (status == MagickFalse)
1741 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,
1743 q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
1744 source_image->columns,1,exception);
1750 source_indexes=GetCacheViewVirtualIndexQueue(source_view);
1751 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1752 (void) memcpy(q,p,source_image->columns*
sizeof(*p));
1753 if ((indexes != (IndexPacket *) NULL) &&
1754 (source_indexes != (
const IndexPacket *) NULL))
1755 (
void) memcpy(indexes,source_indexes,
1756 source_image->columns*
sizeof(*indexes));
1757 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1758 if (sync == MagickFalse)
1760 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1765 proceed=SetImageProgress(image,CompositeImageTag,(MagickOffsetType)
1767 if (proceed == MagickFalse)
1771 source_view=DestroyCacheView(source_view);
1772 image_view=DestroyCacheView(image_view);
1773 source_image=DestroyImage(source_image);
1776 case CopyOpacityCompositeOp:
1777 case ChangeMaskCompositeOp:
1783 if (image->matte == MagickFalse)
1784 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1785 clip_to_self=MagickFalse;
1788 case BlurCompositeOp:
1815 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1816 if (canvas_image == (
Image *) NULL)
1818 source_image=DestroyImage(source_image);
1819 return(MagickFalse);
1824 SetGeometryInfo(&geometry_info);
1826 value=GetImageArtifact(image,
"compose:args");
1827 if (value != (
char *) NULL)
1828 flags=ParseGeometry(value,&geometry_info);
1829 if ((flags & WidthValue) == 0)
1831 (void) ThrowMagickException(exception,GetMagickModule(),
1832 OptionWarning,
"InvalidGeometry",
"'%s' '%s'",
"compose:args",value);
1833 source_image=DestroyImage(source_image);
1834 canvas_image=DestroyImage(canvas_image);
1835 return(MagickFalse);
1842 width=height=geometry_info.rho*2.0;
1843 if ((flags & HeightValue) != 0 )
1844 height=geometry_info.sigma*2.0;
1852 if ((flags & XValue) != 0 )
1857 angle=DegreesToRadians(geometry_info.xi);
1858 blur.x1=width*cos(angle);
1859 blur.x2=width*sin(angle);
1860 blur.y1=(-height*sin(angle));
1861 blur.y2=height*cos(angle);
1866 if ((flags & YValue) != 0 )
1868 angle_start=DegreesToRadians(geometry_info.xi);
1869 angle_range=DegreesToRadians(geometry_info.psi)-angle_start;
1882 resample_filter=AcquireResampleFilter(image,exception);
1883 SetResampleFilter(resample_filter,GaussianFilter,1.0);
1887 source_view=AcquireVirtualCacheView(source_image,exception);
1888 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
1889 for (y=0; y < (ssize_t) source_image->rows; y++)
1901 *magick_restrict canvas_indexes;
1906 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
1908 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,
1910 r=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,
1914 canvas_indexes=GetCacheViewAuthenticIndexQueue(canvas_view);
1915 for (x=0; x < (ssize_t) source_image->columns; x++)
1917 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
1922 if (fabs((
double) angle_range) > MagickEpsilon)
1927 angle=angle_start+angle_range*QuantumScale*(double)
1929 blur.x1=width*cos(angle);
1930 blur.x2=width*sin(angle);
1931 blur.y1=(-height*sin(angle));
1932 blur.y2=height*cos(angle);
1935 if ( x == 10 && y == 60 ) {
1936 fprintf(stderr,
"blur.x=%lf,%lf, blur.y=%lf,%lf\n",
1937 blur.x1, blur.x2, blur.y1, blur.y2);
1938 fprintf(stderr,
"scaled by=%lf,%lf\n",
1939 QuantumScale*GetPixelRed(p), QuantumScale*GetPixelGreen(p));
1942 ScaleResampleFilter(resample_filter,
1943 blur.x1*QuantumScale*(
double) GetPixelRed(p),
1944 blur.y1*QuantumScale*(
double) GetPixelGreen(p),
1945 blur.x2*QuantumScale*(
double) GetPixelRed(p),
1946 blur.y2*QuantumScale*(
double) GetPixelGreen(p));
1947 (void) ResamplePixelColor(resample_filter,(
double) x_offset+x,(double)
1949 SetPixelPacket(canvas_image,&pixel,r,canvas_indexes+x);
1953 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
1954 if (sync == MagickFalse)
1957 resample_filter=DestroyResampleFilter(resample_filter);
1958 source_view=DestroyCacheView(source_view);
1959 canvas_view=DestroyCacheView(canvas_view);
1960 source_image=DestroyImage(source_image);
1961 source_image=canvas_image;
1964 case DisplaceCompositeOp:
1965 case DistortCompositeOp:
1984 *magick_restrict canvas_indexes;
1994 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1995 if (canvas_image == (
Image *) NULL)
1997 source_image=DestroyImage(source_image);
1998 return(MagickFalse);
2000 SetGeometryInfo(&geometry_info);
2002 value=GetImageArtifact(image,
"compose:args");
2003 if (value != (
char *) NULL)
2004 flags=ParseGeometry(value,&geometry_info);
2005 if ((flags & (WidthValue | HeightValue)) == 0 )
2007 if ((flags & AspectValue) == 0)
2009 horizontal_scale=(MagickRealType) (source_image->columns-1)/2.0;
2010 vertical_scale=(MagickRealType) (source_image->rows-1)/2.0;
2014 horizontal_scale=(MagickRealType) (image->columns-1)/2.0;
2015 vertical_scale=(MagickRealType) (image->rows-1)/2.0;
2020 horizontal_scale=geometry_info.rho;
2021 vertical_scale=geometry_info.sigma;
2022 if ((flags & PercentValue) != 0)
2024 if ((flags & AspectValue) == 0)
2026 horizontal_scale*=(source_image->columns-1)/200.0;
2027 vertical_scale*=(source_image->rows-1)/200.0;
2031 horizontal_scale*=(image->columns-1)/200.0;
2032 vertical_scale*=(image->rows-1)/200.0;
2035 if ((flags & HeightValue) == 0)
2036 vertical_scale=horizontal_scale;
2046 center.x=(MagickRealType) x_offset;
2047 center.y=(MagickRealType) y_offset;
2048 if (compose == DistortCompositeOp)
2050 if ((flags & XValue) == 0)
2051 if ((flags & AspectValue) != 0)
2052 center.x=((MagickRealType) image->columns-1)/2.0;
2054 center.x=(MagickRealType) (x_offset+(source_image->columns-1)/
2057 if ((flags & AspectValue) == 0)
2058 center.x=(MagickRealType) (x_offset+geometry_info.xi);
2060 center.x=geometry_info.xi;
2061 if ((flags & YValue) == 0)
2062 if ((flags & AspectValue) != 0)
2063 center.y=((MagickRealType) image->rows-1)/2.0;
2065 center.y=(MagickRealType) (y_offset+(source_image->rows-1)/2.0);
2067 if ((flags & AspectValue) != 0)
2068 center.y=geometry_info.psi;
2070 center.y=(MagickRealType) (y_offset+geometry_info.psi);
2077 image_view=AcquireVirtualCacheView(image,exception);
2078 source_view=AcquireVirtualCacheView(source_image,exception);
2079 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
2080 for (y=0; y < (ssize_t) source_image->rows; y++)
2091 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
2093 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,
2095 r=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,
2099 canvas_indexes=GetCacheViewAuthenticIndexQueue(canvas_view);
2100 for (x=0; x < (ssize_t) source_image->columns; x++)
2102 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
2110 offset.x=(double) ((horizontal_scale*((MagickRealType) GetPixelRed(p)-
2111 (((MagickRealType) QuantumRange+1.0)/2.0)))/(((MagickRealType)
2112 QuantumRange+1.0)/2.0)+center.x+((compose == DisplaceCompositeOp) ?
2114 offset.y=(double) ((vertical_scale*((MagickRealType) GetPixelGreen(p)-
2115 (((MagickRealType) QuantumRange+1.0)/2.0)))/(((MagickRealType)
2116 QuantumRange+1.0)/2.0)+center.y+((compose == DisplaceCompositeOp) ?
2118 status=InterpolateMagickPixelPacket(image,image_view,
2119 UndefinedInterpolatePixel,(
double) offset.x,(
double) offset.y,
2121 if (status == MagickFalse)
2126 pixel.opacity=(MagickRealType) QuantumRange*(1.0-(1.0-QuantumScale*
2127 pixel.opacity)*(1.0-QuantumScale*(double) GetPixelOpacity(p)));
2128 SetPixelPacket(canvas_image,&pixel,r,canvas_indexes+x);
2132 if (x < (ssize_t) source_image->columns)
2134 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
2135 if (sync == MagickFalse)
2138 canvas_view=DestroyCacheView(canvas_view);
2139 source_view=DestroyCacheView(source_view);
2140 image_view=DestroyCacheView(image_view);
2141 source_image=DestroyImage(source_image);
2142 source_image=canvas_image;
2145 case DissolveCompositeOp:
2150 value=GetImageArtifact(image,
"compose:args");
2151 if (value != (
char *) NULL)
2153 flags=ParseGeometry(value,&geometry_info);
2154 source_dissolve=geometry_info.rho/100.0;
2155 canvas_dissolve=1.0;
2156 if ((source_dissolve-MagickEpsilon) < 0.0)
2157 source_dissolve=0.0;
2158 if ((source_dissolve+MagickEpsilon) > 1.0)
2160 canvas_dissolve=2.0-source_dissolve;
2161 source_dissolve=1.0;
2163 if ((flags & SigmaValue) != 0)
2164 canvas_dissolve=geometry_info.sigma/100.0;
2165 if ((canvas_dissolve-MagickEpsilon) < 0.0)
2166 canvas_dissolve=0.0;
2167 clip_to_self=MagickFalse;
2168 if ((canvas_dissolve+MagickEpsilon) > 1.0 )
2170 canvas_dissolve=1.0;
2171 clip_to_self=MagickTrue;
2176 case BlendCompositeOp:
2178 value=GetImageArtifact(image,
"compose:args");
2179 if (value != (
char *) NULL)
2181 flags=ParseGeometry(value,&geometry_info);
2182 source_dissolve=geometry_info.rho/100.0;
2183 canvas_dissolve=1.0-source_dissolve;
2184 if ((flags & SigmaValue) != 0)
2185 canvas_dissolve=geometry_info.sigma/100.0;
2186 clip_to_self=MagickFalse;
2187 if ((canvas_dissolve+MagickEpsilon) > 1.0)
2188 clip_to_self=MagickTrue;
2192 case MathematicsCompositeOp:
2202 SetGeometryInfo(&geometry_info);
2203 value=GetImageArtifact(image,
"compose:args");
2204 if (value != (
char *) NULL)
2206 flags=ParseGeometry(value,&geometry_info);
2207 if (flags == NoValue)
2208 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2209 "InvalidGeometry",
"`%s'",value);
2213 case ModulateCompositeOp:
2218 value=GetImageArtifact(image,
"compose:args");
2219 if (value != (
char *) NULL)
2221 flags=ParseGeometry(value,&geometry_info);
2222 percent_luma=geometry_info.rho;
2223 if ((flags & SigmaValue) != 0)
2224 percent_chroma=geometry_info.sigma;
2228 case ThresholdCompositeOp:
2234 value=GetImageArtifact(image,
"compose:args");
2235 if (value != (
char *) NULL)
2237 flags=ParseGeometry(value,&geometry_info);
2238 amount=geometry_info.rho;
2239 threshold=geometry_info.sigma;
2240 if ((flags & SigmaValue) == 0)
2243 threshold*=(double) QuantumRange;
2249 value=GetImageArtifact(image,
"compose:outside-overlay");
2250 if (value != (
const char *) NULL)
2251 clip_to_self=IsMagickTrue(value) == MagickFalse ? MagickTrue : MagickFalse;
2252 value=GetImageArtifact(image,
"compose:clip-to-self");
2253 if (value != (
const char *) NULL)
2254 clip_to_self=IsMagickTrue(value) != MagickFalse ? MagickTrue : MagickFalse;
2256 value=GetImageArtifact(image,
"compose:clamp");
2257 if (value != (
const char *) NULL)
2258 clamp=IsMagickTrue(value);
2262 #if defined(MAGICKCORE_OPENCL_SUPPORT)
2263 status=AccelerateCompositeImage(image,channel,compose,source_image,
2264 x_offset,y_offset,canvas_dissolve,source_dissolve,exception);
2265 if (status != MagickFalse)
2270 midpoint=((MagickRealType) QuantumRange+1.0)/2;
2271 GetMagickPixelPacket(source_image,&zero);
2272 source_view=AcquireVirtualCacheView(source_image,exception);
2273 image_view=AcquireAuthenticCacheView(image,exception);
2274 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2275 #pragma omp parallel for schedule(static) shared(progress,status) \
2276 magick_number_threads(source_image,image,image->rows,1)
2278 for (y=0; y < (ssize_t) image->rows; y++)
2295 *magick_restrict source_indexes;
2301 *magick_restrict indexes;
2309 if (status == MagickFalse)
2311 if (clip_to_self != MagickFalse)
2315 if ((y-(
double) y_offset) >= (double) source_image->rows)
2323 if ((y >= y_offset) &&
2324 ((y-(double) y_offset) < (double) source_image->rows))
2326 p=GetCacheViewVirtualPixels(source_view,0,
2327 CastDoubleToLong(y-(
double) y_offset),source_image->columns,1,
2338 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2344 indexes=GetCacheViewAuthenticIndexQueue(image_view);
2345 source_indexes=GetCacheViewVirtualIndexQueue(source_view);
2346 GetMagickPixelPacket(source_image,&source);
2347 GetMagickPixelPacket(image,&canvas);
2351 for (x=0; x < (ssize_t) image->columns; x++)
2353 if (clip_to_self != MagickFalse)
2360 if ((x-(
double) x_offset) >= (double) source_image->columns)
2363 canvas.red=(MagickRealType) GetPixelRed(q);
2364 canvas.green=(MagickRealType) GetPixelGreen(q);
2365 canvas.blue=(MagickRealType) GetPixelBlue(q);
2366 if (image->matte != MagickFalse)
2367 canvas.opacity=(MagickRealType) GetPixelOpacity(q);
2368 if (image->colorspace == CMYKColorspace)
2369 canvas.index=(MagickRealType) GetPixelIndex(indexes+x);
2370 if (image->colorspace == CMYKColorspace)
2372 canvas.red=(MagickRealType) QuantumRange-canvas.red;
2373 canvas.green=(MagickRealType) QuantumRange-canvas.green;
2374 canvas.blue=(MagickRealType) QuantumRange-canvas.blue;
2375 canvas.index=(MagickRealType) QuantumRange-canvas.index;
2381 if ((pixels == (
PixelPacket *) NULL) || (x < x_offset) ||
2382 ((x-(double) x_offset) >= (double) source_image->columns))
2386 case DissolveCompositeOp:
2387 case BlendCompositeOp:
2389 composite.opacity=(MagickRealType) ((MagickRealType) QuantumRange-
2390 canvas_dissolve*((MagickRealType) QuantumRange-
2391 composite.opacity));
2394 case ClearCompositeOp:
2395 case SrcCompositeOp:
2397 CompositeClear(&canvas,&composite);
2401 case SrcInCompositeOp:
2402 case OutCompositeOp:
2403 case SrcOutCompositeOp:
2404 case DstInCompositeOp:
2405 case DstAtopCompositeOp:
2406 case CopyOpacityCompositeOp:
2407 case ChangeMaskCompositeOp:
2409 composite.opacity=(MagickRealType) TransparentOpacity;
2414 (void) GetOneVirtualMagickPixel(source_image,
2415 CastDoubleToLong(x-(
double) x_offset),
2416 CastDoubleToLong(y-(
double) y_offset),&composite,exception);
2420 if (image->colorspace == CMYKColorspace)
2422 composite.red=(MagickRealType) QuantumRange-composite.red;
2423 composite.green=(MagickRealType) QuantumRange-composite.green;
2424 composite.blue=(MagickRealType) QuantumRange-composite.blue;
2425 composite.index=(MagickRealType) QuantumRange-composite.index;
2427 SetPixelRed(q,clamp != MagickFalse ?
2428 ClampPixel(composite.red) : ClampToQuantum(composite.red));
2429 SetPixelGreen(q,clamp != MagickFalse ?
2430 ClampPixel(composite.green) : ClampToQuantum(composite.green));
2431 SetPixelBlue(q,clamp != MagickFalse ?
2432 ClampPixel(composite.blue) : ClampToQuantum(composite.blue));
2433 if (image->matte != MagickFalse)
2434 SetPixelOpacity(q,clamp != MagickFalse ?
2435 ClampPixel(composite.opacity) :
2436 ClampToQuantum(composite.opacity));
2437 if (image->colorspace == CMYKColorspace)
2438 SetPixelIndex(indexes+x,clamp != MagickFalse ?
2439 ClampPixel(composite.index) : ClampToQuantum(composite.index));
2446 source.red=(MagickRealType) GetPixelRed(p);
2447 source.green=(MagickRealType) GetPixelGreen(p);
2448 source.blue=(MagickRealType) GetPixelBlue(p);
2449 if (source_image->matte != MagickFalse)
2450 source.opacity=(MagickRealType) GetPixelOpacity(p);
2451 if (source_image->colorspace == CMYKColorspace)
2452 source.index=(MagickRealType) GetPixelIndex(source_indexes+
2453 CastDoubleToLong(x-(
double) x_offset));
2454 if (source_image->colorspace == CMYKColorspace)
2456 source.red=(MagickRealType) QuantumRange-source.red;
2457 source.green=(MagickRealType) QuantumRange-source.green;
2458 source.blue=(MagickRealType) QuantumRange-source.blue;
2459 source.index=(MagickRealType) QuantumRange-source.index;
2464 case ClearCompositeOp:
2466 CompositeClear(&canvas,&composite);
2469 case SrcCompositeOp:
2470 case CopyCompositeOp:
2471 case ReplaceCompositeOp:
2477 case DstCompositeOp:
2479 case OverCompositeOp:
2480 case SrcOverCompositeOp:
2482 MagickPixelCompositeOver(&source,source.opacity,&canvas,
2483 canvas.opacity,&composite);
2486 case DstOverCompositeOp:
2488 MagickPixelCompositeOver(&canvas,canvas.opacity,&source,
2489 source.opacity,&composite);
2492 case SrcInCompositeOp:
2495 CompositeIn(&source,&canvas,&composite);
2498 case DstInCompositeOp:
2500 CompositeIn(&canvas,&source,&composite);
2503 case OutCompositeOp:
2504 case SrcOutCompositeOp:
2506 CompositeOut(&source,&canvas,&composite);
2509 case DstOutCompositeOp:
2511 CompositeOut(&canvas,&source,&composite);
2514 case AtopCompositeOp:
2515 case SrcAtopCompositeOp:
2517 CompositeAtop(&source,&canvas,&composite);
2520 case DstAtopCompositeOp:
2522 CompositeAtop(&canvas,&source,&composite);
2525 case XorCompositeOp:
2527 CompositeXor(&source,&canvas,&composite);
2531 case PlusCompositeOp:
2533 CompositePlus(&source,&canvas,channel,&composite);
2536 case MinusDstCompositeOp:
2538 CompositeMinus(&source,&canvas,channel,&composite);
2541 case MinusSrcCompositeOp:
2543 CompositeMinus(&canvas,&source,channel,&composite);
2546 case ModulusAddCompositeOp:
2548 CompositeModulusAdd(&source,&canvas,channel,&composite);
2551 case ModulusSubtractCompositeOp:
2553 CompositeModulusSubtract(&source,&canvas,channel,&composite);
2556 case DifferenceCompositeOp:
2558 CompositeDifference(&source,&canvas,channel,&composite);
2561 case ExclusionCompositeOp:
2563 CompositeExclusion(&source,&canvas,channel,&composite);
2566 case MultiplyCompositeOp:
2568 CompositeMultiply(&source,&canvas,channel,&composite);
2571 case ScreenCompositeOp:
2573 CompositeScreen(&source,&canvas,channel,&composite);
2576 case DivideDstCompositeOp:
2578 CompositeDivide(&source,&canvas,channel,&composite);
2581 case DivideSrcCompositeOp:
2583 CompositeDivide(&canvas,&source,channel,&composite);
2586 case DarkenCompositeOp:
2588 CompositeDarken(&source,&canvas,channel,&composite);
2591 case LightenCompositeOp:
2593 CompositeLighten(&source,&canvas,channel,&composite);
2596 case DarkenIntensityCompositeOp:
2598 CompositeDarkenIntensity(&source,&canvas,channel,&composite);
2601 case LightenIntensityCompositeOp:
2603 CompositeLightenIntensity(&source,&canvas,channel,&composite);
2606 case MathematicsCompositeOp:
2608 CompositeMathematics(&source,&canvas,channel,&geometry_info,
2613 case ColorDodgeCompositeOp:
2615 CompositeColorDodge(&source,&canvas,&composite);
2618 case ColorBurnCompositeOp:
2620 CompositeColorBurn(&source,&canvas,&composite);
2623 case LinearDodgeCompositeOp:
2625 CompositeLinearDodge(&source,&canvas,&composite);
2628 case LinearBurnCompositeOp:
2630 CompositeLinearBurn(&source,&canvas,&composite);
2633 case HardLightCompositeOp:
2635 CompositeHardLight(&source,&canvas,&composite);
2638 case HardMixCompositeOp:
2640 CompositeHardMix(&source,&canvas,&composite);
2643 case OverlayCompositeOp:
2646 CompositeHardLight(&canvas,&source,&composite);
2649 case SoftLightCompositeOp:
2651 CompositeSoftLight(&source,&canvas,&composite);
2654 case LinearLightCompositeOp:
2656 CompositeLinearLight(&source,&canvas,&composite);
2659 case PegtopLightCompositeOp:
2661 CompositePegtopLight(&source,&canvas,&composite);
2664 case VividLightCompositeOp:
2666 CompositeVividLight(&source,&canvas,&composite);
2669 case PinLightCompositeOp:
2671 CompositePinLight(&source,&canvas,&composite);
2675 case ChangeMaskCompositeOp:
2677 if ((composite.opacity > ((MagickRealType) QuantumRange/2.0)) ||
2678 (IsMagickColorSimilar(&source,&canvas) != MagickFalse))
2679 composite.opacity=(MagickRealType) TransparentOpacity;
2681 composite.opacity=(MagickRealType) OpaqueOpacity;
2684 case BumpmapCompositeOp:
2686 if (source.opacity == (MagickRealType) TransparentOpacity)
2688 CompositeBumpmap(&source,&canvas,&composite);
2691 case DissolveCompositeOp:
2693 MagickPixelCompositeOver(&source,(MagickRealType) QuantumRange-
2694 source_dissolve*((MagickRealType) QuantumRange-source.opacity),
2695 &canvas,(MagickRealType) QuantumRange-canvas_dissolve*
2696 ((MagickRealType) QuantumRange-canvas.opacity),&composite);
2699 case BlendCompositeOp:
2701 MagickPixelCompositeBlend(&source,source_dissolve,&canvas,
2702 canvas_dissolve,&composite);
2705 case StereoCompositeOp:
2707 composite.red=(MagickRealType) GetPixelRed(p);
2708 composite.opacity=(composite.opacity+canvas.opacity/2);
2711 case ThresholdCompositeOp:
2713 CompositeThreshold(&source,&canvas,threshold,amount,&composite);
2716 case ModulateCompositeOp:
2721 if (source.opacity == (MagickRealType) TransparentOpacity)
2723 offset=(ssize_t) ((MagickRealType) MagickPixelIntensityToQuantum(
2724 &source)-(MagickRealType) midpoint);
2727 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2729 luma+=(0.01*percent_luma*offset)/midpoint;
2730 chroma*=0.01*percent_chroma;
2731 HCLComposite(hue,chroma,luma,&composite.red,&composite.green,
2735 case HueCompositeOp:
2737 if (source.opacity == (MagickRealType) TransparentOpacity)
2739 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2744 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2746 CompositeHCL(source.red,source.green,source.blue,&hue,&sans,&sans);
2747 HCLComposite(hue,chroma,luma,&composite.red,
2748 &composite.green,&composite.blue);
2749 if (source.opacity < canvas.opacity)
2750 composite.opacity=source.opacity;
2753 case SaturateCompositeOp:
2755 if (source.opacity == (MagickRealType) TransparentOpacity)
2757 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2762 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2764 CompositeHCL(source.red,source.green,source.blue,&sans,&chroma,
2766 HCLComposite(hue,chroma,luma,&composite.red,
2767 &composite.green,&composite.blue);
2768 if (source.opacity < canvas.opacity)
2769 composite.opacity=source.opacity;
2772 case LuminizeCompositeOp:
2774 if (source.opacity == (MagickRealType) TransparentOpacity)
2776 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2781 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2783 CompositeHCL(source.red,source.green,source.blue,&sans,&sans,
2785 HCLComposite(hue,chroma,luma,&composite.red,
2786 &composite.green,&composite.blue);
2787 if (source.opacity < canvas.opacity)
2788 composite.opacity=source.opacity;
2791 case ColorizeCompositeOp:
2793 if (source.opacity == (MagickRealType) TransparentOpacity)
2795 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2800 CompositeHCL(canvas.red,canvas.green,canvas.blue,&sans,
2802 CompositeHCL(source.red,source.green,source.blue,&hue,&chroma,&sans);
2803 HCLComposite(hue,chroma,luma,&composite.red,
2804 &composite.green,&composite.blue);
2805 if (source.opacity < canvas.opacity)
2806 composite.opacity=source.opacity;
2809 case CopyRedCompositeOp:
2810 case CopyCyanCompositeOp:
2812 composite.red=source.red;
2815 case CopyGreenCompositeOp:
2816 case CopyMagentaCompositeOp:
2818 composite.green=source.green;
2821 case CopyBlueCompositeOp:
2822 case CopyYellowCompositeOp:
2824 composite.blue=source.blue;
2827 case CopyOpacityCompositeOp:
2829 if (source.matte == MagickFalse)
2830 composite.opacity=(MagickRealType) (QuantumRange-
2831 MagickPixelIntensityToQuantum(&source));
2833 composite.opacity=source.opacity;
2836 case CopyBlackCompositeOp:
2838 if (source.colorspace != CMYKColorspace)
2839 ConvertRGBToCMYK(&source);
2840 composite.index=source.index;
2844 case BlurCompositeOp:
2845 case DisplaceCompositeOp:
2846 case DistortCompositeOp:
2854 if (image->colorspace == CMYKColorspace)
2856 composite.red=(MagickRealType) QuantumRange-composite.red;
2857 composite.green=(MagickRealType) QuantumRange-composite.green;
2858 composite.blue=(MagickRealType) QuantumRange-composite.blue;
2859 composite.index=(MagickRealType) QuantumRange-composite.index;
2861 SetPixelRed(q,clamp != MagickFalse ?
2862 ClampPixel(composite.red) : ClampToQuantum(composite.red));
2863 SetPixelGreen(q,clamp != MagickFalse ?
2864 ClampPixel(composite.green) : ClampToQuantum(composite.green));
2865 SetPixelBlue(q,clamp != MagickFalse ?
2866 ClampPixel(composite.blue) : ClampToQuantum(composite.blue));
2867 SetPixelOpacity(q,clamp != MagickFalse ?
2868 ClampPixel(composite.opacity) : ClampToQuantum(composite.opacity));
2869 if (image->colorspace == CMYKColorspace)
2870 SetPixelIndex(indexes+x,clamp != MagickFalse ?
2871 ClampPixel(composite.index) : ClampToQuantum(composite.index));
2873 if (p >= (pixels+source_image->columns))
2877 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2879 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2884 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2888 proceed=SetImageProgress(image,CompositeImageTag,progress,image->rows);
2889 if (proceed == MagickFalse)
2893 source_view=DestroyCacheView(source_view);
2894 image_view=DestroyCacheView(image_view);
2895 if (canvas_image != (
Image * ) NULL)
2896 canvas_image=DestroyImage(canvas_image);
2898 source_image=DestroyImage(source_image);
2927 MagickExport MagickBooleanType TextureImage(
Image *image,
const Image *texture)
2929 #define TextureImageTag "Texture/Image"
2947 assert(image != (
Image *) NULL);
2948 assert(image->signature == MagickCoreSignature);
2949 if (IsEventLogging() != MagickFalse)
2950 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
2951 if (texture == (
const Image *) NULL)
2952 return(MagickFalse);
2953 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2954 return(MagickFalse);
2955 exception=(&image->exception);
2956 texture_image=CloneImage(texture,0,0,MagickTrue,exception);
2957 if (texture_image == (
const Image *) NULL)
2958 return(MagickFalse);
2959 (void) TransformImageColorspace(texture_image,image->colorspace);
2960 (void) SetImageVirtualPixelMethod(texture_image,TileVirtualPixelMethod);
2962 if ((image->compose != CopyCompositeOp) &&
2963 ((image->compose != OverCompositeOp) || (image->matte != MagickFalse) ||
2964 (texture_image->matte != MagickFalse)))
2969 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) texture_image->rows)
2974 if (status == MagickFalse)
2976 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
2981 thread_status=CompositeImage(image,image->compose,texture_image,x+
2982 texture_image->tile_offset.x,y+texture_image->tile_offset.y);
2983 if (thread_status == MagickFalse)
2985 status=thread_status;
2989 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2994 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType)
2996 if (proceed == MagickFalse)
3000 (void) SetImageProgress(image,TextureImageTag,(MagickOffsetType)
3001 image->rows,image->rows);
3002 texture_image=DestroyImage(texture_image);
3009 texture_view=AcquireVirtualCacheView(texture_image,exception);
3010 image_view=AcquireAuthenticCacheView(image,exception);
3011 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3012 #pragma omp parallel for schedule(static) shared(status) \
3013 magick_number_threads(image,texture_image,image->rows,1)
3015 for (y=0; y < (ssize_t) image->rows; y++)
3038 if (status == MagickFalse)
3040 p=GetCacheViewVirtualPixels(texture_view,texture_image->tile_offset.x,(y+
3041 texture_image->tile_offset.y) % texture_image->rows,
3042 texture_image->columns,1,exception);
3043 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3050 texture_indexes=GetCacheViewVirtualIndexQueue(texture_view);
3051 indexes=GetCacheViewAuthenticIndexQueue(image_view);
3052 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
3054 width=texture_image->columns;
3055 if ((x+(ssize_t) width) > (ssize_t) image->columns)
3056 width=image->columns-x;
3057 (void) memcpy(q,p,width*
sizeof(*p));
3058 if ((image->colorspace == CMYKColorspace) &&
3059 (texture_image->colorspace == CMYKColorspace))
3061 (void) memcpy(indexes,texture_indexes,width*
3067 sync=SyncCacheViewAuthenticPixels(image_view,exception);
3068 if (sync == MagickFalse)
3070 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3075 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
3077 if (proceed == MagickFalse)
3081 texture_view=DestroyCacheView(texture_view);
3082 image_view=DestroyCacheView(image_view);
3083 texture_image=DestroyImage(texture_image);