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/random_.h"
75#include "MagickCore/random-private.h"
76#include "MagickCore/resample.h"
77#include "MagickCore/resource_.h"
78#include "MagickCore/string_.h"
79#include "MagickCore/string-private.h"
80#include "MagickCore/thread-private.h"
81#include "MagickCore/threshold.h"
82#include "MagickCore/token.h"
83#include "MagickCore/transform.h"
84#include "MagickCore/utility.h"
85#include "MagickCore/utility-private.h"
86#include "MagickCore/version.h"
187static Image *BlendConvolveImage(
const Image *image,
const char *kernel,
188 ExceptionInfo *exception)
200 kernel_info=AcquireKernelInfo(kernel,exception);
201 if (kernel_info == (KernelInfo *) NULL)
202 return((Image *) NULL);
203 clone_image=CloneImage(image,0,0,MagickTrue,exception);
204 if (clone_image == (Image *) NULL)
206 kernel_info=DestroyKernelInfo(kernel_info);
207 return((Image *) NULL);
209 (void) SetImageAlphaChannel(clone_image,OffAlphaChannel,exception);
210 convolve_image=ConvolveImage(clone_image,kernel_info,exception);
211 kernel_info=DestroyKernelInfo(kernel_info);
212 clone_image=DestroyImage(clone_image);
213 return(convolve_image);
216static Image *BlendMagnitudeImage(
const Image *dx_image,
const Image *dy_image,
217 ExceptionInfo *exception)
236 magnitude_image=CloneImage(dx_image,0,0,MagickTrue,exception);
237 if (magnitude_image == (Image *) NULL)
238 return(magnitude_image);
239 dx_view=AcquireVirtualCacheView(dx_image,exception);
240 dy_view=AcquireVirtualCacheView(dy_image,exception);
241 magnitude_view=AcquireAuthenticCacheView(magnitude_image,exception);
242#if defined(MAGICKCORE_OPENMP_SUPPORT)
243 #pragma omp parallel for schedule(static) shared(status) \
244 magick_number_threads(dx_image,magnitude_image,dx_image->rows,1)
246 for (y=0; y < (ssize_t) dx_image->rows; y++)
258 if (status == MagickFalse)
260 p=GetCacheViewVirtualPixels(dx_view,0,y,dx_image->columns,1,exception);
261 q=GetCacheViewVirtualPixels(dy_view,0,y,dx_image->columns,1,exception);
262 r=GetCacheViewAuthenticPixels(magnitude_view,0,y,dx_image->columns,1,
264 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL) ||
265 (r == (Quantum *) NULL))
270 for (x=0; x < (ssize_t) dx_image->columns; x++)
275 for (i=0; i < (ssize_t) GetPixelChannels(dx_image); i++)
277 PixelChannel channel = GetPixelChannelChannel(dx_image,i);
278 PixelTrait traits = GetPixelChannelTraits(dx_image,channel);
279 PixelTrait dy_traits = GetPixelChannelTraits(dy_image,channel);
280 if ((traits == UndefinedPixelTrait) ||
281 (dy_traits == UndefinedPixelTrait) ||
282 ((dy_traits & UpdatePixelTrait) == 0))
284 r[i]=ClampToQuantum(hypot((
double) p[i],(
double)
285 GetPixelChannel(dy_image,channel,q)));
287 p+=(ptrdiff_t) GetPixelChannels(dx_image);
288 q+=(ptrdiff_t) GetPixelChannels(dy_image);
289 r+=(ptrdiff_t) GetPixelChannels(magnitude_image);
291 if (SyncCacheViewAuthenticPixels(magnitude_view,exception) == MagickFalse)
294 magnitude_view=DestroyCacheView(magnitude_view);
295 dy_view=DestroyCacheView(dy_view);
296 dx_view=DestroyCacheView(dx_view);
297 if (status == MagickFalse)
298 magnitude_image=DestroyImage(magnitude_image);
299 return(magnitude_image);
302static Image *BlendMaxMagnitudeImage(
const Image *alpha_image,
303 const Image *beta_image,
const Image *dx_image,
const Image *dy_image,
304 ExceptionInfo *exception)
325 magnitude_image=CloneImage(alpha_image,0,0,MagickTrue,exception);
326 if (magnitude_image == (Image *) NULL)
327 return(magnitude_image);
328 alpha_view=AcquireVirtualCacheView(alpha_image,exception);
329 beta_view=AcquireVirtualCacheView(beta_image,exception);
330 dx_view=AcquireVirtualCacheView(dx_image,exception);
331 dy_view=AcquireVirtualCacheView(dy_image,exception);
332 magnitude_view=AcquireAuthenticCacheView(magnitude_image,exception);
333#if defined(MAGICKCORE_OPENMP_SUPPORT)
334 #pragma omp parallel for schedule(static) shared(status) \
335 magick_number_threads(alpha_image,magnitude_image,alpha_image->rows,1)
337 for (y=0; y < (ssize_t) alpha_image->rows; y++)
351 if (status == MagickFalse)
353 p=GetCacheViewVirtualPixels(alpha_view,0,y,alpha_image->columns,1,
355 q=GetCacheViewVirtualPixels(beta_view,0,y,alpha_image->columns,1,exception);
356 r=GetCacheViewVirtualPixels(dx_view,0,y,alpha_image->columns,1,exception);
357 s=GetCacheViewVirtualPixels(dy_view,0,y,alpha_image->columns,1,exception);
358 t=GetCacheViewAuthenticPixels(magnitude_view,0,y,alpha_image->columns,1,
360 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL) ||
361 (r == (
const Quantum *) NULL) || (s == (
const Quantum *) NULL) ||
362 (t == (Quantum *) NULL))
367 for (x=0; x < (ssize_t) alpha_image->columns; x++)
372 for (i=0; i < (ssize_t) GetPixelChannels(alpha_image); i++)
374 PixelChannel channel = GetPixelChannelChannel(alpha_image,i);
375 PixelTrait traits = GetPixelChannelTraits(alpha_image,channel);
376 PixelTrait beta_traits = GetPixelChannelTraits(beta_image,channel);
377 if ((traits == UndefinedPixelTrait) ||
378 (beta_traits == UndefinedPixelTrait) ||
379 ((beta_traits & UpdatePixelTrait) == 0))
381 if (p[i] > GetPixelChannel(beta_image,channel,q))
382 t[i]=GetPixelChannel(dx_image,channel,r);
384 t[i]=GetPixelChannel(dy_image,channel,s);
386 p+=(ptrdiff_t) GetPixelChannels(alpha_image);
387 q+=(ptrdiff_t) GetPixelChannels(beta_image);
388 r+=(ptrdiff_t) GetPixelChannels(dx_image);
389 s+=(ptrdiff_t) GetPixelChannels(dy_image);
390 t+=(ptrdiff_t) GetPixelChannels(magnitude_image);
392 if (SyncCacheViewAuthenticPixels(magnitude_view,exception) == MagickFalse)
395 magnitude_view=DestroyCacheView(magnitude_view);
396 dy_view=DestroyCacheView(dy_view);
397 dx_view=DestroyCacheView(dx_view);
398 beta_view=DestroyCacheView(beta_view);
399 alpha_view=DestroyCacheView(alpha_view);
400 if (status == MagickFalse)
401 magnitude_image=DestroyImage(magnitude_image);
402 return(magnitude_image);
405static Image *BlendSumImage(
const Image *alpha_image,
const Image *beta_image,
406 const double attenuate,
const double sign,ExceptionInfo *exception)
425 sum_image=CloneImage(alpha_image,0,0,MagickTrue,exception);
426 if (sum_image == (Image *) NULL)
428 alpha_view=AcquireVirtualCacheView(alpha_image,exception);
429 beta_view=AcquireVirtualCacheView(beta_image,exception);
430 sum_view=AcquireAuthenticCacheView(sum_image,exception);
431#if defined(MAGICKCORE_OPENMP_SUPPORT)
432 #pragma omp parallel for schedule(static) shared(status) \
433 magick_number_threads(alpha_image,sum_image,alpha_image->rows,1)
435 for (y=0; y < (ssize_t) alpha_image->rows; y++)
447 if (status == MagickFalse)
449 p=GetCacheViewVirtualPixels(alpha_view,0,y,alpha_image->columns,1,
451 q=GetCacheViewVirtualPixels(beta_view,0,y,alpha_image->columns,1,exception);
452 r=GetCacheViewAuthenticPixels(sum_view,0,y,alpha_image->columns,1,
454 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL) ||
455 (r == (Quantum *) NULL))
460 for (x=0; x < (ssize_t) alpha_image->columns; x++)
465 for (i=0; i < (ssize_t) GetPixelChannels(alpha_image); i++)
467 PixelChannel channel = GetPixelChannelChannel(alpha_image,i);
468 PixelTrait traits = GetPixelChannelTraits(alpha_image,channel);
469 PixelTrait beta_traits = GetPixelChannelTraits(beta_image,channel);
470 if ((traits == UndefinedPixelTrait) ||
471 (beta_traits == UndefinedPixelTrait) ||
472 ((beta_traits & UpdatePixelTrait) == 0))
474 r[i]=ClampToQuantum(attenuate*((
double) p[i]+sign*
475 (
double) GetPixelChannel(beta_image,channel,q)));
477 p+=(ptrdiff_t) GetPixelChannels(alpha_image);
478 q+=(ptrdiff_t) GetPixelChannels(beta_image);
479 r+=(ptrdiff_t) GetPixelChannels(sum_image);
481 if (SyncCacheViewAuthenticPixels(sum_view,exception) == MagickFalse)
484 sum_view=DestroyCacheView(sum_view);
485 beta_view=DestroyCacheView(beta_view);
486 alpha_view=DestroyCacheView(alpha_view);
487 if (status == MagickFalse)
488 sum_image=DestroyImage(sum_image);
492static Image *BlendDivergentImage(
const Image *alpha_image,
493 const Image *beta_image,ExceptionInfo *exception)
495#define FreeDivergentResources() \
497 if (dy_image != (Image *) NULL) \
498 dy_image=DestroyImage(dy_image); \
499 if (dx_image != (Image *) NULL) \
500 dx_image=DestroyImage(dx_image); \
501 if (magnitude_beta != (Image *) NULL) \
502 magnitude_beta=DestroyImage(magnitude_beta); \
503 if (dy_beta != (Image *) NULL) \
504 dy_beta=DestroyImage(dy_beta); \
505 if (dx_beta != (Image *) NULL) \
506 dx_beta=DestroyImage(dx_beta); \
507 if (magnitude_alpha != (Image *) NULL) \
508 magnitude_alpha=DestroyImage(magnitude_alpha); \
509 if (dy_alpha != (Image *) NULL) \
510 dy_alpha=DestroyImage(dy_alpha); \
511 if (dx_alpha != (Image *) NULL) \
512 dx_alpha=DestroyImage(dx_alpha); \
516 *divergent_image = (Image *) NULL,
517 *dx_alpha = (Image *) NULL,
518 *dx_beta = (Image *) NULL,
519 *dx_divergent = (Image *) NULL,
520 *dx_image = (Image *) NULL,
521 *dy_alpha = (Image *) NULL,
522 *dy_beta = (Image *) NULL,
523 *dy_divergent = (Image *) NULL,
524 *dy_image = (Image *) NULL,
525 *magnitude_alpha = (Image *) NULL,
526 *magnitude_beta = (Image *) NULL;
531 dx_alpha=BlendConvolveImage(alpha_image,
"3x1:-0.5,0.0,0.5",exception);
532 if (dx_alpha == (Image *) NULL)
534 FreeDivergentResources();
535 return((Image *) NULL);
537 dy_alpha=BlendConvolveImage(alpha_image,
"1x3:-0.5,0.0,0.5",exception);
538 if (dy_alpha == (Image *) NULL)
540 FreeDivergentResources();
541 return((Image *) NULL);
543 magnitude_alpha=BlendMagnitudeImage(dx_alpha,dy_alpha,exception);
544 if (magnitude_alpha == (Image *) NULL)
546 FreeDivergentResources();
547 return((Image *) NULL);
552 dx_beta=BlendConvolveImage(beta_image,
"3x1:-0.5,0.0,0.5",exception);
553 if (dx_beta == (Image *) NULL)
555 FreeDivergentResources();
556 return((Image *) NULL);
558 dy_beta=BlendConvolveImage(beta_image,
"1x3:-0.5,0.0,0.5",exception);
559 if (dy_beta == (Image *) NULL)
561 FreeDivergentResources();
562 return((Image *) NULL);
564 magnitude_beta=BlendMagnitudeImage(dx_beta,dy_beta,exception);
565 if (magnitude_beta == (Image *) NULL)
567 FreeDivergentResources();
568 return((Image *) NULL);
573 dx_image=BlendMaxMagnitudeImage(magnitude_alpha,magnitude_beta,dx_alpha,
575 if (dx_image == (Image *) NULL)
577 FreeDivergentResources();
578 return((Image *) NULL);
580 dy_image=BlendMaxMagnitudeImage(magnitude_alpha,magnitude_beta,dy_alpha,
582 if (dy_image == (Image *) NULL)
584 FreeDivergentResources();
585 return((Image *) NULL);
587 dx_beta=DestroyImage(dx_beta);
588 dx_alpha=DestroyImage(dx_alpha);
589 magnitude_beta=DestroyImage(magnitude_beta);
590 magnitude_alpha=DestroyImage(magnitude_alpha);
594 dx_divergent=BlendConvolveImage(dx_image,
"3x1:-0.5,0.0,0.5",exception);
595 if (dx_divergent == (Image *) NULL)
597 FreeDivergentResources();
598 return((Image *) NULL);
600 dy_divergent=BlendConvolveImage(dy_image,
"1x3:-0.5,0.0,0.5",exception);
601 if (dy_divergent == (Image *) NULL)
603 FreeDivergentResources();
604 return((Image *) NULL);
606 divergent_image=BlendSumImage(dx_divergent,dy_divergent,0.25,1.0,exception);
607 dy_divergent=DestroyImage(dy_divergent);
608 dx_divergent=DestroyImage(dx_divergent);
609 if (divergent_image == (Image *) NULL)
611 FreeDivergentResources();
612 return((Image *) NULL);
614 FreeDivergentResources();
615 return(divergent_image);
618static MagickBooleanType BlendMaskAlphaChannel(Image *image,
619 const Image *mask_image,ExceptionInfo *exception)
634 if (SetImageAlpha(image,OpaqueAlpha,exception) == MagickFalse)
636 image_view=AcquireAuthenticCacheView(image,exception);
637 mask_view=AcquireVirtualCacheView(mask_image,exception);
638#if defined(MAGICKCORE_OPENMP_SUPPORT)
639 #pragma omp parallel for schedule(static) shared(status) \
640 magick_number_threads(image,image,image->rows,2)
642 for (y=0; y < (ssize_t) image->rows; y++)
653 if (status == MagickFalse)
655 p=GetCacheViewVirtualPixels(mask_view,0,y,image->columns,1,exception);
656 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
657 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
662 for (x=0; x < (ssize_t) image->columns; x++)
665 alpha = GetPixelAlpha(mask_image,p);
668 i = GetPixelChannelOffset(image,AlphaPixelChannel);
670 if (fabs((
double) alpha) >= MagickEpsilon)
672 p+=(ptrdiff_t) GetPixelChannels(mask_image);
673 q+=(ptrdiff_t) GetPixelChannels(image);
675 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
678 mask_view=DestroyCacheView(mask_view);
679 image_view=DestroyCacheView(image_view);
683static Image *BlendMeanImage(Image *image,
const Image *mask_image,
684 ExceptionInfo *exception)
692 mean[MaxPixelChannels];
707 (void) memset(mean,0,MaxPixelChannels*
sizeof(*mean));
708 alpha_view=AcquireVirtualCacheView(image,exception);
709 for (y=0; y < (ssize_t) image->rows; y++)
717 p=GetCacheViewVirtualPixels(alpha_view,0,y,image->columns,1,
719 if (p == (
const Quantum *) NULL)
721 for (x=0; x < (ssize_t) image->columns; x++)
726 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
728 PixelChannel channel = GetPixelChannelChannel(image,i);
729 PixelTrait traits = GetPixelChannelTraits(image,channel);
730 if (traits == UndefinedPixelTrait)
732 mean[i]+=QuantumScale*(double) p[i];
734 p+=(ptrdiff_t) GetPixelChannels(image);
737 alpha_view=DestroyCacheView(alpha_view);
738 if (y < (ssize_t) image->rows)
739 return((Image *) NULL);
740 for (j=0; j < (ssize_t) GetPixelChannels(image); j++)
741 mean[j]=(
double) QuantumRange*mean[j]/image->columns/
746 mean_image=CloneImage(image,0,0,MagickTrue,exception);
747 if (mean_image == (Image *) NULL)
749 mask_view=AcquireVirtualCacheView(mask_image,exception);
750 mean_view=AcquireAuthenticCacheView(mean_image,exception);
751#if defined(MAGICKCORE_OPENMP_SUPPORT)
752 #pragma omp parallel for schedule(static) shared(status) \
753 magick_number_threads(mask_image,mean_image,mean_image->rows,4)
755 for (y=0; y < (ssize_t) mean_image->rows; y++)
766 if (status == MagickFalse)
768 p=GetCacheViewVirtualPixels(mask_view,0,y,mean_image->columns,1,exception);
769 q=GetCacheViewAuthenticPixels(mean_view,0,y,mean_image->columns,1,
771 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
776 for (x=0; x < (ssize_t) mean_image->columns; x++)
779 alpha = GetPixelAlpha(mask_image,p),
780 mask = GetPixelReadMask(mask_image,p);
785 for (i=0; i < (ssize_t) GetPixelChannels(mean_image); i++)
787 PixelChannel channel = GetPixelChannelChannel(mean_image,i);
788 PixelTrait traits = GetPixelChannelTraits(mean_image,channel);
789 if (traits == UndefinedPixelTrait)
791 if (mask <= (QuantumRange/2))
794 if (fabs((
double) alpha) >= MagickEpsilon)
795 q[i]=ClampToQuantum(mean[i]);
797 p+=(ptrdiff_t) GetPixelChannels(mask_image);
798 q+=(ptrdiff_t) GetPixelChannels(mean_image);
800 if (SyncCacheViewAuthenticPixels(mean_view,exception) == MagickFalse)
803 mask_view=DestroyCacheView(mask_view);
804 mean_view=DestroyCacheView(mean_view);
805 if (status == MagickFalse)
806 mean_image=DestroyImage(mean_image);
810static MagickBooleanType BlendRMSEResidual(
const Image *alpha_image,
811 const Image *beta_image,
double *residual,ExceptionInfo *exception)
819 channel_residual = 0.0;
825 columns = MagickMax(alpha_image->columns,beta_image->columns),
826 rows = MagickMax(alpha_image->rows,beta_image->rows);
831 alpha_view=AcquireVirtualCacheView(alpha_image,exception);
832 beta_view=AcquireVirtualCacheView(beta_image,exception);
833#if defined(MAGICKCORE_OPENMP_SUPPORT)
834 #pragma omp parallel for schedule(static) shared(status) \
835 reduction(+:area) reduction(+:channel_residual) \
836 magick_number_threads(alpha_image,alpha_image,rows,1)
838 for (y=0; y < (ssize_t) rows; y++)
847 if (status == MagickFalse)
849 p=GetCacheViewVirtualPixels(alpha_view,0,y,columns,1,exception);
850 q=GetCacheViewVirtualPixels(beta_view,0,y,columns,1,exception);
851 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL))
856 channel_residual=0.0;
857 for (x=0; x < (ssize_t) columns; x++)
866 if ((GetPixelReadMask(alpha_image,p) <= (QuantumRange/2)) ||
867 (GetPixelReadMask(beta_image,q) <= (QuantumRange/2)))
869 p+=(ptrdiff_t) GetPixelChannels(alpha_image);
870 q+=(ptrdiff_t) GetPixelChannels(beta_image);
873 Sa=QuantumScale*(double) GetPixelAlpha(alpha_image,p);
874 Da=QuantumScale*(double) GetPixelAlpha(beta_image,q);
875 for (i=0; i < (ssize_t) GetPixelChannels(alpha_image); i++)
880 PixelChannel channel = GetPixelChannelChannel(alpha_image,i);
881 PixelTrait traits = GetPixelChannelTraits(alpha_image,channel);
882 PixelTrait beta_traits = GetPixelChannelTraits(beta_image,channel);
883 if ((traits == UndefinedPixelTrait) ||
884 (beta_traits == UndefinedPixelTrait) ||
885 ((beta_traits & UpdatePixelTrait) == 0))
887 if (channel == AlphaPixelChannel)
888 distance=QuantumScale*((double) p[i]-(double) GetPixelChannel(
889 beta_image,channel,q));
891 distance=QuantumScale*(Sa*(double) p[i]-Da*(double) GetPixelChannel(
892 beta_image,channel,q));
893 channel_residual+=distance*distance;
896 p+=(ptrdiff_t) GetPixelChannels(alpha_image);
897 q+=(ptrdiff_t) GetPixelChannels(beta_image);
900 beta_view=DestroyCacheView(beta_view);
901 alpha_view=DestroyCacheView(alpha_view);
902 area=MagickSafeReciprocal(area);
903 *residual=sqrt(area*channel_residual/(
double) GetImageChannels(alpha_image));
907static MagickBooleanType CompositeOverImage(Image *image,
908 const Image *source_image,
const MagickBooleanType clip_to_self,
909 const ssize_t x_offset,
const ssize_t y_offset,ExceptionInfo *exception)
911#define CompositeImageTag "Composite/Image"
936 value=GetImageArtifact(image,
"compose:clamp");
937 if (value != (
const char *) NULL)
938 clamp=IsStringTrue(value);
941 source_view=AcquireVirtualCacheView(source_image,exception);
942 image_view=AcquireAuthenticCacheView(image,exception);
943#if defined(MAGICKCORE_OPENMP_SUPPORT)
944 #pragma omp parallel for schedule(static) shared(progress,status) \
945 magick_number_threads(source_image,image,image->rows,1)
947 for (y=0; y < (ssize_t) image->rows; y++)
965 if (status == MagickFalse)
967 if (clip_to_self != MagickFalse)
971 if ((y-y_offset) >= (ssize_t) source_image->rows)
977 pixels=(Quantum *) NULL;
979 if ((y >= y_offset) &&
980 ((y-y_offset) < (ssize_t) source_image->rows))
982 p=GetCacheViewVirtualPixels(source_view,0,CastDoubleToSsizeT((
double) y-
983 y_offset),source_image->columns,1,exception);
984 if (p == (
const Quantum *) NULL)
991 p-=(ptrdiff_t) CastDoubleToSsizeT((
double) x_offset*
992 GetPixelChannels(source_image));
994 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
995 if (q == (Quantum *) NULL)
1000 GetPixelInfo(image,&canvas_pixel);
1001 GetPixelInfo(source_image,&source_pixel);
1002 for (x=0; x < (ssize_t) image->columns; x++)
1022 if (clip_to_self != MagickFalse)
1026 q+=(ptrdiff_t) GetPixelChannels(image);
1029 if ((x-x_offset) >= (ssize_t) source_image->columns)
1032 if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
1033 ((x-x_offset) >= (ssize_t) source_image->columns))
1036 source[MaxPixelChannels];
1043 (void) GetOneVirtualPixel(source_image,
1044 CastDoubleToSsizeT((
double) x-x_offset),
1045 CastDoubleToSsizeT((
double) y-y_offset),source,exception);
1046 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1051 PixelChannel channel = GetPixelChannelChannel(image,i);
1052 PixelTrait traits = GetPixelChannelTraits(image,channel);
1053 PixelTrait source_traits=GetPixelChannelTraits(source_image,
1055 if ((traits == UndefinedPixelTrait) ||
1056 (source_traits == UndefinedPixelTrait))
1058 if (channel == AlphaPixelChannel)
1059 pixel=(MagickRealType) TransparentAlpha;
1061 pixel=(MagickRealType) q[i];
1062 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
1063 ClampToQuantum(pixel);
1065 q+=(ptrdiff_t) GetPixelChannels(image);
1073 Sa=QuantumScale*(double) GetPixelAlpha(source_image,p);
1074 Da=QuantumScale*(double) GetPixelAlpha(image,q);
1076 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1081 PixelChannel channel = GetPixelChannelChannel(image,i);
1082 PixelTrait traits = GetPixelChannelTraits(image,channel);
1083 PixelTrait source_traits=GetPixelChannelTraits(source_image,channel);
1084 if (traits == UndefinedPixelTrait)
1086 if ((source_traits == UndefinedPixelTrait) &&
1087 (channel != AlphaPixelChannel))
1089 if (channel == AlphaPixelChannel)
1094 pixel=(double) QuantumRange*alpha;
1095 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
1096 ClampToQuantum(pixel);
1103 Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
1104 Dc=(MagickRealType) q[i];
1105 if ((traits & CopyPixelTrait) != 0)
1110 q[i]=ClampToQuantum(Sc);
1118 Sca=QuantumScale*Sa*Sc;
1119 Dca=QuantumScale*Da*Dc;
1120 gamma=MagickSafeReciprocal(alpha);
1121 pixel=(double) QuantumRange*gamma*(Sca+Dca*(1.0-Sa));
1122 q[i]=clamp != MagickFalse ? ClampPixel(pixel) : ClampToQuantum(pixel);
1124 p+=(ptrdiff_t) GetPixelChannels(source_image);
1125 channels=GetPixelChannels(source_image);
1126 if (p >= (pixels+channels*source_image->columns))
1128 q+=(ptrdiff_t) GetPixelChannels(image);
1130 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1132 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1137#if defined(MAGICKCORE_OPENMP_SUPPORT)
1141 proceed=SetImageProgress(image,CompositeImageTag,progress,image->rows);
1142 if (proceed == MagickFalse)
1146 source_view=DestroyCacheView(source_view);
1147 image_view=DestroyCacheView(image_view);
1151static MagickBooleanType SaliencyBlendImage(Image *image,
1152 const Image *source_image,
const ssize_t x_offset,
const ssize_t y_offset,
1153 const double iterations,
const double residual_threshold,
const size_t tick,
1154 ExceptionInfo *exception)
1160 *residual_image = (Image *) NULL;
1166 status = MagickTrue,
1167 verbose = MagickFalse;
1171 source_image->columns,
1183 crop_image=CropImage(image,&crop_info,exception);
1184 if (crop_image == (Image *) NULL)
1185 return(MagickFalse);
1186 DisableCompositeClampUnlessSpecified(crop_image);
1187 divergent_image=BlendDivergentImage(crop_image,source_image,exception);
1188 if (divergent_image == (Image *) NULL)
1190 crop_image=DestroyImage(crop_image);
1191 return(MagickFalse);
1193 (void) ResetImagePage(crop_image,
"0x0+0+0");
1194 relax_image=BlendMeanImage(crop_image,source_image,exception);
1195 if (relax_image == (Image *) NULL)
1197 crop_image=DestroyImage(crop_image);
1198 divergent_image=DestroyImage(divergent_image);
1199 return(MagickFalse);
1201 status=BlendMaskAlphaChannel(crop_image,source_image,exception);
1202 if (status == MagickFalse)
1204 crop_image=DestroyImage(crop_image);
1205 divergent_image=DestroyImage(divergent_image);
1206 return(MagickFalse);
1208 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1209 if (residual_image == (Image *) NULL)
1211 crop_image=DestroyImage(crop_image);
1212 relax_image=DestroyImage(relax_image);
1213 return(MagickFalse);
1218 kernel_info=AcquireKernelInfo(
"3x3:0,0.25,0,0.25,0,0.25,0,0.25,0",exception);
1219 if (kernel_info == (KernelInfo *) NULL)
1221 crop_image=DestroyImage(crop_image);
1222 residual_image=DestroyImage(residual_image);
1223 relax_image=DestroyImage(relax_image);
1224 return(MagickFalse);
1226 verbose=IsStringTrue(GetImageArtifact(image,
"verbose"));
1227 if (verbose != MagickFalse)
1228 (void) FormatLocaleFile(stderr,
"saliency blending:\n");
1229 for (i=0; i < (ssize_t) iterations; i++)
1238 convolve_image=ConvolveImage(relax_image,kernel_info,exception);
1239 if (convolve_image == (Image *) NULL)
1241 relax_image=DestroyImage(relax_image);
1242 relax_image=convolve_image;
1243 sum_image=BlendSumImage(relax_image,divergent_image,1.0,-1.0,exception);
1244 if (sum_image == (Image *) NULL)
1246 relax_image=DestroyImage(relax_image);
1247 relax_image=sum_image;
1248 status=CompositeOverImage(relax_image,crop_image,MagickTrue,0,0,exception);
1249 if (status == MagickFalse)
1251 status=BlendRMSEResidual(relax_image,residual_image,&residual,exception);
1252 if (status == MagickFalse)
1254 if ((verbose != MagickFalse) && ((i % MagickMax(tick,1)) == 0))
1255 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double) residual);
1256 if (residual < residual_threshold)
1258 if (verbose != MagickFalse)
1259 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double)
1263 residual_image=DestroyImage(residual_image);
1264 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1265 if (residual_image == (Image *) NULL)
1268 kernel_info=DestroyKernelInfo(kernel_info);
1269 crop_image=DestroyImage(crop_image);
1270 divergent_image=DestroyImage(divergent_image);
1271 residual_image=DestroyImage(residual_image);
1275 status=CompositeOverImage(image,relax_image,MagickTrue,x_offset,y_offset,
1277 relax_image=DestroyImage(relax_image);
1281static MagickBooleanType SeamlessBlendImage(Image *image,
1282 const Image *source_image,
const ssize_t x_offset,
const ssize_t y_offset,
1283 const double iterations,
const double residual_threshold,
const size_t tick,
1284 ExceptionInfo *exception)
1298 status = MagickTrue,
1299 verbose = MagickFalse;
1303 source_image->columns,
1315 crop_image=CropImage(image,&crop_info,exception);
1316 if (crop_image == (Image *) NULL)
1317 return(MagickFalse);
1318 DisableCompositeClampUnlessSpecified(crop_image);
1319 (void) ResetImagePage(crop_image,
"0x0+0+0");
1320 sum_image=BlendSumImage(crop_image,source_image,1.0,-1.0,exception);
1321 crop_image=DestroyImage(crop_image);
1322 if (sum_image == (Image *) NULL)
1323 return(MagickFalse);
1324 mean_image=BlendMeanImage(sum_image,source_image,exception);
1325 sum_image=DestroyImage(sum_image);
1326 if (mean_image == (Image *) NULL)
1327 return(MagickFalse);
1328 relax_image=CloneImage(mean_image,0,0,MagickTrue,exception);
1329 if (relax_image == (Image *) NULL)
1331 mean_image=DestroyImage(mean_image);
1332 return(MagickFalse);
1334 status=BlendMaskAlphaChannel(mean_image,source_image,exception);
1335 if (status == MagickFalse)
1337 relax_image=DestroyImage(relax_image);
1338 mean_image=DestroyImage(mean_image);
1339 return(MagickFalse);
1341 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1342 if (residual_image == (Image *) NULL)
1344 relax_image=DestroyImage(relax_image);
1345 mean_image=DestroyImage(mean_image);
1346 return(MagickFalse);
1351 kernel_info=AcquireKernelInfo(
"3x3:0,0.25,0,0.25,0,0.25,0,0.25,0",exception);
1352 if (kernel_info == (KernelInfo *) NULL)
1354 residual_image=DestroyImage(residual_image);
1355 relax_image=DestroyImage(relax_image);
1356 mean_image=DestroyImage(mean_image);
1357 return(MagickFalse);
1359 verbose=IsStringTrue(GetImageArtifact(image,
"verbose"));
1360 if (verbose != MagickFalse)
1361 (void) FormatLocaleFile(stderr,
"seamless blending:\n");
1362 for (i=0; i < (ssize_t) iterations; i++)
1370 convolve_image=ConvolveImage(relax_image,kernel_info,exception);
1371 if (convolve_image == (Image *) NULL)
1373 relax_image=DestroyImage(relax_image);
1374 relax_image=convolve_image;
1375 status=CompositeOverImage(relax_image,mean_image,MagickTrue,0,0,exception);
1376 if (status == MagickFalse)
1378 status=BlendRMSEResidual(relax_image,residual_image,&residual,exception);
1379 if (status == MagickFalse)
1381 if ((verbose != MagickFalse) && ((i % MagickMax(tick,1)) == 0))
1382 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double) residual);
1383 if (residual < residual_threshold)
1385 if (verbose != MagickFalse)
1386 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(
double)
1390 if (residual_image != (Image *) NULL)
1391 residual_image=DestroyImage(residual_image);
1392 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1393 if (residual_image == (Image *) NULL)
1396 kernel_info=DestroyKernelInfo(kernel_info);
1397 mean_image=DestroyImage(mean_image);
1398 residual_image=DestroyImage(residual_image);
1402 foreground_image=BlendSumImage(source_image,relax_image,1.0,1.0,exception);
1403 relax_image=DestroyImage(relax_image);
1404 if (foreground_image == (Image *) NULL)
1405 return(MagickFalse);
1406 (void) SetImageMask(foreground_image,ReadPixelMask,(
const Image *) NULL,
1408 status=CompositeOverImage(image,foreground_image,MagickTrue,x_offset,y_offset,
1410 foreground_image=DestroyImage(foreground_image);
1414MagickExport MagickBooleanType CompositeImage(Image *image,
1415 const Image *composite,
const CompositeOperator compose,
1416 const MagickBooleanType clip_to_self,
const ssize_t x_offset,
1417 const ssize_t y_offset,ExceptionInfo *exception)
1419#define CompositeImageTag "Composite/Image"
1426 colorspace = HCLColorspace;
1432 white_luminance = 10000.0;
1438 illuminant = D65Illuminant;
1470 assert(image != (Image *) NULL);
1471 assert(image->signature == MagickCoreSignature);
1472 assert(composite != (Image *) NULL);
1473 assert(composite->signature == MagickCoreSignature);
1474 if (IsEventLogging() != MagickFalse)
1475 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1476 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1477 return(MagickFalse);
1478 source_image=CloneImage(composite,0,0,MagickTrue,exception);
1479 if (source_image == (
const Image *) NULL)
1480 return(MagickFalse);
1481 (void) SetImageColorspace(source_image,image->colorspace,exception);
1482 if ((compose == OverCompositeOp) || (compose == SrcOverCompositeOp))
1484 status=CompositeOverImage(image,source_image,clip_to_self,x_offset,
1485 y_offset,exception);
1486 source_image=DestroyImage(source_image);
1490 canvas_image=(Image *) NULL;
1491 canvas_dissolve=1.0;
1492 white_luminance=10000.0;
1493 artifact=GetImageArtifact(image,
"compose:white-luminance");
1494 if (artifact != (
const char *) NULL)
1495 white_luminance=StringToDouble(artifact,(
char **) NULL);
1496 artifact=GetImageArtifact(image,
"compose:illuminant");
1497 if (artifact != (
const char *) NULL)
1502 illuminant_type=ParseCommandOption(MagickIlluminantOptions,MagickFalse,
1504 if (illuminant_type < 0)
1505 illuminant=UndefinedIlluminant;
1507 illuminant=(IlluminantType) illuminant_type;
1509 artifact=GetImageArtifact(image,
"compose:colorspace");
1510 if (artifact != (
const char *) NULL)
1515 colorspace_type=ParseCommandOption(MagickColorspaceOptions,MagickFalse,
1517 if (colorspace_type < 0)
1518 colorspace=UndefinedColorspace;
1520 colorspace=(ColorspaceType) colorspace_type;
1523 artifact=GetImageArtifact(image,
"compose:clamp");
1524 if (artifact != (
const char *) NULL)
1525 clamp=IsStringTrue(artifact);
1526 compose_sync=MagickTrue;
1527 artifact=GetImageArtifact(image,
"compose:sync");
1528 if (artifact != (
const char *) NULL)
1529 compose_sync=IsStringTrue(artifact);
1530 SetGeometryInfo(&geometry_info);
1532 percent_chroma=100.0;
1533 source_dissolve=1.0;
1537 case CopyCompositeOp:
1539 if ((x_offset < 0) || (y_offset < 0))
1541 if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
1543 if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
1545 if ((source_image->alpha_trait == UndefinedPixelTrait) &&
1546 (image->alpha_trait != UndefinedPixelTrait))
1547 (void) SetImageAlphaChannel(source_image,OpaqueAlphaChannel,exception);
1549 source_view=AcquireVirtualCacheView(source_image,exception);
1550 image_view=AcquireAuthenticCacheView(image,exception);
1551#if defined(MAGICKCORE_OPENMP_SUPPORT)
1552 #pragma omp parallel for schedule(static) shared(status) \
1553 magick_number_threads(source_image,image,source_image->rows,4)
1555 for (y=0; y < (ssize_t) source_image->rows; y++)
1569 if (status == MagickFalse)
1571 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1573 q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
1574 source_image->columns,1,exception);
1575 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1580 for (x=0; x < (ssize_t) source_image->columns; x++)
1585 if (GetPixelReadMask(source_image,p) <= (QuantumRange/2))
1587 p+=(ptrdiff_t) GetPixelChannels(source_image);
1588 q+=(ptrdiff_t) GetPixelChannels(image);
1591 for (i=0; i < (ssize_t) GetPixelChannels(source_image); i++)
1593 PixelChannel channel = GetPixelChannelChannel(source_image,i);
1594 PixelTrait source_traits = GetPixelChannelTraits(source_image,
1596 PixelTrait traits = GetPixelChannelTraits(image,channel);
1597 if ((source_traits == UndefinedPixelTrait) ||
1598 (traits == UndefinedPixelTrait))
1600 SetPixelChannel(image,channel,p[i],q);
1602 p+=(ptrdiff_t) GetPixelChannels(source_image);
1603 q+=(ptrdiff_t) GetPixelChannels(image);
1605 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1606 if (sync == MagickFalse)
1608 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1613 proceed=SetImageProgress(image,CompositeImageTag,(MagickOffsetType)
1615 if (proceed == MagickFalse)
1619 source_view=DestroyCacheView(source_view);
1620 image_view=DestroyCacheView(image_view);
1621 source_image=DestroyImage(source_image);
1624 case IntensityCompositeOp:
1626 if ((x_offset < 0) || (y_offset < 0))
1628 if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
1630 if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
1633 source_view=AcquireVirtualCacheView(source_image,exception);
1634 image_view=AcquireAuthenticCacheView(image,exception);
1635#if defined(MAGICKCORE_OPENMP_SUPPORT)
1636 #pragma omp parallel for schedule(static) shared(status) \
1637 magick_number_threads(source_image,image,source_image->rows,4)
1639 for (y=0; y < (ssize_t) source_image->rows; y++)
1653 if (status == MagickFalse)
1655 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1657 q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
1658 source_image->columns,1,exception);
1659 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1664 for (x=0; x < (ssize_t) source_image->columns; x++)
1666 if (GetPixelReadMask(source_image,p) <= (QuantumRange/2))
1668 p+=(ptrdiff_t) GetPixelChannels(source_image);
1669 q+=(ptrdiff_t) GetPixelChannels(image);
1672 SetPixelAlpha(image,clamp != MagickFalse ?
1673 ClampPixel(GetPixelIntensity(source_image,p)) :
1674 ClampToQuantum(GetPixelIntensity(source_image,p)),q);
1675 p+=(ptrdiff_t) GetPixelChannels(source_image);
1676 q+=(ptrdiff_t) GetPixelChannels(image);
1678 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1679 if (sync == MagickFalse)
1681 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1686 proceed=SetImageProgress(image,CompositeImageTag,(MagickOffsetType)
1688 if (proceed == MagickFalse)
1692 source_view=DestroyCacheView(source_view);
1693 image_view=DestroyCacheView(image_view);
1694 source_image=DestroyImage(source_image);
1697 case CopyAlphaCompositeOp:
1698 case ChangeMaskCompositeOp:
1704 if ((image->alpha_trait & BlendPixelTrait) == 0)
1705 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1708 case BlurCompositeOp:
1733 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1734 if (canvas_image == (Image *) NULL)
1736 source_image=DestroyImage(source_image);
1737 return(MagickFalse);
1743 artifact=GetImageArtifact(image,
"compose:args");
1744 if (artifact != (
const char *) NULL)
1745 flags=ParseGeometry(artifact,&geometry_info);
1746 if ((flags & WidthValue) == 0)
1748 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1749 "InvalidSetting",
"'%s' '%s'",
"compose:args",artifact);
1750 source_image=DestroyImage(source_image);
1751 canvas_image=DestroyImage(canvas_image);
1752 return(MagickFalse);
1759 width=2.0*geometry_info.rho;
1761 if ((flags & HeightValue) != 0)
1762 height=2.0*geometry_info.sigma;
1770 if ((flags & XValue) != 0 )
1778 angle=DegreesToRadians(geometry_info.xi);
1779 blur.x1=width*cos(angle);
1780 blur.x2=width*sin(angle);
1781 blur.y1=(-height*sin(angle));
1782 blur.y2=height*cos(angle);
1786 if ((flags & YValue) != 0 )
1791 angle_start=DegreesToRadians(geometry_info.xi);
1792 angle_range=DegreesToRadians(geometry_info.psi)-angle_start;
1803 resample_filter=AcquireResampleFilter(image,exception);
1804 SetResampleFilter(resample_filter,GaussianFilter);
1808 GetPixelInfo(image,&pixel);
1809 source_view=AcquireVirtualCacheView(source_image,exception);
1810 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
1811 for (y=0; y < (ssize_t) source_image->rows; y++)
1825 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
1827 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1829 q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
1831 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1833 for (x=0; x < (ssize_t) source_image->columns; x++)
1835 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
1837 p+=(ptrdiff_t) GetPixelChannels(source_image);
1840 if (fabs(angle_range) > MagickEpsilon)
1845 angle=angle_start+angle_range*QuantumScale*(double)
1846 GetPixelBlue(source_image,p);
1847 blur.x1=width*cos(angle);
1848 blur.x2=width*sin(angle);
1849 blur.y1=(-height*sin(angle));
1850 blur.y2=height*cos(angle);
1852 ScaleResampleFilter(resample_filter,
1853 blur.x1*QuantumScale*(
double) GetPixelRed(source_image,p),
1854 blur.y1*QuantumScale*(
double) GetPixelGreen(source_image,p),
1855 blur.x2*QuantumScale*(
double) GetPixelRed(source_image,p),
1856 blur.y2*QuantumScale*(
double) GetPixelGreen(source_image,p) );
1857 (void) ResamplePixelColor(resample_filter,(
double) x_offset+x,
1858 (
double) y_offset+y,&pixel,exception);
1859 SetPixelViaPixelInfo(canvas_image,&pixel,q);
1860 p+=(ptrdiff_t) GetPixelChannels(source_image);
1861 q+=(ptrdiff_t) GetPixelChannels(canvas_image);
1863 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
1864 if (sync == MagickFalse)
1867 resample_filter=DestroyResampleFilter(resample_filter);
1868 source_view=DestroyCacheView(source_view);
1869 canvas_view=DestroyCacheView(canvas_view);
1870 source_image=DestroyImage(source_image);
1871 source_image=canvas_image;
1874 case DisplaceCompositeOp:
1875 case DistortCompositeOp:
1896 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1897 if (canvas_image == (Image *) NULL)
1899 source_image=DestroyImage(source_image);
1900 return(MagickFalse);
1902 SetGeometryInfo(&geometry_info);
1904 artifact=GetImageArtifact(image,
"compose:args");
1905 if (artifact != (
char *) NULL)
1906 flags=ParseGeometry(artifact,&geometry_info);
1907 if ((flags & (WidthValue | HeightValue)) == 0 )
1909 if ((flags & AspectValue) == 0)
1911 horizontal_scale=(MagickRealType) (source_image->columns-1)/2.0;
1912 vertical_scale=(MagickRealType) (source_image->rows-1)/2.0;
1916 horizontal_scale=(MagickRealType) (image->columns-1)/2.0;
1917 vertical_scale=(MagickRealType) (image->rows-1)/2.0;
1922 horizontal_scale=geometry_info.rho;
1923 vertical_scale=geometry_info.sigma;
1924 if ((flags & PercentValue) != 0)
1926 if ((flags & AspectValue) == 0)
1928 horizontal_scale*=(source_image->columns-1)/200.0;
1929 vertical_scale*=(source_image->rows-1)/200.0;
1933 horizontal_scale*=(image->columns-1)/200.0;
1934 vertical_scale*=(image->rows-1)/200.0;
1937 if ((flags & HeightValue) == 0)
1938 vertical_scale=horizontal_scale;
1948 center.x=(MagickRealType) x_offset;
1949 center.y=(MagickRealType) y_offset;
1950 if (compose == DistortCompositeOp)
1952 if ((flags & XValue) == 0)
1953 if ((flags & AspectValue) != 0)
1954 center.x=(MagickRealType) ((image->columns-1)/2.0);
1956 center.x=(MagickRealType) (x_offset+(source_image->columns-1)/
1959 if ((flags & AspectValue) != 0)
1960 center.x=geometry_info.xi;
1962 center.x=(MagickRealType) (x_offset+geometry_info.xi);
1963 if ((flags & YValue) == 0)
1964 if ((flags & AspectValue) != 0)
1965 center.y=(MagickRealType) ((image->rows-1)/2.0);
1967 center.y=(MagickRealType) (y_offset+(source_image->rows-1)/2.0);
1969 if ((flags & AspectValue) != 0)
1970 center.y=geometry_info.psi;
1972 center.y=(MagickRealType) (y_offset+geometry_info.psi);
1978 GetPixelInfo(image,&pixel);
1979 image_view=AcquireVirtualCacheView(image,exception);
1980 source_view=AcquireVirtualCacheView(source_image,exception);
1981 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
1982 for (y=0; y < (ssize_t) source_image->rows; y++)
1996 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
1998 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
2000 q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
2002 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
2004 for (x=0; x < (ssize_t) source_image->columns; x++)
2006 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
2008 p+=(ptrdiff_t) GetPixelChannels(source_image);
2014 offset.x=(double) (horizontal_scale*((
double) GetPixelRed(
2015 source_image,p)-(((MagickRealType) QuantumRange+1.0)/2.0)))/
2016 (((MagickRealType) QuantumRange+1.0)/2.0)+center.x+
2017 ((compose == DisplaceCompositeOp) ? x : 0);
2018 offset.y=(double) (vertical_scale*((
double) GetPixelGreen(
2019 source_image,p)-(((MagickRealType) QuantumRange+1.0)/2.0)))/
2020 (((MagickRealType) QuantumRange+1.0)/2.0)+center.y+
2021 ((compose == DisplaceCompositeOp) ? y : 0);
2022 status=InterpolatePixelInfo(image,image_view,
2023 UndefinedInterpolatePixel,(
double) offset.x,(
double) offset.y,
2025 if (status == MagickFalse)
2030 pixel.alpha=(MagickRealType) QuantumRange*(QuantumScale*pixel.alpha)*
2031 (QuantumScale*(double) GetPixelAlpha(source_image,p));
2032 SetPixelViaPixelInfo(canvas_image,&pixel,q);
2033 p+=(ptrdiff_t) GetPixelChannels(source_image);
2034 q+=(ptrdiff_t) GetPixelChannels(canvas_image);
2036 if (x < (ssize_t) source_image->columns)
2038 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
2039 if (sync == MagickFalse)
2042 canvas_view=DestroyCacheView(canvas_view);
2043 source_view=DestroyCacheView(source_view);
2044 image_view=DestroyCacheView(image_view);
2045 source_image=DestroyImage(source_image);
2046 source_image=canvas_image;
2049 case DissolveCompositeOp:
2054 artifact=GetImageArtifact(image,
"compose:args");
2055 if (artifact != (
char *) NULL)
2057 flags=ParseGeometry(artifact,&geometry_info);
2058 source_dissolve=geometry_info.rho/100.0;
2059 canvas_dissolve=1.0;
2060 if ((source_dissolve-MagickEpsilon) < 0.0)
2061 source_dissolve=0.0;
2062 if ((source_dissolve+MagickEpsilon) > 1.0)
2064 canvas_dissolve=2.0-source_dissolve;
2065 source_dissolve=1.0;
2067 if ((flags & SigmaValue) != 0)
2068 canvas_dissolve=geometry_info.sigma/100.0;
2069 if ((canvas_dissolve-MagickEpsilon) < 0.0)
2070 canvas_dissolve=0.0;
2071 if ((canvas_dissolve+MagickEpsilon) > 1.0)
2072 canvas_dissolve=1.0;
2076 case BlendCompositeOp:
2078 artifact=GetImageArtifact(image,
"compose:args");
2079 if (artifact != (
char *) NULL)
2081 flags=ParseGeometry(artifact,&geometry_info);
2082 source_dissolve=geometry_info.rho/100.0;
2083 canvas_dissolve=1.0-source_dissolve;
2084 if ((flags & SigmaValue) != 0)
2085 canvas_dissolve=geometry_info.sigma/100.0;
2089 case SaliencyBlendCompositeOp:
2092 residual_threshold = 0.0002,
2098 artifact=GetImageArtifact(image,
"compose:args");
2099 if (artifact != (
char *) NULL)
2101 flags=ParseGeometry(artifact,&geometry_info);
2102 iterations=geometry_info.rho;
2103 if ((flags & SigmaValue) != 0)
2104 residual_threshold=geometry_info.sigma;
2105 if ((flags & XiValue) != 0)
2106 tick=(size_t) geometry_info.xi;
2108 status=SaliencyBlendImage(image,composite,x_offset,y_offset,iterations,
2109 residual_threshold,tick,exception);
2110 source_image=DestroyImage(source_image);
2113 case SeamlessBlendCompositeOp:
2116 residual_threshold = 0.0002,
2122 artifact=GetImageArtifact(image,
"compose:args");
2123 if (artifact != (
char *) NULL)
2125 flags=ParseGeometry(artifact,&geometry_info);
2126 iterations=geometry_info.rho;
2127 if ((flags & SigmaValue) != 0)
2128 residual_threshold=geometry_info.sigma;
2129 if ((flags & XiValue) != 0)
2130 tick=(size_t) geometry_info.xi;
2132 status=SeamlessBlendImage(image,composite,x_offset,y_offset,iterations,
2133 residual_threshold,tick,exception);
2134 source_image=DestroyImage(source_image);
2137 case MathematicsCompositeOp:
2147 SetGeometryInfo(&geometry_info);
2148 artifact=GetImageArtifact(image,
"compose:args");
2149 if (artifact != (
char *) NULL)
2151 flags=ParseGeometry(artifact,&geometry_info);
2152 if (flags == NoValue)
2153 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2154 "InvalidGeometry",
"`%s'",artifact);
2158 case ModulateCompositeOp:
2163 artifact=GetImageArtifact(image,
"compose:args");
2164 if (artifact != (
char *) NULL)
2166 flags=ParseGeometry(artifact,&geometry_info);
2167 percent_luma=geometry_info.rho;
2168 if ((flags & SigmaValue) != 0)
2169 percent_chroma=geometry_info.sigma;
2173 case ThresholdCompositeOp:
2178 artifact=GetImageArtifact(image,
"compose:args");
2179 if (artifact != (
char *) NULL)
2181 flags=ParseGeometry(artifact,&geometry_info);
2182 amount=geometry_info.rho;
2183 threshold=geometry_info.sigma;
2184 if ((flags & SigmaValue) == 0)
2187 threshold*=(double) QuantumRange;
2198 midpoint=((MagickRealType) QuantumRange+1.0)/2;
2199 random_info=AcquireRandomInfo();
2200 source_view=AcquireVirtualCacheView(source_image,exception);
2201 image_view=AcquireAuthenticCacheView(image,exception);
2202#if defined(MAGICKCORE_OPENMP_SUPPORT)
2203 #pragma omp parallel for schedule(static) shared(progress,status) \
2204 magick_number_threads(source_image,image,image->rows,1)
2206 for (y=0; y < (ssize_t) image->rows; y++)
2230 if (status == MagickFalse)
2232 if (clip_to_self != MagickFalse)
2236 if ((y-y_offset) >= (ssize_t) source_image->rows)
2242 pixels=(Quantum *) NULL;
2244 if ((y >= y_offset) &&
2245 ((y-y_offset) < (ssize_t) source_image->rows))
2247 p=GetCacheViewVirtualPixels(source_view,0,
2248 CastDoubleToSsizeT((
double) y-y_offset),source_image->columns,1,
2250 if (p == (
const Quantum *) NULL)
2257 p-=(ptrdiff_t) CastDoubleToSsizeT((
double) x_offset*
2258 GetPixelChannels(source_image));
2260 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2261 if (q == (Quantum *) NULL)
2266 GetPixelInfo(image,&canvas_pixel);
2267 GetPixelInfo(source_image,&source_pixel);
2268 for (x=0; x < (ssize_t) image->columns; x++)
2293 if (clip_to_self != MagickFalse)
2297 q+=(ptrdiff_t) GetPixelChannels(image);
2300 if ((x-x_offset) >= (ssize_t) source_image->columns)
2303 if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
2304 ((x-x_offset) >= (ssize_t) source_image->columns))
2307 source[MaxPixelChannels];
2314 (void) GetOneVirtualPixel(source_image,
2315 CastDoubleToSsizeT((
double) x-x_offset),
2316 CastDoubleToSsizeT((
double) y-y_offset),source,exception);
2317 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2322 PixelChannel channel = GetPixelChannelChannel(image,i);
2323 PixelTrait traits = GetPixelChannelTraits(image,channel);
2324 PixelTrait source_traits = GetPixelChannelTraits(source_image,
2326 if ((traits == UndefinedPixelTrait) ||
2327 (source_traits == UndefinedPixelTrait))
2331 case AlphaCompositeOp:
2332 case ChangeMaskCompositeOp:
2333 case CopyAlphaCompositeOp:
2334 case DstAtopCompositeOp:
2335 case DstInCompositeOp:
2337 case OutCompositeOp:
2338 case SrcInCompositeOp:
2339 case SrcOutCompositeOp:
2341 if (channel == AlphaPixelChannel)
2342 pixel=(MagickRealType) TransparentAlpha;
2344 pixel=(MagickRealType) q[i];
2347 case ClearCompositeOp:
2348 case CopyCompositeOp:
2349 case ReplaceCompositeOp:
2351 if (channel == AlphaPixelChannel)
2352 pixel=(MagickRealType) TransparentAlpha;
2357 case BlendCompositeOp:
2358 case DissolveCompositeOp:
2360 if (channel == AlphaPixelChannel)
2361 pixel=canvas_dissolve*(double) GetPixelAlpha(source_image,
2364 pixel=(MagickRealType) source[channel];
2369 pixel=(MagickRealType) source[channel];
2373 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
2374 ClampToQuantum(pixel);
2376 q+=(ptrdiff_t) GetPixelChannels(image);
2384 Sa=QuantumScale*(double) GetPixelAlpha(source_image,p);
2385 Da=QuantumScale*(double) GetPixelAlpha(image,q);
2388 case BumpmapCompositeOp:
2389 case ColorBurnCompositeOp:
2390 case ColorDodgeCompositeOp:
2391 case DarkenCompositeOp:
2392 case DifferenceCompositeOp:
2393 case DivideDstCompositeOp:
2394 case DivideSrcCompositeOp:
2395 case ExclusionCompositeOp:
2396 case FreezeCompositeOp:
2397 case HardLightCompositeOp:
2398 case HardMixCompositeOp:
2399 case InterpolateCompositeOp:
2400 case LightenCompositeOp:
2401 case LinearBurnCompositeOp:
2402 case LinearDodgeCompositeOp:
2403 case LinearLightCompositeOp:
2404 case MathematicsCompositeOp:
2405 case MinusDstCompositeOp:
2406 case MinusSrcCompositeOp:
2407 case MultiplyCompositeOp:
2408 case NegateCompositeOp:
2409 case OverlayCompositeOp:
2410 case PegtopLightCompositeOp:
2411 case PinLightCompositeOp:
2412 case ReflectCompositeOp:
2413 case ScreenCompositeOp:
2414 case SoftBurnCompositeOp:
2415 case SoftDodgeCompositeOp:
2416 case SoftLightCompositeOp:
2417 case StampCompositeOp:
2418 case VividLightCompositeOp:
2420 alpha=RoundToUnity(Sa+Da-Sa*Da);
2423 case DstAtopCompositeOp:
2424 case DstInCompositeOp:
2426 case SrcInCompositeOp:
2431 case DissolveCompositeOp:
2433 alpha=source_dissolve*Sa*(-canvas_dissolve*Da)+source_dissolve*Sa+
2437 case DstOverCompositeOp:
2438 case OverCompositeOp:
2439 case SrcOverCompositeOp:
2444 case DstOutCompositeOp:
2449 case OutCompositeOp:
2450 case SrcOutCompositeOp:
2455 case BlendCompositeOp:
2456 case PlusCompositeOp:
2458 alpha=RoundToUnity(source_dissolve*Sa+canvas_dissolve*Da);
2461 case XorCompositeOp:
2463 alpha=Sa+Da-2.0*Sa*Da;
2466 case ModulusAddCompositeOp:
2473 alpha=((Sa+Da)-1.0);
2476 case ModulusSubtractCompositeOp:
2483 alpha=((Sa-Da)+1.0);
2494 case ColorizeCompositeOp:
2495 case HueCompositeOp:
2496 case LuminizeCompositeOp:
2497 case ModulateCompositeOp:
2498 case RMSECompositeOp:
2499 case SaturateCompositeOp:
2501 Si=GetPixelIntensity(source_image,p);
2502 GetPixelInfoPixel(source_image,p,&source_pixel);
2503 GetPixelInfoPixel(image,q,&canvas_pixel);
2506 case BumpmapCompositeOp:
2507 case CopyAlphaCompositeOp:
2508 case DarkenIntensityCompositeOp:
2509 case LightenIntensityCompositeOp:
2511 Si=GetPixelIntensity(source_image,p);
2512 Di=GetPixelIntensity(image,q);
2518 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2524 PixelChannel channel = GetPixelChannelChannel(image,i);
2525 PixelTrait traits = GetPixelChannelTraits(image,channel);
2526 PixelTrait source_traits = GetPixelChannelTraits(source_image,channel);
2527 if (traits == UndefinedPixelTrait)
2529 if ((channel == AlphaPixelChannel) &&
2530 ((traits & UpdatePixelTrait) != 0))
2537 case AlphaCompositeOp:
2539 pixel=(double) QuantumRange*Sa;
2542 case AtopCompositeOp:
2543 case CopyBlackCompositeOp:
2544 case CopyBlueCompositeOp:
2545 case CopyCyanCompositeOp:
2546 case CopyGreenCompositeOp:
2547 case CopyMagentaCompositeOp:
2548 case CopyRedCompositeOp:
2549 case CopyYellowCompositeOp:
2550 case SrcAtopCompositeOp:
2551 case DstCompositeOp:
2554 pixel=(double) QuantumRange*Da;
2557 case BumpmapCompositeOp:
2562 case ChangeMaskCompositeOp:
2564 if (IsFuzzyEquivalencePixel(source_image,p,image,q) != MagickFalse)
2565 pixel=(MagickRealType) TransparentAlpha;
2567 pixel=(double) QuantumRange*Da;
2570 case ClearCompositeOp:
2572 pixel=(MagickRealType) TransparentAlpha;
2575 case ColorizeCompositeOp:
2576 case HueCompositeOp:
2577 case LuminizeCompositeOp:
2578 case RMSECompositeOp:
2579 case SaturateCompositeOp:
2581 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
2583 pixel=(double) QuantumRange*Da;
2586 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
2588 pixel=(double) QuantumRange*Sa;
2593 pixel=(double) QuantumRange*Da;
2596 pixel=(double) QuantumRange*Sa;
2599 case CopyAlphaCompositeOp:
2604 case BlurCompositeOp:
2605 case CopyCompositeOp:
2606 case DisplaceCompositeOp:
2607 case DistortCompositeOp:
2608 case DstAtopCompositeOp:
2609 case ReplaceCompositeOp:
2610 case SrcCompositeOp:
2612 pixel=(double) QuantumRange*Sa;
2615 case DarkenIntensityCompositeOp:
2617 if (compose_sync == MagickFalse)
2619 pixel=Si < Di ? Sa : Da;
2622 pixel=Sa*Si < Da*Di ? Sa : Da;
2625 case DifferenceCompositeOp:
2627 pixel=(double) QuantumRange*fabs((
double) (Sa-Da));
2630 case FreezeCompositeOp:
2632 pixel=(double) QuantumRange*(1.0-(1.0-Sa)*(1.0-Sa)*
2633 MagickSafeReciprocal(Da));
2638 case InterpolateCompositeOp:
2640 pixel=(double) QuantumRange*(0.5-0.25*cos(MagickPI*Sa)-0.25*
2644 case LightenIntensityCompositeOp:
2646 if (compose_sync == MagickFalse)
2648 pixel=Si > Di ? Sa : Da;
2651 pixel=Sa*Si > Da*Di ? Sa : Da;
2654 case ModulateCompositeOp:
2656 pixel=(double) QuantumRange*Da;
2659 case MultiplyCompositeOp:
2661 if (compose_sync == MagickFalse)
2663 pixel=(double) QuantumRange*Sa*Da;
2666 pixel=(double) QuantumRange*alpha;
2669 case NegateCompositeOp:
2671 pixel=(double) QuantumRange*((1.0-Sa-Da));
2674 case ReflectCompositeOp:
2676 pixel=(double) QuantumRange*(Sa*Sa*
2677 MagickSafeReciprocal(1.0-Da));
2678 if (pixel > (
double) QuantumRange)
2679 pixel=(double) QuantumRange;
2682 case StampCompositeOp:
2684 pixel=(double) QuantumRange*(Sa+Da*Da-1.0);
2687 case StereoCompositeOp:
2689 pixel=(double) QuantumRange*(Sa+Da)/2;
2694 pixel=(double) QuantumRange*alpha;
2698 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
2699 ClampToQuantum(pixel);
2702 if (source_traits == UndefinedPixelTrait)
2708 Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
2709 Dc=(MagickRealType) q[i];
2710 if ((traits & CopyPixelTrait) != 0)
2715 q[i]=ClampToQuantum(Dc);
2723 Sca=QuantumScale*Sa*Sc;
2724 Dca=QuantumScale*Da*Dc;
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=(QuantumScale*Si)*Dc;
2783 case ChangeMaskCompositeOp:
2788 case ClearCompositeOp:
2793 case ColorBurnCompositeOp:
2795 D=(Da > 0.0) ? RoundToUnity(Dca/Da) : 0.0;
2796 S=(Sa > 0.0) ? RoundToUnity(Sca/Sa) : 0.0;
2800 blend=1.0-(1.0-D)/S;
2801 pixel=(double) QuantumRange*gamma*RoundToUnity(Sa*Da*
2802 RoundToUnity(blend)+Sa*(1.0-Da)*S+Da*(1.0-Sa)*D);
2805 case ColorDodgeCompositeOp:
2808 S=RoundToUnity(Sca/Sa);
2812 D=RoundToUnity(Dca/Da);
2825 blend=MagickMin(1.0,D/(1.0-S));
2827 pixel=(double) QuantumRange*gamma*(Sa*Da*blend+Sca*(1.0-Da)+Dca*
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:
2861 case DstCompositeOp:
2866 case CopyBlackCompositeOp:
2868 if (channel == BlackPixelChannel)
2869 pixel=(MagickRealType) GetPixelBlack(source_image,p);
2872 case CopyBlueCompositeOp:
2873 case CopyYellowCompositeOp:
2875 if (channel == BluePixelChannel)
2876 pixel=(MagickRealType) GetPixelBlue(source_image,p);
2879 case CopyGreenCompositeOp:
2880 case CopyMagentaCompositeOp:
2882 if (channel == GreenPixelChannel)
2883 pixel=(MagickRealType) GetPixelGreen(source_image,p);
2886 case CopyRedCompositeOp:
2887 case CopyCyanCompositeOp:
2889 if (channel == RedPixelChannel)
2890 pixel=(MagickRealType) GetPixelRed(source_image,p);
2893 case DarkenCompositeOp:
2895 if (compose_sync == MagickFalse)
2897 pixel=RoundToUnity(MagickMin(Sca,Dca)+Sca*(1.0-Da)+Dca*
2901 pixel=(double) QuantumRange*RoundToUnity(MagickMin(Sca,Dca)+Sca*
2902 (1.0-Da)+Dca*(1.0-Sa));
2905 case DarkenIntensityCompositeOp:
2907 if (compose_sync == MagickFalse)
2909 pixel=RoundToUnity(MagickMin(Sca,Dca)+Sca*(1.0-Di)+Dca*
2913 pixel=(double) QuantumRange*RoundToUnity(MagickMin(Sca,Dca)+Sca*
2914 (1.0-Di)+Dca*(1.0-Si));
2917 case DifferenceCompositeOp:
2919 if (compose_sync == MagickFalse)
2921 pixel=(double) QuantumRange*RoundToUnity(fabs((
double) Sc-
2925 S=(Sa > 0.0) ? (Sca/Sa) : 0.0;
2926 D=(Da > 0.0) ? (Dca/Da) : 0.0;
2927 pixel=(double) QuantumRange*RoundToUnity(fabs(S-D));
2930 case DissolveCompositeOp:
2932 if (GetPseudoRandomValue(random_info) < (source_dissolve*Sa))
2938 case DivideDstCompositeOp:
2940 S=(Sa > 0.0) ? (Sca/Sa) : 0.0;
2941 D=(Da > 0.0) ? (Dca/Da) : 0.0;
2945 blend=MagickMin(1.0,D/S);
2946 pixel=(double) QuantumRange*RoundToUnity(Sca*(1.0-Da)+Dca*(1.0-Sa)+
2950 case DivideSrcCompositeOp:
2952 S=(Sa > 0.0) ? (Sca/Sa) : 0.0;
2953 D=(Da > 0.0) ? (Dca/Da) : 0.0;
2957 blend=MagickMin(1.0,S/D);
2958 pixel=(double) QuantumRange*RoundToUnity(Sca*(1.0-Da)+Dca*(1.0-Sa)+
2962 case DstAtopCompositeOp:
2964 pixel=(double) QuantumRange*(Dca*Sa+Sca*(1.0-Da));
2967 case DstInCompositeOp:
2969 pixel=(double) QuantumRange*gamma*(Dca*Sa);
2972 case DstOutCompositeOp:
2974 pixel=(double) QuantumRange*gamma*(Dca*(1.0-Sa));
2977 case DstOverCompositeOp:
2979 pixel=(double) QuantumRange*gamma*(Dca+Sca*(1.0-Da));
2982 case ExclusionCompositeOp:
2984 S=(Sa > 0.0) ? Sca/Sa : 0.0;
2985 D=(Da > 0.0) ? Dca/Da : 0.0;
2986 blend=RoundToUnity(S+D-2.0*S*D);
2987 pixel=(double) QuantumRange*RoundToUnity((blend*Sa+D*(1.0-Sa))*
2991 case FreezeCompositeOp:
2994 blend=1.0-(1.0-Sca)*(1.0-Sca)/Dca;
2997 pixel=(double) QuantumRange*gamma*RoundToUnity(blend);
3000 case HardLightCompositeOp:
3002 D=(Da > 0.0) ? (Dca/Da) : 0.0;
3003 S=(Sa > 0.0) ? (Sca/Sa) : 0.0;
3007 blend=1.0-2.0*(1.0-S)*(1.0-D);
3008 pixel=(double) QuantumRange*gamma*RoundToUnity((1.0-Da)*Sca+
3009 (1.0-Sa)*Dca+blend*Sa*Da);
3012 case HardMixCompositeOp:
3016 if ((2.0*Sca) == 0.0)
3019 blend=1.0-(1.0-Dca)/(2.0*Sca);
3023 if ((1.0-((2.0*Sca)-1.0)) == 0.0)
3026 blend=Dca/(1.0-(2.0*Sca-1.0));
3028 pixel=gamma*((blend < 0.5) ? 0.0 : (double) QuantumRange);
3031 case HueCompositeOp:
3033 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3038 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3043 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3044 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3045 white_luminance,illuminant,&hue,&chroma,&luma);
3046 ConvertRGBToGeneric(colorspace,(
double) source_pixel.red,
3047 (
double) source_pixel.green,(
double) source_pixel.blue,
3048 white_luminance,illuminant,&hue,&sans,&sans);
3049 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3050 white_luminance,illuminant,&red,&green,&blue);
3053 case RedPixelChannel: pixel=red;
break;
3054 case GreenPixelChannel: pixel=green;
break;
3055 case BluePixelChannel: pixel=blue;
break;
3056 default: pixel=Dc;
break;
3061 case SrcInCompositeOp:
3063 pixel=(double) QuantumRange*(Sca*Da);
3066 case InterpolateCompositeOp:
3068 pixel=(double) QuantumRange*(0.5-0.25*cos(MagickPI*Sca)-0.25*
3072 case LinearBurnCompositeOp:
3080 pixel=(double) QuantumRange*(Sca+Dca-Sa*Da);
3083 case LinearDodgeCompositeOp:
3085 pixel=gamma*(Sa*Sc+Da*Dc);
3088 case LinearLightCompositeOp:
3095 D=(Da > 0.0) ? Dca/Da : 0.0,
3096 S=(Sa > 0.0) ? Sca/Sa : 0.0;
3097 pixel=(double) QuantumRange*gamma*(RoundToUnity(D+2.0*S-1.0)*Da);
3100 case LightenCompositeOp:
3102 if (compose_sync == MagickFalse)
3104 pixel=MagickMax(Sc,Dc);
3107 S=(Sa > 0.0) ? (Sca/Sa) : 0.0;
3108 D=(Da > 0.0) ? (Dca/Da) : 0.0;
3109 pixel=(double) QuantumRange*RoundToUnity(Sca*(1.0-Da)+Dca*(1.0-Sa)+
3110 MagickMax(S,D)*Sa*Da);
3113 case LightenIntensityCompositeOp:
3115 pixel=Si > Di ? Sc : Dc;
3118 case LuminizeCompositeOp:
3120 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3125 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3130 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3131 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3132 white_luminance,illuminant,&hue,&chroma,&luma);
3133 ConvertRGBToGeneric(colorspace,(
double) source_pixel.red,
3134 (
double) source_pixel.green,(
double) source_pixel.blue,
3135 white_luminance,illuminant,&sans,&sans,&luma);
3136 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3137 white_luminance,illuminant,&red,&green,&blue);
3140 case RedPixelChannel: pixel=red;
break;
3141 case GreenPixelChannel: pixel=green;
break;
3142 case BluePixelChannel: pixel=blue;
break;
3143 default: pixel=Dc;
break;
3147 case MathematicsCompositeOp:
3168 if (compose_sync == MagickFalse)
3170 pixel=geometry_info.rho*Sc*Dc+geometry_info.sigma*Sc+
3171 geometry_info.xi*Dc+geometry_info.psi;
3174 pixel=(double) QuantumRange*gamma*(geometry_info.rho*Sca*Dca+
3175 geometry_info.sigma*Sca*Da+geometry_info.xi*Dca*Sa+
3176 geometry_info.psi*Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
3179 case MinusDstCompositeOp:
3181 if (compose_sync == MagickFalse)
3186 pixel=gamma*(Sa*Sc+Da*Dc-2.0*Da*Dc*Sa);
3189 case MinusSrcCompositeOp:
3191 if (compose_sync == MagickFalse)
3196 pixel=gamma*(Da*Dc+Sa*Sc-2.0*Sa*Sc*Da);
3199 case ModulateCompositeOp:
3204 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3209 offset=(ssize_t) (Si-midpoint);
3215 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3216 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3217 white_luminance,illuminant,&hue,&chroma,&luma);
3218 luma+=(0.01*percent_luma*offset)/midpoint;
3219 chroma*=0.01*percent_chroma;
3220 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3221 white_luminance,illuminant,&red,&green,&blue);
3224 case RedPixelChannel: pixel=red;
break;
3225 case GreenPixelChannel: pixel=green;
break;
3226 case BluePixelChannel: pixel=blue;
break;
3227 default: pixel=Dc;
break;
3231 case ModulusAddCompositeOp:
3233 if (compose_sync == MagickFalse)
3235 pixel=(Quantum) QuantumRange*((Sc+Dc)-floor(Sc+Dc));
3238 pixel=(Quantum) QuantumRange*((Sca+Dca)-floor(Sca+Dca));
3241 case ModulusSubtractCompositeOp:
3243 if (compose_sync == MagickFalse)
3245 pixel=(Quantum) QuantumRange*((Sc-Dc)-floor(Sc-Dc));
3248 pixel=(Quantum) QuantumRange*((Sca-Dca)-floor(Sca-Dca));
3251 case MultiplyCompositeOp:
3253 if (compose_sync == MagickFalse)
3255 pixel=(double) QuantumRange*Sc*Dc;
3258 pixel=(double) QuantumRange*(Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-Sa));
3261 case NegateCompositeOp:
3263 D=(Da > 0.0) ? Dca/Da : 0.0;
3264 S=(Sa > 0.0) ? Sca/Sa : 0.0;
3265 pixel=(double) QuantumRange*((1.0-fabs(1.0-S-D))*Da);
3270 pixel=(double) QuantumRange*Dca;
3273 case OutCompositeOp:
3274 case SrcOutCompositeOp:
3276 pixel=(double) QuantumRange*(Sca*(1.0-Da));
3279 case OverCompositeOp:
3280 case SrcOverCompositeOp:
3282 if ((Sa+Da*(1.0-Sa)) <= MagickEpsilon)
3285 pixel=(double) QuantumRange*gamma*((Sca+Dca*(1.0-Sa))/
3289 case OverlayCompositeOp:
3293 pixel=(double) QuantumRange*gamma*(2.0*Dca*Sca+Dca*(1.0-Sa)+
3297 pixel=(double) QuantumRange*gamma*(Da*Sa-2.0*(Sa-Sca)*(Da-Dca)+Dca*
3298 (1.0-Sa)+Sca*(1.0-Da));
3301 case PegtopLightCompositeOp:
3303 if (fabs((
double) Da) < MagickEpsilon)
3305 pixel=(double) QuantumRange*gamma*Sca;
3308 if (RoundToUnity(Sca) <= 0.5)
3309 blend=RoundToUnity(Dca/Da)-(1.0-2.0*RoundToUnity(Sca))*
3310 RoundToUnity(Dca/Da)*(1.0-RoundToUnity(Dca/Da));
3313 if (RoundToUnity(Dca/Da) <= 0.25)
3314 blend=((16.0*RoundToUnity(Dca/Da)-12.0)*RoundToUnity(Dca/Da)+
3315 4.0)*RoundToUnity(Dca/Da);
3317 blend=sqrt(RoundToUnity(Dca/Da));
3318 blend=RoundToUnity(Dca/Da)+(2.0*RoundToUnity(Sca)-1.0)*
3319 (blend-RoundToUnity(Dca/Da));
3321 pixel=(double) QuantumRange*gamma*(RoundToUnity(blend)*Da*Sa+Dca*
3325 case PinLightCompositeOp:
3335 D=(Da > 0.0) ? RoundToUnity(Dca/Da) : 0.0;
3336 S=(Sa > 0.0) ? RoundToUnity(Sca/Sa) : 0.0;
3338 blend=MagickMin(D,2.0*S);
3340 blend=MagickMax(D,2.0*S-1.0);
3341 pixel=(double) QuantumRange*gamma*(blend*RoundToUnity(Sa+Da-Sa*Da));
3344 case PlusCompositeOp:
3346 D=(Da > 0.0) ? Dca/Da : 0.0;
3347 S=(Sa > 0.0) ? Sca/Sa : 0.0;
3348 pixel=(double) QuantumRange*(RoundToUnity(Sa+Da-Sa*Da)*
3352 case ReflectCompositeOp:
3354 if (compose_sync == MagickFalse)
3357 blend=(Sc*Sc)/(1.0-Dc);
3360 pixel=(double) QuantumRange*RoundToUnity(blend);
3372 blend=(S*S)/(1.0-D);
3375 pixel=(double) QuantumRange*RoundToUnity((Sa+Da-Sa*Da)*blend);
3378 case RMSECompositeOp:
3383 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3388 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3394 (canvas_pixel.red-source_pixel.red)*
3395 (canvas_pixel.red-source_pixel.red)+
3396 (canvas_pixel.green-source_pixel.green)*
3397 (canvas_pixel.green-source_pixel.green)+
3398 (canvas_pixel.blue-source_pixel.blue)*
3399 (canvas_pixel.blue-source_pixel.blue)/3.0);
3402 case RedPixelChannel: pixel=gray;
break;
3403 case GreenPixelChannel: pixel=gray;
break;
3404 case BluePixelChannel: pixel=gray;
break;
3405 default: pixel=Dc;
break;
3409 case SaturateCompositeOp:
3411 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3416 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3421 ConvertRGBToGeneric(colorspace,(
double) canvas_pixel.red,
3422 (
double) canvas_pixel.green,(
double) canvas_pixel.blue,
3423 white_luminance,illuminant,&hue,&chroma,&luma);
3424 ConvertRGBToGeneric(colorspace,(
double) source_pixel.red,
3425 (
double) source_pixel.green,(
double) source_pixel.blue,
3426 white_luminance,illuminant,&sans,&chroma,&sans);
3427 ConvertGenericToRGB(colorspace,hue,chroma,luma,
3428 white_luminance,illuminant,&red,&green,&blue);
3431 case RedPixelChannel: pixel=red;
break;
3432 case GreenPixelChannel: pixel=green;
break;
3433 case BluePixelChannel: pixel=blue;
break;
3434 default: pixel=Dc;
break;
3438 case ScreenCompositeOp:
3440 if (compose_sync == MagickFalse)
3442 pixel=(double) QuantumRange*RoundToUnity(Sc+Dc-Sc*Dc);
3453 if ((Sa+Da-Sa*Da) > 0.0)
3454 pixel=(double) QuantumRange*RoundToUnity((Sa+Da-Sa*Da)*(S+D-S*D));
3459 case SoftBurnCompositeOp:
3461 if (RoundToUnity(Dca) <= 0.0)
3464 if (RoundToUnity(Sca) >= 1.0)
3467 blend=1.0-MagickMin(1.0,(1.0-RoundToUnity(Dca))/
3469 pixel=(double) QuantumRange*gamma*RoundToUnity(blend);
3472 case SoftDodgeCompositeOp:
3474 if (RoundToUnity(Sca) <= 0.0)
3475 blend=RoundToUnity(Dca);
3477 if (RoundToUnity(Dca) >= 1.0)
3480 blend=MagickMin(1.0,RoundToUnity(Dca)/(1.0-RoundToUnity(Sca)));
3481 pixel=(double) QuantumRange*gamma*RoundToUnity(blend);
3484 case SoftLightCompositeOp:
3486 if (RoundToUnity(Sca) <= 0.5)
3488 pixel=(double) QuantumRange*gamma*(RoundToUnity(Dca)*Sa+Da*
3489 (RoundToUnity(Dca)-(1.0-2.0*RoundToUnity(Sca))*
3490 RoundToUnity(Dca)*(1.0-RoundToUnity(Dca)))+RoundToUnity(Sca)*
3491 (1.0-Da)+RoundToUnity(Dca)*(1.0-Sa));
3494 if (RoundToUnity(Dca) > 0.25)
3495 blend=sqrt(RoundToUnity(Dca));
3497 blend=((16.0*RoundToUnity(Dca)-12.0)*RoundToUnity(Dca)+4.0)*
3499 pixel=(double) QuantumRange*gamma*(RoundToUnity(Dca)*Sa+Da*
3500 (RoundToUnity(Dca)+(2.0*RoundToUnity(Sca)-1.0)*
3501 (RoundToUnity(blend)-RoundToUnity(Dca)))+RoundToUnity(Sca)*
3502 (1.0-Da)+RoundToUnity(Dca)*(1.0-Sa));
3505 case StampCompositeOp:
3507 pixel=(double) QuantumRange*RoundToUnity(Sca+Dca-1.0);
3510 case StereoCompositeOp:
3512 if (channel == RedPixelChannel)
3513 pixel=(MagickRealType) GetPixelRed(source_image,p);
3516 case ThresholdCompositeOp:
3518 S=(Sa > 0.0) ? (Sca/Sa) : 0.0;
3519 D=(Da > 0.0) ? (Dca/Da) : 0.0;
3520 if (fabs(2.0*(S-D)) < threshold)
3523 blend=D+(S-D)*amount;
3524 pixel=(double) QuantumRange*(Sa*Da*RoundToUnity(blend)+Sca*
3525 (1.0-Da)+Dca*(1.0-Sa));
3528 case VividLightCompositeOp:
3530 if ((fabs((
double) Sa) < MagickEpsilon) ||
3531 (fabs((
double) Da) < MagickEpsilon))
3533 pixel=(double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*
3537 if (RoundToUnity(Sca/Sa) <= 0.0)
3540 if (RoundToUnity(Sca/Sa) < 0.5)
3541 blend=1.0-(1.0-RoundToUnity(Dca/Da))/(2.0*RoundToUnity(Sca/Sa));
3543 if (RoundToUnity(Sca/Sa) < 1.0)
3544 blend=RoundToUnity(Dca/Da)/(2.0*(1.0-RoundToUnity(Sca/Sa)));
3547 pixel=(double) QuantumRange*gamma*(Sa*Da*RoundToUnity(blend)+Sca*
3548 (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 random_info=DestroyRandomInfo(random_info);
3589 if (canvas_image != (Image * ) NULL)
3590 canvas_image=DestroyImage(canvas_image);
3592 source_image=DestroyImage(source_image);
3622MagickExport MagickBooleanType TextureImage(Image *image,
const Image *texture,
3623 ExceptionInfo *exception)
3625#define TextureImageTag "Texture/Image"
3640 assert(image != (Image *) NULL);
3641 assert(image->signature == MagickCoreSignature);
3642 if (IsEventLogging() != MagickFalse)
3643 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
3644 if (texture == (
const Image *) NULL)
3645 return(MagickFalse);
3646 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3647 return(MagickFalse);
3648 texture_image=CloneImage(texture,0,0,MagickTrue,exception);
3649 if (texture_image == (
const Image *) NULL)
3650 return(MagickFalse);
3651 (void) TransformImageColorspace(texture_image,image->colorspace,exception);
3652 (void) SetImageVirtualPixelMethod(texture_image,TileVirtualPixelMethod,
3655 if ((image->compose != CopyCompositeOp) &&
3656 ((image->compose != OverCompositeOp) ||
3657 (image->alpha_trait != UndefinedPixelTrait) ||
3658 (texture_image->alpha_trait != UndefinedPixelTrait)))
3663 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) texture_image->rows)
3668 if (status == MagickFalse)
3670 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
3675 thread_status=CompositeImage(image,texture_image,image->compose,
3676 MagickTrue,x+texture_image->tile_offset.x,y+
3677 texture_image->tile_offset.y,exception);
3678 if (thread_status == MagickFalse)
3680 status=thread_status;
3684 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3689 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
3691 if (proceed == MagickFalse)
3695 (void) SetImageProgress(image,TextureImageTag,(MagickOffsetType)
3696 image->rows,image->rows);
3697 texture_image=DestroyImage(texture_image);
3704 texture_view=AcquireVirtualCacheView(texture_image,exception);
3705 image_view=AcquireAuthenticCacheView(image,exception);
3706#if defined(MAGICKCORE_OPENMP_SUPPORT)
3707 #pragma omp parallel for schedule(static) shared(status) \
3708 magick_number_threads(texture_image,image,image->rows,2)
3710 for (y=0; y < (ssize_t) image->rows; y++)
3728 if (status == MagickFalse)
3730 pixels=GetCacheViewVirtualPixels(texture_view,texture_image->tile_offset.x,
3731 (y+texture_image->tile_offset.y) % (ssize_t) texture_image->rows,
3732 texture_image->columns,1,exception);
3733 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3734 if ((pixels == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
3739 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
3745 width=texture_image->columns;
3746 if ((x+(ssize_t) width) > (ssize_t) image->columns)
3747 width=image->columns-(size_t) x;
3748 for (j=0; j < (ssize_t) width; j++)
3753 for (i=0; i < (ssize_t) GetPixelChannels(texture_image); i++)
3755 PixelChannel channel = GetPixelChannelChannel(texture_image,i);
3756 PixelTrait traits = GetPixelChannelTraits(image,channel);
3757 PixelTrait texture_traits=GetPixelChannelTraits(texture_image,
3759 if ((traits == UndefinedPixelTrait) ||
3760 (texture_traits == UndefinedPixelTrait))
3762 SetPixelChannel(image,channel,p[i],q);
3764 p+=(ptrdiff_t) GetPixelChannels(texture_image);
3765 q+=(ptrdiff_t) GetPixelChannels(image);
3768 sync=SyncCacheViewAuthenticPixels(image_view,exception);
3769 if (sync == MagickFalse)
3771 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3776 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
3778 if (proceed == MagickFalse)
3782 texture_view=DestroyCacheView(texture_view);
3783 image_view=DestroyCacheView(image_view);
3784 texture_image=DestroyImage(texture_image);