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,
186 ExceptionInfo *exception)
198 kernel_info=AcquireKernelInfo(kernel,exception);
199 if (kernel_info == (KernelInfo *) NULL)
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,
215 ExceptionInfo *exception)
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,
301 const Image *beta_image,
const Image *dx_image,
const Image *dy_image,
302 ExceptionInfo *exception)
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,
491 const Image *beta_image,ExceptionInfo *exception)
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,
617 const Image *mask_image,ExceptionInfo *exception)
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);
681static Image *BlendMeanImage(Image *image,
const Image *mask_image,
682 ExceptionInfo *exception)
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,
809 const Image *beta_image,
double *residual,ExceptionInfo *exception)
817 channel_residual = 0.0;
823 columns = MagickMax(alpha_image->columns,beta_image->columns),
824 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 reduction(+:area) reduction(+:channel_residual) \
834 magick_number_threads(alpha_image,alpha_image,rows,1)
836 for (y=0; y < (ssize_t) rows; y++)
845 if (status == MagickFalse)
847 p=GetCacheViewVirtualPixels(alpha_view,0,y,columns,1,exception);
848 q=GetCacheViewVirtualPixels(beta_view,0,y,columns,1,exception);
849 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL))
854 channel_residual=0.0;
855 for (x=0; x < (ssize_t) columns; x++)
864 if ((GetPixelReadMask(alpha_image,p) <= (QuantumRange/2)) ||
865 (GetPixelReadMask(beta_image,q) <= (QuantumRange/2)))
867 p+=(ptrdiff_t) GetPixelChannels(alpha_image);
868 q+=(ptrdiff_t) GetPixelChannels(beta_image);
871 Sa=QuantumScale*(double) GetPixelAlpha(alpha_image,p);
872 Da=QuantumScale*(double) GetPixelAlpha(beta_image,q);
873 for (i=0; i < (ssize_t) GetPixelChannels(alpha_image); i++)
878 PixelChannel channel = GetPixelChannelChannel(alpha_image,i);
879 PixelTrait traits = GetPixelChannelTraits(alpha_image,channel);
880 PixelTrait beta_traits = GetPixelChannelTraits(beta_image,channel);
881 if ((traits == UndefinedPixelTrait) ||
882 (beta_traits == UndefinedPixelTrait) ||
883 ((beta_traits & UpdatePixelTrait) == 0))
885 if (channel == AlphaPixelChannel)
886 distance=QuantumScale*((double) p[i]-(double) GetPixelChannel(
887 beta_image,channel,q));
889 distance=QuantumScale*(Sa*(double) p[i]-Da*(double) GetPixelChannel(
890 beta_image,channel,q));
891 channel_residual+=distance*distance;
894 p+=(ptrdiff_t) GetPixelChannels(alpha_image);
895 q+=(ptrdiff_t) GetPixelChannels(beta_image);
898 beta_view=DestroyCacheView(beta_view);
899 alpha_view=DestroyCacheView(alpha_view);
900 area=MagickSafeReciprocal(area);
901 *residual=sqrt(area*channel_residual/(
double) GetImageChannels(alpha_image));
905static MagickBooleanType CompositeOverImage(Image *image,
906 const Image *source_image,
const MagickBooleanType clip_to_self,
907 const ssize_t x_offset,
const ssize_t y_offset,ExceptionInfo *exception)
909#define CompositeImageTag "Composite/Image"
934 value=GetImageArtifact(image,
"compose:clamp");
935 if (value != (
const char *) NULL)
936 clamp=IsStringTrue(value);
939 source_view=AcquireVirtualCacheView(source_image,exception);
940 image_view=AcquireAuthenticCacheView(image,exception);
941#if defined(MAGICKCORE_OPENMP_SUPPORT)
942 #pragma omp parallel for schedule(static) shared(progress,status) \
943 magick_number_threads(source_image,image,image->rows,1)
945 for (y=0; y < (ssize_t) image->rows; y++)
963 if (status == MagickFalse)
965 if (clip_to_self != MagickFalse)
969 if ((y-y_offset) >= (ssize_t) source_image->rows)
975 pixels=(Quantum *) NULL;
977 if ((y >= y_offset) &&
978 ((y-y_offset) < (ssize_t) source_image->rows))
980 p=GetCacheViewVirtualPixels(source_view,0,CastDoubleToSsizeT((
double) y-
981 y_offset),source_image->columns,1,exception);
982 if (p == (
const Quantum *) NULL)
989 p-=(ptrdiff_t)CastDoubleToSsizeT((
double) x_offset*
990 GetPixelChannels(source_image));
992 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
993 if (q == (Quantum *) NULL)
998 GetPixelInfo(image,&canvas_pixel);
999 GetPixelInfo(source_image,&source_pixel);
1000 for (x=0; x < (ssize_t) image->columns; x++)
1020 if (clip_to_self != MagickFalse)
1024 q+=(ptrdiff_t) GetPixelChannels(image);
1027 if ((x-x_offset) >= (ssize_t) source_image->columns)
1030 if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
1031 ((x-x_offset) >= (ssize_t) source_image->columns))
1034 source[MaxPixelChannels];
1041 (void) GetOneVirtualPixel(source_image,
1042 CastDoubleToSsizeT((
double) x-x_offset),
1043 CastDoubleToSsizeT((
double) y-y_offset),source,exception);
1044 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1049 PixelChannel channel = GetPixelChannelChannel(image,i);
1050 PixelTrait traits = GetPixelChannelTraits(image,channel);
1051 PixelTrait source_traits=GetPixelChannelTraits(source_image,
1053 if ((traits == UndefinedPixelTrait) ||
1054 (source_traits == UndefinedPixelTrait))
1056 if (channel == AlphaPixelChannel)
1057 pixel=(MagickRealType) TransparentAlpha;
1059 pixel=(MagickRealType) q[i];
1060 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
1061 ClampToQuantum(pixel);
1063 q+=(ptrdiff_t) GetPixelChannels(image);
1071 Sa=QuantumScale*(double) GetPixelAlpha(source_image,p);
1072 Da=QuantumScale*(double) GetPixelAlpha(image,q);
1074 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1079 PixelChannel channel = GetPixelChannelChannel(image,i);
1080 PixelTrait traits = GetPixelChannelTraits(image,channel);
1081 PixelTrait source_traits=GetPixelChannelTraits(source_image,channel);
1082 if (traits == UndefinedPixelTrait)
1084 if ((source_traits == UndefinedPixelTrait) &&
1085 (channel != AlphaPixelChannel))
1087 if (channel == AlphaPixelChannel)
1092 pixel=(double) QuantumRange*alpha;
1093 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
1094 ClampToQuantum(pixel);
1101 Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
1102 Dc=(MagickRealType) q[i];
1103 if ((traits & CopyPixelTrait) != 0)
1108 q[i]=ClampToQuantum(Sc);
1116 Sca=QuantumScale*Sa*Sc;
1117 Dca=QuantumScale*Da*Dc;
1118 gamma=MagickSafeReciprocal(alpha);
1119 pixel=(double) QuantumRange*gamma*(Sca+Dca*(1.0-Sa));
1120 q[i]=clamp != MagickFalse ? ClampPixel(pixel) : ClampToQuantum(pixel);
1122 p+=(ptrdiff_t) GetPixelChannels(source_image);
1123 channels=GetPixelChannels(source_image);
1124 if (p >= (pixels+channels*source_image->columns))
1126 q+=(ptrdiff_t) GetPixelChannels(image);
1128 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1130 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1135#if defined(MAGICKCORE_OPENMP_SUPPORT)
1139 proceed=SetImageProgress(image,CompositeImageTag,progress,image->rows);
1140 if (proceed == MagickFalse)
1144 source_view=DestroyCacheView(source_view);
1145 image_view=DestroyCacheView(image_view);
1149static MagickBooleanType SaliencyBlendImage(Image *image,
1150 const Image *source_image,
const ssize_t x_offset,
const ssize_t y_offset,
1151 const double iterations,
const double residual_threshold,
const size_t tick,
1152 ExceptionInfo *exception)
1158 *residual_image = (Image *) NULL;
1164 status = MagickTrue,
1165 verbose = MagickFalse;
1169 source_image->columns,
1181 crop_image=CropImage(image,&crop_info,exception);
1182 if (crop_image == (Image *) NULL)
1183 return(MagickFalse);
1184 DisableCompositeClampUnlessSpecified(crop_image);
1185 divergent_image=BlendDivergentImage(crop_image,source_image,exception);
1186 if (divergent_image == (Image *) NULL)
1188 crop_image=DestroyImage(crop_image);
1189 return(MagickFalse);
1191 (void) ResetImagePage(crop_image,
"0x0+0+0");
1192 relax_image=BlendMeanImage(crop_image,source_image,exception);
1193 if (relax_image == (Image *) NULL)
1195 crop_image=DestroyImage(crop_image);
1196 divergent_image=DestroyImage(divergent_image);
1197 return(MagickFalse);
1199 status=BlendMaskAlphaChannel(crop_image,source_image,exception);
1200 if (status == MagickFalse)
1202 crop_image=DestroyImage(crop_image);
1203 divergent_image=DestroyImage(divergent_image);
1204 return(MagickFalse);
1206 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1207 if (residual_image == (Image *) NULL)
1209 crop_image=DestroyImage(crop_image);
1210 relax_image=DestroyImage(relax_image);
1211 return(MagickFalse);
1216 kernel_info=AcquireKernelInfo(
"3x3:0,0.25,0,0.25,0,0.25,0,0.25,0",exception);
1217 if (kernel_info == (KernelInfo *) NULL)
1219 crop_image=DestroyImage(crop_image);
1220 residual_image=DestroyImage(residual_image);
1221 relax_image=DestroyImage(relax_image);
1222 return(MagickFalse);
1224 verbose=IsStringTrue(GetImageArtifact(image,
"verbose"));
1225 if (verbose != MagickFalse)
1226 (void) FormatLocaleFile(stderr,
"saliency blending:\n");
1227 for (i=0; i < (ssize_t) iterations; i++)
1236 convolve_image=ConvolveImage(relax_image,kernel_info,exception);
1237 if (convolve_image == (Image *) NULL)
1239 relax_image=DestroyImage(relax_image);
1240 relax_image=convolve_image;
1241 sum_image=BlendSumImage(relax_image,divergent_image,1.0,-1.0,exception);
1242 if (sum_image == (Image *) NULL)
1244 relax_image=DestroyImage(relax_image);
1245 relax_image=sum_image;
1246 status=CompositeOverImage(relax_image,crop_image,MagickTrue,0,0,exception);
1247 if (status == MagickFalse)
1249 status=BlendRMSEResidual(relax_image,residual_image,&residual,exception);
1250 if (status == MagickFalse)
1252 if ((verbose != MagickFalse) && ((i % MagickMax(tick,1)) == 0))
1253 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double) residual);
1254 if (residual < residual_threshold)
1256 if (verbose != MagickFalse)
1257 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double)
1261 residual_image=DestroyImage(residual_image);
1262 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1263 if (residual_image == (Image *) NULL)
1266 kernel_info=DestroyKernelInfo(kernel_info);
1267 crop_image=DestroyImage(crop_image);
1268 divergent_image=DestroyImage(divergent_image);
1269 residual_image=DestroyImage(residual_image);
1273 status=CompositeOverImage(image,relax_image,MagickTrue,x_offset,y_offset,
1275 relax_image=DestroyImage(relax_image);
1279static MagickBooleanType SeamlessBlendImage(Image *image,
1280 const Image *source_image,
const ssize_t x_offset,
const ssize_t y_offset,
1281 const double iterations,
const double residual_threshold,
const size_t tick,
1282 ExceptionInfo *exception)
1296 status = MagickTrue,
1297 verbose = MagickFalse;
1301 source_image->columns,
1313 crop_image=CropImage(image,&crop_info,exception);
1314 if (crop_image == (Image *) NULL)
1315 return(MagickFalse);
1316 DisableCompositeClampUnlessSpecified(crop_image);
1317 (void) ResetImagePage(crop_image,
"0x0+0+0");
1318 sum_image=BlendSumImage(crop_image,source_image,1.0,-1.0,exception);
1319 crop_image=DestroyImage(crop_image);
1320 if (sum_image == (Image *) NULL)
1321 return(MagickFalse);
1322 mean_image=BlendMeanImage(sum_image,source_image,exception);
1323 sum_image=DestroyImage(sum_image);
1324 if (mean_image == (Image *) NULL)
1325 return(MagickFalse);
1326 relax_image=CloneImage(mean_image,0,0,MagickTrue,exception);
1327 if (relax_image == (Image *) NULL)
1329 mean_image=DestroyImage(mean_image);
1330 return(MagickFalse);
1332 status=BlendMaskAlphaChannel(mean_image,source_image,exception);
1333 if (status == MagickFalse)
1335 relax_image=DestroyImage(relax_image);
1336 mean_image=DestroyImage(mean_image);
1337 return(MagickFalse);
1339 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1340 if (residual_image == (Image *) NULL)
1342 relax_image=DestroyImage(relax_image);
1343 mean_image=DestroyImage(mean_image);
1344 return(MagickFalse);
1349 kernel_info=AcquireKernelInfo(
"3x3:0,0.25,0,0.25,0,0.25,0,0.25,0",exception);
1350 if (kernel_info == (KernelInfo *) NULL)
1352 residual_image=DestroyImage(residual_image);
1353 relax_image=DestroyImage(relax_image);
1354 mean_image=DestroyImage(mean_image);
1355 return(MagickFalse);
1357 verbose=IsStringTrue(GetImageArtifact(image,
"verbose"));
1358 if (verbose != MagickFalse)
1359 (void) FormatLocaleFile(stderr,
"seamless blending:\n");
1360 for (i=0; i < (ssize_t) iterations; i++)
1368 convolve_image=ConvolveImage(relax_image,kernel_info,exception);
1369 if (convolve_image == (Image *) NULL)
1371 relax_image=DestroyImage(relax_image);
1372 relax_image=convolve_image;
1373 status=CompositeOverImage(relax_image,mean_image,MagickTrue,0,0,exception);
1374 if (status == MagickFalse)
1376 status=BlendRMSEResidual(relax_image,residual_image,&residual,exception);
1377 if (status == MagickFalse)
1379 if ((verbose != MagickFalse) && ((i % MagickMax(tick,1)) == 0))
1380 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double) residual);
1381 if (residual < residual_threshold)
1383 if (verbose != MagickFalse)
1384 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double)
1388 if (residual_image != (Image *) NULL)
1389 residual_image=DestroyImage(residual_image);
1390 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1391 if (residual_image == (Image *) NULL)
1394 kernel_info=DestroyKernelInfo(kernel_info);
1395 mean_image=DestroyImage(mean_image);
1396 residual_image=DestroyImage(residual_image);
1400 foreground_image=BlendSumImage(source_image,relax_image,1.0,1.0,exception);
1401 relax_image=DestroyImage(relax_image);
1402 if (foreground_image == (Image *) NULL)
1403 return(MagickFalse);
1404 (void) SetImageMask(foreground_image,ReadPixelMask,(
const Image *) NULL,
1406 status=CompositeOverImage(image,foreground_image,MagickTrue,x_offset,y_offset,
1408 foreground_image=DestroyImage(foreground_image);
1412MagickExport MagickBooleanType CompositeImage(Image *image,
1413 const Image *composite,
const CompositeOperator compose,
1414 const MagickBooleanType clip_to_self,
const ssize_t x_offset,
1415 const ssize_t y_offset,ExceptionInfo *exception)
1417#define CompositeImageTag "Composite/Image"
1424 colorspace = HCLColorspace;
1430 white_luminance = 10000.0;
1436 illuminant = D65Illuminant;
1465 assert(image != (Image *) NULL);
1466 assert(image->signature == MagickCoreSignature);
1467 assert(composite != (Image *) NULL);
1468 assert(composite->signature == MagickCoreSignature);
1469 if (IsEventLogging() != MagickFalse)
1470 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1471 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1472 return(MagickFalse);
1473 source_image=CloneImage(composite,0,0,MagickTrue,exception);
1474 if (source_image == (
const Image *) NULL)
1475 return(MagickFalse);
1476 (void) SetImageColorspace(source_image,image->colorspace,exception);
1477 if ((compose == OverCompositeOp) || (compose == SrcOverCompositeOp))
1479 status=CompositeOverImage(image,source_image,clip_to_self,x_offset,
1480 y_offset,exception);
1481 source_image=DestroyImage(source_image);
1485 canvas_image=(Image *) NULL;
1486 canvas_dissolve=1.0;
1487 white_luminance=10000.0;
1488 artifact=GetImageArtifact(image,
"compose:white-luminance");
1489 if (artifact != (
const char *) NULL)
1490 white_luminance=StringToDouble(artifact,(
char **) NULL);
1491 artifact=GetImageArtifact(image,
"compose:illuminant");
1492 if (artifact != (
const char *) NULL)
1497 illuminant_type=ParseCommandOption(MagickIlluminantOptions,MagickFalse,
1499 if (illuminant_type < 0)
1500 illuminant=UndefinedIlluminant;
1502 illuminant=(IlluminantType) illuminant_type;
1504 artifact=GetImageArtifact(image,
"compose:colorspace");
1505 if (artifact != (
const char *) NULL)
1510 colorspace_type=ParseCommandOption(MagickColorspaceOptions,MagickFalse,
1512 if (colorspace_type < 0)
1513 colorspace=UndefinedColorspace;
1515 colorspace=(ColorspaceType) colorspace_type;
1518 artifact=GetImageArtifact(image,
"compose:clamp");
1519 if (artifact != (
const char *) NULL)
1520 clamp=IsStringTrue(artifact);
1521 compose_sync=MagickTrue;
1522 artifact=GetImageArtifact(image,
"compose:sync");
1523 if (artifact != (
const char *) NULL)
1524 compose_sync=IsStringTrue(artifact);
1525 SetGeometryInfo(&geometry_info);
1527 percent_chroma=100.0;
1528 source_dissolve=1.0;
1532 case CopyCompositeOp:
1534 if ((x_offset < 0) || (y_offset < 0))
1536 if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
1538 if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
1540 if ((source_image->alpha_trait == UndefinedPixelTrait) &&
1541 (image->alpha_trait != UndefinedPixelTrait))
1542 (void) SetImageAlphaChannel(source_image,OpaqueAlphaChannel,exception);
1544 source_view=AcquireVirtualCacheView(source_image,exception);
1545 image_view=AcquireAuthenticCacheView(image,exception);
1546#if defined(MAGICKCORE_OPENMP_SUPPORT)
1547 #pragma omp parallel for schedule(static) shared(status) \
1548 magick_number_threads(source_image,image,source_image->rows,4)
1550 for (y=0; y < (ssize_t) source_image->rows; y++)
1564 if (status == MagickFalse)
1566 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1568 q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
1569 source_image->columns,1,exception);
1570 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1575 for (x=0; x < (ssize_t) source_image->columns; x++)
1580 if (GetPixelReadMask(source_image,p) <= (QuantumRange/2))
1582 p+=(ptrdiff_t) GetPixelChannels(source_image);
1583 q+=(ptrdiff_t) GetPixelChannels(image);
1586 for (i=0; i < (ssize_t) GetPixelChannels(source_image); i++)
1588 PixelChannel channel = GetPixelChannelChannel(source_image,i);
1589 PixelTrait source_traits = GetPixelChannelTraits(source_image,
1591 PixelTrait traits = GetPixelChannelTraits(image,channel);
1592 if ((source_traits == UndefinedPixelTrait) ||
1593 (traits == UndefinedPixelTrait))
1595 SetPixelChannel(image,channel,p[i],q);
1597 p+=(ptrdiff_t) GetPixelChannels(source_image);
1598 q+=(ptrdiff_t) GetPixelChannels(image);
1600 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1601 if (sync == MagickFalse)
1603 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1608 proceed=SetImageProgress(image,CompositeImageTag,(MagickOffsetType)
1610 if (proceed == MagickFalse)
1614 source_view=DestroyCacheView(source_view);
1615 image_view=DestroyCacheView(image_view);
1616 source_image=DestroyImage(source_image);
1619 case IntensityCompositeOp:
1621 if ((x_offset < 0) || (y_offset < 0))
1623 if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
1625 if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
1628 source_view=AcquireVirtualCacheView(source_image,exception);
1629 image_view=AcquireAuthenticCacheView(image,exception);
1630#if defined(MAGICKCORE_OPENMP_SUPPORT)
1631 #pragma omp parallel for schedule(static) shared(status) \
1632 magick_number_threads(source_image,image,source_image->rows,4)
1634 for (y=0; y < (ssize_t) source_image->rows; y++)
1648 if (status == MagickFalse)
1650 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1652 q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
1653 source_image->columns,1,exception);
1654 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1659 for (x=0; x < (ssize_t) source_image->columns; x++)
1661 if (GetPixelReadMask(source_image,p) <= (QuantumRange/2))
1663 p+=(ptrdiff_t) GetPixelChannels(source_image);
1664 q+=(ptrdiff_t) GetPixelChannels(image);
1667 SetPixelAlpha(image,clamp != MagickFalse ?
1668 ClampPixel(GetPixelIntensity(source_image,p)) :
1669 ClampToQuantum(GetPixelIntensity(source_image,p)),q);
1670 p+=(ptrdiff_t) GetPixelChannels(source_image);
1671 q+=(ptrdiff_t) GetPixelChannels(image);
1673 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1674 if (sync == MagickFalse)
1676 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1681 proceed=SetImageProgress(image,CompositeImageTag,(MagickOffsetType)
1683 if (proceed == MagickFalse)
1687 source_view=DestroyCacheView(source_view);
1688 image_view=DestroyCacheView(image_view);
1689 source_image=DestroyImage(source_image);
1692 case CopyAlphaCompositeOp:
1693 case ChangeMaskCompositeOp:
1699 if ((image->alpha_trait & BlendPixelTrait) == 0)
1700 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1703 case BlurCompositeOp:
1728 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1729 if (canvas_image == (Image *) NULL)
1731 source_image=DestroyImage(source_image);
1732 return(MagickFalse);
1738 artifact=GetImageArtifact(image,
"compose:args");
1739 if (artifact != (
const char *) NULL)
1740 flags=ParseGeometry(artifact,&geometry_info);
1741 if ((flags & WidthValue) == 0)
1743 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1744 "InvalidSetting",
"'%s' '%s'",
"compose:args",artifact);
1745 source_image=DestroyImage(source_image);
1746 canvas_image=DestroyImage(canvas_image);
1747 return(MagickFalse);
1754 width=2.0*geometry_info.rho;
1756 if ((flags & HeightValue) != 0)
1757 height=2.0*geometry_info.sigma;
1765 if ((flags & XValue) != 0 )
1773 angle=DegreesToRadians(geometry_info.xi);
1774 blur.x1=width*cos(angle);
1775 blur.x2=width*sin(angle);
1776 blur.y1=(-height*sin(angle));
1777 blur.y2=height*cos(angle);
1781 if ((flags & YValue) != 0 )
1786 angle_start=DegreesToRadians(geometry_info.xi);
1787 angle_range=DegreesToRadians(geometry_info.psi)-angle_start;
1798 resample_filter=AcquireResampleFilter(image,exception);
1799 SetResampleFilter(resample_filter,GaussianFilter);
1803 GetPixelInfo(image,&pixel);
1804 source_view=AcquireVirtualCacheView(source_image,exception);
1805 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
1806 for (y=0; y < (ssize_t) source_image->rows; y++)
1820 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
1822 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1824 q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
1826 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1828 for (x=0; x < (ssize_t) source_image->columns; x++)
1830 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
1832 p+=(ptrdiff_t) GetPixelChannels(source_image);
1835 if (fabs(angle_range) > MagickEpsilon)
1840 angle=angle_start+angle_range*QuantumScale*(double)
1841 GetPixelBlue(source_image,p);
1842 blur.x1=width*cos(angle);
1843 blur.x2=width*sin(angle);
1844 blur.y1=(-height*sin(angle));
1845 blur.y2=height*cos(angle);
1847 ScaleResampleFilter(resample_filter,
1848 blur.x1*QuantumScale*(
double) GetPixelRed(source_image,p),
1849 blur.y1*QuantumScale*(
double) GetPixelGreen(source_image,p),
1850 blur.x2*QuantumScale*(
double) GetPixelRed(source_image,p),
1851 blur.y2*QuantumScale*(
double) GetPixelGreen(source_image,p) );
1852 (void) ResamplePixelColor(resample_filter,(
double) x_offset+x,
1853 (
double) y_offset+y,&pixel,exception);
1854 SetPixelViaPixelInfo(canvas_image,&pixel,q);
1855 p+=(ptrdiff_t) GetPixelChannels(source_image);
1856 q+=(ptrdiff_t) GetPixelChannels(canvas_image);
1858 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
1859 if (sync == MagickFalse)
1862 resample_filter=DestroyResampleFilter(resample_filter);
1863 source_view=DestroyCacheView(source_view);
1864 canvas_view=DestroyCacheView(canvas_view);
1865 source_image=DestroyImage(source_image);
1866 source_image=canvas_image;
1869 case DisplaceCompositeOp:
1870 case DistortCompositeOp:
1891 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1892 if (canvas_image == (Image *) NULL)
1894 source_image=DestroyImage(source_image);
1895 return(MagickFalse);
1897 SetGeometryInfo(&geometry_info);
1899 artifact=GetImageArtifact(image,
"compose:args");
1900 if (artifact != (
char *) NULL)
1901 flags=ParseGeometry(artifact,&geometry_info);
1902 if ((flags & (WidthValue | HeightValue)) == 0 )
1904 if ((flags & AspectValue) == 0)
1906 horizontal_scale=(MagickRealType) (source_image->columns-1)/2.0;
1907 vertical_scale=(MagickRealType) (source_image->rows-1)/2.0;
1911 horizontal_scale=(MagickRealType) (image->columns-1)/2.0;
1912 vertical_scale=(MagickRealType) (image->rows-1)/2.0;
1917 horizontal_scale=geometry_info.rho;
1918 vertical_scale=geometry_info.sigma;
1919 if ((flags & PercentValue) != 0)
1921 if ((flags & AspectValue) == 0)
1923 horizontal_scale*=(source_image->columns-1)/200.0;
1924 vertical_scale*=(source_image->rows-1)/200.0;
1928 horizontal_scale*=(image->columns-1)/200.0;
1929 vertical_scale*=(image->rows-1)/200.0;
1932 if ((flags & HeightValue) == 0)
1933 vertical_scale=horizontal_scale;
1943 center.x=(MagickRealType) x_offset;
1944 center.y=(MagickRealType) y_offset;
1945 if (compose == DistortCompositeOp)
1947 if ((flags & XValue) == 0)
1948 if ((flags & AspectValue) != 0)
1949 center.x=(MagickRealType) ((image->columns-1)/2.0);
1951 center.x=(MagickRealType) (x_offset+(source_image->columns-1)/
1954 if ((flags & AspectValue) != 0)
1955 center.x=geometry_info.xi;
1957 center.x=(MagickRealType) (x_offset+geometry_info.xi);
1958 if ((flags & YValue) == 0)
1959 if ((flags & AspectValue) != 0)
1960 center.y=(MagickRealType) ((image->rows-1)/2.0);
1962 center.y=(MagickRealType) (y_offset+(source_image->rows-1)/2.0);
1964 if ((flags & AspectValue) != 0)
1965 center.y=geometry_info.psi;
1967 center.y=(MagickRealType) (y_offset+geometry_info.psi);
1973 GetPixelInfo(image,&pixel);
1974 image_view=AcquireVirtualCacheView(image,exception);
1975 source_view=AcquireVirtualCacheView(source_image,exception);
1976 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
1977 for (y=0; y < (ssize_t) source_image->rows; y++)
1991 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
1993 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1995 q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
1997 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1999 for (x=0; x < (ssize_t) source_image->columns; x++)
2001 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
2003 p+=(ptrdiff_t) GetPixelChannels(source_image);
2009 offset.x=(double) (horizontal_scale*((
double) GetPixelRed(
2010 source_image,p)-(((MagickRealType) QuantumRange+1.0)/2.0)))/
2011 (((MagickRealType) QuantumRange+1.0)/2.0)+center.x+
2012 ((compose == DisplaceCompositeOp) ? x : 0);
2013 offset.y=(double) (vertical_scale*((
double) GetPixelGreen(
2014 source_image,p)-(((MagickRealType) QuantumRange+1.0)/2.0)))/
2015 (((MagickRealType) QuantumRange+1.0)/2.0)+center.y+
2016 ((compose == DisplaceCompositeOp) ? y : 0);
2017 status=InterpolatePixelInfo(image,image_view,
2018 UndefinedInterpolatePixel,(
double) offset.x,(
double) offset.y,
2020 if (status == MagickFalse)
2025 pixel.alpha=(MagickRealType) QuantumRange*(QuantumScale*pixel.alpha)*
2026 (QuantumScale*(double) GetPixelAlpha(source_image,p));
2027 SetPixelViaPixelInfo(canvas_image,&pixel,q);
2028 p+=(ptrdiff_t) GetPixelChannels(source_image);
2029 q+=(ptrdiff_t) GetPixelChannels(canvas_image);
2031 if (x < (ssize_t) source_image->columns)
2033 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
2034 if (sync == MagickFalse)
2037 canvas_view=DestroyCacheView(canvas_view);
2038 source_view=DestroyCacheView(source_view);
2039 image_view=DestroyCacheView(image_view);
2040 source_image=DestroyImage(source_image);
2041 source_image=canvas_image;
2044 case DissolveCompositeOp:
2049 artifact=GetImageArtifact(image,
"compose:args");
2050 if (artifact != (
char *) NULL)
2052 flags=ParseGeometry(artifact,&geometry_info);
2053 source_dissolve=geometry_info.rho/100.0;
2054 canvas_dissolve=1.0;
2055 if ((source_dissolve-MagickEpsilon) < 0.0)
2056 source_dissolve=0.0;
2057 if ((source_dissolve+MagickEpsilon) > 1.0)
2059 canvas_dissolve=2.0-source_dissolve;
2060 source_dissolve=1.0;
2062 if ((flags & SigmaValue) != 0)
2063 canvas_dissolve=geometry_info.sigma/100.0;
2064 if ((canvas_dissolve-MagickEpsilon) < 0.0)
2065 canvas_dissolve=0.0;
2066 if ((canvas_dissolve+MagickEpsilon) > 1.0)
2067 canvas_dissolve=1.0;
2071 case BlendCompositeOp:
2073 artifact=GetImageArtifact(image,
"compose:args");
2074 if (artifact != (
char *) NULL)
2076 flags=ParseGeometry(artifact,&geometry_info);
2077 source_dissolve=geometry_info.rho/100.0;
2078 canvas_dissolve=1.0-source_dissolve;
2079 if ((flags & SigmaValue) != 0)
2080 canvas_dissolve=geometry_info.sigma/100.0;
2084 case SaliencyBlendCompositeOp:
2087 residual_threshold = 0.0002,
2093 artifact=GetImageArtifact(image,
"compose:args");
2094 if (artifact != (
char *) NULL)
2096 flags=ParseGeometry(artifact,&geometry_info);
2097 iterations=geometry_info.rho;
2098 if ((flags & SigmaValue) != 0)
2099 residual_threshold=geometry_info.sigma;
2100 if ((flags & XiValue) != 0)
2101 tick=(size_t) geometry_info.xi;
2103 status=SaliencyBlendImage(image,composite,x_offset,y_offset,iterations,
2104 residual_threshold,tick,exception);
2105 source_image=DestroyImage(source_image);
2108 case SeamlessBlendCompositeOp:
2111 residual_threshold = 0.0002,
2117 artifact=GetImageArtifact(image,
"compose:args");
2118 if (artifact != (
char *) NULL)
2120 flags=ParseGeometry(artifact,&geometry_info);
2121 iterations=geometry_info.rho;
2122 if ((flags & SigmaValue) != 0)
2123 residual_threshold=geometry_info.sigma;
2124 if ((flags & XiValue) != 0)
2125 tick=(size_t) geometry_info.xi;
2127 status=SeamlessBlendImage(image,composite,x_offset,y_offset,iterations,
2128 residual_threshold,tick,exception);
2129 source_image=DestroyImage(source_image);
2132 case MathematicsCompositeOp:
2142 SetGeometryInfo(&geometry_info);
2143 artifact=GetImageArtifact(image,
"compose:args");
2144 if (artifact != (
char *) NULL)
2146 flags=ParseGeometry(artifact,&geometry_info);
2147 if (flags == NoValue)
2148 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2149 "InvalidGeometry",
"`%s'",artifact);
2153 case ModulateCompositeOp:
2158 artifact=GetImageArtifact(image,
"compose:args");
2159 if (artifact != (
char *) NULL)
2161 flags=ParseGeometry(artifact,&geometry_info);
2162 percent_luma=geometry_info.rho;
2163 if ((flags & SigmaValue) != 0)
2164 percent_chroma=geometry_info.sigma;
2168 case ThresholdCompositeOp:
2173 artifact=GetImageArtifact(image,
"compose:args");
2174 if (artifact != (
char *) NULL)
2176 flags=ParseGeometry(artifact,&geometry_info);
2177 amount=geometry_info.rho;
2178 threshold=geometry_info.sigma;
2179 if ((flags & SigmaValue) == 0)
2182 threshold*=(double) QuantumRange;
2193 midpoint=((MagickRealType) QuantumRange+1.0)/2;
2194 source_view=AcquireVirtualCacheView(source_image,exception);
2195 image_view=AcquireAuthenticCacheView(image,exception);
2196#if defined(MAGICKCORE_OPENMP_SUPPORT)
2197 #pragma omp parallel for schedule(static) shared(progress,status) \
2198 magick_number_threads(source_image,image,image->rows,1)
2200 for (y=0; y < (ssize_t) image->rows; y++)
2226 if (status == MagickFalse)
2228 if (clip_to_self != MagickFalse)
2232 if ((y-y_offset) >= (ssize_t) source_image->rows)
2238 pixels=(Quantum *) NULL;
2240 if ((y >= y_offset) &&
2241 ((y-y_offset) < (ssize_t) source_image->rows))
2243 p=GetCacheViewVirtualPixels(source_view,0,
2244 CastDoubleToSsizeT((
double) y-y_offset),source_image->columns,1,
2246 if (p == (
const Quantum *) NULL)
2253 p-=(ptrdiff_t) CastDoubleToSsizeT((
double) x_offset*
2254 GetPixelChannels(source_image));
2256 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2257 if (q == (Quantum *) NULL)
2262 GetPixelInfo(image,&canvas_pixel);
2263 GetPixelInfo(source_image,&source_pixel);
2264 for (x=0; x < (ssize_t) image->columns; x++)
2288 if (clip_to_self != MagickFalse)
2292 q+=(ptrdiff_t) GetPixelChannels(image);
2295 if ((x-x_offset) >= (ssize_t) source_image->columns)
2298 if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
2299 ((x-x_offset) >= (ssize_t) source_image->columns))
2302 source[MaxPixelChannels];
2309 (void) GetOneVirtualPixel(source_image,
2310 CastDoubleToSsizeT((
double) x-x_offset),
2311 CastDoubleToSsizeT((
double) y-y_offset),source,exception);
2312 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2317 PixelChannel channel = GetPixelChannelChannel(image,i);
2318 PixelTrait traits = GetPixelChannelTraits(image,channel);
2319 PixelTrait source_traits = GetPixelChannelTraits(source_image,
2321 if ((traits == UndefinedPixelTrait) ||
2322 (source_traits == UndefinedPixelTrait))
2326 case AlphaCompositeOp:
2327 case ChangeMaskCompositeOp:
2328 case CopyAlphaCompositeOp:
2329 case DstAtopCompositeOp:
2330 case DstInCompositeOp:
2332 case OutCompositeOp:
2333 case SrcInCompositeOp:
2334 case SrcOutCompositeOp:
2336 if (channel == AlphaPixelChannel)
2337 pixel=(MagickRealType) TransparentAlpha;
2339 pixel=(MagickRealType) q[i];
2342 case ClearCompositeOp:
2343 case CopyCompositeOp:
2344 case ReplaceCompositeOp:
2346 if (channel == AlphaPixelChannel)
2347 pixel=(MagickRealType) TransparentAlpha;
2352 case BlendCompositeOp:
2353 case DissolveCompositeOp:
2355 if (channel == AlphaPixelChannel)
2356 pixel=canvas_dissolve*(double) GetPixelAlpha(source_image,
2359 pixel=(MagickRealType) source[channel];
2364 pixel=(MagickRealType) source[channel];
2368 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
2369 ClampToQuantum(pixel);
2371 q+=(ptrdiff_t) GetPixelChannels(image);
2379 Sa=QuantumScale*(double) GetPixelAlpha(source_image,p);
2380 Da=QuantumScale*(double) GetPixelAlpha(image,q);
2383 case BumpmapCompositeOp:
2384 case ColorBurnCompositeOp:
2385 case ColorDodgeCompositeOp:
2386 case DarkenCompositeOp:
2387 case DifferenceCompositeOp:
2388 case DivideDstCompositeOp:
2389 case DivideSrcCompositeOp:
2390 case ExclusionCompositeOp:
2391 case FreezeCompositeOp:
2392 case HardLightCompositeOp:
2393 case HardMixCompositeOp:
2394 case InterpolateCompositeOp:
2395 case LightenCompositeOp:
2396 case LinearBurnCompositeOp:
2397 case LinearDodgeCompositeOp:
2398 case LinearLightCompositeOp:
2399 case MathematicsCompositeOp:
2400 case MinusDstCompositeOp:
2401 case MinusSrcCompositeOp:
2402 case MultiplyCompositeOp:
2403 case NegateCompositeOp:
2404 case OverlayCompositeOp:
2405 case PegtopLightCompositeOp:
2406 case PinLightCompositeOp:
2407 case ReflectCompositeOp:
2408 case ScreenCompositeOp:
2409 case SoftBurnCompositeOp:
2410 case SoftDodgeCompositeOp:
2411 case SoftLightCompositeOp:
2412 case StampCompositeOp:
2413 case VividLightCompositeOp:
2415 alpha=RoundToUnity(Sa+Da-Sa*Da);
2418 case DstAtopCompositeOp:
2419 case DstInCompositeOp:
2421 case SrcInCompositeOp:
2426 case DissolveCompositeOp:
2428 alpha=source_dissolve*Sa*(-canvas_dissolve*Da)+source_dissolve*Sa+
2432 case DstOverCompositeOp:
2433 case OverCompositeOp:
2434 case SrcOverCompositeOp:
2439 case DstOutCompositeOp:
2444 case OutCompositeOp:
2445 case SrcOutCompositeOp:
2450 case BlendCompositeOp:
2451 case PlusCompositeOp:
2453 alpha=RoundToUnity(source_dissolve*Sa+canvas_dissolve*Da);
2456 case XorCompositeOp:
2458 alpha=Sa+Da-2.0*Sa*Da;
2461 case ModulusAddCompositeOp:
2468 alpha=((Sa+Da)-1.0);
2471 case ModulusSubtractCompositeOp:
2478 alpha=((Sa-Da)+1.0);
2489 case ColorizeCompositeOp:
2490 case HueCompositeOp:
2491 case LuminizeCompositeOp:
2492 case ModulateCompositeOp:
2493 case RMSECompositeOp:
2494 case SaturateCompositeOp:
2496 Si=GetPixelIntensity(source_image,p);
2497 GetPixelInfoPixel(source_image,p,&source_pixel);
2498 GetPixelInfoPixel(image,q,&canvas_pixel);
2501 case BumpmapCompositeOp:
2502 case CopyAlphaCompositeOp:
2503 case DarkenIntensityCompositeOp:
2504 case LightenIntensityCompositeOp:
2506 Si=GetPixelIntensity(source_image,p);
2507 Di=GetPixelIntensity(image,q);
2513 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2519 PixelChannel channel = GetPixelChannelChannel(image,i);
2520 PixelTrait traits = GetPixelChannelTraits(image,channel);
2521 PixelTrait source_traits = GetPixelChannelTraits(source_image,channel);
2522 if (traits == UndefinedPixelTrait)
2524 if ((channel == AlphaPixelChannel) &&
2525 ((traits & UpdatePixelTrait) != 0))
2532 case AlphaCompositeOp:
2534 pixel=(double) QuantumRange*Sa;
2537 case AtopCompositeOp:
2538 case CopyBlackCompositeOp:
2539 case CopyBlueCompositeOp:
2540 case CopyCyanCompositeOp:
2541 case CopyGreenCompositeOp:
2542 case CopyMagentaCompositeOp:
2543 case CopyRedCompositeOp:
2544 case CopyYellowCompositeOp:
2545 case SrcAtopCompositeOp:
2546 case DstCompositeOp:
2549 pixel=(double) QuantumRange*Da;
2552 case BumpmapCompositeOp:
2557 case ChangeMaskCompositeOp:
2559 if (IsFuzzyEquivalencePixel(source_image,p,image,q) != MagickFalse)
2560 pixel=(MagickRealType) TransparentAlpha;
2562 pixel=(double) QuantumRange*Da;
2565 case ClearCompositeOp:
2567 pixel=(MagickRealType) TransparentAlpha;
2570 case ColorizeCompositeOp:
2571 case HueCompositeOp:
2572 case LuminizeCompositeOp:
2573 case RMSECompositeOp:
2574 case SaturateCompositeOp:
2576 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
2578 pixel=(double) QuantumRange*Da;
2581 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
2583 pixel=(double) QuantumRange*Sa;
2588 pixel=(double) QuantumRange*Da;
2591 pixel=(double) QuantumRange*Sa;
2594 case CopyAlphaCompositeOp:
2596 if (source_image->alpha_trait == UndefinedPixelTrait)
2599 pixel=(double) QuantumRange*Sa;
2602 case BlurCompositeOp:
2603 case CopyCompositeOp:
2604 case DisplaceCompositeOp:
2605 case DistortCompositeOp:
2606 case DstAtopCompositeOp:
2607 case ReplaceCompositeOp:
2608 case SrcCompositeOp:
2610 pixel=(double) QuantumRange*Sa;
2613 case DarkenIntensityCompositeOp:
2615 if (compose_sync == MagickFalse)
2617 pixel=Si < Di? Sa : Da;
2620 pixel=Sa*Si < Da*Di ? Sa : Da;
2623 case DifferenceCompositeOp:
2625 pixel=(double) QuantumRange*fabs((
double) (Sa-Da));
2628 case FreezeCompositeOp:
2630 pixel=(double) QuantumRange*(1.0-(1.0-Sa)*(1.0-Sa)*
2631 MagickSafeReciprocal(Da));
2636 case InterpolateCompositeOp:
2638 pixel=(double) QuantumRange*(0.5-0.25*cos(MagickPI*Sa)-0.25*
2642 case LightenIntensityCompositeOp:
2644 if (compose_sync == MagickFalse)
2646 pixel=Si > Di ? Sa : Da;
2649 pixel=Sa*Si > Da*Di ? Sa : Da;
2652 case ModulateCompositeOp:
2654 pixel=(double) QuantumRange*Da;
2657 case MultiplyCompositeOp:
2659 if (compose_sync == MagickFalse)
2661 pixel=(double) QuantumRange*Sa*Da;
2664 pixel=(double) QuantumRange*alpha;
2667 case NegateCompositeOp:
2669 pixel=(double) QuantumRange*((1.0-Sa-Da));
2672 case ReflectCompositeOp:
2674 pixel=(double) QuantumRange*(Sa*Sa*
2675 MagickSafeReciprocal(1.0-Da));
2676 if (pixel > (
double) QuantumRange)
2677 pixel=(double) QuantumRange;
2680 case StampCompositeOp:
2682 pixel=(double) QuantumRange*(Sa+Da*Da-1.0);
2685 case StereoCompositeOp:
2687 pixel=(double) QuantumRange*(Sa+Da)/2;
2692 pixel=(double) QuantumRange*alpha;
2696 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
2697 ClampToQuantum(pixel);
2700 if (source_traits == UndefinedPixelTrait)
2706 Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
2707 Dc=(MagickRealType) q[i];
2708 if ((traits & CopyPixelTrait) != 0)
2713 q[i]=ClampToQuantum(Dc);
2721 Sca=QuantumScale*Sa*Sc;
2722 Dca=QuantumScale*Da*Dc;
2723 SaSca=Sa*MagickSafeReciprocal(Sca);
2724 DcaDa=Dca*MagickSafeReciprocal(Da);
2727 case DarkenCompositeOp:
2728 case LightenCompositeOp:
2729 case ModulusSubtractCompositeOp:
2731 gamma=MagickSafeReciprocal(1.0-alpha);
2736 gamma=MagickSafeReciprocal(alpha);
2743 case AlphaCompositeOp:
2745 pixel=(double) QuantumRange*Sa;
2748 case AtopCompositeOp:
2749 case SrcAtopCompositeOp:
2751 pixel=(double) QuantumRange*(Sca*Da+Dca*(1.0-Sa));
2754 case BlendCompositeOp:
2756 pixel=gamma*(source_dissolve*Sa*Sc+canvas_dissolve*Da*Dc);
2759 case CopyCompositeOp:
2760 case ReplaceCompositeOp:
2762 pixel=(double) QuantumRange*Sca;
2765 case BlurCompositeOp:
2766 case DisplaceCompositeOp:
2767 case DistortCompositeOp:
2768 case SrcCompositeOp:
2773 case BumpmapCompositeOp:
2775 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
2780 pixel=(double) QuantumScale*Si*Dc;
2783 case ChangeMaskCompositeOp:
2788 case ClearCompositeOp:
2793 case ColorBurnCompositeOp:
2795 if ((Sca == 0.0) && (Dca == Da))
2797 pixel=(double) QuantumRange*gamma*(Sa*Da+Dca*(1.0-Sa));
2802 pixel=(double) QuantumRange*gamma*(Dca*(1.0-Sa));
2805 pixel=(double) QuantumRange*gamma*(Sa*Da-Sa*Da*MagickMin(1.0,
2806 (1.0-DcaDa)*SaSca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
2809 case ColorDodgeCompositeOp:
2811 if ((Sca*Da+Dca*Sa) >= Sa*Da)
2812 pixel=(double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*
2815 pixel=(double) QuantumRange*gamma*(Dca*Sa*Sa*
2816 MagickSafeReciprocal(Sa-Sca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
2819 case ColorizeCompositeOp:
2821 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
2826 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
2831 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
2832 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
2833 white_luminance,illuminant,&sans,&sans,&luma);
2834 ConvertRGBToGeneric(colorspace,(
double) source_pixel.red,
2835 (
double) source_pixel.green,(
double) source_pixel.blue,
2836 white_luminance,illuminant,&hue,&chroma,&sans);
2837 ConvertGenericToRGB(colorspace,hue,chroma,luma,
2838 white_luminance,illuminant,&red,&green,&blue);
2841 case RedPixelChannel: pixel=red;
break;
2842 case GreenPixelChannel: pixel=green;
break;
2843 case BluePixelChannel: pixel=blue;
break;
2844 default: pixel=Dc;
break;
2848 case CopyAlphaCompositeOp:
2849 case DstCompositeOp:
2854 case CopyBlackCompositeOp:
2856 if (channel == BlackPixelChannel)
2857 pixel=(MagickRealType) GetPixelBlack(source_image,p);
2860 case CopyBlueCompositeOp:
2861 case CopyYellowCompositeOp:
2863 if (channel == BluePixelChannel)
2864 pixel=(MagickRealType) GetPixelBlue(source_image,p);
2867 case CopyGreenCompositeOp:
2868 case CopyMagentaCompositeOp:
2870 if (channel == GreenPixelChannel)
2871 pixel=(MagickRealType) GetPixelGreen(source_image,p);
2874 case CopyRedCompositeOp:
2875 case CopyCyanCompositeOp:
2877 if (channel == RedPixelChannel)
2878 pixel=(MagickRealType) GetPixelRed(source_image,p);
2881 case DarkenCompositeOp:
2888 if (compose_sync == MagickFalse)
2890 pixel=MagickMin(Sc,Dc);
2893 if ((Sca*Da) < (Dca*Sa))
2895 pixel=(double) QuantumRange*(Sca+Dca*(1.0-Sa));
2898 pixel=(double) QuantumRange*(Dca+Sca*(1.0-Da));
2901 case DarkenIntensityCompositeOp:
2903 if (compose_sync == MagickFalse)
2905 pixel=Si < Di ? Sc : Dc;
2908 pixel=Sa*Si < Da*Di ? Sc : Dc;
2911 case DifferenceCompositeOp:
2913 if (compose_sync == MagickFalse)
2915 pixel=fabs((
double) Sc-Dc);
2918 pixel=(double) QuantumRange*gamma*(Sca+Dca-2.0*MagickMin(Sca*Da,
2922 case DissolveCompositeOp:
2924 pixel=gamma*(source_dissolve*Sa*Sc-source_dissolve*Sa*
2925 canvas_dissolve*Da*Dc+canvas_dissolve*Da*Dc);
2928 case DivideDstCompositeOp:
2930 if (compose_sync == MagickFalse)
2932 pixel=(double) QuantumRange*(Sc/MagickSafeReciprocal(Dc));
2935 if ((fabs((
double) Sca) < MagickEpsilon) &&
2936 (fabs((
double) Dca) < MagickEpsilon))
2938 pixel=(double) QuantumRange*gamma*(Sca*(1.0-Da)+Dca*(1.0-Sa));
2941 if (fabs((
double) Dca) < MagickEpsilon)
2943 pixel=(double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*
2947 pixel=(double) QuantumRange*gamma*(Sca*Da*Da/Dca+Sca*(1.0-Da)+Dca*
2951 case DivideSrcCompositeOp:
2953 if (compose_sync == MagickFalse)
2955 pixel=(double) QuantumRange*(Dc/MagickSafeReciprocal(Sc));
2958 if ((fabs((
double) Dca) < MagickEpsilon) &&
2959 (fabs((
double) Sca) < MagickEpsilon))
2961 pixel=(double) QuantumRange*gamma*(Dca*(1.0-Sa)+Sca*(1.0-Da));
2964 if (fabs((
double) Sca) < MagickEpsilon)
2966 pixel=(double) QuantumRange*gamma*(Da*Sa+Dca*(1.0-Sa)+Sca*
2970 pixel=(double) QuantumRange*gamma*(Dca*Sa*SaSca+Dca*(1.0-Sa)+Sca*
2974 case DstAtopCompositeOp:
2976 pixel=(double) QuantumRange*(Dca*Sa+Sca*(1.0-Da));
2979 case DstInCompositeOp:
2981 pixel=(double) QuantumRange*gamma*(Dca*Sa);
2984 case DstOutCompositeOp:
2986 pixel=(double) QuantumRange*gamma*(Dca*(1.0-Sa));
2989 case DstOverCompositeOp:
2991 pixel=(double) QuantumRange*gamma*(Dca+Sca*(1.0-Da));
2994 case ExclusionCompositeOp:
2996 pixel=(double) QuantumRange*gamma*(Sca*Da+Dca*Sa-2.0*Sca*Dca+Sca*
2997 (1.0-Da)+Dca*(1.0-Sa));
3000 case FreezeCompositeOp:
3002 pixel=(double) QuantumRange*gamma*(1.0-(1.0-Sca)*(1.0-Sca)*
3003 MagickSafeReciprocal(Dca));
3008 case HardLightCompositeOp:
3012 pixel=(double) QuantumRange*gamma*(2.0*Sca*Dca+Sca*(1.0-Da)+Dca*
3016 pixel=(double) QuantumRange*gamma*(Sa*Da-2.0*(Da-Dca)*(Sa-Sca)+Sca*
3017 (1.0-Da)+Dca*(1.0-Sa));
3020 case HardMixCompositeOp:
3022 pixel=gamma*(((Sca+Dca) < 1.0) ? 0.0 : (double) QuantumRange);
3025 case HueCompositeOp:
3027 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3032 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3037 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3038 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3039 white_luminance,illuminant,&hue,&chroma,&luma);
3040 ConvertRGBToGeneric(colorspace,(
double) source_pixel.red,
3041 (
double) source_pixel.green,(
double) source_pixel.blue,
3042 white_luminance,illuminant,&hue,&sans,&sans);
3043 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3044 white_luminance,illuminant,&red,&green,&blue);
3047 case RedPixelChannel: pixel=red;
break;
3048 case GreenPixelChannel: pixel=green;
break;
3049 case BluePixelChannel: pixel=blue;
break;
3050 default: pixel=Dc;
break;
3055 case SrcInCompositeOp:
3057 pixel=(double) QuantumRange*(Sca*Da);
3060 case InterpolateCompositeOp:
3062 pixel=(double) QuantumRange*(0.5-0.25*cos(MagickPI*Sca)-0.25*
3066 case LinearBurnCompositeOp:
3074 pixel=(double) QuantumRange*gamma*(Sca+Dca-Sa*Da);
3077 case LinearDodgeCompositeOp:
3079 pixel=gamma*(Sa*Sc+Da*Dc);
3082 case LinearLightCompositeOp:
3090 pixel=(double) QuantumRange*gamma*((Sca-Sa)*Da+Sca+Dca);
3093 case LightenCompositeOp:
3095 if (compose_sync == MagickFalse)
3097 pixel=MagickMax(Sc,Dc);
3100 if ((Sca*Da) > (Dca*Sa))
3102 pixel=(double) QuantumRange*(Sca+Dca*(1.0-Sa));
3105 pixel=(double) QuantumRange*(Dca+Sca*(1.0-Da));
3108 case LightenIntensityCompositeOp:
3115 if (compose_sync == MagickFalse)
3117 pixel=Si > Di ? Sc : Dc;
3120 pixel=Sa*Si > Da*Di ? Sc : Dc;
3123 case LuminizeCompositeOp:
3125 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3130 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3135 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3136 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3137 white_luminance,illuminant,&hue,&chroma,&luma);
3138 ConvertRGBToGeneric(colorspace,(
double) source_pixel.red,
3139 (
double) source_pixel.green,(
double) source_pixel.blue,
3140 white_luminance,illuminant,&sans,&sans,&luma);
3141 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3142 white_luminance,illuminant,&red,&green,&blue);
3145 case RedPixelChannel: pixel=red;
break;
3146 case GreenPixelChannel: pixel=green;
break;
3147 case BluePixelChannel: pixel=blue;
break;
3148 default: pixel=Dc;
break;
3152 case MathematicsCompositeOp:
3173 if (compose_sync == MagickFalse)
3175 pixel=geometry_info.rho*Sc*Dc+geometry_info.sigma*Sc+
3176 geometry_info.xi*Dc+geometry_info.psi;
3179 pixel=(double) QuantumRange*gamma*(geometry_info.rho*Sca*Dca+
3180 geometry_info.sigma*Sca*Da+geometry_info.xi*Dca*Sa+
3181 geometry_info.psi*Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
3184 case MinusDstCompositeOp:
3186 if (compose_sync == MagickFalse)
3191 pixel=gamma*(Sa*Sc+Da*Dc-2.0*Da*Dc*Sa);
3194 case MinusSrcCompositeOp:
3201 if (compose_sync == MagickFalse)
3206 pixel=gamma*(Da*Dc+Sa*Sc-2.0*Sa*Sc*Da);
3209 case ModulateCompositeOp:
3214 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3219 offset=(ssize_t) (Si-midpoint);
3225 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3226 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3227 white_luminance,illuminant,&hue,&chroma,&luma);
3228 luma+=(0.01*percent_luma*offset)/midpoint;
3229 chroma*=0.01*percent_chroma;
3230 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3231 white_luminance,illuminant,&red,&green,&blue);
3234 case RedPixelChannel: pixel=red;
break;
3235 case GreenPixelChannel: pixel=green;
break;
3236 case BluePixelChannel: pixel=blue;
break;
3237 default: pixel=Dc;
break;
3241 case ModulusAddCompositeOp:
3243 if (compose_sync == MagickFalse)
3248 if ((Sca+Dca) <= 1.0)
3250 pixel=(double) QuantumRange*(Sca+Dca);
3253 pixel=(double) QuantumRange*((Sca+Dca)-1.0);
3256 case ModulusSubtractCompositeOp:
3258 if (compose_sync == MagickFalse)
3263 if ((Sca-Dca) >= 0.0)
3265 pixel=(double) QuantumRange*(Sca-Dca);
3268 pixel=(double) QuantumRange*((Sca-Dca)+1.0);
3271 case MultiplyCompositeOp:
3273 if (compose_sync == MagickFalse)
3275 pixel=(double) QuantumScale*Dc*Sc;
3278 pixel=(double) QuantumRange*gamma*(Sca*Dca+Sca*(1.0-Da)+Dca*
3282 case NegateCompositeOp:
3284 pixel=(double) QuantumRange*(1.0-fabs(1.0-Sca-Dca));
3289 pixel=(double) QuantumRange*Dca;
3292 case OutCompositeOp:
3293 case SrcOutCompositeOp:
3295 pixel=(double) QuantumRange*(Sca*(1.0-Da));
3298 case OverCompositeOp:
3299 case SrcOverCompositeOp:
3301 pixel=(double) QuantumRange*gamma*(Sca+Dca*(1.0-Sa));
3304 case OverlayCompositeOp:
3308 pixel=(double) QuantumRange*gamma*(2.0*Dca*Sca+Dca*(1.0-Sa)+
3312 pixel=(double) QuantumRange*gamma*(Da*Sa-2.0*(Sa-Sca)*(Da-Dca)+Dca*
3313 (1.0-Sa)+Sca*(1.0-Da));
3316 case PegtopLightCompositeOp:
3326 if (fabs((
double) Da) < MagickEpsilon)
3328 pixel=(double) QuantumRange*gamma*Sca;
3331 pixel=(double) QuantumRange*gamma*(Dca*Dca*(Sa-2.0*Sca)/Da+Sca*
3332 (2.0*Dca+1.0-Da)+Dca*(1.0-Sa));
3335 case PinLightCompositeOp:
3343 if ((Dca*Sa) < (Da*(2.0*Sca-Sa)))
3345 pixel=(double) QuantumRange*gamma*(Sca*(Da+1.0)-Sa*Da+Dca*
3349 if ((Dca*Sa) > (2.0*Sca*Da))
3351 pixel=(double) QuantumRange*gamma*(Sca*Da+Sca+Dca*(1.0-Sa));
3354 pixel=(double) QuantumRange*gamma*(Sca*(1.0-Da)+Dca);
3357 case PlusCompositeOp:
3359 if (compose_sync == MagickFalse)
3364 pixel=(double) QuantumRange*(Sca+Dca);
3367 case ReflectCompositeOp:
3369 pixel=(double) QuantumRange*gamma*(Sca*Sca*
3370 MagickSafeReciprocal(1.0-Dca));
3371 if (pixel > (
double) QuantumRange)
3372 pixel=(double) QuantumRange;
3375 case RMSECompositeOp:
3380 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3385 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3391 (canvas_pixel.red-source_pixel.red)*
3392 (canvas_pixel.red-source_pixel.red)+
3393 (canvas_pixel.green-source_pixel.green)*
3394 (canvas_pixel.green-source_pixel.green)+
3395 (canvas_pixel.blue-source_pixel.blue)*
3396 (canvas_pixel.blue-source_pixel.blue)/3.0);
3399 case RedPixelChannel: pixel=gray;
break;
3400 case GreenPixelChannel: pixel=gray;
break;
3401 case BluePixelChannel: pixel=gray;
break;
3402 default: pixel=Dc;
break;
3406 case SaturateCompositeOp:
3408 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3413 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3418 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3419 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3420 white_luminance,illuminant,&hue,&chroma,&luma);
3421 ConvertRGBToGeneric(colorspace,(
double) source_pixel.red,
3422 (
double) source_pixel.green,(
double) source_pixel.blue,
3423 white_luminance,illuminant,&sans,&chroma,&sans);
3424 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3425 white_luminance,illuminant,&red,&green,&blue);
3428 case RedPixelChannel: pixel=red;
break;
3429 case GreenPixelChannel: pixel=green;
break;
3430 case BluePixelChannel: pixel=blue;
break;
3431 default: pixel=Dc;
break;
3435 case ScreenCompositeOp:
3442 if (compose_sync == MagickFalse)
3447 pixel=(double) QuantumRange*gamma*(Sca+Dca-Sca*Dca);
3450 case SoftBurnCompositeOp:
3452 if ((Sca+Dca) < 1.0)
3453 pixel=(double) QuantumRange*gamma*(0.5*Dca*
3454 MagickSafeReciprocal(1.0-Sca));
3456 pixel=(double) QuantumRange*gamma*(1.0-0.5*(1.0-Sca)*
3457 MagickSafeReciprocal(Dca));
3460 case SoftDodgeCompositeOp:
3462 if ((Sca+Dca) < 1.0)
3463 pixel=(double) QuantumRange*gamma*(0.5*Sca*
3464 MagickSafeReciprocal(1.0-Dca));
3466 pixel=(double) QuantumRange*gamma*(1.0-0.5*(1.0-Dca)*
3467 MagickSafeReciprocal(Sca));
3470 case SoftLightCompositeOp:
3474 pixel=(double) QuantumRange*gamma*(Dca*(Sa+(2.0*Sca-Sa)*
3475 (1.0-DcaDa))+Sca*(1.0-Da)+Dca*(1.0-Sa));
3478 if (((2.0*Sca) > Sa) && ((4.0*Dca) <= Da))
3480 pixel=(double) QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)*
3481 (4.0*DcaDa*(4.0*DcaDa+1.0)*(DcaDa-1.0)+7.0*DcaDa)+Sca*
3482 (1.0-Da)+Dca*(1.0-Sa));
3485 pixel=(double) QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)*
3486 (pow(DcaDa,0.5)-DcaDa)+Sca*(1.0-Da)+Dca*(1.0-Sa));
3489 case StampCompositeOp:
3491 pixel=(double) QuantumRange*(Sca+Dca*Dca-1.0);
3494 case StereoCompositeOp:
3496 if (channel == RedPixelChannel)
3497 pixel=(MagickRealType) GetPixelRed(source_image,p);
3500 case ThresholdCompositeOp:
3506 if ((MagickRealType) fabs((
double) (2.0*delta)) < threshold)
3511 pixel=gamma*(Dc+delta*amount);
3514 case VividLightCompositeOp:
3522 if ((fabs((
double) Sa) < MagickEpsilon) ||
3523 (fabs((
double) (Sca-Sa)) < MagickEpsilon))
3525 pixel=(double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*
3529 if ((2.0*Sca) <= Sa)
3531 pixel=(double) QuantumRange*gamma*(Sa*(Da+Sa*(Dca-Da)*
3532 MagickSafeReciprocal(2.0*Sca))+Sca*(1.0-Da)+Dca*(1.0-Sa));
3535 pixel=(double) QuantumRange*gamma*(Dca*Sa*Sa*
3536 MagickSafeReciprocal(2.0*(Sa-Sca))+Sca*(1.0-Da)+Dca*(1.0-Sa));
3539 case XorCompositeOp:
3541 pixel=(double) QuantumRange*(Sca*(1.0-Da)+Dca*(1.0-Sa));
3550 q[i]=clamp != MagickFalse ? ClampPixel(pixel) : ClampToQuantum(pixel);
3552 p+=(ptrdiff_t) GetPixelChannels(source_image);
3553 channels=GetPixelChannels(source_image);
3554 if (p >= (pixels+channels*source_image->columns))
3556 q+=(ptrdiff_t) GetPixelChannels(image);
3558 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3560 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3565#if defined(MAGICKCORE_OPENMP_SUPPORT)
3569 proceed=SetImageProgress(image,CompositeImageTag,progress,image->rows);
3570 if (proceed == MagickFalse)
3574 source_view=DestroyCacheView(source_view);
3575 image_view=DestroyCacheView(image_view);
3576 if (canvas_image != (Image * ) NULL)
3577 canvas_image=DestroyImage(canvas_image);
3579 source_image=DestroyImage(source_image);
3609MagickExport MagickBooleanType TextureImage(Image *image,
const Image *texture,
3610 ExceptionInfo *exception)
3612#define TextureImageTag "Texture/Image"
3627 assert(image != (Image *) NULL);
3628 assert(image->signature == MagickCoreSignature);
3629 if (IsEventLogging() != MagickFalse)
3630 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
3631 if (texture == (
const Image *) NULL)
3632 return(MagickFalse);
3633 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3634 return(MagickFalse);
3635 texture_image=CloneImage(texture,0,0,MagickTrue,exception);
3636 if (texture_image == (
const Image *) NULL)
3637 return(MagickFalse);
3638 (void) TransformImageColorspace(texture_image,image->colorspace,exception);
3639 (void) SetImageVirtualPixelMethod(texture_image,TileVirtualPixelMethod,
3642 if ((image->compose != CopyCompositeOp) &&
3643 ((image->compose != OverCompositeOp) ||
3644 (image->alpha_trait != UndefinedPixelTrait) ||
3645 (texture_image->alpha_trait != UndefinedPixelTrait)))
3650 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) texture_image->rows)
3655 if (status == MagickFalse)
3657 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
3662 thread_status=CompositeImage(image,texture_image,image->compose,
3663 MagickTrue,x+texture_image->tile_offset.x,y+
3664 texture_image->tile_offset.y,exception);
3665 if (thread_status == MagickFalse)
3667 status=thread_status;
3671 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3676 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
3678 if (proceed == MagickFalse)
3682 (void) SetImageProgress(image,TextureImageTag,(MagickOffsetType)
3683 image->rows,image->rows);
3684 texture_image=DestroyImage(texture_image);
3691 texture_view=AcquireVirtualCacheView(texture_image,exception);
3692 image_view=AcquireAuthenticCacheView(image,exception);
3693#if defined(MAGICKCORE_OPENMP_SUPPORT)
3694 #pragma omp parallel for schedule(static) shared(status) \
3695 magick_number_threads(texture_image,image,image->rows,2)
3697 for (y=0; y < (ssize_t) image->rows; y++)
3715 if (status == MagickFalse)
3717 pixels=GetCacheViewVirtualPixels(texture_view,texture_image->tile_offset.x,
3718 (y+texture_image->tile_offset.y) % (ssize_t) texture_image->rows,
3719 texture_image->columns,1,exception);
3720 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3721 if ((pixels == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
3726 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
3732 width=texture_image->columns;
3733 if ((x+(ssize_t) width) > (ssize_t) image->columns)
3734 width=image->columns-(size_t) x;
3735 for (j=0; j < (ssize_t) width; j++)
3740 for (i=0; i < (ssize_t) GetPixelChannels(texture_image); i++)
3742 PixelChannel channel = GetPixelChannelChannel(texture_image,i);
3743 PixelTrait traits = GetPixelChannelTraits(image,channel);
3744 PixelTrait texture_traits=GetPixelChannelTraits(texture_image,
3746 if ((traits == UndefinedPixelTrait) ||
3747 (texture_traits == UndefinedPixelTrait))
3749 SetPixelChannel(image,channel,p[i],q);
3751 p+=(ptrdiff_t) GetPixelChannels(texture_image);
3752 q+=(ptrdiff_t) GetPixelChannels(image);
3755 sync=SyncCacheViewAuthenticPixels(image_view,exception);
3756 if (sync == MagickFalse)
3758 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3763 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
3765 if (proceed == MagickFalse)
3769 texture_view=DestroyCacheView(texture_view);
3770 image_view=DestroyCacheView(image_view);
3771 texture_image=DestroyImage(texture_image);