43#include "MagickCore/studio.h"
44#include "MagickCore/artifact.h"
45#include "MagickCore/cache.h"
46#include "MagickCore/cache-private.h"
47#include "MagickCore/cache-view.h"
48#include "MagickCore/channel.h"
49#include "MagickCore/client.h"
50#include "MagickCore/color.h"
51#include "MagickCore/color-private.h"
52#include "MagickCore/colorspace.h"
53#include "MagickCore/colorspace-private.h"
54#include "MagickCore/composite.h"
55#include "MagickCore/composite-private.h"
56#include "MagickCore/constitute.h"
57#include "MagickCore/draw.h"
58#include "MagickCore/exception-private.h"
59#include "MagickCore/fx.h"
60#include "MagickCore/gem.h"
61#include "MagickCore/geometry.h"
62#include "MagickCore/image.h"
63#include "MagickCore/image-private.h"
64#include "MagickCore/list.h"
65#include "MagickCore/log.h"
66#include "MagickCore/memory_.h"
67#include "MagickCore/monitor.h"
68#include "MagickCore/monitor-private.h"
69#include "MagickCore/morphology.h"
70#include "MagickCore/option.h"
71#include "MagickCore/pixel-accessor.h"
72#include "MagickCore/property.h"
73#include "MagickCore/quantum.h"
74#include "MagickCore/resample.h"
75#include "MagickCore/resource_.h"
76#include "MagickCore/string_.h"
77#include "MagickCore/string-private.h"
78#include "MagickCore/thread-private.h"
79#include "MagickCore/threshold.h"
80#include "MagickCore/token.h"
81#include "MagickCore/transform.h"
82#include "MagickCore/utility.h"
83#include "MagickCore/utility-private.h"
84#include "MagickCore/version.h"
185static Image *BlendConvolveImage(
const Image *image,
const char *kernel,
198 kernel_info=AcquireKernelInfo(kernel,exception);
200 return((
Image *) NULL);
201 clone_image=CloneImage(image,0,0,MagickTrue,exception);
202 if (clone_image == (
Image *) NULL)
204 kernel_info=DestroyKernelInfo(kernel_info);
205 return((
Image *) NULL);
207 (void) SetImageAlphaChannel(clone_image,OffAlphaChannel,exception);
208 convolve_image=ConvolveImage(clone_image,kernel_info,exception);
209 kernel_info=DestroyKernelInfo(kernel_info);
210 clone_image=DestroyImage(clone_image);
211 return(convolve_image);
214static Image *BlendMagnitudeImage(
const Image *dx_image,
const Image *dy_image,
234 magnitude_image=CloneImage(dx_image,0,0,MagickTrue,exception);
235 if (magnitude_image == (
Image *) NULL)
236 return(magnitude_image);
237 dx_view=AcquireVirtualCacheView(dx_image,exception);
238 dy_view=AcquireVirtualCacheView(dy_image,exception);
239 magnitude_view=AcquireAuthenticCacheView(magnitude_image,exception);
240#if defined(MAGICKCORE_OPENMP_SUPPORT)
241 #pragma omp parallel for schedule(static) shared(status) \
242 magick_number_threads(dx_image,magnitude_image,dx_image->rows,1)
244 for (y=0; y < (ssize_t) dx_image->rows; y++)
256 if (status == MagickFalse)
258 p=GetCacheViewVirtualPixels(dx_view,0,y,dx_image->columns,1,exception);
259 q=GetCacheViewVirtualPixels(dy_view,0,y,dx_image->columns,1,exception);
260 r=GetCacheViewAuthenticPixels(magnitude_view,0,y,dx_image->columns,1,
262 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL) ||
263 (r == (Quantum *) NULL))
268 for (x=0; x < (ssize_t) dx_image->columns; x++)
273 for (i=0; i < (ssize_t) GetPixelChannels(dx_image); i++)
275 PixelChannel channel = GetPixelChannelChannel(dx_image,i);
276 PixelTrait traits = GetPixelChannelTraits(dx_image,channel);
277 PixelTrait dy_traits = GetPixelChannelTraits(dy_image,channel);
278 if ((traits == UndefinedPixelTrait) ||
279 (dy_traits == UndefinedPixelTrait) ||
280 ((dy_traits & UpdatePixelTrait) == 0))
282 r[i]=ClampToQuantum(hypot((
double) p[i],(
double)
283 GetPixelChannel(dy_image,channel,q)));
285 p+=(ptrdiff_t) GetPixelChannels(dx_image);
286 q+=(ptrdiff_t) GetPixelChannels(dy_image);
287 r+=(ptrdiff_t) GetPixelChannels(magnitude_image);
289 if (SyncCacheViewAuthenticPixels(magnitude_view,exception) == MagickFalse)
292 magnitude_view=DestroyCacheView(magnitude_view);
293 dy_view=DestroyCacheView(dy_view);
294 dx_view=DestroyCacheView(dx_view);
295 if (status == MagickFalse)
296 magnitude_image=DestroyImage(magnitude_image);
297 return(magnitude_image);
300static Image *BlendMaxMagnitudeImage(
const Image *alpha_image,
323 magnitude_image=CloneImage(alpha_image,0,0,MagickTrue,exception);
324 if (magnitude_image == (
Image *) NULL)
325 return(magnitude_image);
326 alpha_view=AcquireVirtualCacheView(alpha_image,exception);
327 beta_view=AcquireVirtualCacheView(beta_image,exception);
328 dx_view=AcquireVirtualCacheView(dx_image,exception);
329 dy_view=AcquireVirtualCacheView(dy_image,exception);
330 magnitude_view=AcquireAuthenticCacheView(magnitude_image,exception);
331#if defined(MAGICKCORE_OPENMP_SUPPORT)
332 #pragma omp parallel for schedule(static) shared(status) \
333 magick_number_threads(alpha_image,magnitude_image,alpha_image->rows,1)
335 for (y=0; y < (ssize_t) alpha_image->rows; y++)
349 if (status == MagickFalse)
351 p=GetCacheViewVirtualPixels(alpha_view,0,y,alpha_image->columns,1,
353 q=GetCacheViewVirtualPixels(beta_view,0,y,alpha_image->columns,1,exception);
354 r=GetCacheViewVirtualPixels(dx_view,0,y,alpha_image->columns,1,exception);
355 s=GetCacheViewVirtualPixels(dy_view,0,y,alpha_image->columns,1,exception);
356 t=GetCacheViewAuthenticPixels(magnitude_view,0,y,alpha_image->columns,1,
358 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL) ||
359 (r == (
const Quantum *) NULL) || (s == (
const Quantum *) NULL) ||
360 (t == (Quantum *) NULL))
365 for (x=0; x < (ssize_t) alpha_image->columns; x++)
370 for (i=0; i < (ssize_t) GetPixelChannels(alpha_image); i++)
372 PixelChannel channel = GetPixelChannelChannel(alpha_image,i);
373 PixelTrait traits = GetPixelChannelTraits(alpha_image,channel);
374 PixelTrait beta_traits = GetPixelChannelTraits(beta_image,channel);
375 if ((traits == UndefinedPixelTrait) ||
376 (beta_traits == UndefinedPixelTrait) ||
377 ((beta_traits & UpdatePixelTrait) == 0))
379 if (p[i] > GetPixelChannel(beta_image,channel,q))
380 t[i]=GetPixelChannel(dx_image,channel,r);
382 t[i]=GetPixelChannel(dy_image,channel,s);
384 p+=(ptrdiff_t) GetPixelChannels(alpha_image);
385 q+=(ptrdiff_t) GetPixelChannels(beta_image);
386 r+=(ptrdiff_t) GetPixelChannels(dx_image);
387 s+=(ptrdiff_t) GetPixelChannels(dy_image);
388 t+=(ptrdiff_t) GetPixelChannels(magnitude_image);
390 if (SyncCacheViewAuthenticPixels(magnitude_view,exception) == MagickFalse)
393 magnitude_view=DestroyCacheView(magnitude_view);
394 dy_view=DestroyCacheView(dy_view);
395 dx_view=DestroyCacheView(dx_view);
396 beta_view=DestroyCacheView(beta_view);
397 alpha_view=DestroyCacheView(alpha_view);
398 if (status == MagickFalse)
399 magnitude_image=DestroyImage(magnitude_image);
400 return(magnitude_image);
403static Image *BlendSumImage(
const Image *alpha_image,
const Image *beta_image,
404 const double attenuate,
const double sign,
ExceptionInfo *exception)
423 sum_image=CloneImage(alpha_image,0,0,MagickTrue,exception);
424 if (sum_image == (
Image *) NULL)
426 alpha_view=AcquireVirtualCacheView(alpha_image,exception);
427 beta_view=AcquireVirtualCacheView(beta_image,exception);
428 sum_view=AcquireAuthenticCacheView(sum_image,exception);
429#if defined(MAGICKCORE_OPENMP_SUPPORT)
430 #pragma omp parallel for schedule(static) shared(status) \
431 magick_number_threads(alpha_image,sum_image,alpha_image->rows,1)
433 for (y=0; y < (ssize_t) alpha_image->rows; y++)
445 if (status == MagickFalse)
447 p=GetCacheViewVirtualPixels(alpha_view,0,y,alpha_image->columns,1,
449 q=GetCacheViewVirtualPixels(beta_view,0,y,alpha_image->columns,1,exception);
450 r=GetCacheViewAuthenticPixels(sum_view,0,y,alpha_image->columns,1,
452 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL) ||
453 (r == (Quantum *) NULL))
458 for (x=0; x < (ssize_t) alpha_image->columns; x++)
463 for (i=0; i < (ssize_t) GetPixelChannels(alpha_image); i++)
465 PixelChannel channel = GetPixelChannelChannel(alpha_image,i);
466 PixelTrait traits = GetPixelChannelTraits(alpha_image,channel);
467 PixelTrait beta_traits = GetPixelChannelTraits(beta_image,channel);
468 if ((traits == UndefinedPixelTrait) ||
469 (beta_traits == UndefinedPixelTrait) ||
470 ((beta_traits & UpdatePixelTrait) == 0))
472 r[i]=ClampToQuantum(attenuate*((
double) p[i]+sign*
473 (
double) GetPixelChannel(beta_image,channel,q)));
475 p+=(ptrdiff_t) GetPixelChannels(alpha_image);
476 q+=(ptrdiff_t) GetPixelChannels(beta_image);
477 r+=(ptrdiff_t) GetPixelChannels(sum_image);
479 if (SyncCacheViewAuthenticPixels(sum_view,exception) == MagickFalse)
482 sum_view=DestroyCacheView(sum_view);
483 beta_view=DestroyCacheView(beta_view);
484 alpha_view=DestroyCacheView(alpha_view);
485 if (status == MagickFalse)
486 sum_image=DestroyImage(sum_image);
490static Image *BlendDivergentImage(
const Image *alpha_image,
493#define FreeDivergentResources() \
495 if (dy_image != (Image *) NULL) \
496 dy_image=DestroyImage(dy_image); \
497 if (dx_image != (Image *) NULL) \
498 dx_image=DestroyImage(dx_image); \
499 if (magnitude_beta != (Image *) NULL) \
500 magnitude_beta=DestroyImage(magnitude_beta); \
501 if (dy_beta != (Image *) NULL) \
502 dy_beta=DestroyImage(dy_beta); \
503 if (dx_beta != (Image *) NULL) \
504 dx_beta=DestroyImage(dx_beta); \
505 if (magnitude_alpha != (Image *) NULL) \
506 magnitude_alpha=DestroyImage(magnitude_alpha); \
507 if (dy_alpha != (Image *) NULL) \
508 dy_alpha=DestroyImage(dy_alpha); \
509 if (dx_alpha != (Image *) NULL) \
510 dx_alpha=DestroyImage(dx_alpha); \
514 *divergent_image = (
Image *) NULL,
515 *dx_alpha = (
Image *) NULL,
516 *dx_beta = (
Image *) NULL,
517 *dx_divergent = (
Image *) NULL,
518 *dx_image = (
Image *) NULL,
519 *dy_alpha = (
Image *) NULL,
520 *dy_beta = (
Image *) NULL,
521 *dy_divergent = (
Image *) NULL,
522 *dy_image = (
Image *) NULL,
523 *magnitude_alpha = (
Image *) NULL,
524 *magnitude_beta = (
Image *) NULL;
529 dx_alpha=BlendConvolveImage(alpha_image,
"3x1:-0.5,0.0,0.5",exception);
530 if (dx_alpha == (
Image *) NULL)
532 FreeDivergentResources();
533 return((
Image *) NULL);
535 dy_alpha=BlendConvolveImage(alpha_image,
"1x3:-0.5,0.0,0.5",exception);
536 if (dy_alpha == (
Image *) NULL)
538 FreeDivergentResources();
539 return((
Image *) NULL);
541 magnitude_alpha=BlendMagnitudeImage(dx_alpha,dy_alpha,exception);
542 if (magnitude_alpha == (
Image *) NULL)
544 FreeDivergentResources();
545 return((
Image *) NULL);
550 dx_beta=BlendConvolveImage(beta_image,
"3x1:-0.5,0.0,0.5",exception);
551 if (dx_beta == (
Image *) NULL)
553 FreeDivergentResources();
554 return((
Image *) NULL);
556 dy_beta=BlendConvolveImage(beta_image,
"1x3:-0.5,0.0,0.5",exception);
557 if (dy_beta == (
Image *) NULL)
559 FreeDivergentResources();
560 return((
Image *) NULL);
562 magnitude_beta=BlendMagnitudeImage(dx_beta,dy_beta,exception);
563 if (magnitude_beta == (
Image *) NULL)
565 FreeDivergentResources();
566 return((
Image *) NULL);
571 dx_image=BlendMaxMagnitudeImage(magnitude_alpha,magnitude_beta,dx_alpha,
573 if (dx_image == (
Image *) NULL)
575 FreeDivergentResources();
576 return((
Image *) NULL);
578 dy_image=BlendMaxMagnitudeImage(magnitude_alpha,magnitude_beta,dy_alpha,
580 if (dy_image == (
Image *) NULL)
582 FreeDivergentResources();
583 return((
Image *) NULL);
585 dx_beta=DestroyImage(dx_beta);
586 dx_alpha=DestroyImage(dx_alpha);
587 magnitude_beta=DestroyImage(magnitude_beta);
588 magnitude_alpha=DestroyImage(magnitude_alpha);
592 dx_divergent=BlendConvolveImage(dx_image,
"3x1:-0.5,0.0,0.5",exception);
593 if (dx_divergent == (
Image *) NULL)
595 FreeDivergentResources();
596 return((
Image *) NULL);
598 dy_divergent=BlendConvolveImage(dy_image,
"1x3:-0.5,0.0,0.5",exception);
599 if (dy_divergent == (
Image *) NULL)
601 FreeDivergentResources();
602 return((
Image *) NULL);
604 divergent_image=BlendSumImage(dx_divergent,dy_divergent,0.25,1.0,exception);
605 dy_divergent=DestroyImage(dy_divergent);
606 dx_divergent=DestroyImage(dx_divergent);
607 if (divergent_image == (
Image *) NULL)
609 FreeDivergentResources();
610 return((
Image *) NULL);
612 FreeDivergentResources();
613 return(divergent_image);
616static MagickBooleanType BlendMaskAlphaChannel(
Image *image,
632 if (SetImageAlpha(image,OpaqueAlpha,exception) == MagickFalse)
634 image_view=AcquireAuthenticCacheView(image,exception);
635 mask_view=AcquireVirtualCacheView(mask_image,exception);
636#if defined(MAGICKCORE_OPENMP_SUPPORT)
637 #pragma omp parallel for schedule(static) shared(status) \
638 magick_number_threads(image,image,image->rows,2)
640 for (y=0; y < (ssize_t) image->rows; y++)
651 if (status == MagickFalse)
653 p=GetCacheViewVirtualPixels(mask_view,0,y,image->columns,1,exception);
654 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
655 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
660 for (x=0; x < (ssize_t) image->columns; x++)
663 alpha = GetPixelAlpha(mask_image,p);
666 i = GetPixelChannelOffset(image,AlphaPixelChannel);
668 if (fabs((
double) alpha) >= MagickEpsilon)
670 p+=(ptrdiff_t) GetPixelChannels(mask_image);
671 q+=(ptrdiff_t) GetPixelChannels(image);
673 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
676 mask_view=DestroyCacheView(mask_view);
677 image_view=DestroyCacheView(image_view);
690 mean[MaxPixelChannels];
705 (void) memset(mean,0,MaxPixelChannels*
sizeof(*mean));
706 alpha_view=AcquireVirtualCacheView(image,exception);
707 for (y=0; y < (ssize_t) image->rows; y++)
715 p=GetCacheViewVirtualPixels(alpha_view,0,y,image->columns,1,
717 if (p == (
const Quantum *) NULL)
719 for (x=0; x < (ssize_t) image->columns; x++)
724 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
726 PixelChannel channel = GetPixelChannelChannel(image,i);
727 PixelTrait traits = GetPixelChannelTraits(image,channel);
728 if (traits == UndefinedPixelTrait)
730 mean[i]+=QuantumScale*(double) p[i];
732 p+=(ptrdiff_t) GetPixelChannels(image);
735 alpha_view=DestroyCacheView(alpha_view);
736 if (y < (ssize_t) image->rows)
737 return((
Image *) NULL);
738 for (j=0; j < (ssize_t) GetPixelChannels(image); j++)
739 mean[j]=(
double) QuantumRange*mean[j]/image->columns/
744 mean_image=CloneImage(image,0,0,MagickTrue,exception);
745 if (mean_image == (
Image *) NULL)
747 mask_view=AcquireVirtualCacheView(mask_image,exception);
748 mean_view=AcquireAuthenticCacheView(mean_image,exception);
749#if defined(MAGICKCORE_OPENMP_SUPPORT)
750 #pragma omp parallel for schedule(static) shared(status) \
751 magick_number_threads(mask_image,mean_image,mean_image->rows,4)
753 for (y=0; y < (ssize_t) mean_image->rows; y++)
764 if (status == MagickFalse)
766 p=GetCacheViewVirtualPixels(mask_view,0,y,mean_image->columns,1,exception);
767 q=GetCacheViewAuthenticPixels(mean_view,0,y,mean_image->columns,1,
769 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
774 for (x=0; x < (ssize_t) mean_image->columns; x++)
777 alpha = GetPixelAlpha(mask_image,p),
778 mask = GetPixelReadMask(mask_image,p);
783 for (i=0; i < (ssize_t) GetPixelChannels(mean_image); i++)
785 PixelChannel channel = GetPixelChannelChannel(mean_image,i);
786 PixelTrait traits = GetPixelChannelTraits(mean_image,channel);
787 if (traits == UndefinedPixelTrait)
789 if (mask <= (QuantumRange/2))
792 if (fabs((
double) alpha) >= MagickEpsilon)
793 q[i]=ClampToQuantum(mean[i]);
795 p+=(ptrdiff_t) GetPixelChannels(mask_image);
796 q+=(ptrdiff_t) GetPixelChannels(mean_image);
798 if (SyncCacheViewAuthenticPixels(mean_view,exception) == MagickFalse)
801 mask_view=DestroyCacheView(mask_view);
802 mean_view=DestroyCacheView(mean_view);
803 if (status == MagickFalse)
804 mean_image=DestroyImage(mean_image);
808static MagickBooleanType BlendRMSEResidual(
const Image *alpha_image,
822 columns = MagickMax(alpha_image->columns,beta_image->columns),
823 rows = MagickMax(alpha_image->rows,beta_image->rows);
829 alpha_view=AcquireVirtualCacheView(alpha_image,exception);
830 beta_view=AcquireVirtualCacheView(beta_image,exception);
831#if defined(MAGICKCORE_OPENMP_SUPPORT)
832 #pragma omp parallel for schedule(static) shared(status) \
833 magick_number_threads(alpha_image,alpha_image,rows,1)
835 for (y=0; y < (ssize_t) rows; y++)
850 if (status == MagickFalse)
852 p=GetCacheViewVirtualPixels(alpha_view,0,y,columns,1,exception);
853 q=GetCacheViewVirtualPixels(beta_view,0,y,columns,1,exception);
854 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL))
859 channel_residual=0.0;
860 for (x=0; x < (ssize_t) columns; x++)
869 if ((GetPixelReadMask(alpha_image,p) <= (QuantumRange/2)) ||
870 (GetPixelReadMask(beta_image,q) <= (QuantumRange/2)))
872 p+=(ptrdiff_t) GetPixelChannels(alpha_image);
873 q+=(ptrdiff_t) GetPixelChannels(beta_image);
876 Sa=QuantumScale*(double) GetPixelAlpha(alpha_image,p);
877 Da=QuantumScale*(double) GetPixelAlpha(beta_image,q);
878 for (i=0; i < (ssize_t) GetPixelChannels(alpha_image); i++)
883 PixelChannel channel = GetPixelChannelChannel(alpha_image,i);
884 PixelTrait traits = GetPixelChannelTraits(alpha_image,channel);
885 PixelTrait beta_traits = GetPixelChannelTraits(beta_image,channel);
886 if ((traits == UndefinedPixelTrait) ||
887 (beta_traits == UndefinedPixelTrait) ||
888 ((beta_traits & UpdatePixelTrait) == 0))
890 if (channel == AlphaPixelChannel)
891 distance=QuantumScale*((double) p[i]-(double) GetPixelChannel(
892 beta_image,channel,q));
894 distance=QuantumScale*(Sa*(double) p[i]-Da*(double) GetPixelChannel(
895 beta_image,channel,q));
896 channel_residual+=distance*distance;
899 p+=(ptrdiff_t) GetPixelChannels(alpha_image);
900 q+=(ptrdiff_t) GetPixelChannels(beta_image);
902#if defined(MAGICKCORE_OPENMP_SUPPORT)
903 #pragma omp critical (MagickCore_BlendRMSEResidual)
907 *residual+=channel_residual;
910 area=PerceptibleReciprocal(area);
911 beta_view=DestroyCacheView(beta_view);
912 alpha_view=DestroyCacheView(alpha_view);
913 *residual=sqrt(*residual*area/(
double) GetImageChannels(alpha_image));
917static MagickBooleanType CompositeOverImage(
Image *image,
918 const Image *source_image,
const MagickBooleanType clip_to_self,
919 const ssize_t x_offset,
const ssize_t y_offset,
ExceptionInfo *exception)
921#define CompositeImageTag "Composite/Image"
946 value=GetImageArtifact(image,
"compose:clamp");
947 if (value != (
const char *) NULL)
948 clamp=IsStringTrue(value);
951 source_view=AcquireVirtualCacheView(source_image,exception);
952 image_view=AcquireAuthenticCacheView(image,exception);
953#if defined(MAGICKCORE_OPENMP_SUPPORT)
954 #pragma omp parallel for schedule(static) shared(progress,status) \
955 magick_number_threads(source_image,image,image->rows,1)
957 for (y=0; y < (ssize_t) image->rows; y++)
975 if (status == MagickFalse)
977 if (clip_to_self != MagickFalse)
981 if ((y-(
double) y_offset) >= (
double) source_image->rows)
987 pixels=(Quantum *) NULL;
989 if ((y >= y_offset) &&
990 ((y-(
double) y_offset) < (
double) source_image->rows))
992 p=GetCacheViewVirtualPixels(source_view,0,
993 CastDoubleToLong(y-(
double) y_offset),source_image->columns,1,
995 if (p == (
const Quantum *) NULL)
1002 p-=(ptrdiff_t)CastDoubleToLong((
double) x_offset*GetPixelChannels(source_image));
1004 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1005 if (q == (Quantum *) NULL)
1010 GetPixelInfo(image,&canvas_pixel);
1011 GetPixelInfo(source_image,&source_pixel);
1012 for (x=0; x < (ssize_t) image->columns; x++)
1032 if (clip_to_self != MagickFalse)
1036 q+=(ptrdiff_t) GetPixelChannels(image);
1039 if ((x-(
double) x_offset) >= (
double) source_image->columns)
1042 if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
1043 ((x-(
double) x_offset) >= (
double) source_image->columns))
1046 source[MaxPixelChannels];
1053 (void) GetOneVirtualPixel(source_image,
1054 CastDoubleToLong(x-(
double) x_offset),
1055 CastDoubleToLong(y-(
double) y_offset),source,exception);
1056 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1061 PixelChannel channel = GetPixelChannelChannel(image,i);
1062 PixelTrait traits = GetPixelChannelTraits(image,channel);
1063 PixelTrait source_traits=GetPixelChannelTraits(source_image,
1065 if ((traits == UndefinedPixelTrait) ||
1066 (source_traits == UndefinedPixelTrait))
1068 if (channel == AlphaPixelChannel)
1069 pixel=(MagickRealType) TransparentAlpha;
1071 pixel=(MagickRealType) q[i];
1072 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
1073 ClampToQuantum(pixel);
1075 q+=(ptrdiff_t) GetPixelChannels(image);
1083 Sa=QuantumScale*(double) GetPixelAlpha(source_image,p);
1084 Da=QuantumScale*(double) GetPixelAlpha(image,q);
1086 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1091 PixelChannel channel = GetPixelChannelChannel(image,i);
1092 PixelTrait traits = GetPixelChannelTraits(image,channel);
1093 PixelTrait source_traits=GetPixelChannelTraits(source_image,channel);
1094 if (traits == UndefinedPixelTrait)
1096 if ((source_traits == UndefinedPixelTrait) &&
1097 (channel != AlphaPixelChannel))
1099 if (channel == AlphaPixelChannel)
1104 pixel=(double) QuantumRange*alpha;
1105 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
1106 ClampToQuantum(pixel);
1113 Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
1114 Dc=(MagickRealType) q[i];
1115 if ((traits & CopyPixelTrait) != 0)
1120 q[i]=ClampToQuantum(Sc);
1128 Sca=QuantumScale*Sa*Sc;
1129 Dca=QuantumScale*Da*Dc;
1130 gamma=PerceptibleReciprocal(alpha);
1131 pixel=(double) QuantumRange*gamma*(Sca+Dca*(1.0-Sa));
1132 q[i]=clamp != MagickFalse ? ClampPixel(pixel) : ClampToQuantum(pixel);
1134 p+=(ptrdiff_t) GetPixelChannels(source_image);
1135 channels=GetPixelChannels(source_image);
1136 if (p >= (pixels+channels*source_image->columns))
1138 q+=(ptrdiff_t) GetPixelChannels(image);
1140 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1142 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1147#if defined(MAGICKCORE_OPENMP_SUPPORT)
1151 proceed=SetImageProgress(image,CompositeImageTag,progress,image->rows);
1152 if (proceed == MagickFalse)
1156 source_view=DestroyCacheView(source_view);
1157 image_view=DestroyCacheView(image_view);
1161static MagickBooleanType SaliencyBlendImage(
Image *image,
1162 const Image *source_image,
const ssize_t x_offset,
const ssize_t y_offset,
1163 const double iterations,
const double residual_threshold,
const size_t tick,
1170 *residual_image = (
Image *) NULL;
1176 status = MagickTrue,
1177 verbose = MagickFalse;
1181 source_image->columns,
1193 crop_image=CropImage(image,&crop_info,exception);
1194 if (crop_image == (
Image *) NULL)
1195 return(MagickFalse);
1196 DisableCompositeClampUnlessSpecified(crop_image);
1197 divergent_image=BlendDivergentImage(crop_image,source_image,exception);
1198 if (divergent_image == (
Image *) NULL)
1200 crop_image=DestroyImage(crop_image);
1201 return(MagickFalse);
1203 (void) ResetImagePage(crop_image,
"0x0+0+0");
1204 relax_image=BlendMeanImage(crop_image,source_image,exception);
1205 if (relax_image == (
Image *) NULL)
1207 crop_image=DestroyImage(crop_image);
1208 divergent_image=DestroyImage(divergent_image);
1209 return(MagickFalse);
1211 status=BlendMaskAlphaChannel(crop_image,source_image,exception);
1212 if (status == MagickFalse)
1214 crop_image=DestroyImage(crop_image);
1215 divergent_image=DestroyImage(divergent_image);
1216 return(MagickFalse);
1218 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1219 if (residual_image == (
Image *) NULL)
1221 crop_image=DestroyImage(crop_image);
1222 relax_image=DestroyImage(relax_image);
1223 return(MagickFalse);
1228 kernel_info=AcquireKernelInfo(
"3x3:0,0.25,0,0.25,0,0.25,0,0.25,0",exception);
1231 crop_image=DestroyImage(crop_image);
1232 residual_image=DestroyImage(residual_image);
1233 relax_image=DestroyImage(relax_image);
1234 return(MagickFalse);
1236 verbose=IsStringTrue(GetImageArtifact(image,
"verbose"));
1237 if (verbose != MagickFalse)
1238 (void) FormatLocaleFile(stderr,
"saliency blending:\n");
1239 for (i=0; i < iterations; i++)
1248 convolve_image=ConvolveImage(relax_image,kernel_info,exception);
1249 if (convolve_image == (
Image *) NULL)
1251 relax_image=DestroyImage(relax_image);
1252 relax_image=convolve_image;
1253 sum_image=BlendSumImage(relax_image,divergent_image,1.0,-1.0,exception);
1254 if (sum_image == (
Image *) NULL)
1256 relax_image=DestroyImage(relax_image);
1257 relax_image=sum_image;
1258 status=CompositeOverImage(relax_image,crop_image,MagickTrue,0,0,exception);
1259 if (status == MagickFalse)
1261 status=BlendRMSEResidual(relax_image,residual_image,&residual,exception);
1262 if (status == MagickFalse)
1264 if ((verbose != MagickFalse) && ((i % MagickMax(tick,1)) == 0))
1265 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double) residual);
1266 if (residual < residual_threshold)
1268 if (verbose != MagickFalse)
1269 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double)
1273 residual_image=DestroyImage(residual_image);
1274 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1275 if (residual_image == (
Image *) NULL)
1278 kernel_info=DestroyKernelInfo(kernel_info);
1279 crop_image=DestroyImage(crop_image);
1280 divergent_image=DestroyImage(divergent_image);
1281 residual_image=DestroyImage(residual_image);
1285 status=CompositeOverImage(image,relax_image,MagickTrue,x_offset,y_offset,
1287 relax_image=DestroyImage(relax_image);
1291static MagickBooleanType SeamlessBlendImage(
Image *image,
1292 const Image *source_image,
const ssize_t x_offset,
const ssize_t y_offset,
1293 const double iterations,
const double residual_threshold,
const size_t tick,
1308 status = MagickTrue,
1309 verbose = MagickFalse;
1313 source_image->columns,
1325 crop_image=CropImage(image,&crop_info,exception);
1326 if (crop_image == (
Image *) NULL)
1327 return(MagickFalse);
1328 DisableCompositeClampUnlessSpecified(crop_image);
1329 (void) ResetImagePage(crop_image,
"0x0+0+0");
1330 sum_image=BlendSumImage(crop_image,source_image,1.0,-1.0,exception);
1331 crop_image=DestroyImage(crop_image);
1332 if (sum_image == (
Image *) NULL)
1333 return(MagickFalse);
1334 mean_image=BlendMeanImage(sum_image,source_image,exception);
1335 sum_image=DestroyImage(sum_image);
1336 if (mean_image == (
Image *) NULL)
1337 return(MagickFalse);
1338 relax_image=CloneImage(mean_image,0,0,MagickTrue,exception);
1339 if (relax_image == (
Image *) NULL)
1341 mean_image=DestroyImage(mean_image);
1342 return(MagickFalse);
1344 status=BlendMaskAlphaChannel(mean_image,source_image,exception);
1345 if (status == MagickFalse)
1347 relax_image=DestroyImage(relax_image);
1348 mean_image=DestroyImage(mean_image);
1349 return(MagickFalse);
1351 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1352 if (residual_image == (
Image *) NULL)
1354 relax_image=DestroyImage(relax_image);
1355 mean_image=DestroyImage(mean_image);
1356 return(MagickFalse);
1361 kernel_info=AcquireKernelInfo(
"3x3:0,0.25,0,0.25,0,0.25,0,0.25,0",exception);
1364 residual_image=DestroyImage(residual_image);
1365 relax_image=DestroyImage(relax_image);
1366 mean_image=DestroyImage(mean_image);
1367 return(MagickFalse);
1369 verbose=IsStringTrue(GetImageArtifact(image,
"verbose"));
1370 if (verbose != MagickFalse)
1371 (void) FormatLocaleFile(stderr,
"seamless blending:\n");
1372 for (i=0; i < iterations; i++)
1380 convolve_image=ConvolveImage(relax_image,kernel_info,exception);
1381 if (convolve_image == (
Image *) NULL)
1383 relax_image=DestroyImage(relax_image);
1384 relax_image=convolve_image;
1385 status=CompositeOverImage(relax_image,mean_image,MagickTrue,0,0,exception);
1386 if (status == MagickFalse)
1388 status=BlendRMSEResidual(relax_image,residual_image,&residual,exception);
1389 if (status == MagickFalse)
1391 if ((verbose != MagickFalse) && ((i % MagickMax(tick,1)) == 0))
1392 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double) residual);
1393 if (residual < residual_threshold)
1395 if (verbose != MagickFalse)
1396 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double)
1400 if (residual_image != (
Image *) NULL)
1401 residual_image=DestroyImage(residual_image);
1402 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1403 if (residual_image == (
Image *) NULL)
1406 kernel_info=DestroyKernelInfo(kernel_info);
1407 mean_image=DestroyImage(mean_image);
1408 residual_image=DestroyImage(residual_image);
1412 foreground_image=BlendSumImage(source_image,relax_image,1.0,1.0,exception);
1413 relax_image=DestroyImage(relax_image);
1414 if (foreground_image == (
Image *) NULL)
1415 return(MagickFalse);
1416 (void) SetImageMask(foreground_image,ReadPixelMask,(
const Image *) NULL,
1418 status=CompositeOverImage(image,foreground_image,MagickTrue,x_offset,y_offset,
1420 foreground_image=DestroyImage(foreground_image);
1424MagickExport MagickBooleanType CompositeImage(
Image *image,
1425 const Image *composite,
const CompositeOperator compose,
1426 const MagickBooleanType clip_to_self,
const ssize_t x_offset,
1429#define CompositeImageTag "Composite/Image"
1436 colorspace = HCLColorspace;
1442 white_luminance = 10000.0;
1448 illuminant = D65Illuminant;
1477 assert(image != (
Image *) NULL);
1478 assert(image->signature == MagickCoreSignature);
1479 assert(composite != (
Image *) NULL);
1480 assert(composite->signature == MagickCoreSignature);
1481 if (IsEventLogging() != MagickFalse)
1482 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1483 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1484 return(MagickFalse);
1485 source_image=CloneImage(composite,0,0,MagickTrue,exception);
1486 if (source_image == (
const Image *) NULL)
1487 return(MagickFalse);
1488 (void) SetImageColorspace(source_image,image->colorspace,exception);
1489 if ((compose == OverCompositeOp) || (compose == SrcOverCompositeOp))
1491 status=CompositeOverImage(image,source_image,clip_to_self,x_offset,
1492 y_offset,exception);
1493 source_image=DestroyImage(source_image);
1497 canvas_image=(
Image *) NULL;
1498 canvas_dissolve=1.0;
1499 white_luminance=10000.0;
1500 artifact=GetImageArtifact(image,
"compose:white-luminance");
1501 if (artifact != (
const char *) NULL)
1502 white_luminance=StringToDouble(artifact,(
char **) NULL);
1503 artifact=GetImageArtifact(image,
"compose:illuminant");
1504 if (artifact != (
const char *) NULL)
1509 illuminant_type=ParseCommandOption(MagickIlluminantOptions,MagickFalse,
1511 if (illuminant_type < 0)
1512 illuminant=UndefinedIlluminant;
1514 illuminant=(IlluminantType) illuminant_type;
1516 artifact=GetImageArtifact(image,
"compose:colorspace");
1517 if (artifact != (
const char *) NULL)
1522 colorspace_type=ParseCommandOption(MagickColorspaceOptions,MagickFalse,
1524 if (colorspace_type < 0)
1525 colorspace=UndefinedColorspace;
1527 colorspace=(ColorspaceType) colorspace_type;
1530 artifact=GetImageArtifact(image,
"compose:clamp");
1531 if (artifact != (
const char *) NULL)
1532 clamp=IsStringTrue(artifact);
1533 compose_sync=MagickTrue;
1534 artifact=GetImageArtifact(image,
"compose:sync");
1535 if (artifact != (
const char *) NULL)
1536 compose_sync=IsStringTrue(artifact);
1537 SetGeometryInfo(&geometry_info);
1539 percent_chroma=100.0;
1540 source_dissolve=1.0;
1544 case CopyCompositeOp:
1546 if ((x_offset < 0) || (y_offset < 0))
1548 if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
1550 if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
1552 if ((source_image->alpha_trait == UndefinedPixelTrait) &&
1553 (image->alpha_trait != UndefinedPixelTrait))
1554 (void) SetImageAlphaChannel(source_image,OpaqueAlphaChannel,exception);
1556 source_view=AcquireVirtualCacheView(source_image,exception);
1557 image_view=AcquireAuthenticCacheView(image,exception);
1558#if defined(MAGICKCORE_OPENMP_SUPPORT)
1559 #pragma omp parallel for schedule(static) shared(status) \
1560 magick_number_threads(source_image,image,source_image->rows,4)
1562 for (y=0; y < (ssize_t) source_image->rows; y++)
1576 if (status == MagickFalse)
1578 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1580 q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
1581 source_image->columns,1,exception);
1582 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1587 for (x=0; x < (ssize_t) source_image->columns; x++)
1592 if (GetPixelReadMask(source_image,p) <= (QuantumRange/2))
1594 p+=(ptrdiff_t) GetPixelChannels(source_image);
1595 q+=(ptrdiff_t) GetPixelChannels(image);
1598 for (i=0; i < (ssize_t) GetPixelChannels(source_image); i++)
1600 PixelChannel channel = GetPixelChannelChannel(source_image,i);
1601 PixelTrait source_traits = GetPixelChannelTraits(source_image,
1603 PixelTrait traits = GetPixelChannelTraits(image,channel);
1604 if ((source_traits == UndefinedPixelTrait) ||
1605 (traits == UndefinedPixelTrait))
1607 SetPixelChannel(image,channel,p[i],q);
1609 p+=(ptrdiff_t) GetPixelChannels(source_image);
1610 q+=(ptrdiff_t) GetPixelChannels(image);
1612 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1613 if (sync == MagickFalse)
1615 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1620 proceed=SetImageProgress(image,CompositeImageTag,(MagickOffsetType)
1622 if (proceed == MagickFalse)
1626 source_view=DestroyCacheView(source_view);
1627 image_view=DestroyCacheView(image_view);
1628 source_image=DestroyImage(source_image);
1631 case IntensityCompositeOp:
1633 if ((x_offset < 0) || (y_offset < 0))
1635 if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
1637 if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
1640 source_view=AcquireVirtualCacheView(source_image,exception);
1641 image_view=AcquireAuthenticCacheView(image,exception);
1642#if defined(MAGICKCORE_OPENMP_SUPPORT)
1643 #pragma omp parallel for schedule(static) shared(status) \
1644 magick_number_threads(source_image,image,source_image->rows,4)
1646 for (y=0; y < (ssize_t) source_image->rows; y++)
1660 if (status == MagickFalse)
1662 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1664 q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
1665 source_image->columns,1,exception);
1666 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1671 for (x=0; x < (ssize_t) source_image->columns; x++)
1673 if (GetPixelReadMask(source_image,p) <= (QuantumRange/2))
1675 p+=(ptrdiff_t) GetPixelChannels(source_image);
1676 q+=(ptrdiff_t) GetPixelChannels(image);
1679 SetPixelAlpha(image,clamp != MagickFalse ?
1680 ClampPixel(GetPixelIntensity(source_image,p)) :
1681 ClampToQuantum(GetPixelIntensity(source_image,p)),q);
1682 p+=(ptrdiff_t) GetPixelChannels(source_image);
1683 q+=(ptrdiff_t) GetPixelChannels(image);
1685 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1686 if (sync == MagickFalse)
1688 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1693 proceed=SetImageProgress(image,CompositeImageTag,(MagickOffsetType)
1695 if (proceed == MagickFalse)
1699 source_view=DestroyCacheView(source_view);
1700 image_view=DestroyCacheView(image_view);
1701 source_image=DestroyImage(source_image);
1704 case CopyAlphaCompositeOp:
1705 case ChangeMaskCompositeOp:
1711 if ((image->alpha_trait & BlendPixelTrait) == 0)
1712 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1715 case BlurCompositeOp:
1740 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1741 if (canvas_image == (
Image *) NULL)
1743 source_image=DestroyImage(source_image);
1744 return(MagickFalse);
1750 artifact=GetImageArtifact(image,
"compose:args");
1751 if (artifact != (
const char *) NULL)
1752 flags=ParseGeometry(artifact,&geometry_info);
1753 if ((flags & WidthValue) == 0)
1755 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1756 "InvalidSetting",
"'%s' '%s'",
"compose:args",artifact);
1757 source_image=DestroyImage(source_image);
1758 canvas_image=DestroyImage(canvas_image);
1759 return(MagickFalse);
1766 width=2.0*geometry_info.rho;
1768 if ((flags & HeightValue) != 0)
1769 height=2.0*geometry_info.sigma;
1777 if ((flags & XValue) != 0 )
1785 angle=DegreesToRadians(geometry_info.xi);
1786 blur.x1=width*cos(angle);
1787 blur.x2=width*sin(angle);
1788 blur.y1=(-height*sin(angle));
1789 blur.y2=height*cos(angle);
1793 if ((flags & YValue) != 0 )
1798 angle_start=DegreesToRadians(geometry_info.xi);
1799 angle_range=DegreesToRadians(geometry_info.psi)-angle_start;
1810 resample_filter=AcquireResampleFilter(image,exception);
1811 SetResampleFilter(resample_filter,GaussianFilter);
1815 GetPixelInfo(image,&pixel);
1816 source_view=AcquireVirtualCacheView(source_image,exception);
1817 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
1818 for (y=0; y < (ssize_t) source_image->rows; y++)
1832 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
1834 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1836 q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
1838 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1840 for (x=0; x < (ssize_t) source_image->columns; x++)
1842 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
1844 p+=(ptrdiff_t) GetPixelChannels(source_image);
1847 if (fabs(angle_range) > MagickEpsilon)
1852 angle=angle_start+angle_range*QuantumScale*(double)
1853 GetPixelBlue(source_image,p);
1854 blur.x1=width*cos(angle);
1855 blur.x2=width*sin(angle);
1856 blur.y1=(-height*sin(angle));
1857 blur.y2=height*cos(angle);
1859 ScaleResampleFilter(resample_filter,
1860 blur.x1*QuantumScale*(
double) GetPixelRed(source_image,p),
1861 blur.y1*QuantumScale*(
double) GetPixelGreen(source_image,p),
1862 blur.x2*QuantumScale*(
double) GetPixelRed(source_image,p),
1863 blur.y2*QuantumScale*(
double) GetPixelGreen(source_image,p) );
1864 (void) ResamplePixelColor(resample_filter,(
double) x_offset+x,
1865 (
double) y_offset+y,&pixel,exception);
1866 SetPixelViaPixelInfo(canvas_image,&pixel,q);
1867 p+=(ptrdiff_t) GetPixelChannels(source_image);
1868 q+=(ptrdiff_t) GetPixelChannels(canvas_image);
1870 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
1871 if (sync == MagickFalse)
1874 resample_filter=DestroyResampleFilter(resample_filter);
1875 source_view=DestroyCacheView(source_view);
1876 canvas_view=DestroyCacheView(canvas_view);
1877 source_image=DestroyImage(source_image);
1878 source_image=canvas_image;
1881 case DisplaceCompositeOp:
1882 case DistortCompositeOp:
1903 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1904 if (canvas_image == (
Image *) NULL)
1906 source_image=DestroyImage(source_image);
1907 return(MagickFalse);
1909 SetGeometryInfo(&geometry_info);
1911 artifact=GetImageArtifact(image,
"compose:args");
1912 if (artifact != (
char *) NULL)
1913 flags=ParseGeometry(artifact,&geometry_info);
1914 if ((flags & (WidthValue | HeightValue)) == 0 )
1916 if ((flags & AspectValue) == 0)
1918 horizontal_scale=(MagickRealType) (source_image->columns-1)/2.0;
1919 vertical_scale=(MagickRealType) (source_image->rows-1)/2.0;
1923 horizontal_scale=(MagickRealType) (image->columns-1)/2.0;
1924 vertical_scale=(MagickRealType) (image->rows-1)/2.0;
1929 horizontal_scale=geometry_info.rho;
1930 vertical_scale=geometry_info.sigma;
1931 if ((flags & PercentValue) != 0)
1933 if ((flags & AspectValue) == 0)
1935 horizontal_scale*=(source_image->columns-1)/200.0;
1936 vertical_scale*=(source_image->rows-1)/200.0;
1940 horizontal_scale*=(image->columns-1)/200.0;
1941 vertical_scale*=(image->rows-1)/200.0;
1944 if ((flags & HeightValue) == 0)
1945 vertical_scale=horizontal_scale;
1955 center.x=(MagickRealType) x_offset;
1956 center.y=(MagickRealType) y_offset;
1957 if (compose == DistortCompositeOp)
1959 if ((flags & XValue) == 0)
1960 if ((flags & AspectValue) != 0)
1961 center.x=(MagickRealType) ((image->columns-1)/2.0);
1963 center.x=(MagickRealType) (x_offset+(source_image->columns-1)/
1966 if ((flags & AspectValue) != 0)
1967 center.x=geometry_info.xi;
1969 center.x=(MagickRealType) (x_offset+geometry_info.xi);
1970 if ((flags & YValue) == 0)
1971 if ((flags & AspectValue) != 0)
1972 center.y=(MagickRealType) ((image->rows-1)/2.0);
1974 center.y=(MagickRealType) (y_offset+(source_image->rows-1)/2.0);
1976 if ((flags & AspectValue) != 0)
1977 center.y=geometry_info.psi;
1979 center.y=(MagickRealType) (y_offset+geometry_info.psi);
1985 GetPixelInfo(image,&pixel);
1986 image_view=AcquireVirtualCacheView(image,exception);
1987 source_view=AcquireVirtualCacheView(source_image,exception);
1988 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
1989 for (y=0; y < (ssize_t) source_image->rows; y++)
2003 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
2005 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
2007 q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
2009 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
2011 for (x=0; x < (ssize_t) source_image->columns; x++)
2013 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
2015 p+=(ptrdiff_t) GetPixelChannels(source_image);
2021 offset.x=(double) (horizontal_scale*((
double) GetPixelRed(
2022 source_image,p)-(((MagickRealType) QuantumRange+1.0)/2.0)))/
2023 (((MagickRealType) QuantumRange+1.0)/2.0)+center.x+
2024 ((compose == DisplaceCompositeOp) ? x : 0);
2025 offset.y=(double) (vertical_scale*((
double) GetPixelGreen(
2026 source_image,p)-(((MagickRealType) QuantumRange+1.0)/2.0)))/
2027 (((MagickRealType) QuantumRange+1.0)/2.0)+center.y+
2028 ((compose == DisplaceCompositeOp) ? y : 0);
2029 status=InterpolatePixelInfo(image,image_view,
2030 UndefinedInterpolatePixel,(
double) offset.x,(
double) offset.y,
2032 if (status == MagickFalse)
2037 pixel.alpha=(MagickRealType) QuantumRange*(QuantumScale*pixel.alpha)*
2038 (QuantumScale*(double) GetPixelAlpha(source_image,p));
2039 SetPixelViaPixelInfo(canvas_image,&pixel,q);
2040 p+=(ptrdiff_t) GetPixelChannels(source_image);
2041 q+=(ptrdiff_t) GetPixelChannels(canvas_image);
2043 if (x < (ssize_t) source_image->columns)
2045 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
2046 if (sync == MagickFalse)
2049 canvas_view=DestroyCacheView(canvas_view);
2050 source_view=DestroyCacheView(source_view);
2051 image_view=DestroyCacheView(image_view);
2052 source_image=DestroyImage(source_image);
2053 source_image=canvas_image;
2056 case DissolveCompositeOp:
2061 artifact=GetImageArtifact(image,
"compose:args");
2062 if (artifact != (
char *) NULL)
2064 flags=ParseGeometry(artifact,&geometry_info);
2065 source_dissolve=geometry_info.rho/100.0;
2066 canvas_dissolve=1.0;
2067 if ((source_dissolve-MagickEpsilon) < 0.0)
2068 source_dissolve=0.0;
2069 if ((source_dissolve+MagickEpsilon) > 1.0)
2071 canvas_dissolve=2.0-source_dissolve;
2072 source_dissolve=1.0;
2074 if ((flags & SigmaValue) != 0)
2075 canvas_dissolve=geometry_info.sigma/100.0;
2076 if ((canvas_dissolve-MagickEpsilon) < 0.0)
2077 canvas_dissolve=0.0;
2078 if ((canvas_dissolve+MagickEpsilon) > 1.0)
2079 canvas_dissolve=1.0;
2083 case BlendCompositeOp:
2085 artifact=GetImageArtifact(image,
"compose:args");
2086 if (artifact != (
char *) NULL)
2088 flags=ParseGeometry(artifact,&geometry_info);
2089 source_dissolve=geometry_info.rho/100.0;
2090 canvas_dissolve=1.0-source_dissolve;
2091 if ((flags & SigmaValue) != 0)
2092 canvas_dissolve=geometry_info.sigma/100.0;
2096 case SaliencyBlendCompositeOp:
2099 residual_threshold = 0.0002,
2105 artifact=GetImageArtifact(image,
"compose:args");
2106 if (artifact != (
char *) NULL)
2108 flags=ParseGeometry(artifact,&geometry_info);
2109 iterations=geometry_info.rho;
2110 if ((flags & SigmaValue) != 0)
2111 residual_threshold=geometry_info.sigma;
2112 if ((flags & XiValue) != 0)
2113 tick=(size_t) geometry_info.xi;
2115 status=SaliencyBlendImage(image,composite,x_offset,y_offset,iterations,
2116 residual_threshold,tick,exception);
2117 source_image=DestroyImage(source_image);
2120 case SeamlessBlendCompositeOp:
2123 residual_threshold = 0.0002,
2129 artifact=GetImageArtifact(image,
"compose:args");
2130 if (artifact != (
char *) NULL)
2132 flags=ParseGeometry(artifact,&geometry_info);
2133 iterations=geometry_info.rho;
2134 if ((flags & SigmaValue) != 0)
2135 residual_threshold=geometry_info.sigma;
2136 if ((flags & XiValue) != 0)
2137 tick=(size_t) geometry_info.xi;
2139 status=SeamlessBlendImage(image,composite,x_offset,y_offset,iterations,
2140 residual_threshold,tick,exception);
2141 source_image=DestroyImage(source_image);
2144 case MathematicsCompositeOp:
2154 SetGeometryInfo(&geometry_info);
2155 artifact=GetImageArtifact(image,
"compose:args");
2156 if (artifact != (
char *) NULL)
2158 flags=ParseGeometry(artifact,&geometry_info);
2159 if (flags == NoValue)
2160 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2161 "InvalidGeometry",
"`%s'",artifact);
2165 case ModulateCompositeOp:
2170 artifact=GetImageArtifact(image,
"compose:args");
2171 if (artifact != (
char *) NULL)
2173 flags=ParseGeometry(artifact,&geometry_info);
2174 percent_luma=geometry_info.rho;
2175 if ((flags & SigmaValue) != 0)
2176 percent_chroma=geometry_info.sigma;
2180 case ThresholdCompositeOp:
2185 artifact=GetImageArtifact(image,
"compose:args");
2186 if (artifact != (
char *) NULL)
2188 flags=ParseGeometry(artifact,&geometry_info);
2189 amount=geometry_info.rho;
2190 threshold=geometry_info.sigma;
2191 if ((flags & SigmaValue) == 0)
2194 threshold*=(double) QuantumRange;
2205 midpoint=((MagickRealType) QuantumRange+1.0)/2;
2206 source_view=AcquireVirtualCacheView(source_image,exception);
2207 image_view=AcquireAuthenticCacheView(image,exception);
2208#if defined(MAGICKCORE_OPENMP_SUPPORT)
2209 #pragma omp parallel for schedule(static) shared(progress,status) \
2210 magick_number_threads(source_image,image,image->rows,1)
2212 for (y=0; y < (ssize_t) image->rows; y++)
2238 if (status == MagickFalse)
2240 if (clip_to_self != MagickFalse)
2244 if ((y-(
double) y_offset) >= (
double) source_image->rows)
2250 pixels=(Quantum *) NULL;
2252 if ((y >= y_offset) &&
2253 ((y-(
double) y_offset) < (
double) source_image->rows))
2255 p=GetCacheViewVirtualPixels(source_view,0,
2256 CastDoubleToLong(y-(
double) y_offset),source_image->columns,1,
2258 if (p == (
const Quantum *) NULL)
2265 p-=(ptrdiff_t)CastDoubleToLong((
double) x_offset*GetPixelChannels(source_image));
2267 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2268 if (q == (Quantum *) NULL)
2273 GetPixelInfo(image,&canvas_pixel);
2274 GetPixelInfo(source_image,&source_pixel);
2275 for (x=0; x < (ssize_t) image->columns; x++)
2299 if (clip_to_self != MagickFalse)
2303 q+=(ptrdiff_t) GetPixelChannels(image);
2306 if ((x-(
double) x_offset) >= (
double) source_image->columns)
2309 if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
2310 ((x-(
double) x_offset) >= (
double) source_image->columns))
2313 source[MaxPixelChannels];
2320 (void) GetOneVirtualPixel(source_image,
2321 CastDoubleToLong(x-(
double) x_offset),
2322 CastDoubleToLong(y-(
double) y_offset),source,exception);
2323 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2328 PixelChannel channel = GetPixelChannelChannel(image,i);
2329 PixelTrait traits = GetPixelChannelTraits(image,channel);
2330 PixelTrait source_traits = GetPixelChannelTraits(source_image,
2332 if ((traits == UndefinedPixelTrait) ||
2333 (source_traits == UndefinedPixelTrait))
2337 case AlphaCompositeOp:
2338 case ChangeMaskCompositeOp:
2339 case CopyAlphaCompositeOp:
2340 case DstAtopCompositeOp:
2341 case DstInCompositeOp:
2343 case OutCompositeOp:
2344 case SrcInCompositeOp:
2345 case SrcOutCompositeOp:
2347 if (channel == AlphaPixelChannel)
2348 pixel=(MagickRealType) TransparentAlpha;
2350 pixel=(MagickRealType) q[i];
2353 case ClearCompositeOp:
2354 case CopyCompositeOp:
2355 case ReplaceCompositeOp:
2356 case SrcCompositeOp:
2358 if (channel == AlphaPixelChannel)
2359 pixel=(MagickRealType) TransparentAlpha;
2364 case BlendCompositeOp:
2365 case DissolveCompositeOp:
2367 if (channel == AlphaPixelChannel)
2368 pixel=canvas_dissolve*(double) GetPixelAlpha(source_image,
2371 pixel=(MagickRealType) source[channel];
2376 pixel=(MagickRealType) source[channel];
2380 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
2381 ClampToQuantum(pixel);
2383 q+=(ptrdiff_t) GetPixelChannels(image);
2391 Sa=QuantumScale*(double) GetPixelAlpha(source_image,p);
2392 Da=QuantumScale*(double) GetPixelAlpha(image,q);
2395 case BumpmapCompositeOp:
2396 case ColorBurnCompositeOp:
2397 case ColorDodgeCompositeOp:
2398 case DarkenCompositeOp:
2399 case DifferenceCompositeOp:
2400 case DivideDstCompositeOp:
2401 case DivideSrcCompositeOp:
2402 case ExclusionCompositeOp:
2403 case FreezeCompositeOp:
2404 case HardLightCompositeOp:
2405 case HardMixCompositeOp:
2406 case InterpolateCompositeOp:
2407 case LightenCompositeOp:
2408 case LinearBurnCompositeOp:
2409 case LinearDodgeCompositeOp:
2410 case LinearLightCompositeOp:
2411 case MathematicsCompositeOp:
2412 case MinusDstCompositeOp:
2413 case MinusSrcCompositeOp:
2414 case MultiplyCompositeOp:
2415 case NegateCompositeOp:
2416 case OverlayCompositeOp:
2417 case PegtopLightCompositeOp:
2418 case PinLightCompositeOp:
2419 case ReflectCompositeOp:
2420 case ScreenCompositeOp:
2421 case SoftBurnCompositeOp:
2422 case SoftDodgeCompositeOp:
2423 case SoftLightCompositeOp:
2424 case StampCompositeOp:
2425 case VividLightCompositeOp:
2427 alpha=RoundToUnity(Sa+Da-Sa*Da);
2430 case DstAtopCompositeOp:
2431 case DstInCompositeOp:
2433 case SrcInCompositeOp:
2438 case DissolveCompositeOp:
2440 alpha=source_dissolve*Sa*(-canvas_dissolve*Da)+source_dissolve*Sa+
2444 case DstOverCompositeOp:
2445 case OverCompositeOp:
2446 case SrcOverCompositeOp:
2451 case DstOutCompositeOp:
2456 case OutCompositeOp:
2457 case SrcOutCompositeOp:
2462 case BlendCompositeOp:
2463 case PlusCompositeOp:
2465 alpha=RoundToUnity(source_dissolve*Sa+canvas_dissolve*Da);
2468 case XorCompositeOp:
2470 alpha=Sa+Da-2.0*Sa*Da;
2473 case ModulusAddCompositeOp:
2480 alpha=((Sa+Da)-1.0);
2483 case ModulusSubtractCompositeOp:
2490 alpha=((Sa-Da)+1.0);
2501 case ColorizeCompositeOp:
2502 case HueCompositeOp:
2503 case LuminizeCompositeOp:
2504 case ModulateCompositeOp:
2505 case RMSECompositeOp:
2506 case SaturateCompositeOp:
2508 Si=GetPixelIntensity(source_image,p);
2509 GetPixelInfoPixel(source_image,p,&source_pixel);
2510 GetPixelInfoPixel(image,q,&canvas_pixel);
2513 case BumpmapCompositeOp:
2514 case CopyAlphaCompositeOp:
2515 case DarkenIntensityCompositeOp:
2516 case LightenIntensityCompositeOp:
2518 Si=GetPixelIntensity(source_image,p);
2519 Di=GetPixelIntensity(image,q);
2525 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2531 PixelChannel channel = GetPixelChannelChannel(image,i);
2532 PixelTrait traits = GetPixelChannelTraits(image,channel);
2533 PixelTrait source_traits = GetPixelChannelTraits(source_image,channel);
2534 if (traits == UndefinedPixelTrait)
2536 if ((channel == AlphaPixelChannel) &&
2537 ((traits & UpdatePixelTrait) != 0))
2544 case AlphaCompositeOp:
2546 pixel=(double) QuantumRange*Sa;
2549 case AtopCompositeOp:
2550 case CopyBlackCompositeOp:
2551 case CopyBlueCompositeOp:
2552 case CopyCyanCompositeOp:
2553 case CopyGreenCompositeOp:
2554 case CopyMagentaCompositeOp:
2555 case CopyRedCompositeOp:
2556 case CopyYellowCompositeOp:
2557 case SrcAtopCompositeOp:
2558 case DstCompositeOp:
2561 pixel=(double) QuantumRange*Da;
2564 case BumpmapCompositeOp:
2569 case ChangeMaskCompositeOp:
2571 if (IsFuzzyEquivalencePixel(source_image,p,image,q) != MagickFalse)
2572 pixel=(MagickRealType) TransparentAlpha;
2574 pixel=(double) QuantumRange*Da;
2577 case ClearCompositeOp:
2579 pixel=(MagickRealType) TransparentAlpha;
2582 case ColorizeCompositeOp:
2583 case HueCompositeOp:
2584 case LuminizeCompositeOp:
2585 case RMSECompositeOp:
2586 case SaturateCompositeOp:
2588 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
2590 pixel=(double) QuantumRange*Da;
2593 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
2595 pixel=(double) QuantumRange*Sa;
2600 pixel=(double) QuantumRange*Da;
2603 pixel=(double) QuantumRange*Sa;
2606 case CopyAlphaCompositeOp:
2608 if (source_image->alpha_trait == UndefinedPixelTrait)
2611 pixel=(double) QuantumRange*Sa;
2614 case BlurCompositeOp:
2615 case CopyCompositeOp:
2616 case DisplaceCompositeOp:
2617 case DistortCompositeOp:
2618 case DstAtopCompositeOp:
2619 case ReplaceCompositeOp:
2620 case SrcCompositeOp:
2622 pixel=(double) QuantumRange*Sa;
2625 case DarkenIntensityCompositeOp:
2627 if (compose_sync == MagickFalse)
2629 pixel=Si < Di? Sa : Da;
2632 pixel=Sa*Si < Da*Di ? Sa : Da;
2635 case DifferenceCompositeOp:
2637 pixel=(double) QuantumRange*fabs((
double) (Sa-Da));
2640 case FreezeCompositeOp:
2642 pixel=(double) QuantumRange*(1.0-(1.0-Sa)*(1.0-Sa)*
2643 PerceptibleReciprocal(Da));
2648 case InterpolateCompositeOp:
2650 pixel=(double) QuantumRange*(0.5-0.25*cos(MagickPI*Sa)-0.25*
2654 case LightenIntensityCompositeOp:
2656 if (compose_sync == MagickFalse)
2658 pixel=Si > Di ? Sa : Da;
2661 pixel=Sa*Si > Da*Di ? Sa : Da;
2664 case ModulateCompositeOp:
2666 pixel=(double) QuantumRange*Da;
2669 case MultiplyCompositeOp:
2671 if (compose_sync == MagickFalse)
2673 pixel=(double) QuantumRange*Sa*Da;
2676 pixel=(double) QuantumRange*alpha;
2679 case NegateCompositeOp:
2681 pixel=(double) QuantumRange*((1.0-Sa-Da));
2684 case ReflectCompositeOp:
2686 pixel=(double) QuantumRange*(Sa*Sa*
2687 PerceptibleReciprocal(1.0-Da));
2688 if (pixel > (
double) QuantumRange)
2689 pixel=(double) QuantumRange;
2692 case StampCompositeOp:
2694 pixel=(double) QuantumRange*(Sa+Da*Da-1.0);
2697 case StereoCompositeOp:
2699 pixel=(double) QuantumRange*(Sa+Da)/2;
2704 pixel=(double) QuantumRange*alpha;
2708 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
2709 ClampToQuantum(pixel);
2712 if (source_traits == UndefinedPixelTrait)
2718 Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
2719 Dc=(MagickRealType) q[i];
2720 if ((traits & CopyPixelTrait) != 0)
2725 q[i]=ClampToQuantum(Dc);
2733 Sca=QuantumScale*Sa*Sc;
2734 Dca=QuantumScale*Da*Dc;
2735 SaSca=Sa*PerceptibleReciprocal(Sca);
2736 DcaDa=Dca*PerceptibleReciprocal(Da);
2739 case DarkenCompositeOp:
2740 case LightenCompositeOp:
2741 case ModulusSubtractCompositeOp:
2743 gamma=PerceptibleReciprocal(1.0-alpha);
2748 gamma=PerceptibleReciprocal(alpha);
2755 case AlphaCompositeOp:
2757 pixel=(double) QuantumRange*Sa;
2760 case AtopCompositeOp:
2761 case SrcAtopCompositeOp:
2763 pixel=(double) QuantumRange*(Sca*Da+Dca*(1.0-Sa));
2766 case BlendCompositeOp:
2768 pixel=gamma*(source_dissolve*Sa*Sc+canvas_dissolve*Da*Dc);
2771 case CopyCompositeOp:
2772 case ReplaceCompositeOp:
2773 case SrcCompositeOp:
2775 pixel=(double) QuantumRange*Sca;
2778 case BlurCompositeOp:
2779 case DisplaceCompositeOp:
2780 case DistortCompositeOp:
2785 case BumpmapCompositeOp:
2787 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
2792 pixel=(double) QuantumScale*Si*Dc;
2795 case ChangeMaskCompositeOp:
2800 case ClearCompositeOp:
2805 case ColorBurnCompositeOp:
2807 if ((Sca == 0.0) && (Dca == Da))
2809 pixel=(double) QuantumRange*gamma*(Sa*Da+Dca*(1.0-Sa));
2814 pixel=(double) QuantumRange*gamma*(Dca*(1.0-Sa));
2817 pixel=(double) QuantumRange*gamma*(Sa*Da-Sa*Da*MagickMin(1.0,
2818 (1.0-DcaDa)*SaSca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
2821 case ColorDodgeCompositeOp:
2823 if ((Sca*Da+Dca*Sa) >= Sa*Da)
2824 pixel=(double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*
2827 pixel=(double) QuantumRange*gamma*(Dca*Sa*Sa*
2828 PerceptibleReciprocal(Sa-Sca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
2831 case ColorizeCompositeOp:
2833 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
2838 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
2843 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
2844 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
2845 white_luminance,illuminant,&sans,&sans,&luma);
2846 ConvertRGBToGeneric(colorspace,(
double) source_pixel.red,
2847 (
double) source_pixel.green,(
double) source_pixel.blue,
2848 white_luminance,illuminant,&hue,&chroma,&sans);
2849 ConvertGenericToRGB(colorspace,hue,chroma,luma,
2850 white_luminance,illuminant,&red,&green,&blue);
2853 case RedPixelChannel: pixel=red;
break;
2854 case GreenPixelChannel: pixel=green;
break;
2855 case BluePixelChannel: pixel=blue;
break;
2856 default: pixel=Dc;
break;
2860 case CopyAlphaCompositeOp:
2865 case CopyBlackCompositeOp:
2867 if (channel == BlackPixelChannel)
2868 pixel=(MagickRealType) GetPixelBlack(source_image,p);
2871 case CopyBlueCompositeOp:
2872 case CopyYellowCompositeOp:
2874 if (channel == BluePixelChannel)
2875 pixel=(MagickRealType) GetPixelBlue(source_image,p);
2878 case CopyGreenCompositeOp:
2879 case CopyMagentaCompositeOp:
2881 if (channel == GreenPixelChannel)
2882 pixel=(MagickRealType) GetPixelGreen(source_image,p);
2885 case CopyRedCompositeOp:
2886 case CopyCyanCompositeOp:
2888 if (channel == RedPixelChannel)
2889 pixel=(MagickRealType) GetPixelRed(source_image,p);
2892 case DarkenCompositeOp:
2899 if (compose_sync == MagickFalse)
2901 pixel=MagickMin(Sc,Dc);
2904 if ((Sca*Da) < (Dca*Sa))
2906 pixel=(double) QuantumRange*(Sca+Dca*(1.0-Sa));
2909 pixel=(double) QuantumRange*(Dca+Sca*(1.0-Da));
2912 case DarkenIntensityCompositeOp:
2914 if (compose_sync == MagickFalse)
2916 pixel=Si < Di ? Sc : Dc;
2919 pixel=Sa*Si < Da*Di ? Sc : Dc;
2922 case DifferenceCompositeOp:
2924 if (compose_sync == MagickFalse)
2926 pixel=fabs((
double) Sc-Dc);
2929 pixel=(double) QuantumRange*gamma*(Sca+Dca-2.0*MagickMin(Sca*Da,
2933 case DissolveCompositeOp:
2935 pixel=gamma*(source_dissolve*Sa*Sc-source_dissolve*Sa*
2936 canvas_dissolve*Da*Dc+canvas_dissolve*Da*Dc);
2939 case DivideDstCompositeOp:
2941 if (compose_sync == MagickFalse)
2943 pixel=(double) QuantumRange*(Sc/PerceptibleReciprocal(Dc));
2946 if ((fabs((
double) Sca) < MagickEpsilon) &&
2947 (fabs((
double) Dca) < MagickEpsilon))
2949 pixel=(double) QuantumRange*gamma*(Sca*(1.0-Da)+Dca*(1.0-Sa));
2952 if (fabs((
double) Dca) < MagickEpsilon)
2954 pixel=(double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*
2958 pixel=(double) QuantumRange*gamma*(Sca*Da*Da/Dca+Sca*(1.0-Da)+Dca*
2962 case DivideSrcCompositeOp:
2964 if (compose_sync == MagickFalse)
2966 pixel=(double) QuantumRange*(Dc/PerceptibleReciprocal(Sc));
2969 if ((fabs((
double) Dca) < MagickEpsilon) &&
2970 (fabs((
double) Sca) < MagickEpsilon))
2972 pixel=(double) QuantumRange*gamma*(Dca*(1.0-Sa)+Sca*(1.0-Da));
2975 if (fabs((
double) Sca) < MagickEpsilon)
2977 pixel=(double) QuantumRange*gamma*(Da*Sa+Dca*(1.0-Sa)+Sca*
2981 pixel=(double) QuantumRange*gamma*(Dca*Sa*SaSca+Dca*(1.0-Sa)+Sca*
2985 case DstAtopCompositeOp:
2987 pixel=(double) QuantumRange*(Dca*Sa+Sca*(1.0-Da));
2990 case DstCompositeOp:
2993 pixel=(double) QuantumRange*Dca;
2996 case DstInCompositeOp:
2998 pixel=(double) QuantumRange*gamma*(Dca*Sa);
3001 case DstOutCompositeOp:
3003 pixel=(double) QuantumRange*gamma*(Dca*(1.0-Sa));
3006 case DstOverCompositeOp:
3008 pixel=(double) QuantumRange*gamma*(Dca+Sca*(1.0-Da));
3011 case ExclusionCompositeOp:
3013 pixel=(double) QuantumRange*gamma*(Sca*Da+Dca*Sa-2.0*Sca*Dca+Sca*
3014 (1.0-Da)+Dca*(1.0-Sa));
3017 case FreezeCompositeOp:
3019 pixel=(double) QuantumRange*gamma*(1.0-(1.0-Sca)*(1.0-Sca)*
3020 PerceptibleReciprocal(Dca));
3025 case HardLightCompositeOp:
3029 pixel=(double) QuantumRange*gamma*(2.0*Sca*Dca+Sca*(1.0-Da)+Dca*
3033 pixel=(double) QuantumRange*gamma*(Sa*Da-2.0*(Da-Dca)*(Sa-Sca)+Sca*
3034 (1.0-Da)+Dca*(1.0-Sa));
3037 case HardMixCompositeOp:
3039 pixel=gamma*(((Sca+Dca) < 1.0) ? 0.0 : (double) QuantumRange);
3042 case HueCompositeOp:
3044 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3049 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3054 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3055 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3056 white_luminance,illuminant,&hue,&chroma,&luma);
3057 ConvertRGBToGeneric(colorspace,(
double) source_pixel.red,
3058 (
double) source_pixel.green,(
double) source_pixel.blue,
3059 white_luminance,illuminant,&hue,&sans,&sans);
3060 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3061 white_luminance,illuminant,&red,&green,&blue);
3064 case RedPixelChannel: pixel=red;
break;
3065 case GreenPixelChannel: pixel=green;
break;
3066 case BluePixelChannel: pixel=blue;
break;
3067 default: pixel=Dc;
break;
3072 case SrcInCompositeOp:
3074 pixel=(double) QuantumRange*(Sca*Da);
3077 case InterpolateCompositeOp:
3079 pixel=(double) QuantumRange*(0.5-0.25*cos(MagickPI*Sca)-0.25*
3083 case LinearBurnCompositeOp:
3091 pixel=(double) QuantumRange*gamma*(Sca+Dca-Sa*Da);
3094 case LinearDodgeCompositeOp:
3096 pixel=gamma*(Sa*Sc+Da*Dc);
3099 case LinearLightCompositeOp:
3107 pixel=(double) QuantumRange*gamma*((Sca-Sa)*Da+Sca+Dca);
3110 case LightenCompositeOp:
3112 if (compose_sync == MagickFalse)
3114 pixel=MagickMax(Sc,Dc);
3117 if ((Sca*Da) > (Dca*Sa))
3119 pixel=(double) QuantumRange*(Sca+Dca*(1.0-Sa));
3122 pixel=(double) QuantumRange*(Dca+Sca*(1.0-Da));
3125 case LightenIntensityCompositeOp:
3132 if (compose_sync == MagickFalse)
3134 pixel=Si > Di ? Sc : Dc;
3137 pixel=Sa*Si > Da*Di ? Sc : Dc;
3140 case LuminizeCompositeOp:
3142 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3147 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3152 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3153 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3154 white_luminance,illuminant,&hue,&chroma,&luma);
3155 ConvertRGBToGeneric(colorspace,(
double) source_pixel.red,
3156 (
double) source_pixel.green,(
double) source_pixel.blue,
3157 white_luminance,illuminant,&sans,&sans,&luma);
3158 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3159 white_luminance,illuminant,&red,&green,&blue);
3162 case RedPixelChannel: pixel=red;
break;
3163 case GreenPixelChannel: pixel=green;
break;
3164 case BluePixelChannel: pixel=blue;
break;
3165 default: pixel=Dc;
break;
3169 case MathematicsCompositeOp:
3190 if (compose_sync == MagickFalse)
3192 pixel=geometry_info.rho*Sc*Dc+geometry_info.sigma*Sc+
3193 geometry_info.xi*Dc+geometry_info.psi;
3196 pixel=(double) QuantumRange*gamma*(geometry_info.rho*Sca*Dca+
3197 geometry_info.sigma*Sca*Da+geometry_info.xi*Dca*Sa+
3198 geometry_info.psi*Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
3201 case MinusDstCompositeOp:
3203 if (compose_sync == MagickFalse)
3208 pixel=gamma*(Sa*Sc+Da*Dc-2.0*Da*Dc*Sa);
3211 case MinusSrcCompositeOp:
3218 if (compose_sync == MagickFalse)
3223 pixel=gamma*(Da*Dc+Sa*Sc-2.0*Sa*Sc*Da);
3226 case ModulateCompositeOp:
3231 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3236 offset=(ssize_t) (Si-midpoint);
3242 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3243 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3244 white_luminance,illuminant,&hue,&chroma,&luma);
3245 luma+=(0.01*percent_luma*offset)/midpoint;
3246 chroma*=0.01*percent_chroma;
3247 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3248 white_luminance,illuminant,&red,&green,&blue);
3251 case RedPixelChannel: pixel=red;
break;
3252 case GreenPixelChannel: pixel=green;
break;
3253 case BluePixelChannel: pixel=blue;
break;
3254 default: pixel=Dc;
break;
3258 case ModulusAddCompositeOp:
3260 if (compose_sync == MagickFalse)
3265 if ((Sca+Dca) <= 1.0)
3267 pixel=(double) QuantumRange*(Sca+Dca);
3270 pixel=(double) QuantumRange*((Sca+Dca)-1.0);
3273 case ModulusSubtractCompositeOp:
3275 if (compose_sync == MagickFalse)
3280 if ((Sca-Dca) >= 0.0)
3282 pixel=(double) QuantumRange*(Sca-Dca);
3285 pixel=(double) QuantumRange*((Sca-Dca)+1.0);
3288 case MultiplyCompositeOp:
3290 if (compose_sync == MagickFalse)
3292 pixel=(double) QuantumScale*Dc*Sc;
3295 pixel=(double) QuantumRange*gamma*(Sca*Dca+Sca*(1.0-Da)+Dca*
3299 case NegateCompositeOp:
3301 pixel=(double) QuantumRange*(1.0-fabs(1.0-Sca-Dca));
3304 case OutCompositeOp:
3305 case SrcOutCompositeOp:
3307 pixel=(double) QuantumRange*(Sca*(1.0-Da));
3310 case OverCompositeOp:
3311 case SrcOverCompositeOp:
3313 pixel=(double) QuantumRange*gamma*(Sca+Dca*(1.0-Sa));
3316 case OverlayCompositeOp:
3320 pixel=(double) QuantumRange*gamma*(2.0*Dca*Sca+Dca*(1.0-Sa)+
3324 pixel=(double) QuantumRange*gamma*(Da*Sa-2.0*(Sa-Sca)*(Da-Dca)+Dca*
3325 (1.0-Sa)+Sca*(1.0-Da));
3328 case PegtopLightCompositeOp:
3338 if (fabs((
double) Da) < MagickEpsilon)
3340 pixel=(double) QuantumRange*gamma*Sca;
3343 pixel=(double) QuantumRange*gamma*(Dca*Dca*(Sa-2.0*Sca)/Da+Sca*
3344 (2.0*Dca+1.0-Da)+Dca*(1.0-Sa));
3347 case PinLightCompositeOp:
3355 if ((Dca*Sa) < (Da*(2.0*Sca-Sa)))
3357 pixel=(double) QuantumRange*gamma*(Sca*(Da+1.0)-Sa*Da+Dca*
3361 if ((Dca*Sa) > (2.0*Sca*Da))
3363 pixel=(double) QuantumRange*gamma*(Sca*Da+Sca+Dca*(1.0-Sa));
3366 pixel=(double) QuantumRange*gamma*(Sca*(1.0-Da)+Dca);
3369 case PlusCompositeOp:
3371 if (compose_sync == MagickFalse)
3376 pixel=(double) QuantumRange*(Sca+Dca);
3379 case ReflectCompositeOp:
3381 pixel=(double) QuantumRange*gamma*(Sca*Sca*
3382 PerceptibleReciprocal(1.0-Dca));
3383 if (pixel > (
double) QuantumRange)
3384 pixel=(double) QuantumRange;
3387 case RMSECompositeOp:
3392 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3397 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3403 (canvas_pixel.red-source_pixel.red)*
3404 (canvas_pixel.red-source_pixel.red)+
3405 (canvas_pixel.green-source_pixel.green)*
3406 (canvas_pixel.green-source_pixel.green)+
3407 (canvas_pixel.blue-source_pixel.blue)*
3408 (canvas_pixel.blue-source_pixel.blue)/3.0);
3411 case RedPixelChannel: pixel=gray;
break;
3412 case GreenPixelChannel: pixel=gray;
break;
3413 case BluePixelChannel: pixel=gray;
break;
3414 default: pixel=Dc;
break;
3418 case SaturateCompositeOp:
3420 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3425 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3430 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3431 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3432 white_luminance,illuminant,&hue,&chroma,&luma);
3433 ConvertRGBToGeneric(colorspace,(
double) source_pixel.red,
3434 (
double) source_pixel.green,(
double) source_pixel.blue,
3435 white_luminance,illuminant,&sans,&chroma,&sans);
3436 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3437 white_luminance,illuminant,&red,&green,&blue);
3440 case RedPixelChannel: pixel=red;
break;
3441 case GreenPixelChannel: pixel=green;
break;
3442 case BluePixelChannel: pixel=blue;
break;
3443 default: pixel=Dc;
break;
3447 case ScreenCompositeOp:
3454 if (compose_sync == MagickFalse)
3459 pixel=(double) QuantumRange*gamma*(Sca+Dca-Sca*Dca);
3462 case SoftBurnCompositeOp:
3464 if ((Sca+Dca) < 1.0)
3465 pixel=(double) QuantumRange*gamma*(0.5*Dca*
3466 PerceptibleReciprocal(1.0-Sca));
3468 pixel=(double) QuantumRange*gamma*(1.0-0.5*(1.0-Sca)*
3469 PerceptibleReciprocal(Dca));
3472 case SoftDodgeCompositeOp:
3474 if ((Sca+Dca) < 1.0)
3475 pixel=(double) QuantumRange*gamma*(0.5*Sca*
3476 PerceptibleReciprocal(1.0-Dca));
3478 pixel=(double) QuantumRange*gamma*(1.0-0.5*(1.0-Dca)*
3479 PerceptibleReciprocal(Sca));
3482 case SoftLightCompositeOp:
3486 pixel=(double) QuantumRange*gamma*(Dca*(Sa+(2.0*Sca-Sa)*
3487 (1.0-DcaDa))+Sca*(1.0-Da)+Dca*(1.0-Sa));
3490 if (((2.0*Sca) > Sa) && ((4.0*Dca) <= Da))
3492 pixel=(double) QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)*
3493 (4.0*DcaDa*(4.0*DcaDa+1.0)*(DcaDa-1.0)+7.0*DcaDa)+Sca*
3494 (1.0-Da)+Dca*(1.0-Sa));
3497 pixel=(double) QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)*
3498 (pow(DcaDa,0.5)-DcaDa)+Sca*(1.0-Da)+Dca*(1.0-Sa));
3501 case StampCompositeOp:
3503 pixel=(double) QuantumRange*(Sca+Dca*Dca-1.0);
3506 case StereoCompositeOp:
3508 if (channel == RedPixelChannel)
3509 pixel=(MagickRealType) GetPixelRed(source_image,p);
3512 case ThresholdCompositeOp:
3518 if ((MagickRealType) fabs((
double) (2.0*delta)) < threshold)
3523 pixel=gamma*(Dc+delta*amount);
3526 case VividLightCompositeOp:
3534 if ((fabs((
double) Sa) < MagickEpsilon) ||
3535 (fabs((
double) (Sca-Sa)) < MagickEpsilon))
3537 pixel=(double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*
3541 if ((2.0*Sca) <= Sa)
3543 pixel=(double) QuantumRange*gamma*(Sa*(Da+Sa*(Dca-Da)*
3544 PerceptibleReciprocal(2.0*Sca))+Sca*(1.0-Da)+Dca*(1.0-Sa));
3547 pixel=(double) QuantumRange*gamma*(Dca*Sa*Sa*
3548 PerceptibleReciprocal(2.0*(Sa-Sca))+Sca*(1.0-Da)+Dca*(1.0-Sa));
3551 case XorCompositeOp:
3553 pixel=(double) QuantumRange*(Sca*(1.0-Da)+Dca*(1.0-Sa));
3562 q[i]=clamp != MagickFalse ? ClampPixel(pixel) : ClampToQuantum(pixel);
3564 p+=(ptrdiff_t) GetPixelChannels(source_image);
3565 channels=GetPixelChannels(source_image);
3566 if (p >= (pixels+channels*source_image->columns))
3568 q+=(ptrdiff_t) GetPixelChannels(image);
3570 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3572 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3577#if defined(MAGICKCORE_OPENMP_SUPPORT)
3581 proceed=SetImageProgress(image,CompositeImageTag,progress,image->rows);
3582 if (proceed == MagickFalse)
3586 source_view=DestroyCacheView(source_view);
3587 image_view=DestroyCacheView(image_view);
3588 if (canvas_image != (
Image * ) NULL)
3589 canvas_image=DestroyImage(canvas_image);
3591 source_image=DestroyImage(source_image);
3621MagickExport MagickBooleanType TextureImage(
Image *image,
const Image *texture,
3624#define TextureImageTag "Texture/Image"
3639 assert(image != (
Image *) NULL);
3640 assert(image->signature == MagickCoreSignature);
3641 if (IsEventLogging() != MagickFalse)
3642 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
3643 if (texture == (
const Image *) NULL)
3644 return(MagickFalse);
3645 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3646 return(MagickFalse);
3647 texture_image=CloneImage(texture,0,0,MagickTrue,exception);
3648 if (texture_image == (
const Image *) NULL)
3649 return(MagickFalse);
3650 (void) TransformImageColorspace(texture_image,image->colorspace,exception);
3651 (void) SetImageVirtualPixelMethod(texture_image,TileVirtualPixelMethod,
3654 if ((image->compose != CopyCompositeOp) &&
3655 ((image->compose != OverCompositeOp) ||
3656 (image->alpha_trait != UndefinedPixelTrait) ||
3657 (texture_image->alpha_trait != UndefinedPixelTrait)))
3662 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) texture_image->rows)
3667 if (status == MagickFalse)
3669 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
3674 thread_status=CompositeImage(image,texture_image,image->compose,
3675 MagickTrue,x+texture_image->tile_offset.x,y+
3676 texture_image->tile_offset.y,exception);
3677 if (thread_status == MagickFalse)
3679 status=thread_status;
3683 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3688 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
3690 if (proceed == MagickFalse)
3694 (void) SetImageProgress(image,TextureImageTag,(MagickOffsetType)
3695 image->rows,image->rows);
3696 texture_image=DestroyImage(texture_image);
3703 texture_view=AcquireVirtualCacheView(texture_image,exception);
3704 image_view=AcquireAuthenticCacheView(image,exception);
3705#if defined(MAGICKCORE_OPENMP_SUPPORT)
3706 #pragma omp parallel for schedule(static) shared(status) \
3707 magick_number_threads(texture_image,image,image->rows,2)
3709 for (y=0; y < (ssize_t) image->rows; y++)
3727 if (status == MagickFalse)
3729 pixels=GetCacheViewVirtualPixels(texture_view,texture_image->tile_offset.x,
3730 (y+texture_image->tile_offset.y) % (ssize_t) texture_image->rows,
3731 texture_image->columns,1,exception);
3732 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3733 if ((pixels == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
3738 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
3744 width=texture_image->columns;
3745 if ((x+(ssize_t) width) > (ssize_t) image->columns)
3746 width=image->columns-(size_t) x;
3747 for (j=0; j < (ssize_t) width; j++)
3752 for (i=0; i < (ssize_t) GetPixelChannels(texture_image); i++)
3754 PixelChannel channel = GetPixelChannelChannel(texture_image,i);
3755 PixelTrait traits = GetPixelChannelTraits(image,channel);
3756 PixelTrait texture_traits=GetPixelChannelTraits(texture_image,
3758 if ((traits == UndefinedPixelTrait) ||
3759 (texture_traits == UndefinedPixelTrait))
3761 SetPixelChannel(image,channel,p[i],q);
3763 p+=(ptrdiff_t) GetPixelChannels(texture_image);
3764 q+=(ptrdiff_t) GetPixelChannels(image);
3767 sync=SyncCacheViewAuthenticPixels(image_view,exception);
3768 if (sync == MagickFalse)
3770 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3775 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
3777 if (proceed == MagickFalse)
3781 texture_view=DestroyCacheView(texture_view);
3782 image_view=DestroyCacheView(image_view);
3783 texture_image=DestroyImage(texture_image);