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-y_offset) >= (ssize_t) source_image->rows)
2323 if ((y >= y_offset) && ((y-y_offset) < (ssize_t) source_image->rows))
2325 p=GetCacheViewVirtualPixels(source_view,0,y-y_offset,
2326 source_image->columns,1,exception);
2336 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2342 indexes=GetCacheViewAuthenticIndexQueue(image_view);
2343 source_indexes=GetCacheViewVirtualIndexQueue(source_view);
2344 GetMagickPixelPacket(source_image,&source);
2345 GetMagickPixelPacket(image,&canvas);
2349 for (x=0; x < (ssize_t) image->columns; x++)
2351 if (clip_to_self != MagickFalse)
2358 if ((x-x_offset) >= (ssize_t) source_image->columns)
2361 canvas.red=(MagickRealType) GetPixelRed(q);
2362 canvas.green=(MagickRealType) GetPixelGreen(q);
2363 canvas.blue=(MagickRealType) GetPixelBlue(q);
2364 if (image->matte != MagickFalse)
2365 canvas.opacity=(MagickRealType) GetPixelOpacity(q);
2366 if (image->colorspace == CMYKColorspace)
2367 canvas.index=(MagickRealType) GetPixelIndex(indexes+x);
2368 if (image->colorspace == CMYKColorspace)
2370 canvas.red=(MagickRealType) QuantumRange-canvas.red;
2371 canvas.green=(MagickRealType) QuantumRange-canvas.green;
2372 canvas.blue=(MagickRealType) QuantumRange-canvas.blue;
2373 canvas.index=(MagickRealType) QuantumRange-canvas.index;
2379 if ((pixels == (
PixelPacket *) NULL) || (x < x_offset) ||
2380 ((x-x_offset) >= (ssize_t) source_image->columns))
2384 case DissolveCompositeOp:
2385 case BlendCompositeOp:
2387 composite.opacity=(MagickRealType) ((MagickRealType) QuantumRange-
2388 canvas_dissolve*((MagickRealType) QuantumRange-
2389 composite.opacity));
2392 case ClearCompositeOp:
2393 case SrcCompositeOp:
2395 CompositeClear(&canvas,&composite);
2399 case SrcInCompositeOp:
2400 case OutCompositeOp:
2401 case SrcOutCompositeOp:
2402 case DstInCompositeOp:
2403 case DstAtopCompositeOp:
2404 case CopyOpacityCompositeOp:
2405 case ChangeMaskCompositeOp:
2407 composite.opacity=(MagickRealType) TransparentOpacity;
2412 (void) GetOneVirtualMagickPixel(source_image,x-x_offset,
2413 y-y_offset,&composite,exception);
2417 if (image->colorspace == CMYKColorspace)
2419 composite.red=(MagickRealType) QuantumRange-composite.red;
2420 composite.green=(MagickRealType) QuantumRange-composite.green;
2421 composite.blue=(MagickRealType) QuantumRange-composite.blue;
2422 composite.index=(MagickRealType) QuantumRange-composite.index;
2424 SetPixelRed(q,clamp != MagickFalse ?
2425 ClampPixel(composite.red) : ClampToQuantum(composite.red));
2426 SetPixelGreen(q,clamp != MagickFalse ?
2427 ClampPixel(composite.green) : ClampToQuantum(composite.green));
2428 SetPixelBlue(q,clamp != MagickFalse ?
2429 ClampPixel(composite.blue) : ClampToQuantum(composite.blue));
2430 if (image->matte != MagickFalse)
2431 SetPixelOpacity(q,clamp != MagickFalse ?
2432 ClampPixel(composite.opacity) :
2433 ClampToQuantum(composite.opacity));
2434 if (image->colorspace == CMYKColorspace)
2435 SetPixelIndex(indexes+x,clamp != MagickFalse ?
2436 ClampPixel(composite.index) : ClampToQuantum(composite.index));
2443 source.red=(MagickRealType) GetPixelRed(p);
2444 source.green=(MagickRealType) GetPixelGreen(p);
2445 source.blue=(MagickRealType) GetPixelBlue(p);
2446 if (source_image->matte != MagickFalse)
2447 source.opacity=(MagickRealType) GetPixelOpacity(p);
2448 if (source_image->colorspace == CMYKColorspace)
2449 source.index=(MagickRealType) GetPixelIndex(source_indexes+
2451 if (source_image->colorspace == CMYKColorspace)
2453 source.red=(MagickRealType) QuantumRange-source.red;
2454 source.green=(MagickRealType) QuantumRange-source.green;
2455 source.blue=(MagickRealType) QuantumRange-source.blue;
2456 source.index=(MagickRealType) QuantumRange-source.index;
2461 case ClearCompositeOp:
2463 CompositeClear(&canvas,&composite);
2466 case SrcCompositeOp:
2467 case CopyCompositeOp:
2468 case ReplaceCompositeOp:
2474 case DstCompositeOp:
2476 case OverCompositeOp:
2477 case SrcOverCompositeOp:
2479 MagickPixelCompositeOver(&source,source.opacity,&canvas,
2480 canvas.opacity,&composite);
2483 case DstOverCompositeOp:
2485 MagickPixelCompositeOver(&canvas,canvas.opacity,&source,
2486 source.opacity,&composite);
2489 case SrcInCompositeOp:
2492 CompositeIn(&source,&canvas,&composite);
2495 case DstInCompositeOp:
2497 CompositeIn(&canvas,&source,&composite);
2500 case OutCompositeOp:
2501 case SrcOutCompositeOp:
2503 CompositeOut(&source,&canvas,&composite);
2506 case DstOutCompositeOp:
2508 CompositeOut(&canvas,&source,&composite);
2511 case AtopCompositeOp:
2512 case SrcAtopCompositeOp:
2514 CompositeAtop(&source,&canvas,&composite);
2517 case DstAtopCompositeOp:
2519 CompositeAtop(&canvas,&source,&composite);
2522 case XorCompositeOp:
2524 CompositeXor(&source,&canvas,&composite);
2528 case PlusCompositeOp:
2530 CompositePlus(&source,&canvas,channel,&composite);
2533 case MinusDstCompositeOp:
2535 CompositeMinus(&source,&canvas,channel,&composite);
2538 case MinusSrcCompositeOp:
2540 CompositeMinus(&canvas,&source,channel,&composite);
2543 case ModulusAddCompositeOp:
2545 CompositeModulusAdd(&source,&canvas,channel,&composite);
2548 case ModulusSubtractCompositeOp:
2550 CompositeModulusSubtract(&source,&canvas,channel,&composite);
2553 case DifferenceCompositeOp:
2555 CompositeDifference(&source,&canvas,channel,&composite);
2558 case ExclusionCompositeOp:
2560 CompositeExclusion(&source,&canvas,channel,&composite);
2563 case MultiplyCompositeOp:
2565 CompositeMultiply(&source,&canvas,channel,&composite);
2568 case ScreenCompositeOp:
2570 CompositeScreen(&source,&canvas,channel,&composite);
2573 case DivideDstCompositeOp:
2575 CompositeDivide(&source,&canvas,channel,&composite);
2578 case DivideSrcCompositeOp:
2580 CompositeDivide(&canvas,&source,channel,&composite);
2583 case DarkenCompositeOp:
2585 CompositeDarken(&source,&canvas,channel,&composite);
2588 case LightenCompositeOp:
2590 CompositeLighten(&source,&canvas,channel,&composite);
2593 case DarkenIntensityCompositeOp:
2595 CompositeDarkenIntensity(&source,&canvas,channel,&composite);
2598 case LightenIntensityCompositeOp:
2600 CompositeLightenIntensity(&source,&canvas,channel,&composite);
2603 case MathematicsCompositeOp:
2605 CompositeMathematics(&source,&canvas,channel,&geometry_info,
2610 case ColorDodgeCompositeOp:
2612 CompositeColorDodge(&source,&canvas,&composite);
2615 case ColorBurnCompositeOp:
2617 CompositeColorBurn(&source,&canvas,&composite);
2620 case LinearDodgeCompositeOp:
2622 CompositeLinearDodge(&source,&canvas,&composite);
2625 case LinearBurnCompositeOp:
2627 CompositeLinearBurn(&source,&canvas,&composite);
2630 case HardLightCompositeOp:
2632 CompositeHardLight(&source,&canvas,&composite);
2635 case HardMixCompositeOp:
2637 CompositeHardMix(&source,&canvas,&composite);
2640 case OverlayCompositeOp:
2643 CompositeHardLight(&canvas,&source,&composite);
2646 case SoftLightCompositeOp:
2648 CompositeSoftLight(&source,&canvas,&composite);
2651 case LinearLightCompositeOp:
2653 CompositeLinearLight(&source,&canvas,&composite);
2656 case PegtopLightCompositeOp:
2658 CompositePegtopLight(&source,&canvas,&composite);
2661 case VividLightCompositeOp:
2663 CompositeVividLight(&source,&canvas,&composite);
2666 case PinLightCompositeOp:
2668 CompositePinLight(&source,&canvas,&composite);
2672 case ChangeMaskCompositeOp:
2674 if ((composite.opacity > ((MagickRealType) QuantumRange/2.0)) ||
2675 (IsMagickColorSimilar(&source,&canvas) != MagickFalse))
2676 composite.opacity=(MagickRealType) TransparentOpacity;
2678 composite.opacity=(MagickRealType) OpaqueOpacity;
2681 case BumpmapCompositeOp:
2683 if (source.opacity == (MagickRealType) TransparentOpacity)
2685 CompositeBumpmap(&source,&canvas,&composite);
2688 case DissolveCompositeOp:
2690 MagickPixelCompositeOver(&source,(MagickRealType) QuantumRange-
2691 source_dissolve*((MagickRealType) QuantumRange-source.opacity),
2692 &canvas,(MagickRealType) QuantumRange-canvas_dissolve*
2693 ((MagickRealType) QuantumRange-canvas.opacity),&composite);
2696 case BlendCompositeOp:
2698 MagickPixelCompositeBlend(&source,source_dissolve,&canvas,
2699 canvas_dissolve,&composite);
2702 case StereoCompositeOp:
2704 composite.red=(MagickRealType) GetPixelRed(p);
2705 composite.opacity=(composite.opacity+canvas.opacity/2);
2708 case ThresholdCompositeOp:
2710 CompositeThreshold(&source,&canvas,threshold,amount,&composite);
2713 case ModulateCompositeOp:
2718 if (source.opacity == (MagickRealType) TransparentOpacity)
2720 offset=(ssize_t) ((MagickRealType) MagickPixelIntensityToQuantum(
2721 &source)-(MagickRealType) midpoint);
2724 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2726 luma+=(0.01*percent_luma*offset)/midpoint;
2727 chroma*=0.01*percent_chroma;
2728 HCLComposite(hue,chroma,luma,&composite.red,&composite.green,
2732 case HueCompositeOp:
2734 if (source.opacity == (MagickRealType) TransparentOpacity)
2736 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2741 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2743 CompositeHCL(source.red,source.green,source.blue,&hue,&sans,&sans);
2744 HCLComposite(hue,chroma,luma,&composite.red,
2745 &composite.green,&composite.blue);
2746 if (source.opacity < canvas.opacity)
2747 composite.opacity=source.opacity;
2750 case SaturateCompositeOp:
2752 if (source.opacity == (MagickRealType) TransparentOpacity)
2754 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2759 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2761 CompositeHCL(source.red,source.green,source.blue,&sans,&chroma,
2763 HCLComposite(hue,chroma,luma,&composite.red,
2764 &composite.green,&composite.blue);
2765 if (source.opacity < canvas.opacity)
2766 composite.opacity=source.opacity;
2769 case LuminizeCompositeOp:
2771 if (source.opacity == (MagickRealType) TransparentOpacity)
2773 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2778 CompositeHCL(canvas.red,canvas.green,canvas.blue,&hue,
2780 CompositeHCL(source.red,source.green,source.blue,&sans,&sans,
2782 HCLComposite(hue,chroma,luma,&composite.red,
2783 &composite.green,&composite.blue);
2784 if (source.opacity < canvas.opacity)
2785 composite.opacity=source.opacity;
2788 case ColorizeCompositeOp:
2790 if (source.opacity == (MagickRealType) TransparentOpacity)
2792 if (canvas.opacity == (MagickRealType) TransparentOpacity)
2797 CompositeHCL(canvas.red,canvas.green,canvas.blue,&sans,
2799 CompositeHCL(source.red,source.green,source.blue,&hue,&chroma,&sans);
2800 HCLComposite(hue,chroma,luma,&composite.red,
2801 &composite.green,&composite.blue);
2802 if (source.opacity < canvas.opacity)
2803 composite.opacity=source.opacity;
2806 case CopyRedCompositeOp:
2807 case CopyCyanCompositeOp:
2809 composite.red=source.red;
2812 case CopyGreenCompositeOp:
2813 case CopyMagentaCompositeOp:
2815 composite.green=source.green;
2818 case CopyBlueCompositeOp:
2819 case CopyYellowCompositeOp:
2821 composite.blue=source.blue;
2824 case CopyOpacityCompositeOp:
2826 if (source.matte == MagickFalse)
2827 composite.opacity=(MagickRealType) (QuantumRange-
2828 MagickPixelIntensityToQuantum(&source));
2830 composite.opacity=source.opacity;
2833 case CopyBlackCompositeOp:
2835 if (source.colorspace != CMYKColorspace)
2836 ConvertRGBToCMYK(&source);
2837 composite.index=source.index;
2841 case BlurCompositeOp:
2842 case DisplaceCompositeOp:
2843 case DistortCompositeOp:
2851 if (image->colorspace == CMYKColorspace)
2853 composite.red=(MagickRealType) QuantumRange-composite.red;
2854 composite.green=(MagickRealType) QuantumRange-composite.green;
2855 composite.blue=(MagickRealType) QuantumRange-composite.blue;
2856 composite.index=(MagickRealType) QuantumRange-composite.index;
2858 SetPixelRed(q,clamp != MagickFalse ?
2859 ClampPixel(composite.red) : ClampToQuantum(composite.red));
2860 SetPixelGreen(q,clamp != MagickFalse ?
2861 ClampPixel(composite.green) : ClampToQuantum(composite.green));
2862 SetPixelBlue(q,clamp != MagickFalse ?
2863 ClampPixel(composite.blue) : ClampToQuantum(composite.blue));
2864 SetPixelOpacity(q,clamp != MagickFalse ?
2865 ClampPixel(composite.opacity) : ClampToQuantum(composite.opacity));
2866 if (image->colorspace == CMYKColorspace)
2867 SetPixelIndex(indexes+x,clamp != MagickFalse ?
2868 ClampPixel(composite.index) : ClampToQuantum(composite.index));
2870 if (p >= (pixels+source_image->columns))
2874 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2876 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2881 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2885 proceed=SetImageProgress(image,CompositeImageTag,progress,image->rows);
2886 if (proceed == MagickFalse)
2890 source_view=DestroyCacheView(source_view);
2891 image_view=DestroyCacheView(image_view);
2892 if (canvas_image != (
Image * ) NULL)
2893 canvas_image=DestroyImage(canvas_image);
2895 source_image=DestroyImage(source_image);
2924 MagickExport MagickBooleanType TextureImage(
Image *image,
const Image *texture)
2926 #define TextureImageTag "Texture/Image"
2944 assert(image != (
Image *) NULL);
2945 assert(image->signature == MagickCoreSignature);
2946 if (IsEventLogging() != MagickFalse)
2947 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
2948 if (texture == (
const Image *) NULL)
2949 return(MagickFalse);
2950 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2951 return(MagickFalse);
2952 exception=(&image->exception);
2953 texture_image=CloneImage(texture,0,0,MagickTrue,exception);
2954 if (texture_image == (
const Image *) NULL)
2955 return(MagickFalse);
2956 (void) TransformImageColorspace(texture_image,image->colorspace);
2957 (void) SetImageVirtualPixelMethod(texture_image,TileVirtualPixelMethod);
2959 if ((image->compose != CopyCompositeOp) &&
2960 ((image->compose != OverCompositeOp) || (image->matte != MagickFalse) ||
2961 (texture_image->matte != MagickFalse)))
2966 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) texture_image->rows)
2971 if (status == MagickFalse)
2973 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
2978 thread_status=CompositeImage(image,image->compose,texture_image,x+
2979 texture_image->tile_offset.x,y+texture_image->tile_offset.y);
2980 if (thread_status == MagickFalse)
2982 status=thread_status;
2986 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2991 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType)
2993 if (proceed == MagickFalse)
2997 (void) SetImageProgress(image,TextureImageTag,(MagickOffsetType)
2998 image->rows,image->rows);
2999 texture_image=DestroyImage(texture_image);
3006 texture_view=AcquireVirtualCacheView(texture_image,exception);
3007 image_view=AcquireAuthenticCacheView(image,exception);
3008 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3009 #pragma omp parallel for schedule(static) shared(status) \
3010 magick_number_threads(image,texture_image,image->rows,1)
3012 for (y=0; y < (ssize_t) image->rows; y++)
3035 if (status == MagickFalse)
3037 p=GetCacheViewVirtualPixels(texture_view,texture_image->tile_offset.x,(y+
3038 texture_image->tile_offset.y) % texture_image->rows,
3039 texture_image->columns,1,exception);
3040 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3047 texture_indexes=GetCacheViewVirtualIndexQueue(texture_view);
3048 indexes=GetCacheViewAuthenticIndexQueue(image_view);
3049 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
3051 width=texture_image->columns;
3052 if ((x+(ssize_t) width) > (ssize_t) image->columns)
3053 width=image->columns-x;
3054 (void) memcpy(q,p,width*
sizeof(*p));
3055 if ((image->colorspace == CMYKColorspace) &&
3056 (texture_image->colorspace == CMYKColorspace))
3058 (void) memcpy(indexes,texture_indexes,width*
3064 sync=SyncCacheViewAuthenticPixels(image_view,exception);
3065 if (sync == MagickFalse)
3067 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3072 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
3074 if (proceed == MagickFalse)
3078 texture_view=DestroyCacheView(texture_view);
3079 image_view=DestroyCacheView(image_view);
3080 texture_image=DestroyImage(texture_image);