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/thread-private.h"
78#include "MagickCore/threshold.h"
79#include "MagickCore/token.h"
80#include "MagickCore/transform.h"
81#include "MagickCore/utility.h"
82#include "MagickCore/utility-private.h"
83#include "MagickCore/version.h"
184static Image *BlendConvolveImage(
const Image *image,
const char *kernel,
197 kernel_info=AcquireKernelInfo(kernel,exception);
199 return((
Image *) NULL);
200 clone_image=CloneImage(image,0,0,MagickTrue,exception);
201 if (clone_image == (
Image *) NULL)
203 kernel_info=DestroyKernelInfo(kernel_info);
204 return((
Image *) NULL);
206 (void) SetImageAlphaChannel(clone_image,OffAlphaChannel,exception);
207 convolve_image=ConvolveImage(clone_image,kernel_info,exception);
208 kernel_info=DestroyKernelInfo(kernel_info);
209 clone_image=DestroyImage(clone_image);
210 return(convolve_image);
213static Image *BlendMagnitudeImage(
const Image *dx_image,
const Image *dy_image,
233 magnitude_image=CloneImage(dx_image,0,0,MagickTrue,exception);
234 if (magnitude_image == (
Image *) NULL)
235 return(magnitude_image);
236 dx_view=AcquireVirtualCacheView(dx_image,exception);
237 dy_view=AcquireVirtualCacheView(dy_image,exception);
238 magnitude_view=AcquireAuthenticCacheView(magnitude_image,exception);
239#if defined(MAGICKCORE_OPENMP_SUPPORT)
240 #pragma omp parallel for schedule(static) shared(status) \
241 magick_number_threads(dx_image,magnitude_image,dx_image->rows,1)
243 for (y=0; y < (ssize_t) dx_image->rows; y++)
255 if (status == MagickFalse)
257 p=GetCacheViewVirtualPixels(dx_view,0,y,dx_image->columns,1,exception);
258 q=GetCacheViewVirtualPixels(dy_view,0,y,dx_image->columns,1,exception);
259 r=GetCacheViewAuthenticPixels(magnitude_view,0,y,dx_image->columns,1,
261 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL) ||
262 (r == (Quantum *) NULL))
267 for (x=0; x < (ssize_t) dx_image->columns; x++)
272 for (i=0; i < (ssize_t) GetPixelChannels(dx_image); i++)
274 PixelChannel channel = GetPixelChannelChannel(dx_image,i);
275 PixelTrait traits = GetPixelChannelTraits(dx_image,channel);
276 PixelTrait dy_traits = GetPixelChannelTraits(dy_image,channel);
277 if ((traits == UndefinedPixelTrait) ||
278 (dy_traits == UndefinedPixelTrait) ||
279 ((dy_traits & UpdatePixelTrait) == 0))
281 r[i]=ClampToQuantum(hypot((
double) p[i],(
double)
282 GetPixelChannel(dy_image,channel,q)));
284 p+=GetPixelChannels(dx_image);
285 q+=GetPixelChannels(dy_image);
286 r+=GetPixelChannels(magnitude_image);
288 if (SyncCacheViewAuthenticPixels(magnitude_view,exception) == MagickFalse)
291 magnitude_view=DestroyCacheView(magnitude_view);
292 dy_view=DestroyCacheView(dy_view);
293 dx_view=DestroyCacheView(dx_view);
294 if (status == MagickFalse)
295 magnitude_image=DestroyImage(magnitude_image);
296 return(magnitude_image);
299static Image *BlendMaxMagnitudeImage(
const Image *alpha_image,
322 magnitude_image=CloneImage(alpha_image,0,0,MagickTrue,exception);
323 if (magnitude_image == (
Image *) NULL)
324 return(magnitude_image);
325 alpha_view=AcquireVirtualCacheView(alpha_image,exception);
326 beta_view=AcquireVirtualCacheView(beta_image,exception);
327 dx_view=AcquireVirtualCacheView(dx_image,exception);
328 dy_view=AcquireVirtualCacheView(dy_image,exception);
329 magnitude_view=AcquireAuthenticCacheView(magnitude_image,exception);
330#if defined(MAGICKCORE_OPENMP_SUPPORT)
331 #pragma omp parallel for schedule(static) shared(status) \
332 magick_number_threads(alpha_image,magnitude_image,alpha_image->rows,1)
334 for (y=0; y < (ssize_t) alpha_image->rows; y++)
348 if (status == MagickFalse)
350 p=GetCacheViewVirtualPixels(alpha_view,0,y,alpha_image->columns,1,
352 q=GetCacheViewVirtualPixels(beta_view,0,y,alpha_image->columns,1,exception);
353 r=GetCacheViewVirtualPixels(dx_view,0,y,alpha_image->columns,1,exception);
354 s=GetCacheViewVirtualPixels(dy_view,0,y,alpha_image->columns,1,exception);
355 t=GetCacheViewAuthenticPixels(magnitude_view,0,y,alpha_image->columns,1,
357 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL) ||
358 (r == (
const Quantum *) NULL) || (s == (
const Quantum *) NULL) ||
359 (t == (Quantum *) NULL))
364 for (x=0; x < (ssize_t) alpha_image->columns; x++)
369 for (i=0; i < (ssize_t) GetPixelChannels(alpha_image); i++)
371 PixelChannel channel = GetPixelChannelChannel(alpha_image,i);
372 PixelTrait traits = GetPixelChannelTraits(alpha_image,channel);
373 PixelTrait beta_traits = GetPixelChannelTraits(beta_image,channel);
374 if ((traits == UndefinedPixelTrait) ||
375 (beta_traits == UndefinedPixelTrait) ||
376 ((beta_traits & UpdatePixelTrait) == 0))
378 if (p[i] > GetPixelChannel(beta_image,channel,q))
379 t[i]=GetPixelChannel(dx_image,channel,r);
381 t[i]=GetPixelChannel(dy_image,channel,s);
383 p+=GetPixelChannels(alpha_image);
384 q+=GetPixelChannels(beta_image);
385 r+=GetPixelChannels(dx_image);
386 s+=GetPixelChannels(dy_image);
387 t+=GetPixelChannels(magnitude_image);
389 if (SyncCacheViewAuthenticPixels(magnitude_view,exception) == MagickFalse)
392 magnitude_view=DestroyCacheView(magnitude_view);
393 dy_view=DestroyCacheView(dy_view);
394 dx_view=DestroyCacheView(dx_view);
395 beta_view=DestroyCacheView(beta_view);
396 alpha_view=DestroyCacheView(alpha_view);
397 if (status == MagickFalse)
398 magnitude_image=DestroyImage(magnitude_image);
399 return(magnitude_image);
402static Image *BlendSumImage(
const Image *alpha_image,
const Image *beta_image,
403 const double attenuate,
const double sign,
ExceptionInfo *exception)
422 sum_image=CloneImage(alpha_image,0,0,MagickTrue,exception);
423 if (sum_image == (
Image *) NULL)
425 alpha_view=AcquireVirtualCacheView(alpha_image,exception);
426 beta_view=AcquireVirtualCacheView(beta_image,exception);
427 sum_view=AcquireAuthenticCacheView(sum_image,exception);
428#if defined(MAGICKCORE_OPENMP_SUPPORT)
429 #pragma omp parallel for schedule(static) shared(status) \
430 magick_number_threads(alpha_image,sum_image,alpha_image->rows,1)
432 for (y=0; y < (ssize_t) alpha_image->rows; y++)
444 if (status == MagickFalse)
446 p=GetCacheViewVirtualPixels(alpha_view,0,y,alpha_image->columns,1,
448 q=GetCacheViewVirtualPixels(beta_view,0,y,alpha_image->columns,1,exception);
449 r=GetCacheViewAuthenticPixels(sum_view,0,y,alpha_image->columns,1,
451 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL) ||
452 (r == (Quantum *) NULL))
457 for (x=0; x < (ssize_t) alpha_image->columns; x++)
462 for (i=0; i < (ssize_t) GetPixelChannels(alpha_image); i++)
464 PixelChannel channel = GetPixelChannelChannel(alpha_image,i);
465 PixelTrait traits = GetPixelChannelTraits(alpha_image,channel);
466 PixelTrait beta_traits = GetPixelChannelTraits(beta_image,channel);
467 if ((traits == UndefinedPixelTrait) ||
468 (beta_traits == UndefinedPixelTrait) ||
469 ((beta_traits & UpdatePixelTrait) == 0))
471 r[i]=ClampToQuantum(attenuate*((
double) p[i]+sign*
472 (
double) GetPixelChannel(beta_image,channel,q)));
474 p+=GetPixelChannels(alpha_image);
475 q+=GetPixelChannels(beta_image);
476 r+=GetPixelChannels(sum_image);
478 if (SyncCacheViewAuthenticPixels(sum_view,exception) == MagickFalse)
481 sum_view=DestroyCacheView(sum_view);
482 beta_view=DestroyCacheView(beta_view);
483 alpha_view=DestroyCacheView(alpha_view);
484 if (status == MagickFalse)
485 sum_image=DestroyImage(sum_image);
489static Image *BlendDivergentImage(
const Image *alpha_image,
492#define FreeDivergentResources() \
494 if (dy_image != (Image *) NULL) \
495 dy_image=DestroyImage(dy_image); \
496 if (dx_image != (Image *) NULL) \
497 dx_image=DestroyImage(dx_image); \
498 if (magnitude_beta != (Image *) NULL) \
499 magnitude_beta=DestroyImage(magnitude_beta); \
500 if (dy_beta != (Image *) NULL) \
501 dy_beta=DestroyImage(dy_beta); \
502 if (dx_beta != (Image *) NULL) \
503 dx_beta=DestroyImage(dx_beta); \
504 if (magnitude_alpha != (Image *) NULL) \
505 magnitude_alpha=DestroyImage(magnitude_alpha); \
506 if (dy_alpha != (Image *) NULL) \
507 dy_alpha=DestroyImage(dy_alpha); \
508 if (dx_alpha != (Image *) NULL) \
509 dx_alpha=DestroyImage(dx_alpha); \
513 *divergent_image = (
Image *) NULL,
514 *dx_alpha = (
Image *) NULL,
515 *dx_beta = (
Image *) NULL,
516 *dx_divergent = (
Image *) NULL,
517 *dx_image = (
Image *) NULL,
518 *dy_alpha = (
Image *) NULL,
519 *dy_beta = (
Image *) NULL,
520 *dy_divergent = (
Image *) NULL,
521 *dy_image = (
Image *) NULL,
522 *magnitude_alpha = (
Image *) NULL,
523 *magnitude_beta = (
Image *) NULL;
528 dx_alpha=BlendConvolveImage(alpha_image,
"3x1:-0.5,0.0,0.5",exception);
529 if (dx_alpha == (
Image *) NULL)
531 FreeDivergentResources();
532 return((
Image *) NULL);
534 dy_alpha=BlendConvolveImage(alpha_image,
"1x3:-0.5,0.0,0.5",exception);
535 if (dy_alpha == (
Image *) NULL)
537 FreeDivergentResources();
538 return((
Image *) NULL);
540 magnitude_alpha=BlendMagnitudeImage(dx_alpha,dy_alpha,exception);
541 if (magnitude_alpha == (
Image *) NULL)
543 FreeDivergentResources();
544 return((
Image *) NULL);
549 dx_beta=BlendConvolveImage(beta_image,
"3x1:-0.5,0.0,0.5",exception);
550 if (dx_beta == (
Image *) NULL)
552 FreeDivergentResources();
553 return((
Image *) NULL);
555 dy_beta=BlendConvolveImage(beta_image,
"1x3:-0.5,0.0,0.5",exception);
556 if (dy_beta == (
Image *) NULL)
558 FreeDivergentResources();
559 return((
Image *) NULL);
561 magnitude_beta=BlendMagnitudeImage(dx_beta,dy_beta,exception);
562 if (magnitude_beta == (
Image *) NULL)
564 FreeDivergentResources();
565 return((
Image *) NULL);
570 dx_image=BlendMaxMagnitudeImage(magnitude_alpha,magnitude_beta,dx_alpha,
572 if (dx_image == (
Image *) NULL)
574 FreeDivergentResources();
575 return((
Image *) NULL);
577 dy_image=BlendMaxMagnitudeImage(magnitude_alpha,magnitude_beta,dy_alpha,
579 if (dy_image == (
Image *) NULL)
581 FreeDivergentResources();
582 return((
Image *) NULL);
584 dx_beta=DestroyImage(dx_beta);
585 dx_alpha=DestroyImage(dx_alpha);
586 magnitude_beta=DestroyImage(magnitude_beta);
587 magnitude_alpha=DestroyImage(magnitude_alpha);
591 dx_divergent=BlendConvolveImage(dx_image,
"3x1:-0.5,0.0,0.5",exception);
592 if (dx_divergent == (
Image *) NULL)
594 FreeDivergentResources();
595 return((
Image *) NULL);
597 dy_divergent=BlendConvolveImage(dy_image,
"1x3:-0.5,0.0,0.5",exception);
598 if (dy_divergent == (
Image *) NULL)
600 FreeDivergentResources();
601 return((
Image *) NULL);
603 divergent_image=BlendSumImage(dx_divergent,dy_divergent,0.25,1.0,exception);
604 dy_divergent=DestroyImage(dy_divergent);
605 dx_divergent=DestroyImage(dx_divergent);
606 if (divergent_image == (
Image *) NULL)
608 FreeDivergentResources();
609 return((
Image *) NULL);
611 FreeDivergentResources();
612 return(divergent_image);
615static MagickBooleanType BlendMaskAlphaChannel(
Image *image,
631 if (SetImageAlpha(image,OpaqueAlpha,exception) == MagickFalse)
633 image_view=AcquireAuthenticCacheView(image,exception);
634 mask_view=AcquireVirtualCacheView(mask_image,exception);
635#if defined(MAGICKCORE_OPENMP_SUPPORT)
636 #pragma omp parallel for schedule(static) shared(status) \
637 magick_number_threads(image,image,image->rows,2)
639 for (y=0; y < (ssize_t) image->rows; y++)
650 if (status == MagickFalse)
652 p=GetCacheViewVirtualPixels(mask_view,0,y,image->columns,1,exception);
653 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
654 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
659 for (x=0; x < (ssize_t) image->columns; x++)
662 alpha = GetPixelAlpha(mask_image,p);
665 i = GetPixelChannelOffset(image,AlphaPixelChannel);
667 if (fabs((
double) alpha) >= MagickEpsilon)
669 p+=GetPixelChannels(mask_image);
670 q+=GetPixelChannels(image);
672 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
675 mask_view=DestroyCacheView(mask_view);
676 image_view=DestroyCacheView(image_view);
689 mean[MaxPixelChannels];
704 (void) memset(mean,0,MaxPixelChannels*
sizeof(*mean));
705 alpha_view=AcquireVirtualCacheView(image,exception);
706 for (y=0; y < (ssize_t) image->rows; y++)
714 p=GetCacheViewVirtualPixels(alpha_view,0,y,image->columns,1,
716 if (p == (
const Quantum *) NULL)
718 for (x=0; x < (ssize_t) image->columns; x++)
723 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
725 PixelChannel channel = GetPixelChannelChannel(image,i);
726 PixelTrait traits = GetPixelChannelTraits(image,channel);
727 if (traits == UndefinedPixelTrait)
729 mean[i]+=QuantumScale*(double) p[i];
731 p+=GetPixelChannels(image);
734 alpha_view=DestroyCacheView(alpha_view);
735 if (y < (ssize_t) image->rows)
736 return((
Image *) NULL);
737 for (j=0; j < (ssize_t) GetPixelChannels(image); j++)
738 mean[j]=(
double) QuantumRange*mean[j]/image->columns/
743 mean_image=CloneImage(image,0,0,MagickTrue,exception);
744 if (mean_image == (
Image *) NULL)
746 mask_view=AcquireVirtualCacheView(mask_image,exception);
747 mean_view=AcquireAuthenticCacheView(mean_image,exception);
748#if defined(MAGICKCORE_OPENMP_SUPPORT)
749 #pragma omp parallel for schedule(static) shared(status) \
750 magick_number_threads(mask_image,mean_image,mean_image->rows,4)
752 for (y=0; y < (ssize_t) mean_image->rows; y++)
763 if (status == MagickFalse)
765 p=GetCacheViewVirtualPixels(mask_view,0,y,mean_image->columns,1,exception);
766 q=GetCacheViewAuthenticPixels(mean_view,0,y,mean_image->columns,1,
768 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
773 for (x=0; x < (ssize_t) mean_image->columns; x++)
776 alpha = GetPixelAlpha(mask_image,p),
777 mask = GetPixelReadMask(mask_image,p);
782 for (i=0; i < (ssize_t) GetPixelChannels(mean_image); i++)
784 PixelChannel channel = GetPixelChannelChannel(mean_image,i);
785 PixelTrait traits = GetPixelChannelTraits(mean_image,channel);
786 if (traits == UndefinedPixelTrait)
788 if (mask <= (QuantumRange/2))
791 if (fabs((
double) alpha) >= MagickEpsilon)
792 q[i]=ClampToQuantum(mean[i]);
794 p+=GetPixelChannels(mask_image);
795 q+=GetPixelChannels(mean_image);
797 if (SyncCacheViewAuthenticPixels(mean_view,exception) == MagickFalse)
800 mask_view=DestroyCacheView(mask_view);
801 mean_view=DestroyCacheView(mean_view);
802 if (status == MagickFalse)
803 mean_image=DestroyImage(mean_image);
807static MagickBooleanType BlendRMSEResidual(
const Image *alpha_image,
821 columns = MagickMax(alpha_image->columns,beta_image->columns),
822 rows = MagickMax(alpha_image->rows,beta_image->rows);
828 alpha_view=AcquireVirtualCacheView(alpha_image,exception);
829 beta_view=AcquireVirtualCacheView(beta_image,exception);
830#if defined(MAGICKCORE_OPENMP_SUPPORT)
831 #pragma omp parallel for schedule(static) shared(status) \
832 magick_number_threads(alpha_image,alpha_image,rows,1)
834 for (y=0; y < (ssize_t) rows; y++)
849 if (status == MagickFalse)
851 p=GetCacheViewVirtualPixels(alpha_view,0,y,columns,1,exception);
852 q=GetCacheViewVirtualPixels(beta_view,0,y,columns,1,exception);
853 if ((p == (
const Quantum *) NULL) || (q == (
const Quantum *) NULL))
858 channel_residual=0.0;
859 for (x=0; x < (ssize_t) columns; x++)
868 if ((GetPixelReadMask(alpha_image,p) <= (QuantumRange/2)) ||
869 (GetPixelReadMask(beta_image,q) <= (QuantumRange/2)))
871 p+=GetPixelChannels(alpha_image);
872 q+=GetPixelChannels(beta_image);
875 Sa=QuantumScale*(double) GetPixelAlpha(alpha_image,p);
876 Da=QuantumScale*(double) GetPixelAlpha(beta_image,q);
877 for (i=0; i < (ssize_t) GetPixelChannels(alpha_image); i++)
882 PixelChannel channel = GetPixelChannelChannel(alpha_image,i);
883 PixelTrait traits = GetPixelChannelTraits(alpha_image,channel);
884 PixelTrait beta_traits = GetPixelChannelTraits(beta_image,channel);
885 if ((traits == UndefinedPixelTrait) ||
886 (beta_traits == UndefinedPixelTrait) ||
887 ((beta_traits & UpdatePixelTrait) == 0))
889 if (channel == AlphaPixelChannel)
890 distance=QuantumScale*((double) p[i]-(
double) GetPixelChannel(
891 beta_image,channel,q));
893 distance=QuantumScale*(Sa*(double) p[i]-Da*(
double) GetPixelChannel(
894 beta_image,channel,q));
895 channel_residual+=distance*distance;
898 p+=GetPixelChannels(alpha_image);
899 q+=GetPixelChannels(beta_image);
901#if defined(MAGICKCORE_OPENMP_SUPPORT)
902 #pragma omp critical (MagickCore_BlendRMSEResidual)
906 *residual+=channel_residual;
909 area=PerceptibleReciprocal(area);
910 beta_view=DestroyCacheView(beta_view);
911 alpha_view=DestroyCacheView(alpha_view);
912 *residual=sqrt(*residual*area/(
double) GetImageChannels(alpha_image));
916static void CompositeHCL(
const MagickRealType red,
const MagickRealType green,
917 const MagickRealType blue,MagickRealType *hue,MagickRealType *chroma,
918 MagickRealType *luma)
931 assert(hue != (MagickRealType *) NULL);
932 assert(chroma != (MagickRealType *) NULL);
933 assert(luma != (MagickRealType *) NULL);
937 max=MagickMax(r,MagickMax(g,b));
938 c=max-(MagickRealType) MagickMin(r,MagickMin(g,b));
944 h=fmod((g-b)/c+6.0,6.0);
952 *chroma=QuantumScale*c;
953 *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
956static MagickBooleanType CompositeOverImage(
Image *image,
957 const Image *source_image,
const MagickBooleanType clip_to_self,
958 const ssize_t x_offset,
const ssize_t y_offset,
ExceptionInfo *exception)
960#define CompositeImageTag "Composite/Image"
985 value=GetImageArtifact(image,
"compose:clamp");
986 if (value != (
const char *) NULL)
987 clamp=IsStringTrue(value);
990 source_view=AcquireVirtualCacheView(source_image,exception);
991 image_view=AcquireAuthenticCacheView(image,exception);
992#if defined(MAGICKCORE_OPENMP_SUPPORT)
993 #pragma omp parallel for schedule(static) shared(progress,status) \
994 magick_number_threads(source_image,image,image->rows,1)
996 for (y=0; y < (ssize_t) image->rows; y++)
1014 if (status == MagickFalse)
1016 if (clip_to_self != MagickFalse)
1020 if ((y-(
double) y_offset) >= (double) source_image->rows)
1026 pixels=(Quantum *) NULL;
1028 if ((y >= y_offset) &&
1029 ((y-(double) y_offset) < (double) source_image->rows))
1031 p=GetCacheViewVirtualPixels(source_view,0,
1032 CastDoubleToLong(y-(
double) y_offset),source_image->columns,1,
1034 if (p == (
const Quantum *) NULL)
1041 p-=CastDoubleToLong((
double) x_offset*GetPixelChannels(source_image));
1043 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1044 if (q == (Quantum *) NULL)
1049 GetPixelInfo(image,&canvas_pixel);
1050 GetPixelInfo(source_image,&source_pixel);
1051 for (x=0; x < (ssize_t) image->columns; x++)
1071 if (clip_to_self != MagickFalse)
1075 q+=GetPixelChannels(image);
1078 if ((x-(
double) x_offset) >= (
double) source_image->columns)
1081 if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
1082 ((x-(
double) x_offset) >= (
double) source_image->columns))
1085 source[MaxPixelChannels];
1092 (void) GetOneVirtualPixel(source_image,
1093 CastDoubleToLong(x-(
double) x_offset),
1094 CastDoubleToLong(y-(
double) y_offset),source,exception);
1095 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1100 PixelChannel channel = GetPixelChannelChannel(image,i);
1101 PixelTrait traits = GetPixelChannelTraits(image,channel);
1102 PixelTrait source_traits=GetPixelChannelTraits(source_image,
1104 if ((traits == UndefinedPixelTrait) ||
1105 (source_traits == UndefinedPixelTrait))
1107 if (channel == AlphaPixelChannel)
1108 pixel=(MagickRealType) TransparentAlpha;
1110 pixel=(MagickRealType) q[i];
1111 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
1112 ClampToQuantum(pixel);
1114 q+=GetPixelChannels(image);
1122 Sa=QuantumScale*(double) GetPixelAlpha(source_image,p);
1123 Da=QuantumScale*(double) GetPixelAlpha(image,q);
1125 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1130 PixelChannel channel = GetPixelChannelChannel(image,i);
1131 PixelTrait traits = GetPixelChannelTraits(image,channel);
1132 PixelTrait source_traits=GetPixelChannelTraits(source_image,channel);
1133 if (traits == UndefinedPixelTrait)
1135 if ((source_traits == UndefinedPixelTrait) &&
1136 (channel != AlphaPixelChannel))
1138 if (channel == AlphaPixelChannel)
1143 pixel=(double) QuantumRange*alpha;
1144 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
1145 ClampToQuantum(pixel);
1152 Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
1153 Dc=(MagickRealType) q[i];
1154 if ((traits & CopyPixelTrait) != 0)
1159 q[i]=ClampToQuantum(Sc);
1167 Sca=QuantumScale*Sa*Sc;
1168 Dca=QuantumScale*Da*Dc;
1169 gamma=PerceptibleReciprocal(alpha);
1170 pixel=(double) QuantumRange*gamma*(Sca+Dca*(1.0-Sa));
1171 q[i]=clamp != MagickFalse ? ClampPixel(pixel) : ClampToQuantum(pixel);
1173 p+=GetPixelChannels(source_image);
1174 channels=GetPixelChannels(source_image);
1175 if (p >= (pixels+channels*source_image->columns))
1177 q+=GetPixelChannels(image);
1179 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1181 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1186#if defined(MAGICKCORE_OPENMP_SUPPORT)
1190 proceed=SetImageProgress(image,CompositeImageTag,progress,image->rows);
1191 if (proceed == MagickFalse)
1195 source_view=DestroyCacheView(source_view);
1196 image_view=DestroyCacheView(image_view);
1200static void HCLComposite(
const MagickRealType hue,
const MagickRealType chroma,
1201 const MagickRealType luma,MagickRealType *red,MagickRealType *green,
1202 MagickRealType *blue)
1216 assert(red != (MagickRealType *) NULL);
1217 assert(green != (MagickRealType *) NULL);
1218 assert(blue != (MagickRealType *) NULL);
1221 x=c*(1.0-fabs(fmod(h,2.0)-1.0));
1225 if ((0.0 <= h) && (h < 1.0))
1231 if ((1.0 <= h) && (h < 2.0))
1237 if ((2.0 <= h) && (h < 3.0))
1243 if ((3.0 <= h) && (h < 4.0))
1249 if ((4.0 <= h) && (h < 5.0))
1255 if ((5.0 <= h) && (h < 6.0))
1260 m=luma-(0.298839*r+0.586811*g+0.114350*b);
1261 *red=(double) QuantumRange*(r+m);
1262 *green=(double) QuantumRange*(g+m);
1263 *blue=(double) QuantumRange*(b+m);
1266static MagickBooleanType SaliencyBlendImage(
Image *image,
1267 const Image *source_image,
const ssize_t x_offset,
const ssize_t y_offset,
1268 const double iterations,
const double residual_threshold,
const size_t tick,
1275 *residual_image = (
Image *) NULL;
1281 status = MagickTrue,
1282 verbose = MagickFalse;
1286 source_image->columns,
1298 crop_image=CropImage(image,&crop_info,exception);
1299 if (crop_image == (
Image *) NULL)
1300 return(MagickFalse);
1301 DisableCompositeClampUnlessSpecified(crop_image);
1302 divergent_image=BlendDivergentImage(crop_image,source_image,exception);
1303 if (divergent_image == (
Image *) NULL)
1305 crop_image=DestroyImage(crop_image);
1306 return(MagickFalse);
1308 (void) ResetImagePage(crop_image,
"0x0+0+0");
1309 relax_image=BlendMeanImage(crop_image,source_image,exception);
1310 if (relax_image == (
Image *) NULL)
1312 crop_image=DestroyImage(crop_image);
1313 divergent_image=DestroyImage(divergent_image);
1314 return(MagickFalse);
1316 status=BlendMaskAlphaChannel(crop_image,source_image,exception);
1317 if (status == MagickFalse)
1319 crop_image=DestroyImage(crop_image);
1320 divergent_image=DestroyImage(divergent_image);
1321 return(MagickFalse);
1323 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1324 if (residual_image == (
Image *) NULL)
1326 crop_image=DestroyImage(crop_image);
1327 relax_image=DestroyImage(relax_image);
1328 return(MagickFalse);
1333 kernel_info=AcquireKernelInfo(
"3x3:0,0.25,0,0.25,0,0.25,0,0.25,0",exception);
1336 crop_image=DestroyImage(crop_image);
1337 residual_image=DestroyImage(residual_image);
1338 relax_image=DestroyImage(relax_image);
1339 return(MagickFalse);
1341 verbose=IsStringTrue(GetImageArtifact(image,
"verbose"));
1342 if (verbose != MagickFalse)
1343 (void) FormatLocaleFile(stderr,
"saliency blending:\n");
1344 for (i=0; i < iterations; i++)
1353 convolve_image=ConvolveImage(relax_image,kernel_info,exception);
1354 if (convolve_image == (
Image *) NULL)
1356 relax_image=DestroyImage(relax_image);
1357 relax_image=convolve_image;
1358 sum_image=BlendSumImage(relax_image,divergent_image,1.0,-1.0,exception);
1359 if (sum_image == (
Image *) NULL)
1361 relax_image=DestroyImage(relax_image);
1362 relax_image=sum_image;
1363 status=CompositeOverImage(relax_image,crop_image,MagickTrue,0,0,exception);
1364 if (status == MagickFalse)
1366 status=BlendRMSEResidual(relax_image,residual_image,&residual,exception);
1367 if (status == MagickFalse)
1369 if ((verbose != MagickFalse) && ((i % MagickMax(tick,1)) == 0))
1370 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(double) residual);
1371 if (residual < residual_threshold)
1373 if (verbose != MagickFalse)
1374 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(double)
1378 residual_image=DestroyImage(residual_image);
1379 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1380 if (residual_image == (
Image *) NULL)
1383 kernel_info=DestroyKernelInfo(kernel_info);
1384 crop_image=DestroyImage(crop_image);
1385 divergent_image=DestroyImage(divergent_image);
1386 residual_image=DestroyImage(residual_image);
1390 status=CompositeOverImage(image,relax_image,MagickTrue,x_offset,y_offset,
1392 relax_image=DestroyImage(relax_image);
1396static MagickBooleanType SeamlessBlendImage(
Image *image,
1397 const Image *source_image,
const ssize_t x_offset,
const ssize_t y_offset,
1398 const double iterations,
const double residual_threshold,
const size_t tick,
1413 status = MagickTrue,
1414 verbose = MagickFalse;
1418 source_image->columns,
1430 crop_image=CropImage(image,&crop_info,exception);
1431 if (crop_image == (
Image *) NULL)
1432 return(MagickFalse);
1433 DisableCompositeClampUnlessSpecified(crop_image);
1434 (void) ResetImagePage(crop_image,
"0x0+0+0");
1435 sum_image=BlendSumImage(crop_image,source_image,1.0,-1.0,exception);
1436 crop_image=DestroyImage(crop_image);
1437 if (sum_image == (
Image *) NULL)
1438 return(MagickFalse);
1439 mean_image=BlendMeanImage(sum_image,source_image,exception);
1440 sum_image=DestroyImage(sum_image);
1441 if (mean_image == (
Image *) NULL)
1442 return(MagickFalse);
1443 relax_image=CloneImage(mean_image,0,0,MagickTrue,exception);
1444 if (relax_image == (
Image *) NULL)
1446 mean_image=DestroyImage(mean_image);
1447 return(MagickFalse);
1449 status=BlendMaskAlphaChannel(mean_image,source_image,exception);
1450 if (status == MagickFalse)
1452 relax_image=DestroyImage(relax_image);
1453 mean_image=DestroyImage(mean_image);
1454 return(MagickFalse);
1456 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1457 if (residual_image == (
Image *) NULL)
1459 relax_image=DestroyImage(relax_image);
1460 mean_image=DestroyImage(mean_image);
1461 return(MagickFalse);
1466 kernel_info=AcquireKernelInfo(
"3x3:0,0.25,0,0.25,0,0.25,0,0.25,0",exception);
1469 residual_image=DestroyImage(residual_image);
1470 relax_image=DestroyImage(relax_image);
1471 mean_image=DestroyImage(mean_image);
1472 return(MagickFalse);
1474 verbose=IsStringTrue(GetImageArtifact(image,
"verbose"));
1475 if (verbose != MagickFalse)
1476 (void) FormatLocaleFile(stderr,
"seamless blending:\n");
1477 for (i=0; i < iterations; i++)
1485 convolve_image=ConvolveImage(relax_image,kernel_info,exception);
1486 if (convolve_image == (
Image *) NULL)
1488 relax_image=DestroyImage(relax_image);
1489 relax_image=convolve_image;
1490 status=CompositeOverImage(relax_image,mean_image,MagickTrue,0,0,exception);
1491 if (status == MagickFalse)
1493 status=BlendRMSEResidual(relax_image,residual_image,&residual,exception);
1494 if (status == MagickFalse)
1496 if ((verbose != MagickFalse) && ((i % MagickMax(tick,1)) == 0))
1497 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(double) residual);
1498 if (residual < residual_threshold)
1500 if (verbose != MagickFalse)
1501 (void) FormatLocaleFile(stderr,
" %g: %g\n",(
double) i,(double)
1505 if (residual_image != (
Image *) NULL)
1506 residual_image=DestroyImage(residual_image);
1507 residual_image=CloneImage(relax_image,0,0,MagickTrue,exception);
1508 if (residual_image == (
Image *) NULL)
1511 kernel_info=DestroyKernelInfo(kernel_info);
1512 mean_image=DestroyImage(mean_image);
1513 residual_image=DestroyImage(residual_image);
1517 foreground_image=BlendSumImage(source_image,relax_image,1.0,1.0,exception);
1518 relax_image=DestroyImage(relax_image);
1519 if (foreground_image == (
Image *) NULL)
1520 return(MagickFalse);
1521 (void) SetImageMask(foreground_image,ReadPixelMask,(
const Image *) NULL,
1523 status=CompositeOverImage(image,foreground_image,MagickTrue,x_offset,y_offset,
1525 foreground_image=DestroyImage(foreground_image);
1529MagickExport MagickBooleanType CompositeImage(
Image *image,
1530 const Image *composite,
const CompositeOperator compose,
1531 const MagickBooleanType clip_to_self,
const ssize_t x_offset,
1534#define CompositeImageTag "Composite/Image"
1573 assert(image != (
Image *) NULL);
1574 assert(image->signature == MagickCoreSignature);
1575 assert(composite != (
Image *) NULL);
1576 assert(composite->signature == MagickCoreSignature);
1577 if (IsEventLogging() != MagickFalse)
1578 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1579 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1580 return(MagickFalse);
1581 source_image=CloneImage(composite,0,0,MagickTrue,exception);
1582 if (source_image == (
const Image *) NULL)
1583 return(MagickFalse);
1584 (void) SetImageColorspace(source_image,image->colorspace,exception);
1585 if ((compose == OverCompositeOp) || (compose == SrcOverCompositeOp))
1587 status=CompositeOverImage(image,source_image,clip_to_self,x_offset,
1588 y_offset,exception);
1589 source_image=DestroyImage(source_image);
1593 canvas_image=(
Image *) NULL;
1594 canvas_dissolve=1.0;
1596 value=GetImageArtifact(image,
"compose:clamp");
1597 if (value != (
const char *) NULL)
1598 clamp=IsStringTrue(value);
1599 compose_sync=MagickTrue;
1600 value=GetImageArtifact(image,
"compose:sync");
1601 if (value != (
const char *) NULL)
1602 compose_sync=IsStringTrue(value);
1603 SetGeometryInfo(&geometry_info);
1605 percent_chroma=100.0;
1606 source_dissolve=1.0;
1610 case CopyCompositeOp:
1612 if ((x_offset < 0) || (y_offset < 0))
1614 if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
1616 if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
1618 if ((source_image->alpha_trait == UndefinedPixelTrait) &&
1619 (image->alpha_trait != UndefinedPixelTrait))
1620 (void) SetImageAlphaChannel(source_image,OpaqueAlphaChannel,exception);
1622 source_view=AcquireVirtualCacheView(source_image,exception);
1623 image_view=AcquireAuthenticCacheView(image,exception);
1624#if defined(MAGICKCORE_OPENMP_SUPPORT)
1625 #pragma omp parallel for schedule(static) shared(status) \
1626 magick_number_threads(source_image,image,source_image->rows,4)
1628 for (y=0; y < (ssize_t) source_image->rows; y++)
1642 if (status == MagickFalse)
1644 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1646 q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
1647 source_image->columns,1,exception);
1648 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1653 for (x=0; x < (ssize_t) source_image->columns; x++)
1658 if (GetPixelReadMask(source_image,p) <= (QuantumRange/2))
1660 p+=GetPixelChannels(source_image);
1661 q+=GetPixelChannels(image);
1664 for (i=0; i < (ssize_t) GetPixelChannels(source_image); i++)
1666 PixelChannel channel = GetPixelChannelChannel(source_image,i);
1667 PixelTrait source_traits = GetPixelChannelTraits(source_image,
1669 PixelTrait traits = GetPixelChannelTraits(image,channel);
1670 if ((source_traits == UndefinedPixelTrait) ||
1671 (traits == UndefinedPixelTrait))
1673 SetPixelChannel(image,channel,p[i],q);
1675 p+=GetPixelChannels(source_image);
1676 q+=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 IntensityCompositeOp:
1699 if ((x_offset < 0) || (y_offset < 0))
1701 if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
1703 if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
1706 source_view=AcquireVirtualCacheView(source_image,exception);
1707 image_view=AcquireAuthenticCacheView(image,exception);
1708#if defined(MAGICKCORE_OPENMP_SUPPORT)
1709 #pragma omp parallel for schedule(static) shared(status) \
1710 magick_number_threads(source_image,image,source_image->rows,4)
1712 for (y=0; y < (ssize_t) source_image->rows; y++)
1726 if (status == MagickFalse)
1728 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1730 q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
1731 source_image->columns,1,exception);
1732 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1737 for (x=0; x < (ssize_t) source_image->columns; x++)
1739 if (GetPixelReadMask(source_image,p) <= (QuantumRange/2))
1741 p+=GetPixelChannels(source_image);
1742 q+=GetPixelChannels(image);
1745 SetPixelAlpha(image,clamp != MagickFalse ?
1746 ClampPixel(GetPixelIntensity(source_image,p)) :
1747 ClampToQuantum(GetPixelIntensity(source_image,p)),q);
1748 p+=GetPixelChannels(source_image);
1749 q+=GetPixelChannels(image);
1751 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1752 if (sync == MagickFalse)
1754 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1759 proceed=SetImageProgress(image,CompositeImageTag,(MagickOffsetType)
1761 if (proceed == MagickFalse)
1765 source_view=DestroyCacheView(source_view);
1766 image_view=DestroyCacheView(image_view);
1767 source_image=DestroyImage(source_image);
1770 case CopyAlphaCompositeOp:
1771 case ChangeMaskCompositeOp:
1777 if ((image->alpha_trait & BlendPixelTrait) == 0)
1778 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1781 case BlurCompositeOp:
1806 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1807 if (canvas_image == (
Image *) NULL)
1809 source_image=DestroyImage(source_image);
1810 return(MagickFalse);
1816 value=GetImageArtifact(image,
"compose:args");
1817 if (value != (
const char *) NULL)
1818 flags=ParseGeometry(value,&geometry_info);
1819 if ((flags & WidthValue) == 0)
1821 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1822 "InvalidSetting",
"'%s' '%s'",
"compose:args",value);
1823 source_image=DestroyImage(source_image);
1824 canvas_image=DestroyImage(canvas_image);
1825 return(MagickFalse);
1832 width=2.0*geometry_info.rho;
1834 if ((flags & HeightValue) != 0)
1835 height=2.0*geometry_info.sigma;
1843 if ((flags & XValue) != 0 )
1851 angle=DegreesToRadians(geometry_info.xi);
1852 blur.x1=width*cos(angle);
1853 blur.x2=width*sin(angle);
1854 blur.y1=(-height*sin(angle));
1855 blur.y2=height*cos(angle);
1859 if ((flags & YValue) != 0 )
1864 angle_start=DegreesToRadians(geometry_info.xi);
1865 angle_range=DegreesToRadians(geometry_info.psi)-angle_start;
1876 resample_filter=AcquireResampleFilter(image,exception);
1877 SetResampleFilter(resample_filter,GaussianFilter);
1881 GetPixelInfo(image,&pixel);
1882 source_view=AcquireVirtualCacheView(source_image,exception);
1883 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
1884 for (y=0; y < (ssize_t) source_image->rows; y++)
1898 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
1900 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1902 q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
1904 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
1906 for (x=0; x < (ssize_t) source_image->columns; x++)
1908 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
1910 p+=GetPixelChannels(source_image);
1913 if (fabs(angle_range) > MagickEpsilon)
1918 angle=angle_start+angle_range*QuantumScale*(double)
1919 GetPixelBlue(source_image,p);
1920 blur.x1=width*cos(angle);
1921 blur.x2=width*sin(angle);
1922 blur.y1=(-height*sin(angle));
1923 blur.y2=height*cos(angle);
1925 ScaleResampleFilter(resample_filter,
1926 blur.x1*QuantumScale*(
double) GetPixelRed(source_image,p),
1927 blur.y1*QuantumScale*(
double) GetPixelGreen(source_image,p),
1928 blur.x2*QuantumScale*(
double) GetPixelRed(source_image,p),
1929 blur.y2*QuantumScale*(
double) GetPixelGreen(source_image,p) );
1930 (void) ResamplePixelColor(resample_filter,(
double) x_offset+x,
1931 (double) y_offset+y,&pixel,exception);
1932 SetPixelViaPixelInfo(canvas_image,&pixel,q);
1933 p+=GetPixelChannels(source_image);
1934 q+=GetPixelChannels(canvas_image);
1936 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
1937 if (sync == MagickFalse)
1940 resample_filter=DestroyResampleFilter(resample_filter);
1941 source_view=DestroyCacheView(source_view);
1942 canvas_view=DestroyCacheView(canvas_view);
1943 source_image=DestroyImage(source_image);
1944 source_image=canvas_image;
1947 case DisplaceCompositeOp:
1948 case DistortCompositeOp:
1969 canvas_image=CloneImage(image,0,0,MagickTrue,exception);
1970 if (canvas_image == (
Image *) NULL)
1972 source_image=DestroyImage(source_image);
1973 return(MagickFalse);
1975 SetGeometryInfo(&geometry_info);
1977 value=GetImageArtifact(image,
"compose:args");
1978 if (value != (
char *) NULL)
1979 flags=ParseGeometry(value,&geometry_info);
1980 if ((flags & (WidthValue | HeightValue)) == 0 )
1982 if ((flags & AspectValue) == 0)
1984 horizontal_scale=(MagickRealType) (source_image->columns-1)/2.0;
1985 vertical_scale=(MagickRealType) (source_image->rows-1)/2.0;
1989 horizontal_scale=(MagickRealType) (image->columns-1)/2.0;
1990 vertical_scale=(MagickRealType) (image->rows-1)/2.0;
1995 horizontal_scale=geometry_info.rho;
1996 vertical_scale=geometry_info.sigma;
1997 if ((flags & PercentValue) != 0)
1999 if ((flags & AspectValue) == 0)
2001 horizontal_scale*=(source_image->columns-1)/200.0;
2002 vertical_scale*=(source_image->rows-1)/200.0;
2006 horizontal_scale*=(image->columns-1)/200.0;
2007 vertical_scale*=(image->rows-1)/200.0;
2010 if ((flags & HeightValue) == 0)
2011 vertical_scale=horizontal_scale;
2021 center.x=(MagickRealType) x_offset;
2022 center.y=(MagickRealType) y_offset;
2023 if (compose == DistortCompositeOp)
2025 if ((flags & XValue) == 0)
2026 if ((flags & AspectValue) != 0)
2027 center.x=(MagickRealType) ((image->columns-1)/2.0);
2029 center.x=(MagickRealType) (x_offset+(source_image->columns-1)/
2032 if ((flags & AspectValue) != 0)
2033 center.x=geometry_info.xi;
2035 center.x=(MagickRealType) (x_offset+geometry_info.xi);
2036 if ((flags & YValue) == 0)
2037 if ((flags & AspectValue) != 0)
2038 center.y=(MagickRealType) ((image->rows-1)/2.0);
2040 center.y=(MagickRealType) (y_offset+(source_image->rows-1)/2.0);
2042 if ((flags & AspectValue) != 0)
2043 center.y=geometry_info.psi;
2045 center.y=(MagickRealType) (y_offset+geometry_info.psi);
2051 GetPixelInfo(image,&pixel);
2052 image_view=AcquireVirtualCacheView(image,exception);
2053 source_view=AcquireVirtualCacheView(source_image,exception);
2054 canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
2055 for (y=0; y < (ssize_t) source_image->rows; y++)
2069 if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
2071 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
2073 q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
2075 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
2077 for (x=0; x < (ssize_t) source_image->columns; x++)
2079 if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
2081 p+=GetPixelChannels(source_image);
2087 offset.x=(double) (horizontal_scale*((
double) GetPixelRed(
2088 source_image,p)-(((MagickRealType) QuantumRange+1.0)/2.0)))/
2089 (((MagickRealType) QuantumRange+1.0)/2.0)+center.x+
2090 ((compose == DisplaceCompositeOp) ? x : 0);
2091 offset.y=(double) (vertical_scale*((
double) GetPixelGreen(
2092 source_image,p)-(((MagickRealType) QuantumRange+1.0)/2.0)))/
2093 (((MagickRealType) QuantumRange+1.0)/2.0)+center.y+
2094 ((compose == DisplaceCompositeOp) ? y : 0);
2095 status=InterpolatePixelInfo(image,image_view,
2096 UndefinedInterpolatePixel,(
double) offset.x,(
double) offset.y,
2098 if (status == MagickFalse)
2103 pixel.alpha=(MagickRealType) QuantumRange*(QuantumScale*pixel.alpha)*
2104 (QuantumScale*(double) GetPixelAlpha(source_image,p));
2105 SetPixelViaPixelInfo(canvas_image,&pixel,q);
2106 p+=GetPixelChannels(source_image);
2107 q+=GetPixelChannels(canvas_image);
2109 if (x < (ssize_t) source_image->columns)
2111 sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
2112 if (sync == MagickFalse)
2115 canvas_view=DestroyCacheView(canvas_view);
2116 source_view=DestroyCacheView(source_view);
2117 image_view=DestroyCacheView(image_view);
2118 source_image=DestroyImage(source_image);
2119 source_image=canvas_image;
2122 case DissolveCompositeOp:
2127 value=GetImageArtifact(image,
"compose:args");
2128 if (value != (
char *) NULL)
2130 flags=ParseGeometry(value,&geometry_info);
2131 source_dissolve=geometry_info.rho/100.0;
2132 canvas_dissolve=1.0;
2133 if ((source_dissolve-MagickEpsilon) < 0.0)
2134 source_dissolve=0.0;
2135 if ((source_dissolve+MagickEpsilon) > 1.0)
2137 canvas_dissolve=2.0-source_dissolve;
2138 source_dissolve=1.0;
2140 if ((flags & SigmaValue) != 0)
2141 canvas_dissolve=geometry_info.sigma/100.0;
2142 if ((canvas_dissolve-MagickEpsilon) < 0.0)
2143 canvas_dissolve=0.0;
2144 if ((canvas_dissolve+MagickEpsilon) > 1.0)
2145 canvas_dissolve=1.0;
2149 case BlendCompositeOp:
2151 value=GetImageArtifact(image,
"compose:args");
2152 if (value != (
char *) NULL)
2154 flags=ParseGeometry(value,&geometry_info);
2155 source_dissolve=geometry_info.rho/100.0;
2156 canvas_dissolve=1.0-source_dissolve;
2157 if ((flags & SigmaValue) != 0)
2158 canvas_dissolve=geometry_info.sigma/100.0;
2162 case SaliencyBlendCompositeOp:
2165 residual_threshold = 0.0002,
2171 value=GetImageArtifact(image,
"compose:args");
2172 if (value != (
char *) NULL)
2174 flags=ParseGeometry(value,&geometry_info);
2175 iterations=geometry_info.rho;
2176 if ((flags & SigmaValue) != 0)
2177 residual_threshold=geometry_info.sigma;
2178 if ((flags & XiValue) != 0)
2179 tick=(size_t) geometry_info.xi;
2181 status=SaliencyBlendImage(image,composite,x_offset,y_offset,iterations,
2182 residual_threshold,tick,exception);
2183 source_image=DestroyImage(source_image);
2186 case SeamlessBlendCompositeOp:
2189 residual_threshold = 0.0002,
2195 value=GetImageArtifact(image,
"compose:args");
2196 if (value != (
char *) NULL)
2198 flags=ParseGeometry(value,&geometry_info);
2199 iterations=geometry_info.rho;
2200 if ((flags & SigmaValue) != 0)
2201 residual_threshold=geometry_info.sigma;
2202 if ((flags & XiValue) != 0)
2203 tick=(size_t) geometry_info.xi;
2205 status=SeamlessBlendImage(image,composite,x_offset,y_offset,iterations,
2206 residual_threshold,tick,exception);
2207 source_image=DestroyImage(source_image);
2210 case MathematicsCompositeOp:
2220 SetGeometryInfo(&geometry_info);
2221 value=GetImageArtifact(image,
"compose:args");
2222 if (value != (
char *) NULL)
2224 flags=ParseGeometry(value,&geometry_info);
2225 if (flags == NoValue)
2226 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2227 "InvalidGeometry",
"`%s'",value);
2231 case ModulateCompositeOp:
2236 value=GetImageArtifact(image,
"compose:args");
2237 if (value != (
char *) NULL)
2239 flags=ParseGeometry(value,&geometry_info);
2240 percent_luma=geometry_info.rho;
2241 if ((flags & SigmaValue) != 0)
2242 percent_chroma=geometry_info.sigma;
2246 case ThresholdCompositeOp:
2251 value=GetImageArtifact(image,
"compose:args");
2252 if (value != (
char *) NULL)
2254 flags=ParseGeometry(value,&geometry_info);
2255 amount=geometry_info.rho;
2256 threshold=geometry_info.sigma;
2257 if ((flags & SigmaValue) == 0)
2260 threshold*=(double) QuantumRange;
2271 midpoint=((MagickRealType) QuantumRange+1.0)/2;
2272 source_view=AcquireVirtualCacheView(source_image,exception);
2273 image_view=AcquireAuthenticCacheView(image,exception);
2274#if defined(MAGICKCORE_OPENMP_SUPPORT)
2275 #pragma omp parallel for schedule(static) shared(progress,status) \
2276 magick_number_threads(source_image,image,image->rows,1)
2278 for (y=0; y < (ssize_t) image->rows; y++)
2304 if (status == MagickFalse)
2306 if (clip_to_self != MagickFalse)
2310 if ((y-(
double) y_offset) >= (double) source_image->rows)
2316 pixels=(Quantum *) NULL;
2318 if ((y >= y_offset) &&
2319 ((y-(double) y_offset) < (double) source_image->rows))
2321 p=GetCacheViewVirtualPixels(source_view,0,
2322 CastDoubleToLong(y-(
double) y_offset),source_image->columns,1,
2324 if (p == (
const Quantum *) NULL)
2331 p-=CastDoubleToLong((
double) x_offset*GetPixelChannels(source_image));
2333 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2334 if (q == (Quantum *) NULL)
2339 GetPixelInfo(image,&canvas_pixel);
2340 GetPixelInfo(source_image,&source_pixel);
2341 for (x=0; x < (ssize_t) image->columns; x++)
2365 if (clip_to_self != MagickFalse)
2369 q+=GetPixelChannels(image);
2372 if ((x-(
double) x_offset) >= (
double) source_image->columns)
2375 if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
2376 ((x-(
double) x_offset) >= (
double) source_image->columns))
2379 source[MaxPixelChannels];
2386 (void) GetOneVirtualPixel(source_image,
2387 CastDoubleToLong(x-(
double) x_offset),
2388 CastDoubleToLong(y-(
double) y_offset),source,exception);
2389 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2394 PixelChannel channel = GetPixelChannelChannel(image,i);
2395 PixelTrait traits = GetPixelChannelTraits(image,channel);
2396 PixelTrait source_traits = GetPixelChannelTraits(source_image,
2398 if ((traits == UndefinedPixelTrait) ||
2399 (source_traits == UndefinedPixelTrait))
2403 case AlphaCompositeOp:
2404 case ChangeMaskCompositeOp:
2405 case CopyAlphaCompositeOp:
2406 case DstAtopCompositeOp:
2407 case DstInCompositeOp:
2409 case OutCompositeOp:
2410 case SrcInCompositeOp:
2411 case SrcOutCompositeOp:
2413 if (channel == AlphaPixelChannel)
2414 pixel=(MagickRealType) TransparentAlpha;
2416 pixel=(MagickRealType) q[i];
2419 case ClearCompositeOp:
2420 case CopyCompositeOp:
2421 case ReplaceCompositeOp:
2422 case SrcCompositeOp:
2424 if (channel == AlphaPixelChannel)
2425 pixel=(MagickRealType) TransparentAlpha;
2430 case BlendCompositeOp:
2431 case DissolveCompositeOp:
2433 if (channel == AlphaPixelChannel)
2434 pixel=canvas_dissolve*(double) GetPixelAlpha(source_image,
2437 pixel=(MagickRealType) source[channel];
2442 pixel=(MagickRealType) source[channel];
2446 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
2447 ClampToQuantum(pixel);
2449 q+=GetPixelChannels(image);
2457 Sa=QuantumScale*(double) GetPixelAlpha(source_image,p);
2458 Da=QuantumScale*(double) GetPixelAlpha(image,q);
2461 case BumpmapCompositeOp:
2462 case ColorBurnCompositeOp:
2463 case ColorDodgeCompositeOp:
2464 case DarkenCompositeOp:
2465 case DifferenceCompositeOp:
2466 case DivideDstCompositeOp:
2467 case DivideSrcCompositeOp:
2468 case ExclusionCompositeOp:
2469 case FreezeCompositeOp:
2470 case HardLightCompositeOp:
2471 case HardMixCompositeOp:
2472 case InterpolateCompositeOp:
2473 case LightenCompositeOp:
2474 case LinearBurnCompositeOp:
2475 case LinearDodgeCompositeOp:
2476 case LinearLightCompositeOp:
2477 case MathematicsCompositeOp:
2478 case MinusDstCompositeOp:
2479 case MinusSrcCompositeOp:
2480 case MultiplyCompositeOp:
2481 case NegateCompositeOp:
2482 case OverlayCompositeOp:
2483 case PegtopLightCompositeOp:
2484 case PinLightCompositeOp:
2485 case ReflectCompositeOp:
2486 case ScreenCompositeOp:
2487 case SoftBurnCompositeOp:
2488 case SoftDodgeCompositeOp:
2489 case SoftLightCompositeOp:
2490 case StampCompositeOp:
2491 case VividLightCompositeOp:
2493 alpha=RoundToUnity(Sa+Da-Sa*Da);
2496 case DstAtopCompositeOp:
2497 case DstInCompositeOp:
2499 case SrcInCompositeOp:
2504 case DissolveCompositeOp:
2506 alpha=source_dissolve*Sa*(-canvas_dissolve*Da)+source_dissolve*Sa+
2510 case DstOverCompositeOp:
2511 case OverCompositeOp:
2512 case SrcOverCompositeOp:
2517 case DstOutCompositeOp:
2522 case OutCompositeOp:
2523 case SrcOutCompositeOp:
2528 case BlendCompositeOp:
2529 case PlusCompositeOp:
2531 alpha=RoundToUnity(source_dissolve*Sa+canvas_dissolve*Da);
2534 case XorCompositeOp:
2536 alpha=Sa+Da-2.0*Sa*Da;
2539 case ModulusAddCompositeOp:
2546 alpha=((Sa+Da)-1.0);
2549 case ModulusSubtractCompositeOp:
2556 alpha=((Sa-Da)+1.0);
2567 case ColorizeCompositeOp:
2568 case HueCompositeOp:
2569 case LuminizeCompositeOp:
2570 case ModulateCompositeOp:
2571 case RMSECompositeOp:
2572 case SaturateCompositeOp:
2574 Si=GetPixelIntensity(source_image,p);
2575 GetPixelInfoPixel(source_image,p,&source_pixel);
2576 GetPixelInfoPixel(image,q,&canvas_pixel);
2579 case BumpmapCompositeOp:
2580 case CopyAlphaCompositeOp:
2581 case DarkenIntensityCompositeOp:
2582 case LightenIntensityCompositeOp:
2584 Si=GetPixelIntensity(source_image,p);
2585 Di=GetPixelIntensity(image,q);
2591 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2597 PixelChannel channel = GetPixelChannelChannel(image,i);
2598 PixelTrait traits = GetPixelChannelTraits(image,channel);
2599 PixelTrait source_traits = GetPixelChannelTraits(source_image,channel);
2600 if (traits == UndefinedPixelTrait)
2602 if ((channel == AlphaPixelChannel) &&
2603 ((traits & UpdatePixelTrait) != 0))
2610 case AlphaCompositeOp:
2612 pixel=(double) QuantumRange*Sa;
2615 case AtopCompositeOp:
2616 case CopyBlackCompositeOp:
2617 case CopyBlueCompositeOp:
2618 case CopyCyanCompositeOp:
2619 case CopyGreenCompositeOp:
2620 case CopyMagentaCompositeOp:
2621 case CopyRedCompositeOp:
2622 case CopyYellowCompositeOp:
2623 case SrcAtopCompositeOp:
2624 case DstCompositeOp:
2627 pixel=(double) QuantumRange*Da;
2630 case BumpmapCompositeOp:
2635 case ChangeMaskCompositeOp:
2637 if (IsFuzzyEquivalencePixel(source_image,p,image,q) != MagickFalse)
2638 pixel=(MagickRealType) TransparentAlpha;
2640 pixel=(double) QuantumRange*Da;
2643 case ClearCompositeOp:
2645 pixel=(MagickRealType) TransparentAlpha;
2648 case ColorizeCompositeOp:
2649 case HueCompositeOp:
2650 case LuminizeCompositeOp:
2651 case RMSECompositeOp:
2652 case SaturateCompositeOp:
2654 if (fabs((
double) QuantumRange*Sa-(double) TransparentAlpha) < MagickEpsilon)
2656 pixel=(double) QuantumRange*Da;
2659 if (fabs((
double) QuantumRange*Da-(double) TransparentAlpha) < MagickEpsilon)
2661 pixel=(double) QuantumRange*Sa;
2666 pixel=(double) QuantumRange*Da;
2669 pixel=(double) QuantumRange*Sa;
2672 case CopyAlphaCompositeOp:
2674 if (source_image->alpha_trait == UndefinedPixelTrait)
2677 pixel=(double) QuantumRange*Sa;
2680 case BlurCompositeOp:
2681 case CopyCompositeOp:
2682 case DisplaceCompositeOp:
2683 case DistortCompositeOp:
2684 case DstAtopCompositeOp:
2685 case ReplaceCompositeOp:
2686 case SrcCompositeOp:
2688 pixel=(double) QuantumRange*Sa;
2691 case DarkenIntensityCompositeOp:
2693 if (compose_sync == MagickFalse)
2695 pixel=Si < Di? Sa : Da;
2698 pixel=Sa*Si < Da*Di ? Sa : Da;
2701 case DifferenceCompositeOp:
2703 pixel=(double) QuantumRange*fabs((
double) (Sa-Da));
2706 case FreezeCompositeOp:
2708 pixel=(double) QuantumRange*(1.0-(1.0-Sa)*(1.0-Sa)*
2709 PerceptibleReciprocal(Da));
2714 case InterpolateCompositeOp:
2716 pixel=(double) QuantumRange*(0.5-0.25*cos(MagickPI*Sa)-0.25*
2720 case LightenIntensityCompositeOp:
2722 if (compose_sync == MagickFalse)
2724 pixel=Si > Di ? Sa : Da;
2727 pixel=Sa*Si > Da*Di ? Sa : Da;
2730 case ModulateCompositeOp:
2732 pixel=(double) QuantumRange*Da;
2735 case MultiplyCompositeOp:
2737 if (compose_sync == MagickFalse)
2739 pixel=(double) QuantumRange*Sa*Da;
2742 pixel=(double) QuantumRange*alpha;
2745 case NegateCompositeOp:
2747 pixel=(double) QuantumRange*((1.0-Sa-Da));
2750 case ReflectCompositeOp:
2752 pixel=(double) QuantumRange*(Sa*Sa*
2753 PerceptibleReciprocal(1.0-Da));
2754 if (pixel > (
double) QuantumRange)
2755 pixel=(
double) QuantumRange;
2758 case StampCompositeOp:
2760 pixel=(double) QuantumRange*(Sa+Da*Da-1.0);
2763 case StereoCompositeOp:
2765 pixel=(double) QuantumRange*(Sa+Da)/2;
2770 pixel=(double) QuantumRange*alpha;
2774 q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
2775 ClampToQuantum(pixel);
2778 if (source_traits == UndefinedPixelTrait)
2784 Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
2785 Dc=(MagickRealType) q[i];
2786 if ((traits & CopyPixelTrait) != 0)
2791 q[i]=ClampToQuantum(Dc);
2799 Sca=QuantumScale*Sa*Sc;
2800 Dca=QuantumScale*Da*Dc;
2801 SaSca=Sa*PerceptibleReciprocal(Sca);
2802 DcaDa=Dca*PerceptibleReciprocal(Da);
2805 case DarkenCompositeOp:
2806 case LightenCompositeOp:
2807 case ModulusSubtractCompositeOp:
2809 gamma=PerceptibleReciprocal(1.0-alpha);
2814 gamma=PerceptibleReciprocal(alpha);
2821 case AlphaCompositeOp:
2823 pixel=(double) QuantumRange*Sa;
2826 case AtopCompositeOp:
2827 case SrcAtopCompositeOp:
2829 pixel=(double) QuantumRange*(Sca*Da+Dca*(1.0-Sa));
2832 case BlendCompositeOp:
2834 pixel=gamma*(source_dissolve*Sa*Sc+canvas_dissolve*Da*Dc);
2837 case CopyCompositeOp:
2838 case ReplaceCompositeOp:
2839 case SrcCompositeOp:
2841 pixel=(double) QuantumRange*Sca;
2844 case BlurCompositeOp:
2845 case DisplaceCompositeOp:
2846 case DistortCompositeOp:
2851 case BumpmapCompositeOp:
2853 if (fabs((
double) QuantumRange*Sa-(double) TransparentAlpha) < MagickEpsilon)
2858 pixel=(double) QuantumScale*Si*Dc;
2861 case ChangeMaskCompositeOp:
2866 case ClearCompositeOp:
2871 case ColorBurnCompositeOp:
2873 if ((Sca == 0.0) && (Dca == Da))
2875 pixel=(double) QuantumRange*gamma*(Sa*Da+Dca*(1.0-Sa));
2880 pixel=(double) QuantumRange*gamma*(Dca*(1.0-Sa));
2883 pixel=(double) QuantumRange*gamma*(Sa*Da-Sa*Da*MagickMin(1.0,
2884 (1.0-DcaDa)*SaSca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
2887 case ColorDodgeCompositeOp:
2889 if ((Sca*Da+Dca*Sa) >= Sa*Da)
2890 pixel=(
double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*
2893 pixel=(double) QuantumRange*gamma*(Dca*Sa*Sa*
2894 PerceptibleReciprocal(Sa-Sca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
2897 case ColorizeCompositeOp:
2899 if (fabs((
double) QuantumRange*Sa-(double) TransparentAlpha) < MagickEpsilon)
2904 if (fabs((
double) QuantumRange*Da-(double) TransparentAlpha) < MagickEpsilon)
2909 CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
2911 CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
2912 &hue,&chroma,&sans);
2913 HCLComposite(hue,chroma,luma,&red,&green,&blue);
2916 case RedPixelChannel: pixel=red;
break;
2917 case GreenPixelChannel: pixel=green;
break;
2918 case BluePixelChannel: pixel=blue;
break;
2919 default: pixel=Dc;
break;
2923 case CopyAlphaCompositeOp:
2928 case CopyBlackCompositeOp:
2930 if (channel == BlackPixelChannel)
2931 pixel=(MagickRealType) GetPixelBlack(source_image,p);
2934 case CopyBlueCompositeOp:
2935 case CopyYellowCompositeOp:
2937 if (channel == BluePixelChannel)
2938 pixel=(MagickRealType) GetPixelBlue(source_image,p);
2941 case CopyGreenCompositeOp:
2942 case CopyMagentaCompositeOp:
2944 if (channel == GreenPixelChannel)
2945 pixel=(MagickRealType) GetPixelGreen(source_image,p);
2948 case CopyRedCompositeOp:
2949 case CopyCyanCompositeOp:
2951 if (channel == RedPixelChannel)
2952 pixel=(MagickRealType) GetPixelRed(source_image,p);
2955 case DarkenCompositeOp:
2962 if (compose_sync == MagickFalse)
2964 pixel=MagickMin(Sc,Dc);
2967 if ((Sca*Da) < (Dca*Sa))
2969 pixel=(double) QuantumRange*(Sca+Dca*(1.0-Sa));
2972 pixel=(double) QuantumRange*(Dca+Sca*(1.0-Da));
2975 case DarkenIntensityCompositeOp:
2977 if (compose_sync == MagickFalse)
2979 pixel=Si < Di ? Sc : Dc;
2982 pixel=Sa*Si < Da*Di ? Sc : Dc;
2985 case DifferenceCompositeOp:
2987 if (compose_sync == MagickFalse)
2989 pixel=fabs((
double) Sc-Dc);
2992 pixel=(double) QuantumRange*gamma*(Sca+Dca-2.0*MagickMin(Sca*Da,
2996 case DissolveCompositeOp:
2998 pixel=gamma*(source_dissolve*Sa*Sc-source_dissolve*Sa*
2999 canvas_dissolve*Da*Dc+canvas_dissolve*Da*Dc);
3002 case DivideDstCompositeOp:
3004 if (compose_sync == MagickFalse)
3006 pixel=(double) QuantumRange*(Sc/PerceptibleReciprocal(Dc));
3009 if ((fabs((
double) Sca) < MagickEpsilon) &&
3010 (fabs((
double) Dca) < MagickEpsilon))
3012 pixel=(double) QuantumRange*gamma*(Sca*(1.0-Da)+Dca*(1.0-Sa));
3015 if (fabs((
double) Dca) < MagickEpsilon)
3017 pixel=(double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*
3021 pixel=(double) QuantumRange*gamma*(Sca*Da*Da/Dca+Sca*(1.0-Da)+Dca*
3025 case DivideSrcCompositeOp:
3027 if (compose_sync == MagickFalse)
3029 pixel=(double) QuantumRange*(Dc/PerceptibleReciprocal(Sc));
3032 if ((fabs((
double) Dca) < MagickEpsilon) &&
3033 (fabs((
double) Sca) < MagickEpsilon))
3035 pixel=(double) QuantumRange*gamma*(Dca*(1.0-Sa)+Sca*(1.0-Da));
3038 if (fabs((
double) Sca) < MagickEpsilon)
3040 pixel=(double) QuantumRange*gamma*(Da*Sa+Dca*(1.0-Sa)+Sca*
3044 pixel=(double) QuantumRange*gamma*(Dca*Sa*SaSca+Dca*(1.0-Sa)+Sca*
3048 case DstAtopCompositeOp:
3050 pixel=(double) QuantumRange*(Dca*Sa+Sca*(1.0-Da));
3053 case DstCompositeOp:
3056 pixel=(double) QuantumRange*Dca;
3059 case DstInCompositeOp:
3061 pixel=(double) QuantumRange*gamma*(Dca*Sa);
3064 case DstOutCompositeOp:
3066 pixel=(double) QuantumRange*gamma*(Dca*(1.0-Sa));
3069 case DstOverCompositeOp:
3071 pixel=(double) QuantumRange*gamma*(Dca+Sca*(1.0-Da));
3074 case ExclusionCompositeOp:
3076 pixel=(double) QuantumRange*gamma*(Sca*Da+Dca*Sa-2.0*Sca*Dca+Sca*
3077 (1.0-Da)+Dca*(1.0-Sa));
3080 case FreezeCompositeOp:
3082 pixel=(double) QuantumRange*gamma*(1.0-(1.0-Sca)*(1.0-Sca)*
3083 PerceptibleReciprocal(Dca));
3088 case HardLightCompositeOp:
3092 pixel=(double) QuantumRange*gamma*(2.0*Sca*Dca+Sca*(1.0-Da)+Dca*
3096 pixel=(double) QuantumRange*gamma*(Sa*Da-2.0*(Da-Dca)*(Sa-Sca)+Sca*
3097 (1.0-Da)+Dca*(1.0-Sa));
3100 case HardMixCompositeOp:
3102 pixel=gamma*(((Sca+Dca) < 1.0) ? 0.0 : (double) QuantumRange);
3105 case HueCompositeOp:
3107 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3112 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3117 CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
3118 &hue,&chroma,&luma);
3119 CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
3121 HCLComposite(hue,chroma,luma,&red,&green,&blue);
3124 case RedPixelChannel: pixel=red;
break;
3125 case GreenPixelChannel: pixel=green;
break;
3126 case BluePixelChannel: pixel=blue;
break;
3127 default: pixel=Dc;
break;
3132 case SrcInCompositeOp:
3134 pixel=(double) QuantumRange*(Sca*Da);
3137 case InterpolateCompositeOp:
3139 pixel=(double) QuantumRange*(0.5-0.25*cos(MagickPI*Sca)-0.25*
3143 case LinearBurnCompositeOp:
3151 pixel=(double) QuantumRange*gamma*(Sca+Dca-Sa*Da);
3154 case LinearDodgeCompositeOp:
3156 pixel=gamma*(Sa*Sc+Da*Dc);
3159 case LinearLightCompositeOp:
3167 pixel=(double) QuantumRange*gamma*((Sca-Sa)*Da+Sca+Dca);
3170 case LightenCompositeOp:
3172 if (compose_sync == MagickFalse)
3174 pixel=MagickMax(Sc,Dc);
3177 if ((Sca*Da) > (Dca*Sa))
3179 pixel=(double) QuantumRange*(Sca+Dca*(1.0-Sa));
3182 pixel=(double) QuantumRange*(Dca+Sca*(1.0-Da));
3185 case LightenIntensityCompositeOp:
3192 if (compose_sync == MagickFalse)
3194 pixel=Si > Di ? Sc : Dc;
3197 pixel=Sa*Si > Da*Di ? Sc : Dc;
3200 case LuminizeCompositeOp:
3202 if (fabs((
double) QuantumRange*Sa-(double) TransparentAlpha) < MagickEpsilon)
3207 if (fabs((
double) QuantumRange*Da-(double) TransparentAlpha) < MagickEpsilon)
3212 CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
3213 &hue,&chroma,&luma);
3214 CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
3216 HCLComposite(hue,chroma,luma,&red,&green,&blue);
3219 case RedPixelChannel: pixel=red;
break;
3220 case GreenPixelChannel: pixel=green;
break;
3221 case BluePixelChannel: pixel=blue;
break;
3222 default: pixel=Dc;
break;
3226 case MathematicsCompositeOp:
3247 if (compose_sync == MagickFalse)
3249 pixel=geometry_info.rho*Sc*Dc+geometry_info.sigma*Sc+
3250 geometry_info.xi*Dc+geometry_info.psi;
3253 pixel=(double) QuantumRange*gamma*(geometry_info.rho*Sca*Dca+
3254 geometry_info.sigma*Sca*Da+geometry_info.xi*Dca*Sa+
3255 geometry_info.psi*Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
3258 case MinusDstCompositeOp:
3260 if (compose_sync == MagickFalse)
3265 pixel=gamma*(Sa*Sc+Da*Dc-2.0*Da*Dc*Sa);
3268 case MinusSrcCompositeOp:
3275 if (compose_sync == MagickFalse)
3280 pixel=gamma*(Da*Dc+Sa*Sc-2.0*Sa*Sc*Da);
3283 case ModulateCompositeOp:
3288 if (fabs((
double) QuantumRange*Sa-(double) TransparentAlpha) < MagickEpsilon)
3293 offset=(ssize_t) (Si-midpoint);
3299 CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
3300 &hue,&chroma,&luma);
3301 luma+=(0.01*percent_luma*offset)/midpoint;
3302 chroma*=0.01*percent_chroma;
3303 HCLComposite(hue,chroma,luma,&red,&green,&blue);
3306 case RedPixelChannel: pixel=red;
break;
3307 case GreenPixelChannel: pixel=green;
break;
3308 case BluePixelChannel: pixel=blue;
break;
3309 default: pixel=Dc;
break;
3313 case ModulusAddCompositeOp:
3315 if (compose_sync == MagickFalse)
3320 if ((Sca+Dca) <= 1.0)
3322 pixel=(double) QuantumRange*(Sca+Dca);
3325 pixel=(double) QuantumRange*((Sca+Dca)-1.0);
3328 case ModulusSubtractCompositeOp:
3330 if (compose_sync == MagickFalse)
3335 if ((Sca-Dca) >= 0.0)
3337 pixel=(double) QuantumRange*(Sca-Dca);
3340 pixel=(double) QuantumRange*((Sca-Dca)+1.0);
3343 case MultiplyCompositeOp:
3345 if (compose_sync == MagickFalse)
3347 pixel=(double) QuantumScale*Dc*Sc;
3350 pixel=(double) QuantumRange*gamma*(Sca*Dca+Sca*(1.0-Da)+Dca*
3354 case NegateCompositeOp:
3356 pixel=(double) QuantumRange*(1.0-fabs(1.0-Sca-Dca));
3359 case OutCompositeOp:
3360 case SrcOutCompositeOp:
3362 pixel=(double) QuantumRange*(Sca*(1.0-Da));
3365 case OverCompositeOp:
3366 case SrcOverCompositeOp:
3368 pixel=(double) QuantumRange*gamma*(Sca+Dca*(1.0-Sa));
3371 case OverlayCompositeOp:
3375 pixel=(double) QuantumRange*gamma*(2.0*Dca*Sca+Dca*(1.0-Sa)+
3379 pixel=(double) QuantumRange*gamma*(Da*Sa-2.0*(Sa-Sca)*(Da-Dca)+Dca*
3380 (1.0-Sa)+Sca*(1.0-Da));
3383 case PegtopLightCompositeOp:
3393 if (fabs((
double) Da) < MagickEpsilon)
3395 pixel=(double) QuantumRange*gamma*Sca;
3398 pixel=(double) QuantumRange*gamma*(Dca*Dca*(Sa-2.0*Sca)/Da+Sca*
3399 (2.0*Dca+1.0-Da)+Dca*(1.0-Sa));
3402 case PinLightCompositeOp:
3410 if ((Dca*Sa) < (Da*(2.0*Sca-Sa)))
3412 pixel=(double) QuantumRange*gamma*(Sca*(Da+1.0)-Sa*Da+Dca*
3416 if ((Dca*Sa) > (2.0*Sca*Da))
3418 pixel=(double) QuantumRange*gamma*(Sca*Da+Sca+Dca*(1.0-Sa));
3421 pixel=(double) QuantumRange*gamma*(Sca*(1.0-Da)+Dca);
3424 case PlusCompositeOp:
3426 if (compose_sync == MagickFalse)
3431 pixel=(double) QuantumRange*(Sca+Dca);
3434 case ReflectCompositeOp:
3436 pixel=(double) QuantumRange*gamma*(Sca*Sca*
3437 PerceptibleReciprocal(1.0-Dca));
3438 if (pixel > (
double) QuantumRange)
3439 pixel=(
double) QuantumRange;
3442 case RMSECompositeOp:
3447 if (fabs((
double) QuantumRange*Sa-(double) TransparentAlpha) < MagickEpsilon)
3452 if (fabs((
double) QuantumRange*Da-(double) TransparentAlpha) < MagickEpsilon)
3458 (canvas_pixel.red-source_pixel.red)*
3459 (canvas_pixel.red-source_pixel.red)+
3460 (canvas_pixel.green-source_pixel.green)*
3461 (canvas_pixel.green-source_pixel.green)+
3462 (canvas_pixel.blue-source_pixel.blue)*
3463 (canvas_pixel.blue-source_pixel.blue)/3.0);
3466 case RedPixelChannel: pixel=gray;
break;
3467 case GreenPixelChannel: pixel=gray;
break;
3468 case BluePixelChannel: pixel=gray;
break;
3469 default: pixel=Dc;
break;
3473 case SaturateCompositeOp:
3475 if (fabs((
double) QuantumRange*Sa-(
double) TransparentAlpha) < MagickEpsilon)
3480 if (fabs((
double) QuantumRange*Da-(
double) TransparentAlpha) < MagickEpsilon)
3485 CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
3486 &hue,&chroma,&luma);
3487 CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
3488 &sans,&chroma,&sans);
3489 HCLComposite(hue,chroma,luma,&red,&green,&blue);
3492 case RedPixelChannel: pixel=red;
break;
3493 case GreenPixelChannel: pixel=green;
break;
3494 case BluePixelChannel: pixel=blue;
break;
3495 default: pixel=Dc;
break;
3499 case ScreenCompositeOp:
3506 if (compose_sync == MagickFalse)
3511 pixel=(double) QuantumRange*gamma*(Sca+Dca-Sca*Dca);
3514 case SoftBurnCompositeOp:
3516 if ((Sca+Dca) < 1.0)
3517 pixel=(
double) QuantumRange*gamma*(0.5*Dca*
3518 PerceptibleReciprocal(1.0-Sca));
3520 pixel=(double) QuantumRange*gamma*(1.0-0.5*(1.0-Sca)*
3521 PerceptibleReciprocal(Dca));
3524 case SoftDodgeCompositeOp:
3526 if ((Sca+Dca) < 1.0)
3527 pixel=(
double) QuantumRange*gamma*(0.5*Sca*
3528 PerceptibleReciprocal(1.0-Dca));
3530 pixel=(double) QuantumRange*gamma*(1.0-0.5*(1.0-Dca)*
3531 PerceptibleReciprocal(Sca));
3534 case SoftLightCompositeOp:
3538 pixel=(double) QuantumRange*gamma*(Dca*(Sa+(2.0*Sca-Sa)*
3539 (1.0-DcaDa))+Sca*(1.0-Da)+Dca*(1.0-Sa));
3542 if (((2.0*Sca) > Sa) && ((4.0*Dca) <= Da))
3544 pixel=(double) QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)*
3545 (4.0*DcaDa*(4.0*DcaDa+1.0)*(DcaDa-1.0)+7.0*DcaDa)+Sca*
3546 (1.0-Da)+Dca*(1.0-Sa));
3549 pixel=(double) QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)*
3550 (pow(DcaDa,0.5)-DcaDa)+Sca*(1.0-Da)+Dca*(1.0-Sa));
3553 case StampCompositeOp:
3555 pixel=(double) QuantumRange*(Sca+Dca*Dca-1.0);
3558 case StereoCompositeOp:
3560 if (channel == RedPixelChannel)
3561 pixel=(MagickRealType) GetPixelRed(source_image,p);
3564 case ThresholdCompositeOp:
3570 if ((MagickRealType) fabs((
double) (2.0*delta)) < threshold)
3575 pixel=gamma*(Dc+delta*amount);
3578 case VividLightCompositeOp:
3586 if ((fabs((
double) Sa) < MagickEpsilon) ||
3587 (fabs((
double) (Sca-Sa)) < MagickEpsilon))
3589 pixel=(double) QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*
3593 if ((2.0*Sca) <= Sa)
3595 pixel=(double) QuantumRange*gamma*(Sa*(Da+Sa*(Dca-Da)*
3596 PerceptibleReciprocal(2.0*Sca))+Sca*(1.0-Da)+Dca*(1.0-Sa));
3599 pixel=(double) QuantumRange*gamma*(Dca*Sa*Sa*
3600 PerceptibleReciprocal(2.0*(Sa-Sca))+Sca*(1.0-Da)+Dca*(1.0-Sa));
3603 case XorCompositeOp:
3605 pixel=(double) QuantumRange*(Sca*(1.0-Da)+Dca*(1.0-Sa));
3614 q[i]=clamp != MagickFalse ? ClampPixel(pixel) : ClampToQuantum(pixel);
3616 p+=GetPixelChannels(source_image);
3617 channels=GetPixelChannels(source_image);
3618 if (p >= (pixels+channels*source_image->columns))
3620 q+=GetPixelChannels(image);
3622 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3624 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3629#if defined(MAGICKCORE_OPENMP_SUPPORT)
3633 proceed=SetImageProgress(image,CompositeImageTag,progress,image->rows);
3634 if (proceed == MagickFalse)
3638 source_view=DestroyCacheView(source_view);
3639 image_view=DestroyCacheView(image_view);
3640 if (canvas_image != (
Image * ) NULL)
3641 canvas_image=DestroyImage(canvas_image);
3643 source_image=DestroyImage(source_image);
3673MagickExport MagickBooleanType TextureImage(
Image *image,
const Image *texture,
3676#define TextureImageTag "Texture/Image"
3691 assert(image != (
Image *) NULL);
3692 assert(image->signature == MagickCoreSignature);
3693 if (IsEventLogging() != MagickFalse)
3694 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
3695 if (texture == (
const Image *) NULL)
3696 return(MagickFalse);
3697 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3698 return(MagickFalse);
3699 texture_image=CloneImage(texture,0,0,MagickTrue,exception);
3700 if (texture_image == (
const Image *) NULL)
3701 return(MagickFalse);
3702 (void) TransformImageColorspace(texture_image,image->colorspace,exception);
3703 (void) SetImageVirtualPixelMethod(texture_image,TileVirtualPixelMethod,
3706 if ((image->compose != CopyCompositeOp) &&
3707 ((image->compose != OverCompositeOp) ||
3708 (image->alpha_trait != UndefinedPixelTrait) ||
3709 (texture_image->alpha_trait != UndefinedPixelTrait)))
3714 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) texture_image->rows)
3719 if (status == MagickFalse)
3721 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
3726 thread_status=CompositeImage(image,texture_image,image->compose,
3727 MagickTrue,x+texture_image->tile_offset.x,y+
3728 texture_image->tile_offset.y,exception);
3729 if (thread_status == MagickFalse)
3731 status=thread_status;
3735 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3740 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
3742 if (proceed == MagickFalse)
3746 (void) SetImageProgress(image,TextureImageTag,(MagickOffsetType)
3747 image->rows,image->rows);
3748 texture_image=DestroyImage(texture_image);
3755 texture_view=AcquireVirtualCacheView(texture_image,exception);
3756 image_view=AcquireAuthenticCacheView(image,exception);
3757#if defined(MAGICKCORE_OPENMP_SUPPORT)
3758 #pragma omp parallel for schedule(static) shared(status) \
3759 magick_number_threads(texture_image,image,image->rows,2)
3761 for (y=0; y < (ssize_t) image->rows; y++)
3779 if (status == MagickFalse)
3781 pixels=GetCacheViewVirtualPixels(texture_view,texture_image->tile_offset.x,
3782 (y+texture_image->tile_offset.y) % (ssize_t) texture_image->rows,
3783 texture_image->columns,1,exception);
3784 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3785 if ((pixels == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
3790 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
3796 width=texture_image->columns;
3797 if ((x+(ssize_t) width) > (ssize_t) image->columns)
3798 width=image->columns-(
size_t) x;
3799 for (j=0; j < (ssize_t) width; j++)
3804 for (i=0; i < (ssize_t) GetPixelChannels(texture_image); i++)
3806 PixelChannel channel = GetPixelChannelChannel(texture_image,i);
3807 PixelTrait traits = GetPixelChannelTraits(image,channel);
3808 PixelTrait texture_traits=GetPixelChannelTraits(texture_image,
3810 if ((traits == UndefinedPixelTrait) ||
3811 (texture_traits == UndefinedPixelTrait))
3813 SetPixelChannel(image,channel,p[i],q);
3815 p+=GetPixelChannels(texture_image);
3816 q+=GetPixelChannels(image);
3819 sync=SyncCacheViewAuthenticPixels(image_view,exception);
3820 if (sync == MagickFalse)
3822 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3827 proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
3829 if (proceed == MagickFalse)
3833 texture_view=DestroyCacheView(texture_view);
3834 image_view=DestroyCacheView(image_view);
3835 texture_image=DestroyImage(texture_image);