MagickCore  7.0.9
visual-effects.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % FFFFF X X %
7 % F X X %
8 % FFF X %
9 % F X X %
10 % F X X %
11 % %
12 % %
13 % MagickCore Image Special Effects Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % October 1996 %
18 % %
19 % %
20 % %
21 % Copyright 1999-2020 ImageMagick Studio LLC, a non-profit organization %
22 % dedicated to making software imaging solutions freely available. %
23 % %
24 % You may not use this file except in compliance with the License. You may %
25 % obtain a copy of the License at %
26 % %
27 % https://imagemagick.org/script/license.php %
28 % %
29 % Unless required by applicable law or agreed to in writing, software %
30 % distributed under the License is distributed on an "AS IS" BASIS, %
31 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
32 % See the License for the specific language governing permissions and %
33 % limitations under the License. %
34 % %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 %
37 %
38 %
39 */
40 
41 /*
42  Include declarations.
43 */
44 #include "MagickCore/studio.h"
46 #include "MagickCore/annotate.h"
47 #include "MagickCore/artifact.h"
48 #include "MagickCore/attribute.h"
49 #include "MagickCore/cache.h"
50 #include "MagickCore/cache-view.h"
51 #include "MagickCore/channel.h"
52 #include "MagickCore/color.h"
55 #include "MagickCore/composite.h"
56 #include "MagickCore/decorate.h"
57 #include "MagickCore/distort.h"
58 #include "MagickCore/draw.h"
59 #include "MagickCore/effect.h"
60 #include "MagickCore/enhance.h"
61 #include "MagickCore/exception.h"
63 #include "MagickCore/gem.h"
64 #include "MagickCore/gem-private.h"
65 #include "MagickCore/geometry.h"
66 #include "MagickCore/layer.h"
67 #include "MagickCore/list.h"
68 #include "MagickCore/log.h"
69 #include "MagickCore/image.h"
71 #include "MagickCore/magick.h"
72 #include "MagickCore/memory_.h"
74 #include "MagickCore/monitor.h"
76 #include "MagickCore/option.h"
77 #include "MagickCore/pixel.h"
79 #include "MagickCore/property.h"
80 #include "MagickCore/quantum.h"
82 #include "MagickCore/random_.h"
84 #include "MagickCore/resample.h"
86 #include "MagickCore/resize.h"
87 #include "MagickCore/resource_.h"
88 #include "MagickCore/splay-tree.h"
89 #include "MagickCore/statistic.h"
90 #include "MagickCore/string_.h"
93 #include "MagickCore/threshold.h"
94 #include "MagickCore/transform.h"
96 #include "MagickCore/utility.h"
98 
99 /*
100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101 % %
102 % %
103 % %
104 % A d d N o i s e I m a g e %
105 % %
106 % %
107 % %
108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109 %
110 % AddNoiseImage() adds random noise to the image.
111 %
112 % The format of the AddNoiseImage method is:
113 %
114 % Image *AddNoiseImage(const Image *image,const NoiseType noise_type,
115 % const double attenuate,ExceptionInfo *exception)
116 %
117 % A description of each parameter follows:
118 %
119 % o image: the image.
120 %
121 % o channel: the channel type.
122 %
123 % o noise_type: The type of noise: Uniform, Gaussian, Multiplicative,
124 % Impulse, Laplacian, or Poisson.
125 %
126 % o attenuate: attenuate the random distribution.
127 %
128 % o exception: return any errors or warnings in this structure.
129 %
130 */
131 MagickExport Image *AddNoiseImage(const Image *image,const NoiseType noise_type,
132  const double attenuate,ExceptionInfo *exception)
133 {
134 #define AddNoiseImageTag "AddNoise/Image"
135 
136  CacheView
137  *image_view,
138  *noise_view;
139 
140  Image
141  *noise_image;
142 
144  status;
145 
147  progress;
148 
149  RandomInfo
151 
152  ssize_t
153  y;
154 
155 #if defined(MAGICKCORE_OPENMP_SUPPORT)
156  unsigned long
157  key;
158 #endif
159 
160  /*
161  Initialize noise image attributes.
162  */
163  assert(image != (const Image *) NULL);
164  assert(image->signature == MagickCoreSignature);
165  if (image->debug != MagickFalse)
166  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
167  assert(exception != (ExceptionInfo *) NULL);
168  assert(exception->signature == MagickCoreSignature);
169 #if defined(MAGICKCORE_OPENCL_SUPPORT)
170  noise_image=AccelerateAddNoiseImage(image,noise_type,attenuate,exception);
171  if (noise_image != (Image *) NULL)
172  return(noise_image);
173 #endif
174  noise_image=CloneImage(image,0,0,MagickTrue,exception);
175  if (noise_image == (Image *) NULL)
176  return((Image *) NULL);
177  if (SetImageStorageClass(noise_image,DirectClass,exception) == MagickFalse)
178  {
179  noise_image=DestroyImage(noise_image);
180  return((Image *) NULL);
181  }
182  /*
183  Add noise in each row.
184  */
185  status=MagickTrue;
186  progress=0;
187  random_info=AcquireRandomInfoThreadSet();
188  image_view=AcquireVirtualCacheView(image,exception);
189  noise_view=AcquireAuthenticCacheView(noise_image,exception);
190 #if defined(MAGICKCORE_OPENMP_SUPPORT)
191  key=GetRandomSecretKey(random_info[0]);
192  #pragma omp parallel for schedule(static) shared(progress,status) \
193  magick_number_threads(image,noise_image,image->rows,key == ~0UL)
194 #endif
195  for (y=0; y < (ssize_t) image->rows; y++)
196  {
197  const int
198  id = GetOpenMPThreadId();
199 
201  sync;
202 
203  register const Quantum
204  *magick_restrict p;
205 
206  register ssize_t
207  x;
208 
209  register Quantum
210  *magick_restrict q;
211 
212  if (status == MagickFalse)
213  continue;
214  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
215  q=QueueCacheViewAuthenticPixels(noise_view,0,y,noise_image->columns,1,
216  exception);
217  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
218  {
219  status=MagickFalse;
220  continue;
221  }
222  for (x=0; x < (ssize_t) image->columns; x++)
223  {
224  register ssize_t
225  i;
226 
227  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
228  {
229  PixelChannel channel = GetPixelChannelChannel(image,i);
230  PixelTrait traits = GetPixelChannelTraits(image,channel);
231  PixelTrait noise_traits=GetPixelChannelTraits(noise_image,channel);
232  if ((traits == UndefinedPixelTrait) ||
233  (noise_traits == UndefinedPixelTrait))
234  continue;
235  if ((noise_traits & CopyPixelTrait) != 0)
236  {
237  SetPixelChannel(noise_image,channel,p[i],q);
238  continue;
239  }
240  SetPixelChannel(noise_image,channel,ClampToQuantum(
241  GenerateDifferentialNoise(random_info[id],p[i],noise_type,attenuate)),
242  q);
243  }
244  p+=GetPixelChannels(image);
245  q+=GetPixelChannels(noise_image);
246  }
247  sync=SyncCacheViewAuthenticPixels(noise_view,exception);
248  if (sync == MagickFalse)
249  status=MagickFalse;
250  if (image->progress_monitor != (MagickProgressMonitor) NULL)
251  {
253  proceed;
254 
255 #if defined(MAGICKCORE_OPENMP_SUPPORT)
256  #pragma omp atomic
257 #endif
258  progress++;
259  proceed=SetImageProgress(image,AddNoiseImageTag,progress,image->rows);
260  if (proceed == MagickFalse)
261  status=MagickFalse;
262  }
263  }
264  noise_view=DestroyCacheView(noise_view);
265  image_view=DestroyCacheView(image_view);
266  random_info=DestroyRandomInfoThreadSet(random_info);
267  if (status == MagickFalse)
268  noise_image=DestroyImage(noise_image);
269  return(noise_image);
270 }
271 
272 /*
273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 % %
275 % %
276 % %
277 % B l u e S h i f t I m a g e %
278 % %
279 % %
280 % %
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282 %
283 % BlueShiftImage() mutes the colors of the image to simulate a scene at
284 % nighttime in the moonlight.
285 %
286 % The format of the BlueShiftImage method is:
287 %
288 % Image *BlueShiftImage(const Image *image,const double factor,
289 % ExceptionInfo *exception)
290 %
291 % A description of each parameter follows:
292 %
293 % o image: the image.
294 %
295 % o factor: the shift factor.
296 %
297 % o exception: return any errors or warnings in this structure.
298 %
299 */
300 MagickExport Image *BlueShiftImage(const Image *image,const double factor,
301  ExceptionInfo *exception)
302 {
303 #define BlueShiftImageTag "BlueShift/Image"
304 
305  CacheView
306  *image_view,
307  *shift_view;
308 
309  Image
310  *shift_image;
311 
313  status;
314 
316  progress;
317 
318  ssize_t
319  y;
320 
321  /*
322  Allocate blue shift image.
323  */
324  assert(image != (const Image *) NULL);
325  assert(image->signature == MagickCoreSignature);
326  if (image->debug != MagickFalse)
327  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
328  assert(exception != (ExceptionInfo *) NULL);
329  assert(exception->signature == MagickCoreSignature);
330  shift_image=CloneImage(image,0,0,MagickTrue,exception);
331  if (shift_image == (Image *) NULL)
332  return((Image *) NULL);
333  if (SetImageStorageClass(shift_image,DirectClass,exception) == MagickFalse)
334  {
335  shift_image=DestroyImage(shift_image);
336  return((Image *) NULL);
337  }
338  /*
339  Blue-shift DirectClass image.
340  */
341  status=MagickTrue;
342  progress=0;
343  image_view=AcquireVirtualCacheView(image,exception);
344  shift_view=AcquireAuthenticCacheView(shift_image,exception);
345 #if defined(MAGICKCORE_OPENMP_SUPPORT)
346  #pragma omp parallel for schedule(static) shared(progress,status) \
347  magick_number_threads(image,shift_image,image->rows,1)
348 #endif
349  for (y=0; y < (ssize_t) image->rows; y++)
350  {
352  sync;
353 
354  PixelInfo
355  pixel;
356 
357  Quantum
358  quantum;
359 
360  register const Quantum
361  *magick_restrict p;
362 
363  register ssize_t
364  x;
365 
366  register Quantum
367  *magick_restrict q;
368 
369  if (status == MagickFalse)
370  continue;
371  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
372  q=QueueCacheViewAuthenticPixels(shift_view,0,y,shift_image->columns,1,
373  exception);
374  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
375  {
376  status=MagickFalse;
377  continue;
378  }
379  for (x=0; x < (ssize_t) image->columns; x++)
380  {
381  quantum=GetPixelRed(image,p);
382  if (GetPixelGreen(image,p) < quantum)
383  quantum=GetPixelGreen(image,p);
384  if (GetPixelBlue(image,p) < quantum)
385  quantum=GetPixelBlue(image,p);
386  pixel.red=0.5*(GetPixelRed(image,p)+factor*quantum);
387  pixel.green=0.5*(GetPixelGreen(image,p)+factor*quantum);
388  pixel.blue=0.5*(GetPixelBlue(image,p)+factor*quantum);
389  quantum=GetPixelRed(image,p);
390  if (GetPixelGreen(image,p) > quantum)
391  quantum=GetPixelGreen(image,p);
392  if (GetPixelBlue(image,p) > quantum)
393  quantum=GetPixelBlue(image,p);
394  pixel.red=0.5*(pixel.red+factor*quantum);
395  pixel.green=0.5*(pixel.green+factor*quantum);
396  pixel.blue=0.5*(pixel.blue+factor*quantum);
397  SetPixelRed(shift_image,ClampToQuantum(pixel.red),q);
398  SetPixelGreen(shift_image,ClampToQuantum(pixel.green),q);
399  SetPixelBlue(shift_image,ClampToQuantum(pixel.blue),q);
400  p+=GetPixelChannels(image);
401  q+=GetPixelChannels(shift_image);
402  }
403  sync=SyncCacheViewAuthenticPixels(shift_view,exception);
404  if (sync == MagickFalse)
405  status=MagickFalse;
406  if (image->progress_monitor != (MagickProgressMonitor) NULL)
407  {
409  proceed;
410 
411 #if defined(MAGICKCORE_OPENMP_SUPPORT)
412  #pragma omp atomic
413 #endif
414  progress++;
415  proceed=SetImageProgress(image,BlueShiftImageTag,progress,image->rows);
416  if (proceed == MagickFalse)
417  status=MagickFalse;
418  }
419  }
420  image_view=DestroyCacheView(image_view);
421  shift_view=DestroyCacheView(shift_view);
422  if (status == MagickFalse)
423  shift_image=DestroyImage(shift_image);
424  return(shift_image);
425 }
426 
427 /*
428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429 % %
430 % %
431 % %
432 % C h a r c o a l I m a g e %
433 % %
434 % %
435 % %
436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437 %
438 % CharcoalImage() creates a new image that is a copy of an existing one with
439 % the edge highlighted. It allocates the memory necessary for the new Image
440 % structure and returns a pointer to the new image.
441 %
442 % The format of the CharcoalImage method is:
443 %
444 % Image *CharcoalImage(const Image *image,const double radius,
445 % const double sigma,ExceptionInfo *exception)
446 %
447 % A description of each parameter follows:
448 %
449 % o image: the image.
450 %
451 % o radius: the radius of the pixel neighborhood.
452 %
453 % o sigma: the standard deviation of the Gaussian, in pixels.
454 %
455 % o exception: return any errors or warnings in this structure.
456 %
457 */
458 MagickExport Image *CharcoalImage(const Image *image,const double radius,
459  const double sigma,ExceptionInfo *exception)
460 {
461  Image
462  *charcoal_image,
463  *edge_image;
464 
466  status;
467 
468  assert(image != (Image *) NULL);
469  assert(image->signature == MagickCoreSignature);
470  if (image->debug != MagickFalse)
471  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
472  assert(exception != (ExceptionInfo *) NULL);
473  assert(exception->signature == MagickCoreSignature);
474  edge_image=EdgeImage(image,radius,exception);
475  if (edge_image == (Image *) NULL)
476  return((Image *) NULL);
477  charcoal_image=(Image *) NULL;
478  status=ClampImage(edge_image,exception);
479  if (status != MagickFalse)
480  charcoal_image=BlurImage(edge_image,radius,sigma,exception);
481  edge_image=DestroyImage(edge_image);
482  if (charcoal_image == (Image *) NULL)
483  return((Image *) NULL);
484  status=NormalizeImage(charcoal_image,exception);
485  if (status != MagickFalse)
486  status=NegateImage(charcoal_image,MagickFalse,exception);
487  if (status != MagickFalse)
488  status=GrayscaleImage(charcoal_image,image->intensity,exception);
489  if (status == MagickFalse)
490  charcoal_image=DestroyImage(charcoal_image);
491  return(charcoal_image);
492 }
493 
494 /*
495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
496 % %
497 % %
498 % %
499 % C o l o r i z e I m a g e %
500 % %
501 % %
502 % %
503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504 %
505 % ColorizeImage() blends the fill color with each pixel in the image.
506 % A percentage blend is specified with opacity. Control the application
507 % of different color components by specifying a different percentage for
508 % each component (e.g. 90/100/10 is 90% red, 100% green, and 10% blue).
509 %
510 % The format of the ColorizeImage method is:
511 %
512 % Image *ColorizeImage(const Image *image,const char *blend,
513 % const PixelInfo *colorize,ExceptionInfo *exception)
514 %
515 % A description of each parameter follows:
516 %
517 % o image: the image.
518 %
519 % o blend: A character string indicating the level of blending as a
520 % percentage.
521 %
522 % o colorize: A color value.
523 %
524 % o exception: return any errors or warnings in this structure.
525 %
526 */
527 MagickExport Image *ColorizeImage(const Image *image,const char *blend,
528  const PixelInfo *colorize,ExceptionInfo *exception)
529 {
530 #define ColorizeImageTag "Colorize/Image"
531 #define Colorize(pixel,blend_percentage,colorize) \
532  (((pixel)*(100.0-(blend_percentage))+(colorize)*(blend_percentage))/100.0)
533 
534  CacheView
535  *image_view;
536 
538  geometry_info;
539 
540  Image
541  *colorize_image;
542 
544  status;
545 
547  progress;
548 
550  flags;
551 
552  PixelInfo
553  blend_percentage;
554 
555  ssize_t
556  y;
557 
558  /*
559  Allocate colorized image.
560  */
561  assert(image != (const Image *) NULL);
562  assert(image->signature == MagickCoreSignature);
563  if (image->debug != MagickFalse)
564  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
565  assert(exception != (ExceptionInfo *) NULL);
566  assert(exception->signature == MagickCoreSignature);
567  colorize_image=CloneImage(image,0,0,MagickTrue,exception);
568  if (colorize_image == (Image *) NULL)
569  return((Image *) NULL);
570  if (SetImageStorageClass(colorize_image,DirectClass,exception) == MagickFalse)
571  {
572  colorize_image=DestroyImage(colorize_image);
573  return((Image *) NULL);
574  }
575  if ((IsGrayColorspace(colorize_image->colorspace) != MagickFalse) ||
576  (IsPixelInfoGray(colorize) != MagickFalse))
577  (void) SetImageColorspace(colorize_image,sRGBColorspace,exception);
578  if ((colorize_image->alpha_trait == UndefinedPixelTrait) &&
579  (colorize->alpha_trait != UndefinedPixelTrait))
580  (void) SetImageAlpha(colorize_image,OpaqueAlpha,exception);
581  if (blend == (const char *) NULL)
582  return(colorize_image);
583  GetPixelInfo(colorize_image,&blend_percentage);
584  flags=ParseGeometry(blend,&geometry_info);
585  blend_percentage.red=geometry_info.rho;
586  blend_percentage.green=geometry_info.rho;
587  blend_percentage.blue=geometry_info.rho;
588  blend_percentage.black=geometry_info.rho;
589  blend_percentage.alpha=(MagickRealType) TransparentAlpha;
590  if ((flags & SigmaValue) != 0)
591  blend_percentage.green=geometry_info.sigma;
592  if ((flags & XiValue) != 0)
593  blend_percentage.blue=geometry_info.xi;
594  if ((flags & PsiValue) != 0)
595  blend_percentage.alpha=geometry_info.psi;
596  if (blend_percentage.colorspace == CMYKColorspace)
597  {
598  if ((flags & PsiValue) != 0)
599  blend_percentage.black=geometry_info.psi;
600  if ((flags & ChiValue) != 0)
601  blend_percentage.alpha=geometry_info.chi;
602  }
603  /*
604  Colorize DirectClass image.
605  */
606  status=MagickTrue;
607  progress=0;
608  image_view=AcquireVirtualCacheView(colorize_image,exception);
609 #if defined(MAGICKCORE_OPENMP_SUPPORT)
610  #pragma omp parallel for schedule(static) shared(progress,status) \
611  magick_number_threads(colorize_image,colorize_image,colorize_image->rows,1)
612 #endif
613  for (y=0; y < (ssize_t) colorize_image->rows; y++)
614  {
616  sync;
617 
618  register Quantum
619  *magick_restrict q;
620 
621  register ssize_t
622  x;
623 
624  if (status == MagickFalse)
625  continue;
626  q=GetCacheViewAuthenticPixels(image_view,0,y,colorize_image->columns,1,
627  exception);
628  if (q == (Quantum *) NULL)
629  {
630  status=MagickFalse;
631  continue;
632  }
633  for (x=0; x < (ssize_t) colorize_image->columns; x++)
634  {
635  register ssize_t
636  i;
637 
638  for (i=0; i < (ssize_t) GetPixelChannels(colorize_image); i++)
639  {
640  PixelTrait traits = GetPixelChannelTraits(colorize_image,
641  (PixelChannel) i);
642  if (traits == UndefinedPixelTrait)
643  continue;
644  if ((traits & CopyPixelTrait) != 0)
645  continue;
646  SetPixelChannel(colorize_image,(PixelChannel) i,ClampToQuantum(
647  Colorize(q[i],GetPixelInfoChannel(&blend_percentage,(PixelChannel) i),
648  GetPixelInfoChannel(colorize,(PixelChannel) i))),q);
649  }
650  q+=GetPixelChannels(colorize_image);
651  }
652  sync=SyncCacheViewAuthenticPixels(image_view,exception);
653  if (sync == MagickFalse)
654  status=MagickFalse;
655  if (image->progress_monitor != (MagickProgressMonitor) NULL)
656  {
658  proceed;
659 
660 #if defined(MAGICKCORE_OPENMP_SUPPORT)
661  #pragma omp atomic
662 #endif
663  progress++;
664  proceed=SetImageProgress(image,ColorizeImageTag,progress,
665  colorize_image->rows);
666  if (proceed == MagickFalse)
667  status=MagickFalse;
668  }
669  }
670  image_view=DestroyCacheView(image_view);
671  if (status == MagickFalse)
672  colorize_image=DestroyImage(colorize_image);
673  return(colorize_image);
674 }
675 
676 /*
677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678 % %
679 % %
680 % %
681 % C o l o r M a t r i x I m a g e %
682 % %
683 % %
684 % %
685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
686 %
687 % ColorMatrixImage() applies color transformation to an image. This method
688 % permits saturation changes, hue rotation, luminance to alpha, and various
689 % other effects. Although variable-sized transformation matrices can be used,
690 % typically one uses a 5x5 matrix for an RGBA image and a 6x6 for CMYKA
691 % (or RGBA with offsets). The matrix is similar to those used by Adobe Flash
692 % except offsets are in column 6 rather than 5 (in support of CMYKA images)
693 % and offsets are normalized (divide Flash offset by 255).
694 %
695 % The format of the ColorMatrixImage method is:
696 %
697 % Image *ColorMatrixImage(const Image *image,
698 % const KernelInfo *color_matrix,ExceptionInfo *exception)
699 %
700 % A description of each parameter follows:
701 %
702 % o image: the image.
703 %
704 % o color_matrix: the color matrix.
705 %
706 % o exception: return any errors or warnings in this structure.
707 %
708 */
709 /* FUTURE: modify to make use of a MagickMatrix Mutliply function
710  That should be provided in "matrix.c"
711  (ASIDE: actually distorts should do this too but currently doesn't)
712 */
713 
715  const KernelInfo *color_matrix,ExceptionInfo *exception)
716 {
717 #define ColorMatrixImageTag "ColorMatrix/Image"
718 
719  CacheView
720  *color_view,
721  *image_view;
722 
723  double
724  ColorMatrix[6][6] =
725  {
726  { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
727  { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0 },
728  { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 },
729  { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
730  { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 },
731  { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }
732  };
733 
734  Image
735  *color_image;
736 
738  status;
739 
741  progress;
742 
743  register ssize_t
744  i;
745 
746  ssize_t
747  u,
748  v,
749  y;
750 
751  /*
752  Map given color_matrix, into a 6x6 matrix RGBKA and a constant
753  */
754  assert(image != (Image *) NULL);
755  assert(image->signature == MagickCoreSignature);
756  if (image->debug != MagickFalse)
757  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
758  assert(exception != (ExceptionInfo *) NULL);
759  assert(exception->signature == MagickCoreSignature);
760  i=0;
761  for (v=0; v < (ssize_t) color_matrix->height; v++)
762  for (u=0; u < (ssize_t) color_matrix->width; u++)
763  {
764  if ((v < 6) && (u < 6))
765  ColorMatrix[v][u]=color_matrix->values[i];
766  i++;
767  }
768  /*
769  Initialize color image.
770  */
771  color_image=CloneImage(image,0,0,MagickTrue,exception);
772  if (color_image == (Image *) NULL)
773  return((Image *) NULL);
774  if (SetImageStorageClass(color_image,DirectClass,exception) == MagickFalse)
775  {
776  color_image=DestroyImage(color_image);
777  return((Image *) NULL);
778  }
779  if (image->debug != MagickFalse)
780  {
781  char
782  format[MagickPathExtent],
783  *message;
784 
786  " ColorMatrix image with color matrix:");
787  message=AcquireString("");
788  for (v=0; v < 6; v++)
789  {
790  *message='\0';
791  (void) FormatLocaleString(format,MagickPathExtent,"%.20g: ",(double) v);
792  (void) ConcatenateString(&message,format);
793  for (u=0; u < 6; u++)
794  {
795  (void) FormatLocaleString(format,MagickPathExtent,"%+f ",
796  ColorMatrix[v][u]);
797  (void) ConcatenateString(&message,format);
798  }
799  (void) LogMagickEvent(TransformEvent,GetMagickModule(),"%s",message);
800  }
801  message=DestroyString(message);
802  }
803  /*
804  Apply the ColorMatrix to image.
805  */
806  status=MagickTrue;
807  progress=0;
808  image_view=AcquireVirtualCacheView(image,exception);
809  color_view=AcquireAuthenticCacheView(color_image,exception);
810 #if defined(MAGICKCORE_OPENMP_SUPPORT)
811  #pragma omp parallel for schedule(static) shared(progress,status) \
812  magick_number_threads(image,color_image,image->rows,1)
813 #endif
814  for (y=0; y < (ssize_t) image->rows; y++)
815  {
816  PixelInfo
817  pixel;
818 
819  register const Quantum
820  *magick_restrict p;
821 
822  register Quantum
823  *magick_restrict q;
824 
825  register ssize_t
826  x;
827 
828  if (status == MagickFalse)
829  continue;
830  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
831  q=GetCacheViewAuthenticPixels(color_view,0,y,color_image->columns,1,
832  exception);
833  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
834  {
835  status=MagickFalse;
836  continue;
837  }
838  GetPixelInfo(image,&pixel);
839  for (x=0; x < (ssize_t) image->columns; x++)
840  {
841  register ssize_t
842  v;
843 
844  size_t
845  height;
846 
847  GetPixelInfoPixel(image,p,&pixel);
848  height=color_matrix->height > 6 ? 6UL : color_matrix->height;
849  for (v=0; v < (ssize_t) height; v++)
850  {
851  double
852  sum;
853 
854  sum=ColorMatrix[v][0]*GetPixelRed(image,p)+ColorMatrix[v][1]*
855  GetPixelGreen(image,p)+ColorMatrix[v][2]*GetPixelBlue(image,p);
856  if (image->colorspace == CMYKColorspace)
857  sum+=ColorMatrix[v][3]*GetPixelBlack(image,p);
858  if (image->alpha_trait != UndefinedPixelTrait)
859  sum+=ColorMatrix[v][4]*GetPixelAlpha(image,p);
860  sum+=QuantumRange*ColorMatrix[v][5];
861  switch (v)
862  {
863  case 0: pixel.red=sum; break;
864  case 1: pixel.green=sum; break;
865  case 2: pixel.blue=sum; break;
866  case 3: pixel.black=sum; break;
867  case 4: pixel.alpha=sum; break;
868  default: break;
869  }
870  }
871  SetPixelViaPixelInfo(color_image,&pixel,q);
872  p+=GetPixelChannels(image);
873  q+=GetPixelChannels(color_image);
874  }
875  if (SyncCacheViewAuthenticPixels(color_view,exception) == MagickFalse)
876  status=MagickFalse;
877  if (image->progress_monitor != (MagickProgressMonitor) NULL)
878  {
880  proceed;
881 
882 #if defined(MAGICKCORE_OPENMP_SUPPORT)
883  #pragma omp atomic
884 #endif
885  progress++;
886  proceed=SetImageProgress(image,ColorMatrixImageTag,progress,
887  image->rows);
888  if (proceed == MagickFalse)
889  status=MagickFalse;
890  }
891  }
892  color_view=DestroyCacheView(color_view);
893  image_view=DestroyCacheView(image_view);
894  if (status == MagickFalse)
895  color_image=DestroyImage(color_image);
896  return(color_image);
897 }
898 
899 /*
900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901 % %
902 % %
903 % %
904 % I m p l o d e I m a g e %
905 % %
906 % %
907 % %
908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909 %
910 % ImplodeImage() creates a new image that is a copy of an existing
911 % one with the image pixels "implode" by the specified percentage. It
912 % allocates the memory necessary for the new Image structure and returns a
913 % pointer to the new image.
914 %
915 % The format of the ImplodeImage method is:
916 %
917 % Image *ImplodeImage(const Image *image,const double amount,
918 % const PixelInterpolateMethod method,ExceptionInfo *exception)
919 %
920 % A description of each parameter follows:
921 %
922 % o implode_image: Method ImplodeImage returns a pointer to the image
923 % after it is implode. A null image is returned if there is a memory
924 % shortage.
925 %
926 % o image: the image.
927 %
928 % o amount: Define the extent of the implosion.
929 %
930 % o method: the pixel interpolation method.
931 %
932 % o exception: return any errors or warnings in this structure.
933 %
934 */
935 MagickExport Image *ImplodeImage(const Image *image,const double amount,
936  const PixelInterpolateMethod method,ExceptionInfo *exception)
937 {
938 #define ImplodeImageTag "Implode/Image"
939 
940  CacheView
941  *canvas_view,
942  *implode_view,
943  *interpolate_view;
944 
945  double
946  radius;
947 
948  Image
949  *canvas_image,
950  *implode_image;
951 
953  status;
954 
956  progress;
957 
958  PointInfo
959  center,
960  scale;
961 
962  ssize_t
963  y;
964 
965  /*
966  Initialize implode image attributes.
967  */
968  assert(image != (Image *) NULL);
969  assert(image->signature == MagickCoreSignature);
970  if (image->debug != MagickFalse)
971  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
972  assert(exception != (ExceptionInfo *) NULL);
973  assert(exception->signature == MagickCoreSignature);
974  canvas_image=CloneImage(image,0,0,MagickTrue,exception);
975  if (canvas_image == (Image *) NULL)
976  return((Image *) NULL);
977  if ((canvas_image->alpha_trait == UndefinedPixelTrait) &&
978  (canvas_image->background_color.alpha != OpaqueAlpha))
979  (void) SetImageAlphaChannel(canvas_image,OpaqueAlphaChannel,exception);
980  implode_image=CloneImage(canvas_image,0,0,MagickTrue,exception);
981  if (implode_image == (Image *) NULL)
982  {
983  canvas_image=DestroyImage(canvas_image);
984  return((Image *) NULL);
985  }
986  if (SetImageStorageClass(implode_image,DirectClass,exception) == MagickFalse)
987  {
988  canvas_image=DestroyImage(canvas_image);
989  implode_image=DestroyImage(implode_image);
990  return((Image *) NULL);
991  }
992  /*
993  Compute scaling factor.
994  */
995  scale.x=1.0;
996  scale.y=1.0;
997  center.x=0.5*canvas_image->columns;
998  center.y=0.5*canvas_image->rows;
999  radius=center.x;
1000  if (canvas_image->columns > canvas_image->rows)
1001  scale.y=(double) canvas_image->columns/(double) canvas_image->rows;
1002  else
1003  if (canvas_image->columns < canvas_image->rows)
1004  {
1005  scale.x=(double) canvas_image->rows/(double) canvas_image->columns;
1006  radius=center.y;
1007  }
1008  /*
1009  Implode image.
1010  */
1011  status=MagickTrue;
1012  progress=0;
1013  canvas_view=AcquireVirtualCacheView(canvas_image,exception);
1014  interpolate_view=AcquireVirtualCacheView(canvas_image,exception);
1015  implode_view=AcquireAuthenticCacheView(implode_image,exception);
1016 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1017  #pragma omp parallel for schedule(static) shared(progress,status) \
1018  magick_number_threads(canvas_image,implode_image,canvas_image->rows,1)
1019 #endif
1020  for (y=0; y < (ssize_t) canvas_image->rows; y++)
1021  {
1022  double
1023  distance;
1024 
1025  PointInfo
1026  delta;
1027 
1028  register const Quantum
1029  *magick_restrict p;
1030 
1031  register ssize_t
1032  x;
1033 
1034  register Quantum
1035  *magick_restrict q;
1036 
1037  if (status == MagickFalse)
1038  continue;
1039  p=GetCacheViewVirtualPixels(canvas_view,0,y,canvas_image->columns,1,
1040  exception);
1041  q=QueueCacheViewAuthenticPixels(implode_view,0,y,implode_image->columns,1,
1042  exception);
1043  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1044  {
1045  status=MagickFalse;
1046  continue;
1047  }
1048  delta.y=scale.y*(double) (y-center.y);
1049  for (x=0; x < (ssize_t) canvas_image->columns; x++)
1050  {
1051  register ssize_t
1052  i;
1053 
1054  /*
1055  Determine if the pixel is within an ellipse.
1056  */
1057  delta.x=scale.x*(double) (x-center.x);
1058  distance=delta.x*delta.x+delta.y*delta.y;
1059  if (distance >= (radius*radius))
1060  for (i=0; i < (ssize_t) GetPixelChannels(canvas_image); i++)
1061  {
1062  PixelChannel channel = GetPixelChannelChannel(canvas_image,i);
1063  PixelTrait traits = GetPixelChannelTraits(canvas_image,channel);
1064  PixelTrait implode_traits = GetPixelChannelTraits(implode_image,
1065  channel);
1066  if ((traits == UndefinedPixelTrait) ||
1067  (implode_traits == UndefinedPixelTrait))
1068  continue;
1069  SetPixelChannel(implode_image,channel,p[i],q);
1070  }
1071  else
1072  {
1073  double
1074  factor;
1075 
1076  /*
1077  Implode the pixel.
1078  */
1079  factor=1.0;
1080  if (distance > 0.0)
1081  factor=pow(sin(MagickPI*sqrt((double) distance)/radius/2),-amount);
1082  status=InterpolatePixelChannels(canvas_image,interpolate_view,
1083  implode_image,method,(double) (factor*delta.x/scale.x+center.x),
1084  (double) (factor*delta.y/scale.y+center.y),q,exception);
1085  if (status == MagickFalse)
1086  break;
1087  }
1088  p+=GetPixelChannels(canvas_image);
1089  q+=GetPixelChannels(implode_image);
1090  }
1091  if (SyncCacheViewAuthenticPixels(implode_view,exception) == MagickFalse)
1092  status=MagickFalse;
1093  if (canvas_image->progress_monitor != (MagickProgressMonitor) NULL)
1094  {
1096  proceed;
1097 
1098 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1099  #pragma omp atomic
1100 #endif
1101  progress++;
1102  proceed=SetImageProgress(canvas_image,ImplodeImageTag,progress,
1103  canvas_image->rows);
1104  if (proceed == MagickFalse)
1105  status=MagickFalse;
1106  }
1107  }
1108  implode_view=DestroyCacheView(implode_view);
1109  interpolate_view=DestroyCacheView(interpolate_view);
1110  canvas_view=DestroyCacheView(canvas_view);
1111  canvas_image=DestroyImage(canvas_image);
1112  if (status == MagickFalse)
1113  implode_image=DestroyImage(implode_image);
1114  return(implode_image);
1115 }
1116 
1117 /*
1118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1119 % %
1120 % %
1121 % %
1122 % M o r p h I m a g e s %
1123 % %
1124 % %
1125 % %
1126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1127 %
1128 % The MorphImages() method requires a minimum of two images. The first
1129 % image is transformed into the second by a number of intervening images
1130 % as specified by frames.
1131 %
1132 % The format of the MorphImage method is:
1133 %
1134 % Image *MorphImages(const Image *image,const size_t number_frames,
1135 % ExceptionInfo *exception)
1136 %
1137 % A description of each parameter follows:
1138 %
1139 % o image: the image.
1140 %
1141 % o number_frames: Define the number of in-between image to generate.
1142 % The more in-between frames, the smoother the morph.
1143 %
1144 % o exception: return any errors or warnings in this structure.
1145 %
1146 */
1147 MagickExport Image *MorphImages(const Image *image,const size_t number_frames,
1148  ExceptionInfo *exception)
1149 {
1150 #define MorphImageTag "Morph/Image"
1151 
1152  double
1153  alpha,
1154  beta;
1155 
1156  Image
1157  *morph_image,
1158  *morph_images;
1159 
1161  status;
1162 
1164  scene;
1165 
1166  register const Image
1167  *next;
1168 
1169  register ssize_t
1170  n;
1171 
1172  ssize_t
1173  y;
1174 
1175  /*
1176  Clone first frame in sequence.
1177  */
1178  assert(image != (Image *) NULL);
1179  assert(image->signature == MagickCoreSignature);
1180  if (image->debug != MagickFalse)
1181  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1182  assert(exception != (ExceptionInfo *) NULL);
1183  assert(exception->signature == MagickCoreSignature);
1184  morph_images=CloneImage(image,0,0,MagickTrue,exception);
1185  if (morph_images == (Image *) NULL)
1186  return((Image *) NULL);
1187  if (GetNextImageInList(image) == (Image *) NULL)
1188  {
1189  /*
1190  Morph single image.
1191  */
1192  for (n=1; n < (ssize_t) number_frames; n++)
1193  {
1194  morph_image=CloneImage(image,0,0,MagickTrue,exception);
1195  if (morph_image == (Image *) NULL)
1196  {
1197  morph_images=DestroyImageList(morph_images);
1198  return((Image *) NULL);
1199  }
1200  AppendImageToList(&morph_images,morph_image);
1201  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1202  {
1204  proceed;
1205 
1207  number_frames);
1208  if (proceed == MagickFalse)
1209  status=MagickFalse;
1210  }
1211  }
1212  return(GetFirstImageInList(morph_images));
1213  }
1214  /*
1215  Morph image sequence.
1216  */
1217  status=MagickTrue;
1218  scene=0;
1219  next=image;
1220  for ( ; GetNextImageInList(next) != (Image *) NULL; next=GetNextImageInList(next))
1221  {
1222  for (n=0; n < (ssize_t) number_frames; n++)
1223  {
1224  CacheView
1225  *image_view,
1226  *morph_view;
1227 
1228  beta=(double) (n+1.0)/(double) (number_frames+1.0);
1229  alpha=1.0-beta;
1230  morph_image=ResizeImage(next,(size_t) (alpha*next->columns+beta*
1231  GetNextImageInList(next)->columns+0.5),(size_t) (alpha*next->rows+beta*
1232  GetNextImageInList(next)->rows+0.5),next->filter,exception);
1233  if (morph_image == (Image *) NULL)
1234  {
1235  morph_images=DestroyImageList(morph_images);
1236  return((Image *) NULL);
1237  }
1238  status=SetImageStorageClass(morph_image,DirectClass,exception);
1239  if (status == MagickFalse)
1240  {
1241  morph_image=DestroyImage(morph_image);
1242  return((Image *) NULL);
1243  }
1244  AppendImageToList(&morph_images,morph_image);
1245  morph_images=GetLastImageInList(morph_images);
1246  morph_image=ResizeImage(GetNextImageInList(next),morph_images->columns,
1247  morph_images->rows,GetNextImageInList(next)->filter,exception);
1248  if (morph_image == (Image *) NULL)
1249  {
1250  morph_images=DestroyImageList(morph_images);
1251  return((Image *) NULL);
1252  }
1253  image_view=AcquireVirtualCacheView(morph_image,exception);
1254  morph_view=AcquireAuthenticCacheView(morph_images,exception);
1255 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1256  #pragma omp parallel for schedule(static) shared(status) \
1257  magick_number_threads(morph_image,morph_image,morph_image->rows,1)
1258 #endif
1259  for (y=0; y < (ssize_t) morph_images->rows; y++)
1260  {
1262  sync;
1263 
1264  register const Quantum
1265  *magick_restrict p;
1266 
1267  register ssize_t
1268  x;
1269 
1270  register Quantum
1271  *magick_restrict q;
1272 
1273  if (status == MagickFalse)
1274  continue;
1275  p=GetCacheViewVirtualPixels(image_view,0,y,morph_image->columns,1,
1276  exception);
1277  q=GetCacheViewAuthenticPixels(morph_view,0,y,morph_images->columns,1,
1278  exception);
1279  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1280  {
1281  status=MagickFalse;
1282  continue;
1283  }
1284  for (x=0; x < (ssize_t) morph_images->columns; x++)
1285  {
1286  register ssize_t
1287  i;
1288 
1289  for (i=0; i < (ssize_t) GetPixelChannels(morph_image); i++)
1290  {
1291  PixelChannel channel = GetPixelChannelChannel(morph_image,i);
1292  PixelTrait traits = GetPixelChannelTraits(morph_image,channel);
1293  PixelTrait morph_traits=GetPixelChannelTraits(morph_images,channel);
1294  if ((traits == UndefinedPixelTrait) ||
1295  (morph_traits == UndefinedPixelTrait))
1296  continue;
1297  if ((morph_traits & CopyPixelTrait) != 0)
1298  {
1299  SetPixelChannel(morph_image,channel,p[i],q);
1300  continue;
1301  }
1302  SetPixelChannel(morph_image,channel,ClampToQuantum(alpha*
1303  GetPixelChannel(morph_images,channel,q)+beta*p[i]),q);
1304  }
1305  p+=GetPixelChannels(morph_image);
1306  q+=GetPixelChannels(morph_images);
1307  }
1308  sync=SyncCacheViewAuthenticPixels(morph_view,exception);
1309  if (sync == MagickFalse)
1310  status=MagickFalse;
1311  }
1312  morph_view=DestroyCacheView(morph_view);
1313  image_view=DestroyCacheView(image_view);
1314  morph_image=DestroyImage(morph_image);
1315  }
1316  if (n < (ssize_t) number_frames)
1317  break;
1318  /*
1319  Clone last frame in sequence.
1320  */
1321  morph_image=CloneImage(GetNextImageInList(next),0,0,MagickTrue,exception);
1322  if (morph_image == (Image *) NULL)
1323  {
1324  morph_images=DestroyImageList(morph_images);
1325  return((Image *) NULL);
1326  }
1327  AppendImageToList(&morph_images,morph_image);
1328  morph_images=GetLastImageInList(morph_images);
1329  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1330  {
1332  proceed;
1333 
1334  proceed=SetImageProgress(image,MorphImageTag,scene,
1335  GetImageListLength(image));
1336  if (proceed == MagickFalse)
1337  status=MagickFalse;
1338  }
1339  scene++;
1340  }
1341  if (GetNextImageInList(next) != (Image *) NULL)
1342  {
1343  morph_images=DestroyImageList(morph_images);
1344  return((Image *) NULL);
1345  }
1346  return(GetFirstImageInList(morph_images));
1347 }
1348 
1349 /*
1350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1351 % %
1352 % %
1353 % %
1354 % P l a s m a I m a g e %
1355 % %
1356 % %
1357 % %
1358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1359 %
1360 % PlasmaImage() initializes an image with plasma fractal values. The image
1361 % must be initialized with a base color and the random number generator
1362 % seeded before this method is called.
1363 %
1364 % The format of the PlasmaImage method is:
1365 %
1366 % MagickBooleanType PlasmaImage(Image *image,const SegmentInfo *segment,
1367 % size_t attenuate,size_t depth,ExceptionInfo *exception)
1368 %
1369 % A description of each parameter follows:
1370 %
1371 % o image: the image.
1372 %
1373 % o segment: Define the region to apply plasma fractals values.
1374 %
1375 % o attenuate: Define the plasma attenuation factor.
1376 %
1377 % o depth: Limit the plasma recursion depth.
1378 %
1379 % o exception: return any errors or warnings in this structure.
1380 %
1381 */
1382 
1384  const double pixel,const double noise)
1385 {
1387  plasma;
1388 
1389  plasma=pixel+noise*GetPseudoRandomValue(random_info)-noise/2.0;
1390  return(ClampToQuantum(plasma));
1391 }
1392 
1395  const SegmentInfo *magick_restrict segment,size_t attenuate,size_t depth,
1396  ExceptionInfo *exception)
1397 {
1398  double
1399  plasma;
1400 
1402  status;
1403 
1404  register const Quantum
1405  *magick_restrict u,
1406  *magick_restrict v;
1407 
1408  register Quantum
1409  *magick_restrict q;
1410 
1411  register ssize_t
1412  i;
1413 
1414  ssize_t
1415  x,
1416  x_mid,
1417  y,
1418  y_mid;
1419 
1420  if ((fabs(segment->x2-segment->x1) < MagickEpsilon) &&
1421  (fabs(segment->y2-segment->y1) < MagickEpsilon))
1422  return(MagickTrue);
1423  if (depth != 0)
1424  {
1425  SegmentInfo
1426  local_info;
1427 
1428  /*
1429  Divide the area into quadrants and recurse.
1430  */
1431  depth--;
1432  attenuate++;
1433  x_mid=(ssize_t) ceil((segment->x1+segment->x2)/2-0.5);
1434  y_mid=(ssize_t) ceil((segment->y1+segment->y2)/2-0.5);
1435  local_info=(*segment);
1436  local_info.x2=(double) x_mid;
1437  local_info.y2=(double) y_mid;
1438  status=PlasmaImageProxy(image,image_view,u_view,v_view,random_info,
1439  &local_info,attenuate,depth,exception);
1440  local_info=(*segment);
1441  local_info.y1=(double) y_mid;
1442  local_info.x2=(double) x_mid;
1443  status&=PlasmaImageProxy(image,image_view,u_view,v_view,random_info,
1444  &local_info,attenuate,depth,exception);
1445  local_info=(*segment);
1446  local_info.x1=(double) x_mid;
1447  local_info.y2=(double) y_mid;
1448  status&=PlasmaImageProxy(image,image_view,u_view,v_view,random_info,
1449  &local_info,attenuate,depth,exception);
1450  local_info=(*segment);
1451  local_info.x1=(double) x_mid;
1452  local_info.y1=(double) y_mid;
1453  status&=PlasmaImageProxy(image,image_view,u_view,v_view,random_info,
1454  &local_info,attenuate,depth,exception);
1455  return(status == 0 ? MagickFalse : MagickTrue);
1456  }
1457  x_mid=(ssize_t) ceil((segment->x1+segment->x2)/2-0.5);
1458  y_mid=(ssize_t) ceil((segment->y1+segment->y2)/2-0.5);
1459  if ((fabs(segment->x1-x_mid) < MagickEpsilon) &&
1460  (fabs(segment->x2-x_mid) < MagickEpsilon) &&
1461  (fabs(segment->y1-y_mid) < MagickEpsilon) &&
1462  (fabs(segment->y2-y_mid) < MagickEpsilon))
1463  return(MagickFalse);
1464  /*
1465  Average pixels and apply plasma.
1466  */
1467  status=MagickTrue;
1468  plasma=(double) QuantumRange/(2.0*attenuate);
1469  if ((fabs(segment->x1-x_mid) >= MagickEpsilon) ||
1470  (fabs(segment->x2-x_mid) >= MagickEpsilon))
1471  {
1472  /*
1473  Left pixel.
1474  */
1475  x=(ssize_t) ceil(segment->x1-0.5);
1476  u=GetCacheViewVirtualPixels(u_view,x,(ssize_t) ceil(segment->y1-0.5),1,1,
1477  exception);
1478  v=GetCacheViewVirtualPixels(v_view,x,(ssize_t) ceil(segment->y2-0.5),1,1,
1479  exception);
1480  q=QueueCacheViewAuthenticPixels(image_view,x,y_mid,1,1,exception);
1481  if ((u == (const Quantum *) NULL) || (v == (const Quantum *) NULL) ||
1482  (q == (Quantum *) NULL))
1483  return(MagickTrue);
1484  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1485  {
1486  PixelChannel channel = GetPixelChannelChannel(image,i);
1487  PixelTrait traits = GetPixelChannelTraits(image,channel);
1488  if (traits == UndefinedPixelTrait)
1489  continue;
1490  q[i]=PlasmaPixel(random_info,((double) u[i]+v[i])/2.0,plasma);
1491  }
1492  status=SyncCacheViewAuthenticPixels(image_view,exception);
1493  if (fabs(segment->x1-segment->x2) >= MagickEpsilon)
1494  {
1495  /*
1496  Right pixel.
1497  */
1498  x=(ssize_t) ceil(segment->x2-0.5);
1499  u=GetCacheViewVirtualPixels(u_view,x,(ssize_t) ceil(segment->y1-0.5),
1500  1,1,exception);
1501  v=GetCacheViewVirtualPixels(v_view,x,(ssize_t) ceil(segment->y2-0.5),
1502  1,1,exception);
1503  q=QueueCacheViewAuthenticPixels(image_view,x,y_mid,1,1,exception);
1504  if ((u == (const Quantum *) NULL) || (v == (const Quantum *) NULL) ||
1505  (q == (Quantum *) NULL))
1506  return(MagickFalse);
1507  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1508  {
1509  PixelChannel channel = GetPixelChannelChannel(image,i);
1510  PixelTrait traits = GetPixelChannelTraits(image,channel);
1511  if (traits == UndefinedPixelTrait)
1512  continue;
1513  q[i]=PlasmaPixel(random_info,((double) u[i]+v[i])/2.0,plasma);
1514  }
1515  status=SyncCacheViewAuthenticPixels(image_view,exception);
1516  }
1517  }
1518  if ((fabs(segment->y1-y_mid) >= MagickEpsilon) ||
1519  (fabs(segment->y2-y_mid) >= MagickEpsilon))
1520  {
1521  if ((fabs(segment->x1-x_mid) >= MagickEpsilon) ||
1522  (fabs(segment->y2-y_mid) >= MagickEpsilon))
1523  {
1524  /*
1525  Bottom pixel.
1526  */
1527  y=(ssize_t) ceil(segment->y2-0.5);
1528  u=GetCacheViewVirtualPixels(u_view,(ssize_t) ceil(segment->x1-0.5),y,
1529  1,1,exception);
1530  v=GetCacheViewVirtualPixels(v_view,(ssize_t) ceil(segment->x2-0.5),y,
1531  1,1,exception);
1532  q=QueueCacheViewAuthenticPixels(image_view,x_mid,y,1,1,exception);
1533  if ((u == (const Quantum *) NULL) || (v == (const Quantum *) NULL) ||
1534  (q == (Quantum *) NULL))
1535  return(MagickTrue);
1536  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1537  {
1538  PixelChannel channel = GetPixelChannelChannel(image,i);
1539  PixelTrait traits = GetPixelChannelTraits(image,channel);
1540  if (traits == UndefinedPixelTrait)
1541  continue;
1542  q[i]=PlasmaPixel(random_info,((double) u[i]+v[i])/2.0,plasma);
1543  }
1544  status=SyncCacheViewAuthenticPixels(image_view,exception);
1545  }
1546  if (fabs(segment->y1-segment->y2) >= MagickEpsilon)
1547  {
1548  /*
1549  Top pixel.
1550  */
1551  y=(ssize_t) ceil(segment->y1-0.5);
1552  u=GetCacheViewVirtualPixels(u_view,(ssize_t) ceil(segment->x1-0.5),y,
1553  1,1,exception);
1554  v=GetCacheViewVirtualPixels(v_view,(ssize_t) ceil(segment->x2-0.5),y,
1555  1,1,exception);
1556  q=QueueCacheViewAuthenticPixels(image_view,x_mid,y,1,1,exception);
1557  if ((u == (const Quantum *) NULL) || (v == (const Quantum *) NULL) ||
1558  (q == (Quantum *) NULL))
1559  return(MagickTrue);
1560  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1561  {
1562  PixelChannel channel = GetPixelChannelChannel(image,i);
1563  PixelTrait traits = GetPixelChannelTraits(image,channel);
1564  if (traits == UndefinedPixelTrait)
1565  continue;
1566  q[i]=PlasmaPixel(random_info,((double) u[i]+v[i])/2.0,plasma);
1567  }
1568  status=SyncCacheViewAuthenticPixels(image_view,exception);
1569  }
1570  }
1571  if ((fabs(segment->x1-segment->x2) >= MagickEpsilon) ||
1572  (fabs(segment->y1-segment->y2) >= MagickEpsilon))
1573  {
1574  /*
1575  Middle pixel.
1576  */
1577  x=(ssize_t) ceil(segment->x1-0.5);
1578  y=(ssize_t) ceil(segment->y1-0.5);
1579  u=GetCacheViewVirtualPixels(u_view,x,y,1,1,exception);
1580  x=(ssize_t) ceil(segment->x2-0.5);
1581  y=(ssize_t) ceil(segment->y2-0.5);
1582  v=GetCacheViewVirtualPixels(v_view,x,y,1,1,exception);
1583  q=QueueCacheViewAuthenticPixels(image_view,x_mid,y_mid,1,1,exception);
1584  if ((u == (const Quantum *) NULL) || (v == (const Quantum *) NULL) ||
1585  (q == (Quantum *) NULL))
1586  return(MagickTrue);
1587  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1588  {
1589  PixelChannel channel = GetPixelChannelChannel(image,i);
1590  PixelTrait traits = GetPixelChannelTraits(image,channel);
1591  if (traits == UndefinedPixelTrait)
1592  continue;
1593  q[i]=PlasmaPixel(random_info,((double) u[i]+v[i])/2.0,plasma);
1594  }
1595  status=SyncCacheViewAuthenticPixels(image_view,exception);
1596  }
1597  if ((fabs(segment->x2-segment->x1) < 3.0) &&
1598  (fabs(segment->y2-segment->y1) < 3.0))
1599  return(status == 0 ? MagickFalse : MagickTrue);
1600  return(MagickFalse);
1601 }
1602 
1604  const SegmentInfo *segment,size_t attenuate,size_t depth,
1605  ExceptionInfo *exception)
1606 {
1607  CacheView
1608  *image_view,
1609  *u_view,
1610  *v_view;
1611 
1613  status;
1614 
1615  RandomInfo
1616  *random_info;
1617 
1618  assert(image != (Image *) NULL);
1619  if (image->debug != MagickFalse)
1620  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1621  assert(image->signature == MagickCoreSignature);
1622  if (image->debug != MagickFalse)
1623  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1624  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1625  return(MagickFalse);
1626  image_view=AcquireAuthenticCacheView(image,exception);
1627  u_view=AcquireVirtualCacheView(image,exception);
1628  v_view=AcquireVirtualCacheView(image,exception);
1629  random_info=AcquireRandomInfo();
1630  status=PlasmaImageProxy(image,image_view,u_view,v_view,random_info,segment,
1631  attenuate,depth,exception);
1632  random_info=DestroyRandomInfo(random_info);
1633  v_view=DestroyCacheView(v_view);
1634  u_view=DestroyCacheView(u_view);
1635  image_view=DestroyCacheView(image_view);
1636  return(status);
1637 }
1638 
1639 /*
1640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1641 % %
1642 % %
1643 % %
1644 % P o l a r o i d I m a g e %
1645 % %
1646 % %
1647 % %
1648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1649 %
1650 % PolaroidImage() simulates a Polaroid picture.
1651 %
1652 % The format of the PolaroidImage method is:
1653 %
1654 % Image *PolaroidImage(const Image *image,const DrawInfo *draw_info,
1655 % const char *caption,const double angle,
1656 % const PixelInterpolateMethod method,ExceptionInfo exception)
1657 %
1658 % A description of each parameter follows:
1659 %
1660 % o image: the image.
1661 %
1662 % o draw_info: the draw info.
1663 %
1664 % o caption: the Polaroid caption.
1665 %
1666 % o angle: Apply the effect along this angle.
1667 %
1668 % o method: the pixel interpolation method.
1669 %
1670 % o exception: return any errors or warnings in this structure.
1671 %
1672 */
1673 MagickExport Image *PolaroidImage(const Image *image,const DrawInfo *draw_info,
1674  const char *caption,const double angle,const PixelInterpolateMethod method,
1675  ExceptionInfo *exception)
1676 {
1677  Image
1678  *bend_image,
1679  *caption_image,
1680  *flop_image,
1681  *picture_image,
1682  *polaroid_image,
1683  *rotate_image,
1684  *trim_image;
1685 
1686  size_t
1687  height;
1688 
1689  ssize_t
1690  quantum;
1691 
1692  /*
1693  Simulate a Polaroid picture.
1694  */
1695  assert(image != (Image *) NULL);
1696  assert(image->signature == MagickCoreSignature);
1697  if (image->debug != MagickFalse)
1698  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1699  assert(exception != (ExceptionInfo *) NULL);
1700  assert(exception->signature == MagickCoreSignature);
1701  quantum=(ssize_t) MagickMax(MagickMax((double) image->columns,(double)
1702  image->rows)/25.0,10.0);
1703  height=image->rows+2*quantum;
1704  caption_image=(Image *) NULL;
1705  if (caption != (const char *) NULL)
1706  {
1707  char
1708  *text;
1709 
1710  /*
1711  Generate caption image.
1712  */
1713  caption_image=CloneImage(image,image->columns,1,MagickTrue,exception);
1714  if (caption_image == (Image *) NULL)
1715  return((Image *) NULL);
1716  text=InterpretImageProperties((ImageInfo *) NULL,(Image *) image,caption,
1717  exception);
1718  if (text != (char *) NULL)
1719  {
1720  char
1721  geometry[MagickPathExtent];
1722 
1723  DrawInfo
1724  *annotate_info;
1725 
1727  status;
1728 
1729  ssize_t
1730  count;
1731 
1732  TypeMetric
1733  metrics;
1734 
1735  annotate_info=CloneDrawInfo((const ImageInfo *) NULL,draw_info);
1736  (void) CloneString(&annotate_info->text,text);
1737  count=FormatMagickCaption(caption_image,annotate_info,MagickTrue,
1738  &metrics,&text,exception);
1739  status=SetImageExtent(caption_image,image->columns,(size_t)
1740  ((count+1)*(metrics.ascent-metrics.descent)+0.5),exception);
1741  if (status == MagickFalse)
1742  caption_image=DestroyImage(caption_image);
1743  else
1744  {
1745  caption_image->background_color=image->border_color;
1746  (void) SetImageBackgroundColor(caption_image,exception);
1747  (void) CloneString(&annotate_info->text,text);
1748  (void) FormatLocaleString(geometry,MagickPathExtent,"+0+%.20g",
1749  metrics.ascent);
1750  if (annotate_info->gravity == UndefinedGravity)
1751  (void) CloneString(&annotate_info->geometry,AcquireString(
1752  geometry));
1753  (void) AnnotateImage(caption_image,annotate_info,exception);
1754  height+=caption_image->rows;
1755  }
1756  annotate_info=DestroyDrawInfo(annotate_info);
1757  text=DestroyString(text);
1758  }
1759  }
1760  picture_image=CloneImage(image,image->columns+2*quantum,height,MagickTrue,
1761  exception);
1762  if (picture_image == (Image *) NULL)
1763  {
1764  if (caption_image != (Image *) NULL)
1765  caption_image=DestroyImage(caption_image);
1766  return((Image *) NULL);
1767  }
1768  picture_image->background_color=image->border_color;
1769  (void) SetImageBackgroundColor(picture_image,exception);
1770  (void) CompositeImage(picture_image,image,OverCompositeOp,MagickTrue,quantum,
1771  quantum,exception);
1772  if (caption_image != (Image *) NULL)
1773  {
1774  (void) CompositeImage(picture_image,caption_image,OverCompositeOp,
1775  MagickTrue,quantum,(ssize_t) (image->rows+3*quantum/2),exception);
1776  caption_image=DestroyImage(caption_image);
1777  }
1778  (void) QueryColorCompliance("none",AllCompliance,
1779  &picture_image->background_color,exception);
1780  (void) SetImageAlphaChannel(picture_image,OpaqueAlphaChannel,exception);
1781  rotate_image=RotateImage(picture_image,90.0,exception);
1782  picture_image=DestroyImage(picture_image);
1783  if (rotate_image == (Image *) NULL)
1784  return((Image *) NULL);
1785  picture_image=rotate_image;
1786  bend_image=WaveImage(picture_image,0.01*picture_image->rows,2.0*
1787  picture_image->columns,method,exception);
1788  picture_image=DestroyImage(picture_image);
1789  if (bend_image == (Image *) NULL)
1790  return((Image *) NULL);
1791  picture_image=bend_image;
1792  rotate_image=RotateImage(picture_image,-90.0,exception);
1793  picture_image=DestroyImage(picture_image);
1794  if (rotate_image == (Image *) NULL)
1795  return((Image *) NULL);
1796  picture_image=rotate_image;
1797  picture_image->background_color=image->background_color;
1798  polaroid_image=ShadowImage(picture_image,80.0,2.0,quantum/3,quantum/3,
1799  exception);
1800  if (polaroid_image == (Image *) NULL)
1801  {
1802  picture_image=DestroyImage(picture_image);
1803  return(picture_image);
1804  }
1805  flop_image=FlopImage(polaroid_image,exception);
1806  polaroid_image=DestroyImage(polaroid_image);
1807  if (flop_image == (Image *) NULL)
1808  {
1809  picture_image=DestroyImage(picture_image);
1810  return(picture_image);
1811  }
1812  polaroid_image=flop_image;
1813  (void) CompositeImage(polaroid_image,picture_image,OverCompositeOp,
1814  MagickTrue,(ssize_t) (-0.01*picture_image->columns/2.0),0L,exception);
1815  picture_image=DestroyImage(picture_image);
1816  (void) QueryColorCompliance("none",AllCompliance,
1817  &polaroid_image->background_color,exception);
1818  rotate_image=RotateImage(polaroid_image,angle,exception);
1819  polaroid_image=DestroyImage(polaroid_image);
1820  if (rotate_image == (Image *) NULL)
1821  return((Image *) NULL);
1822  polaroid_image=rotate_image;
1823  trim_image=TrimImage(polaroid_image,exception);
1824  polaroid_image=DestroyImage(polaroid_image);
1825  if (trim_image == (Image *) NULL)
1826  return((Image *) NULL);
1827  polaroid_image=trim_image;
1828  return(polaroid_image);
1829 }
1830 
1831 /*
1832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1833 % %
1834 % %
1835 % %
1836 % S e p i a T o n e I m a g e %
1837 % %
1838 % %
1839 % %
1840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1841 %
1842 % MagickSepiaToneImage() applies a special effect to the image, similar to the
1843 % effect achieved in a photo darkroom by sepia toning. Threshold ranges from
1844 % 0 to QuantumRange and is a measure of the extent of the sepia toning. A
1845 % threshold of 80% is a good starting point for a reasonable tone.
1846 %
1847 % The format of the SepiaToneImage method is:
1848 %
1849 % Image *SepiaToneImage(const Image *image,const double threshold,
1850 % ExceptionInfo *exception)
1851 %
1852 % A description of each parameter follows:
1853 %
1854 % o image: the image.
1855 %
1856 % o threshold: the tone threshold.
1857 %
1858 % o exception: return any errors or warnings in this structure.
1859 %
1860 */
1861 MagickExport Image *SepiaToneImage(const Image *image,const double threshold,
1862  ExceptionInfo *exception)
1863 {
1864 #define SepiaToneImageTag "SepiaTone/Image"
1865 
1866  CacheView
1867  *image_view,
1868  *sepia_view;
1869 
1870  Image
1871  *sepia_image;
1872 
1874  status;
1875 
1877  progress;
1878 
1879  ssize_t
1880  y;
1881 
1882  /*
1883  Initialize sepia-toned image attributes.
1884  */
1885  assert(image != (const Image *) NULL);
1886  assert(image->signature == MagickCoreSignature);
1887  if (image->debug != MagickFalse)
1888  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1889  assert(exception != (ExceptionInfo *) NULL);
1890  assert(exception->signature == MagickCoreSignature);
1891  sepia_image=CloneImage(image,0,0,MagickTrue,exception);
1892  if (sepia_image == (Image *) NULL)
1893  return((Image *) NULL);
1894  if (SetImageStorageClass(sepia_image,DirectClass,exception) == MagickFalse)
1895  {
1896  sepia_image=DestroyImage(sepia_image);
1897  return((Image *) NULL);
1898  }
1899  /*
1900  Tone each row of the image.
1901  */
1902  status=MagickTrue;
1903  progress=0;
1904  image_view=AcquireVirtualCacheView(image,exception);
1905  sepia_view=AcquireAuthenticCacheView(sepia_image,exception);
1906 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1907  #pragma omp parallel for schedule(static) shared(progress,status) \
1908  magick_number_threads(image,sepia_image,image->rows,1)
1909 #endif
1910  for (y=0; y < (ssize_t) image->rows; y++)
1911  {
1912  register const Quantum
1913  *magick_restrict p;
1914 
1915  register ssize_t
1916  x;
1917 
1918  register Quantum
1919  *magick_restrict q;
1920 
1921  if (status == MagickFalse)
1922  continue;
1923  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1924  q=GetCacheViewAuthenticPixels(sepia_view,0,y,sepia_image->columns,1,
1925  exception);
1926  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1927  {
1928  status=MagickFalse;
1929  continue;
1930  }
1931  for (x=0; x < (ssize_t) image->columns; x++)
1932  {
1933  double
1934  intensity,
1935  tone;
1936 
1937  intensity=GetPixelIntensity(image,p);
1938  tone=intensity > threshold ? (double) QuantumRange : intensity+
1939  (double) QuantumRange-threshold;
1940  SetPixelRed(sepia_image,ClampToQuantum(tone),q);
1941  tone=intensity > (7.0*threshold/6.0) ? (double) QuantumRange :
1942  intensity+(double) QuantumRange-7.0*threshold/6.0;
1943  SetPixelGreen(sepia_image,ClampToQuantum(tone),q);
1944  tone=intensity < (threshold/6.0) ? 0 : intensity-threshold/6.0;
1945  SetPixelBlue(sepia_image,ClampToQuantum(tone),q);
1946  tone=threshold/7.0;
1947  if ((double) GetPixelGreen(image,q) < tone)
1948  SetPixelGreen(sepia_image,ClampToQuantum(tone),q);
1949  if ((double) GetPixelBlue(image,q) < tone)
1950  SetPixelBlue(sepia_image,ClampToQuantum(tone),q);
1951  SetPixelAlpha(sepia_image,GetPixelAlpha(image,p),q);
1952  p+=GetPixelChannels(image);
1953  q+=GetPixelChannels(sepia_image);
1954  }
1955  if (SyncCacheViewAuthenticPixels(sepia_view,exception) == MagickFalse)
1956  status=MagickFalse;
1957  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1958  {
1960  proceed;
1961 
1962 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1963  #pragma omp atomic
1964 #endif
1965  progress++;
1966  proceed=SetImageProgress(image,SepiaToneImageTag,progress,image->rows);
1967  if (proceed == MagickFalse)
1968  status=MagickFalse;
1969  }
1970  }
1971  sepia_view=DestroyCacheView(sepia_view);
1972  image_view=DestroyCacheView(image_view);
1973  (void) NormalizeImage(sepia_image,exception);
1974  (void) ContrastImage(sepia_image,MagickTrue,exception);
1975  if (status == MagickFalse)
1976  sepia_image=DestroyImage(sepia_image);
1977  return(sepia_image);
1978 }
1979 
1980 /*
1981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1982 % %
1983 % %
1984 % %
1985 % S h a d o w I m a g e %
1986 % %
1987 % %
1988 % %
1989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1990 %
1991 % ShadowImage() simulates a shadow from the specified image and returns it.
1992 %
1993 % The format of the ShadowImage method is:
1994 %
1995 % Image *ShadowImage(const Image *image,const double alpha,
1996 % const double sigma,const ssize_t x_offset,const ssize_t y_offset,
1997 % ExceptionInfo *exception)
1998 %
1999 % A description of each parameter follows:
2000 %
2001 % o image: the image.
2002 %
2003 % o alpha: percentage transparency.
2004 %
2005 % o sigma: the standard deviation of the Gaussian, in pixels.
2006 %
2007 % o x_offset: the shadow x-offset.
2008 %
2009 % o y_offset: the shadow y-offset.
2010 %
2011 % o exception: return any errors or warnings in this structure.
2012 %
2013 */
2014 MagickExport Image *ShadowImage(const Image *image,const double alpha,
2015  const double sigma,const ssize_t x_offset,const ssize_t y_offset,
2016  ExceptionInfo *exception)
2017 {
2018 #define ShadowImageTag "Shadow/Image"
2019 
2020  CacheView
2021  *image_view;
2022 
2023  ChannelType
2024  channel_mask;
2025 
2026  Image
2027  *border_image,
2028  *clone_image,
2029  *shadow_image;
2030 
2032  status;
2033 
2034  PixelInfo
2035  background_color;
2036 
2038  border_info;
2039 
2040  ssize_t
2041  y;
2042 
2043  assert(image != (Image *) NULL);
2044  assert(image->signature == MagickCoreSignature);
2045  if (image->debug != MagickFalse)
2046  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2047  assert(exception != (ExceptionInfo *) NULL);
2048  assert(exception->signature == MagickCoreSignature);
2049  clone_image=CloneImage(image,0,0,MagickTrue,exception);
2050  if (clone_image == (Image *) NULL)
2051  return((Image *) NULL);
2052  if (IsGrayColorspace(image->colorspace) != MagickFalse)
2053  (void) SetImageColorspace(clone_image,sRGBColorspace,exception);
2055  exception);
2056  border_info.width=(size_t) floor(2.0*sigma+0.5);
2057  border_info.height=(size_t) floor(2.0*sigma+0.5);
2058  border_info.x=0;
2059  border_info.y=0;
2060  (void) QueryColorCompliance("none",AllCompliance,&clone_image->border_color,
2061  exception);
2062  clone_image->alpha_trait=BlendPixelTrait;
2063  border_image=BorderImage(clone_image,&border_info,OverCompositeOp,exception);
2064  clone_image=DestroyImage(clone_image);
2065  if (border_image == (Image *) NULL)
2066  return((Image *) NULL);
2067  if (border_image->alpha_trait == UndefinedPixelTrait)
2068  (void) SetImageAlphaChannel(border_image,OpaqueAlphaChannel,exception);
2069  /*
2070  Shadow image.
2071  */
2072  status=MagickTrue;
2073  background_color=border_image->background_color;
2074  background_color.alpha_trait=BlendPixelTrait;
2075  image_view=AcquireAuthenticCacheView(border_image,exception);
2076  for (y=0; y < (ssize_t) border_image->rows; y++)
2077  {
2078  register Quantum
2079  *magick_restrict q;
2080 
2081  register ssize_t
2082  x;
2083 
2084  if (status == MagickFalse)
2085  continue;
2086  q=QueueCacheViewAuthenticPixels(image_view,0,y,border_image->columns,1,
2087  exception);
2088  if (q == (Quantum *) NULL)
2089  {
2090  status=MagickFalse;
2091  continue;
2092  }
2093  for (x=0; x < (ssize_t) border_image->columns; x++)
2094  {
2095  if (border_image->alpha_trait != UndefinedPixelTrait)
2096  background_color.alpha=GetPixelAlpha(border_image,q)*alpha/100.0;
2097  SetPixelViaPixelInfo(border_image,&background_color,q);
2098  q+=GetPixelChannels(border_image);
2099  }
2100  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2101  status=MagickFalse;
2102  }
2103  image_view=DestroyCacheView(image_view);
2104  if (status == MagickFalse)
2105  {
2106  border_image=DestroyImage(border_image);
2107  return((Image *) NULL);
2108  }
2109  channel_mask=SetImageChannelMask(border_image,AlphaChannel);
2110  shadow_image=BlurImage(border_image,0.0,sigma,exception);
2111  border_image=DestroyImage(border_image);
2112  if (shadow_image == (Image *) NULL)
2113  return((Image *) NULL);
2114  (void) SetPixelChannelMask(shadow_image,channel_mask);
2115  if (shadow_image->page.width == 0)
2116  shadow_image->page.width=shadow_image->columns;
2117  if (shadow_image->page.height == 0)
2118  shadow_image->page.height=shadow_image->rows;
2119  shadow_image->page.width+=x_offset-(ssize_t) border_info.width;
2120  shadow_image->page.height+=y_offset-(ssize_t) border_info.height;
2121  shadow_image->page.x+=x_offset-(ssize_t) border_info.width;
2122  shadow_image->page.y+=y_offset-(ssize_t) border_info.height;
2123  return(shadow_image);
2124 }
2125 
2126 /*
2127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2128 % %
2129 % %
2130 % %
2131 % S k e t c h I m a g e %
2132 % %
2133 % %
2134 % %
2135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2136 %
2137 % SketchImage() simulates a pencil sketch. We convolve the image with a
2138 % Gaussian operator of the given radius and standard deviation (sigma). For
2139 % reasonable results, radius should be larger than sigma. Use a radius of 0
2140 % and SketchImage() selects a suitable radius for you. Angle gives the angle
2141 % of the sketch.
2142 %
2143 % The format of the SketchImage method is:
2144 %
2145 % Image *SketchImage(const Image *image,const double radius,
2146 % const double sigma,const double angle,ExceptionInfo *exception)
2147 %
2148 % A description of each parameter follows:
2149 %
2150 % o image: the image.
2151 %
2152 % o radius: the radius of the Gaussian, in pixels, not counting the
2153 % center pixel.
2154 %
2155 % o sigma: the standard deviation of the Gaussian, in pixels.
2156 %
2157 % o angle: apply the effect along this angle.
2158 %
2159 % o exception: return any errors or warnings in this structure.
2160 %
2161 */
2162 MagickExport Image *SketchImage(const Image *image,const double radius,
2163  const double sigma,const double angle,ExceptionInfo *exception)
2164 {
2165  CacheView
2166  *random_view;
2167 
2168  Image
2169  *blend_image,
2170  *blur_image,
2171  *dodge_image,
2172  *random_image,
2173  *sketch_image;
2174 
2176  status;
2177 
2178  RandomInfo
2180 
2181  ssize_t
2182  y;
2183 
2184 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2185  unsigned long
2186  key;
2187 #endif
2188 
2189  /*
2190  Sketch image.
2191  */
2192  random_image=CloneImage(image,image->columns << 1,image->rows << 1,
2193  MagickTrue,exception);
2194  if (random_image == (Image *) NULL)
2195  return((Image *) NULL);
2196  status=MagickTrue;
2197  random_info=AcquireRandomInfoThreadSet();
2198  random_view=AcquireAuthenticCacheView(random_image,exception);
2199 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2200  key=GetRandomSecretKey(random_info[0]);
2201  #pragma omp parallel for schedule(static) shared(status) \
2202  magick_number_threads(random_image,random_image,random_image->rows,key == ~0UL)
2203 #endif
2204  for (y=0; y < (ssize_t) random_image->rows; y++)
2205  {
2206  const int
2207  id = GetOpenMPThreadId();
2208 
2209  register Quantum
2210  *magick_restrict q;
2211 
2212  register ssize_t
2213  x;
2214 
2215  if (status == MagickFalse)
2216  continue;
2217  q=QueueCacheViewAuthenticPixels(random_view,0,y,random_image->columns,1,
2218  exception);
2219  if (q == (Quantum *) NULL)
2220  {
2221  status=MagickFalse;
2222  continue;
2223  }
2224  for (x=0; x < (ssize_t) random_image->columns; x++)
2225  {
2226  double
2227  value;
2228 
2229  register ssize_t
2230  i;
2231 
2232  value=GetPseudoRandomValue(random_info[id]);
2233  for (i=0; i < (ssize_t) GetPixelChannels(random_image); i++)
2234  {
2235  PixelChannel channel = GetPixelChannelChannel(image,i);
2236  PixelTrait traits = GetPixelChannelTraits(image,channel);
2237  if (traits == UndefinedPixelTrait)
2238  continue;
2239  q[i]=ClampToQuantum(QuantumRange*value);
2240  }
2241  q+=GetPixelChannels(random_image);
2242  }
2243  if (SyncCacheViewAuthenticPixels(random_view,exception) == MagickFalse)
2244  status=MagickFalse;
2245  }
2246  random_view=DestroyCacheView(random_view);
2247  random_info=DestroyRandomInfoThreadSet(random_info);
2248  if (status == MagickFalse)
2249  {
2250  random_image=DestroyImage(random_image);
2251  return(random_image);
2252  }
2253  blur_image=MotionBlurImage(random_image,radius,sigma,angle,exception);
2254  random_image=DestroyImage(random_image);
2255  if (blur_image == (Image *) NULL)
2256  return((Image *) NULL);
2257  dodge_image=EdgeImage(blur_image,radius,exception);
2258  blur_image=DestroyImage(blur_image);
2259  if (dodge_image == (Image *) NULL)
2260  return((Image *) NULL);
2261  status=ClampImage(dodge_image,exception);
2262  if (status != MagickFalse)
2263  status=NormalizeImage(dodge_image,exception);
2264  if (status != MagickFalse)
2265  status=NegateImage(dodge_image,MagickFalse,exception);
2266  if (status != MagickFalse)
2267  status=TransformImage(&dodge_image,(char *) NULL,"50%",exception);
2268  sketch_image=CloneImage(image,0,0,MagickTrue,exception);
2269  if (sketch_image == (Image *) NULL)
2270  {
2271  dodge_image=DestroyImage(dodge_image);
2272  return((Image *) NULL);
2273  }
2274  (void) CompositeImage(sketch_image,dodge_image,ColorDodgeCompositeOp,
2275  MagickTrue,0,0,exception);
2276  dodge_image=DestroyImage(dodge_image);
2277  blend_image=CloneImage(image,0,0,MagickTrue,exception);
2278  if (blend_image == (Image *) NULL)
2279  {
2280  sketch_image=DestroyImage(sketch_image);
2281  return((Image *) NULL);
2282  }
2283  if (blend_image->alpha_trait != BlendPixelTrait)
2284  (void) SetImageAlpha(blend_image,TransparentAlpha,exception);
2285  (void) SetImageArtifact(blend_image,"compose:args","20x80");
2286  (void) CompositeImage(sketch_image,blend_image,BlendCompositeOp,MagickTrue,
2287  0,0,exception);
2288  blend_image=DestroyImage(blend_image);
2289  return(sketch_image);
2290 }
2291 
2292 /*
2293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2294 % %
2295 % %
2296 % %
2297 % S o l a r i z e I m a g e %
2298 % %
2299 % %
2300 % %
2301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2302 %
2303 % SolarizeImage() applies a special effect to the image, similar to the effect
2304 % achieved in a photo darkroom by selectively exposing areas of photo
2305 % sensitive paper to light. Threshold ranges from 0 to QuantumRange and is a
2306 % measure of the extent of the solarization.
2307 %
2308 % The format of the SolarizeImage method is:
2309 %
2310 % MagickBooleanType SolarizeImage(Image *image,const double threshold,
2311 % ExceptionInfo *exception)
2312 %
2313 % A description of each parameter follows:
2314 %
2315 % o image: the image.
2316 %
2317 % o threshold: Define the extent of the solarization.
2318 %
2319 % o exception: return any errors or warnings in this structure.
2320 %
2321 */
2323  const double threshold,ExceptionInfo *exception)
2324 {
2325 #define SolarizeImageTag "Solarize/Image"
2326 
2327  CacheView
2328  *image_view;
2329 
2331  status;
2332 
2334  progress;
2335 
2336  ssize_t
2337  y;
2338 
2339  assert(image != (Image *) NULL);
2340  assert(image->signature == MagickCoreSignature);
2341  if (image->debug != MagickFalse)
2342  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2343  if (IsGrayColorspace(image->colorspace) != MagickFalse)
2344  (void) SetImageColorspace(image,sRGBColorspace,exception);
2345  if (image->storage_class == PseudoClass)
2346  {
2347  register ssize_t
2348  i;
2349 
2350  /*
2351  Solarize colormap.
2352  */
2353  for (i=0; i < (ssize_t) image->colors; i++)
2354  {
2355  if ((double) image->colormap[i].red > threshold)
2356  image->colormap[i].red=QuantumRange-image->colormap[i].red;
2357  if ((double) image->colormap[i].green > threshold)
2358  image->colormap[i].green=QuantumRange-image->colormap[i].green;
2359  if ((double) image->colormap[i].blue > threshold)
2360  image->colormap[i].blue=QuantumRange-image->colormap[i].blue;
2361  }
2362  }
2363  /*
2364  Solarize image.
2365  */
2366  status=MagickTrue;
2367  progress=0;
2368  image_view=AcquireAuthenticCacheView(image,exception);
2369 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2370  #pragma omp parallel for schedule(static) shared(progress,status) \
2371  magick_number_threads(image,image,image->rows,1)
2372 #endif
2373  for (y=0; y < (ssize_t) image->rows; y++)
2374  {
2375  register ssize_t
2376  x;
2377 
2378  register Quantum
2379  *magick_restrict q;
2380 
2381  if (status == MagickFalse)
2382  continue;
2383  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2384  if (q == (Quantum *) NULL)
2385  {
2386  status=MagickFalse;
2387  continue;
2388  }
2389  for (x=0; x < (ssize_t) image->columns; x++)
2390  {
2391  register ssize_t
2392  i;
2393 
2394  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2395  {
2396  PixelChannel channel = GetPixelChannelChannel(image,i);
2397  PixelTrait traits = GetPixelChannelTraits(image,channel);
2398  if ((traits & UpdatePixelTrait) == 0)
2399  continue;
2400  if ((double) q[i] > threshold)
2401  q[i]=QuantumRange-q[i];
2402  }
2403  q+=GetPixelChannels(image);
2404  }
2405  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2406  status=MagickFalse;
2407  if (image->progress_monitor != (MagickProgressMonitor) NULL)
2408  {
2410  proceed;
2411 
2412 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2413  #pragma omp atomic
2414 #endif
2415  progress++;
2416  proceed=SetImageProgress(image,SolarizeImageTag,progress,image->rows);
2417  if (proceed == MagickFalse)
2418  status=MagickFalse;
2419  }
2420  }
2421  image_view=DestroyCacheView(image_view);
2422  return(status);
2423 }
2424 
2425 /*
2426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2427 % %
2428 % %
2429 % %
2430 % S t e g a n o I m a g e %
2431 % %
2432 % %
2433 % %
2434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2435 %
2436 % SteganoImage() hides a digital watermark within the image. Recover
2437 % the hidden watermark later to prove that the authenticity of an image.
2438 % Offset defines the start position within the image to hide the watermark.
2439 %
2440 % The format of the SteganoImage method is:
2441 %
2442 % Image *SteganoImage(const Image *image,Image *watermark,
2443 % ExceptionInfo *exception)
2444 %
2445 % A description of each parameter follows:
2446 %
2447 % o image: the image.
2448 %
2449 % o watermark: the watermark image.
2450 %
2451 % o exception: return any errors or warnings in this structure.
2452 %
2453 */
2454 MagickExport Image *SteganoImage(const Image *image,const Image *watermark,
2455  ExceptionInfo *exception)
2456 {
2457 #define GetBit(alpha,i) ((((size_t) (alpha) >> (size_t) (i)) & 0x01) != 0)
2458 #define SetBit(alpha,i,set) (Quantum) ((set) != 0 ? (size_t) (alpha) \
2459  | (one << (size_t) (i)) : (size_t) (alpha) & ~(one << (size_t) (i)))
2460 #define SteganoImageTag "Stegano/Image"
2461 
2462  CacheView
2463  *stegano_view,
2464  *watermark_view;
2465 
2466  Image
2467  *stegano_image;
2468 
2469  int
2470  c;
2471 
2473  status;
2474 
2475  PixelInfo
2476  pixel;
2477 
2478  register Quantum
2479  *q;
2480 
2481  register ssize_t
2482  x;
2483 
2484  size_t
2485  depth,
2486  one;
2487 
2488  ssize_t
2489  i,
2490  j,
2491  k,
2492  y;
2493 
2494  /*
2495  Initialize steganographic image attributes.
2496  */
2497  assert(image != (const Image *) NULL);
2498  assert(image->signature == MagickCoreSignature);
2499  if (image->debug != MagickFalse)
2500  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2501  assert(watermark != (const Image *) NULL);
2502  assert(watermark->signature == MagickCoreSignature);
2503  assert(exception != (ExceptionInfo *) NULL);
2504  assert(exception->signature == MagickCoreSignature);
2505  one=1UL;
2506  stegano_image=CloneImage(image,0,0,MagickTrue,exception);
2507  if (stegano_image == (Image *) NULL)
2508  return((Image *) NULL);
2509  stegano_image->depth=MAGICKCORE_QUANTUM_DEPTH;
2510  if (SetImageStorageClass(stegano_image,DirectClass,exception) == MagickFalse)
2511  {
2512  stegano_image=DestroyImage(stegano_image);
2513  return((Image *) NULL);
2514  }
2515  /*
2516  Hide watermark in low-order bits of image.
2517  */
2518  c=0;
2519  i=0;
2520  j=0;
2521  depth=stegano_image->depth;
2522  k=stegano_image->offset;
2523  status=MagickTrue;
2524  watermark_view=AcquireVirtualCacheView(watermark,exception);
2525  stegano_view=AcquireAuthenticCacheView(stegano_image,exception);
2526  for (i=(ssize_t) depth-1; (i >= 0) && (j < (ssize_t) depth); i--)
2527  {
2528  for (y=0; (y < (ssize_t) watermark->rows) && (j < (ssize_t) depth); y++)
2529  {
2530  for (x=0; (x < (ssize_t) watermark->columns) && (j < (ssize_t) depth); x++)
2531  {
2532  ssize_t
2533  offset;
2534 
2535  (void) GetOneCacheViewVirtualPixelInfo(watermark_view,x,y,&pixel,
2536  exception);
2537  offset=k/(ssize_t) stegano_image->columns;
2538  if (offset >= (ssize_t) stegano_image->rows)
2539  break;
2540  q=GetCacheViewAuthenticPixels(stegano_view,k % (ssize_t)
2541  stegano_image->columns,k/(ssize_t) stegano_image->columns,1,1,
2542  exception);
2543  if (q == (Quantum *) NULL)
2544  break;
2545  switch (c)
2546  {
2547  case 0:
2548  {
2549  SetPixelRed(stegano_image,SetBit(GetPixelRed(stegano_image,q),j,
2550  GetBit(GetPixelInfoIntensity(stegano_image,&pixel),i)),q);
2551  break;
2552  }
2553  case 1:
2554  {
2555  SetPixelGreen(stegano_image,SetBit(GetPixelGreen(stegano_image,q),j,
2556  GetBit(GetPixelInfoIntensity(stegano_image,&pixel),i)),q);
2557  break;
2558  }
2559  case 2:
2560  {
2561  SetPixelBlue(stegano_image,SetBit(GetPixelBlue(stegano_image,q),j,
2562  GetBit(GetPixelInfoIntensity(stegano_image,&pixel),i)),q);
2563  break;
2564  }
2565  }
2566  if (SyncCacheViewAuthenticPixels(stegano_view,exception) == MagickFalse)
2567  break;
2568  c++;
2569  if (c == 3)
2570  c=0;
2571  k++;
2572  if (k == (ssize_t) (stegano_image->columns*stegano_image->columns))
2573  k=0;
2574  if (k == stegano_image->offset)
2575  j++;
2576  }
2577  }
2578  if (image->progress_monitor != (MagickProgressMonitor) NULL)
2579  {
2581  proceed;
2582 
2584  (depth-i),depth);
2585  if (proceed == MagickFalse)
2586  status=MagickFalse;
2587  }
2588  }
2589  stegano_view=DestroyCacheView(stegano_view);
2590  watermark_view=DestroyCacheView(watermark_view);
2591  if (status == MagickFalse)
2592  stegano_image=DestroyImage(stegano_image);
2593  return(stegano_image);
2594 }
2595 
2596 /*
2597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2598 % %
2599 % %
2600 % %
2601 % S t e r e o A n a g l y p h I m a g e %
2602 % %
2603 % %
2604 % %
2605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2606 %
2607 % StereoAnaglyphImage() combines two images and produces a single image that
2608 % is the composite of a left and right image of a stereo pair. Special
2609 % red-green stereo glasses are required to view this effect.
2610 %
2611 % The format of the StereoAnaglyphImage method is:
2612 %
2613 % Image *StereoImage(const Image *left_image,const Image *right_image,
2614 % ExceptionInfo *exception)
2615 % Image *StereoAnaglyphImage(const Image *left_image,
2616 % const Image *right_image,const ssize_t x_offset,const ssize_t y_offset,
2617 % ExceptionInfo *exception)
2618 %
2619 % A description of each parameter follows:
2620 %
2621 % o left_image: the left image.
2622 %
2623 % o right_image: the right image.
2624 %
2625 % o exception: return any errors or warnings in this structure.
2626 %
2627 % o x_offset: amount, in pixels, by which the left image is offset to the
2628 % right of the right image.
2629 %
2630 % o y_offset: amount, in pixels, by which the left image is offset to the
2631 % bottom of the right image.
2632 %
2633 %
2634 */
2636  const Image *right_image,ExceptionInfo *exception)
2637 {
2638  return(StereoAnaglyphImage(left_image,right_image,0,0,exception));
2639 }
2640 
2642  const Image *right_image,const ssize_t x_offset,const ssize_t y_offset,
2643  ExceptionInfo *exception)
2644 {
2645 #define StereoImageTag "Stereo/Image"
2646 
2647  const Image
2648  *image;
2649 
2650  Image
2651  *stereo_image;
2652 
2654  status;
2655 
2656  ssize_t
2657  y;
2658 
2659  assert(left_image != (const Image *) NULL);
2660  assert(left_image->signature == MagickCoreSignature);
2661  if (left_image->debug != MagickFalse)
2663  left_image->filename);
2664  assert(right_image != (const Image *) NULL);
2665  assert(right_image->signature == MagickCoreSignature);
2666  assert(exception != (ExceptionInfo *) NULL);
2667  assert(exception->signature == MagickCoreSignature);
2668  image=left_image;
2669  if ((left_image->columns != right_image->columns) ||
2670  (left_image->rows != right_image->rows))
2671  ThrowImageException(ImageError,"LeftAndRightImageSizesDiffer");
2672  /*
2673  Initialize stereo image attributes.
2674  */
2675  stereo_image=CloneImage(left_image,left_image->columns,left_image->rows,
2676  MagickTrue,exception);
2677  if (stereo_image == (Image *) NULL)
2678  return((Image *) NULL);
2679  if (SetImageStorageClass(stereo_image,DirectClass,exception) == MagickFalse)
2680  {
2681  stereo_image=DestroyImage(stereo_image);
2682  return((Image *) NULL);
2683  }
2684  (void) SetImageColorspace(stereo_image,sRGBColorspace,exception);
2685  /*
2686  Copy left image to red channel and right image to blue channel.
2687  */
2688  status=MagickTrue;
2689  for (y=0; y < (ssize_t) stereo_image->rows; y++)
2690  {
2691  register const Quantum
2692  *magick_restrict p,
2693  *magick_restrict q;
2694 
2695  register ssize_t
2696  x;
2697 
2698  register Quantum
2699  *magick_restrict r;
2700 
2701  p=GetVirtualPixels(left_image,-x_offset,y-y_offset,image->columns,1,
2702  exception);
2703  q=GetVirtualPixels(right_image,0,y,right_image->columns,1,exception);
2704  r=QueueAuthenticPixels(stereo_image,0,y,stereo_image->columns,1,exception);
2705  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL) ||
2706  (r == (Quantum *) NULL))
2707  break;
2708  for (x=0; x < (ssize_t) stereo_image->columns; x++)
2709  {
2710  SetPixelRed(stereo_image,GetPixelRed(left_image,p),r);
2711  SetPixelGreen(stereo_image,GetPixelGreen(right_image,q),r);
2712  SetPixelBlue(stereo_image,GetPixelBlue(right_image,q),r);
2713  if ((GetPixelAlphaTraits(stereo_image) & CopyPixelTrait) != 0)
2714  SetPixelAlpha(stereo_image,(GetPixelAlpha(left_image,p)+
2715  GetPixelAlpha(right_image,q))/2,r);
2716  p+=GetPixelChannels(left_image);
2717  q+=GetPixelChannels(right_image);
2718  r+=GetPixelChannels(stereo_image);
2719  }
2720  if (SyncAuthenticPixels(stereo_image,exception) == MagickFalse)
2721  break;
2722  if (image->progress_monitor != (MagickProgressMonitor) NULL)
2723  {
2725  proceed;
2726 
2728  stereo_image->rows);
2729  if (proceed == MagickFalse)
2730  status=MagickFalse;
2731  }
2732  }
2733  if (status == MagickFalse)
2734  stereo_image=DestroyImage(stereo_image);
2735  return(stereo_image);
2736 }
2737 
2738 /*
2739 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2740 % %
2741 % %
2742 % %
2743 % S w i r l I m a g e %
2744 % %
2745 % %
2746 % %
2747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2748 %
2749 % SwirlImage() swirls the pixels about the center of the image, where
2750 % degrees indicates the sweep of the arc through which each pixel is moved.
2751 % You get a more dramatic effect as the degrees move from 1 to 360.
2752 %
2753 % The format of the SwirlImage method is:
2754 %
2755 % Image *SwirlImage(const Image *image,double degrees,
2756 % const PixelInterpolateMethod method,ExceptionInfo *exception)
2757 %
2758 % A description of each parameter follows:
2759 %
2760 % o image: the image.
2761 %
2762 % o degrees: Define the tightness of the swirling effect.
2763 %
2764 % o method: the pixel interpolation method.
2765 %
2766 % o exception: return any errors or warnings in this structure.
2767 %
2768 */
2769 MagickExport Image *SwirlImage(const Image *image,double degrees,
2770  const PixelInterpolateMethod method,ExceptionInfo *exception)
2771 {
2772 #define SwirlImageTag "Swirl/Image"
2773 
2774  CacheView
2775  *canvas_view,
2776  *interpolate_view,
2777  *swirl_view;
2778 
2779  double
2780  radius;
2781 
2782  Image
2783  *canvas_image,
2784  *swirl_image;
2785 
2787  status;
2788 
2790  progress;
2791 
2792  PointInfo
2793  center,
2794  scale;
2795 
2796  ssize_t
2797  y;
2798 
2799  /*
2800  Initialize swirl image attributes.
2801  */
2802  assert(image != (const Image *) NULL);
2803  assert(image->signature == MagickCoreSignature);
2804  if (image->debug != MagickFalse)
2805  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2806  assert(exception != (ExceptionInfo *) NULL);
2807  assert(exception->signature == MagickCoreSignature);
2808  canvas_image=CloneImage(image,0,0,MagickTrue,exception);
2809  if (canvas_image == (Image *) NULL)
2810  return((Image *) NULL);
2811  swirl_image=CloneImage(canvas_image,0,0,MagickTrue,exception);
2812  if (swirl_image == (Image *) NULL)
2813  {
2814  canvas_image=DestroyImage(canvas_image);
2815  return((Image *) NULL);
2816  }
2817  if (SetImageStorageClass(swirl_image,DirectClass,exception) == MagickFalse)
2818  {
2819  canvas_image=DestroyImage(canvas_image);
2820  swirl_image=DestroyImage(swirl_image);
2821  return((Image *) NULL);
2822  }
2823  if (swirl_image->background_color.alpha_trait != UndefinedPixelTrait)
2824  (void) SetImageAlphaChannel(swirl_image,OnAlphaChannel,exception);
2825  /*
2826  Compute scaling factor.
2827  */
2828  center.x=(double) canvas_image->columns/2.0;
2829  center.y=(double) canvas_image->rows/2.0;
2830  radius=MagickMax(center.x,center.y);
2831  scale.x=1.0;
2832  scale.y=1.0;
2833  if (canvas_image->columns > canvas_image->rows)
2834  scale.y=(double) canvas_image->columns/(double) canvas_image->rows;
2835  else
2836  if (canvas_image->columns < canvas_image->rows)
2837  scale.x=(double) canvas_image->rows/(double) canvas_image->columns;
2838  degrees=(double) DegreesToRadians(degrees);
2839  /*
2840  Swirl image.
2841  */
2842  status=MagickTrue;
2843  progress=0;
2844  canvas_view=AcquireVirtualCacheView(canvas_image,exception);
2845  interpolate_view=AcquireVirtualCacheView(image,exception);
2846  swirl_view=AcquireAuthenticCacheView(swirl_image,exception);
2847 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2848  #pragma omp parallel for schedule(static) shared(progress,status) \
2849  magick_number_threads(canvas_image,swirl_image,canvas_image->rows,1)
2850 #endif
2851  for (y=0; y < (ssize_t) canvas_image->rows; y++)
2852  {
2853  double
2854  distance;
2855 
2856  PointInfo
2857  delta;
2858 
2859  register const Quantum
2860  *magick_restrict p;
2861 
2862  register ssize_t
2863  x;
2864 
2865  register Quantum
2866  *magick_restrict q;
2867 
2868  if (status == MagickFalse)
2869  continue;
2870  p=GetCacheViewVirtualPixels(canvas_view,0,y,canvas_image->columns,1,
2871  exception);
2872  q=QueueCacheViewAuthenticPixels(swirl_view,0,y,swirl_image->columns,1,
2873  exception);
2874  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
2875  {
2876  status=MagickFalse;
2877  continue;
2878  }
2879  delta.y=scale.y*(double) (y-center.y);
2880  for (x=0; x < (ssize_t) canvas_image->columns; x++)
2881  {
2882  /*
2883  Determine if the pixel is within an ellipse.
2884  */
2885  delta.x=scale.x*(double) (x-center.x);
2886  distance=delta.x*delta.x+delta.y*delta.y;
2887  if (distance >= (radius*radius))
2888  {
2889  register ssize_t
2890  i;
2891 
2892  for (i=0; i < (ssize_t) GetPixelChannels(canvas_image); i++)
2893  {
2894  PixelChannel channel = GetPixelChannelChannel(canvas_image,i);
2895  PixelTrait traits = GetPixelChannelTraits(canvas_image,channel);
2896  PixelTrait swirl_traits = GetPixelChannelTraits(swirl_image,
2897  channel);
2898  if ((traits == UndefinedPixelTrait) ||
2899  (swirl_traits == UndefinedPixelTrait))
2900  continue;
2901  SetPixelChannel(swirl_image,channel,p[i],q);
2902  }
2903  }
2904  else
2905  {
2906  double
2907  cosine,
2908  factor,
2909  sine;
2910 
2911  /*
2912  Swirl the pixel.
2913  */
2914  factor=1.0-sqrt((double) distance)/radius;
2915  sine=sin((double) (degrees*factor*factor));
2916  cosine=cos((double) (degrees*factor*factor));
2917  status=InterpolatePixelChannels(canvas_image,interpolate_view,
2918  swirl_image,method,((cosine*delta.x-sine*delta.y)/scale.x+center.x),
2919  (double) ((sine*delta.x+cosine*delta.y)/scale.y+center.y),q,
2920  exception);
2921  if (status == MagickFalse)
2922  break;
2923  }
2924  p+=GetPixelChannels(canvas_image);
2925  q+=GetPixelChannels(swirl_image);
2926  }
2927  if (SyncCacheViewAuthenticPixels(swirl_view,exception) == MagickFalse)
2928  status=MagickFalse;
2929  if (canvas_image->progress_monitor != (MagickProgressMonitor) NULL)
2930  {
2932  proceed;
2933 
2934 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2935  #pragma omp atomic
2936 #endif
2937  progress++;
2938  proceed=SetImageProgress(canvas_image,SwirlImageTag,progress,
2939  canvas_image->rows);
2940  if (proceed == MagickFalse)
2941  status=MagickFalse;
2942  }
2943  }
2944  swirl_view=DestroyCacheView(swirl_view);
2945  interpolate_view=DestroyCacheView(interpolate_view);
2946  canvas_view=DestroyCacheView(canvas_view);
2947  canvas_image=DestroyImage(canvas_image);
2948  if (status == MagickFalse)
2949  swirl_image=DestroyImage(swirl_image);
2950  return(swirl_image);
2951 }
2952 
2953 /*
2954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2955 % %
2956 % %
2957 % %
2958 % T i n t I m a g e %
2959 % %
2960 % %
2961 % %
2962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2963 %
2964 % TintImage() applies a color vector to each pixel in the image. The length
2965 % of the vector is 0 for black and white and at its maximum for the midtones.
2966 % The vector weighting function is f(x)=(1-(4.0*((x-0.5)*(x-0.5))))
2967 %
2968 % The format of the TintImage method is:
2969 %
2970 % Image *TintImage(const Image *image,const char *blend,
2971 % const PixelInfo *tint,ExceptionInfo *exception)
2972 %
2973 % A description of each parameter follows:
2974 %
2975 % o image: the image.
2976 %
2977 % o blend: A color value used for tinting.
2978 %
2979 % o tint: A color value used for tinting.
2980 %
2981 % o exception: return any errors or warnings in this structure.
2982 %
2983 */
2984 MagickExport Image *TintImage(const Image *image,const char *blend,
2985  const PixelInfo *tint,ExceptionInfo *exception)
2986 {
2987 #define TintImageTag "Tint/Image"
2988 
2989  CacheView
2990  *image_view,
2991  *tint_view;
2992 
2993  double
2994  intensity;
2995 
2996  GeometryInfo
2997  geometry_info;
2998 
2999  Image
3000  *tint_image;
3001 
3003  status;
3004 
3006  progress;
3007 
3008  PixelInfo
3009  color_vector;
3010 
3012  flags;
3013 
3014  ssize_t
3015  y;
3016 
3017  /*
3018  Allocate tint image.
3019  */
3020  assert(image != (const Image *) NULL);
3021  assert(image->signature == MagickCoreSignature);
3022  if (image->debug != MagickFalse)
3023  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3024  assert(exception != (ExceptionInfo *) NULL);
3025  assert(exception->signature == MagickCoreSignature);
3026  tint_image=CloneImage(image,0,0,MagickTrue,exception);
3027  if (tint_image == (Image *) NULL)
3028  return((Image *) NULL);
3029  if (SetImageStorageClass(tint_image,DirectClass,exception) == MagickFalse)
3030  {
3031  tint_image=DestroyImage(tint_image);
3032  return((Image *) NULL);
3033  }
3034  if ((IsGrayColorspace(image->colorspace) != MagickFalse) &&
3035  (IsPixelInfoGray(tint) == MagickFalse))
3036  (void) SetImageColorspace(tint_image,sRGBColorspace,exception);
3037  if (blend == (const char *) NULL)
3038  return(tint_image);
3039  /*
3040  Determine RGB values of the color.
3041  */
3042  GetPixelInfo(image,&color_vector);
3043  flags=ParseGeometry(blend,&geometry_info);
3044  color_vector.red=geometry_info.rho;
3045  color_vector.green=geometry_info.rho;
3046  color_vector.blue=geometry_info.rho;
3047  color_vector.alpha=(MagickRealType) OpaqueAlpha;
3048  if ((flags & SigmaValue) != 0)
3049  color_vector.green=geometry_info.sigma;
3050  if ((flags & XiValue) != 0)
3051  color_vector.blue=geometry_info.xi;
3052  if ((flags & PsiValue) != 0)
3053  color_vector.alpha=geometry_info.psi;
3054  if (image->colorspace == CMYKColorspace)
3055  {
3056  color_vector.black=geometry_info.rho;
3057  if ((flags & PsiValue) != 0)
3058  color_vector.black=geometry_info.psi;
3059  if ((flags & ChiValue) != 0)
3060  color_vector.alpha=geometry_info.chi;
3061  }
3062  intensity=(double) GetPixelInfoIntensity((const Image *) NULL,tint);
3063  color_vector.red=(double) (color_vector.red*tint->red/100.0-intensity);
3064  color_vector.green=(double) (color_vector.green*tint->green/100.0-intensity);
3065  color_vector.blue=(double) (color_vector.blue*tint->blue/100.0-intensity);
3066  color_vector.black=(double) (color_vector.black*tint->black/100.0-intensity);
3067  color_vector.alpha=(double) (color_vector.alpha*tint->alpha/100.0-intensity);
3068  /*
3069  Tint image.
3070  */
3071  status=MagickTrue;
3072  progress=0;
3073  image_view=AcquireVirtualCacheView(image,exception);
3074  tint_view=AcquireAuthenticCacheView(tint_image,exception);
3075 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3076  #pragma omp parallel for schedule(static) shared(progress,status) \
3077  magick_number_threads(image,tint_image,image->rows,1)
3078 #endif
3079  for (y=0; y < (ssize_t) image->rows; y++)
3080  {
3081  register const Quantum
3082  *magick_restrict p;
3083 
3084  register Quantum
3085  *magick_restrict q;
3086 
3087  register ssize_t
3088  x;
3089 
3090  if (status == MagickFalse)
3091  continue;
3092  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
3093  q=QueueCacheViewAuthenticPixels(tint_view,0,y,tint_image->columns,1,
3094  exception);
3095  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
3096  {
3097  status=MagickFalse;
3098  continue;
3099  }
3100  for (x=0; x < (ssize_t) image->columns; x++)
3101  {
3102  PixelInfo
3103  pixel;
3104 
3105  double
3106  weight;
3107 
3108  GetPixelInfo(image,&pixel);
3109  weight=QuantumScale*GetPixelRed(image,p)-0.5;
3110  pixel.red=(MagickRealType) GetPixelRed(image,p)+color_vector.red*
3111  (1.0-(4.0*(weight*weight)));
3112  weight=QuantumScale*GetPixelGreen(image,p)-0.5;
3113  pixel.green=(MagickRealType) GetPixelGreen(image,p)+color_vector.green*
3114  (1.0-(4.0*(weight*weight)));
3115  weight=QuantumScale*GetPixelBlue(image,p)-0.5;
3116  pixel.blue=(MagickRealType) GetPixelBlue(image,p)+color_vector.blue*
3117  (1.0-(4.0*(weight*weight)));
3118  weight=QuantumScale*GetPixelBlack(image,p)-0.5;
3119  pixel.black=(MagickRealType) GetPixelBlack(image,p)+color_vector.black*
3120  (1.0-(4.0*(weight*weight)));
3121  pixel.alpha=(MagickRealType) GetPixelAlpha(image,p);
3122  SetPixelViaPixelInfo(tint_image,&pixel,q);
3123  p+=GetPixelChannels(image);
3124  q+=GetPixelChannels(tint_image);
3125  }
3126  if (SyncCacheViewAuthenticPixels(tint_view,exception) == MagickFalse)
3127  status=MagickFalse;
3128  if (image->progress_monitor != (MagickProgressMonitor) NULL)
3129  {
3131  proceed;
3132 
3133 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3134  #pragma omp atomic
3135 #endif
3136  progress++;
3137  proceed=SetImageProgress(image,TintImageTag,progress,image->rows);
3138  if (proceed == MagickFalse)
3139  status=MagickFalse;
3140  }
3141  }
3142  tint_view=DestroyCacheView(tint_view);
3143  image_view=DestroyCacheView(image_view);
3144  if (status == MagickFalse)
3145  tint_image=DestroyImage(tint_image);
3146  return(tint_image);
3147 }
3148 
3149 /*
3150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3151 % %
3152 % %
3153 % %
3154 % V i g n e t t e I m a g e %
3155 % %
3156 % %
3157 % %
3158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3159 %
3160 % VignetteImage() softens the edges of the image in vignette style.
3161 %
3162 % The format of the VignetteImage method is:
3163 %
3164 % Image *VignetteImage(const Image *image,const double radius,
3165 % const double sigma,const ssize_t x,const ssize_t y,
3166 % ExceptionInfo *exception)
3167 %
3168 % A description of each parameter follows:
3169 %
3170 % o image: the image.
3171 %
3172 % o radius: the radius of the pixel neighborhood.
3173 %
3174 % o sigma: the standard deviation of the Gaussian, in pixels.
3175 %
3176 % o x, y: Define the x and y ellipse offset.
3177 %
3178 % o exception: return any errors or warnings in this structure.
3179 %
3180 */
3181 MagickExport Image *VignetteImage(const Image *image,const double radius,
3182  const double sigma,const ssize_t x,const ssize_t y,ExceptionInfo *exception)
3183 {
3184  char
3185  ellipse[MagickPathExtent];
3186 
3187  DrawInfo
3188  *draw_info;
3189 
3190  Image
3191  *canvas,
3192  *blur_image,
3193  *oval_image,
3194  *vignette_image;
3195 
3196  assert(image != (Image *) NULL);
3197  assert(image->signature == MagickCoreSignature);
3198  if (image->debug != MagickFalse)
3199  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3200  assert(exception != (ExceptionInfo *) NULL);
3201  assert(exception->signature == MagickCoreSignature);
3202  canvas=CloneImage(image,0,0,MagickTrue,exception);
3203  if (canvas == (Image *) NULL)
3204  return((Image *) NULL);
3205  if (SetImageStorageClass(canvas,DirectClass,exception) == MagickFalse)
3206  {
3207  canvas=DestroyImage(canvas);
3208  return((Image *) NULL);
3209  }
3210  canvas->alpha_trait=BlendPixelTrait;
3211  oval_image=CloneImage(canvas,canvas->columns,canvas->rows,MagickTrue,
3212  exception);
3213  if (oval_image == (Image *) NULL)
3214  {
3215  canvas=DestroyImage(canvas);
3216  return((Image *) NULL);
3217  }
3218  (void) QueryColorCompliance("#000000",AllCompliance,
3219  &oval_image->background_color,exception);
3220  (void) SetImageBackgroundColor(oval_image,exception);
3221  draw_info=CloneDrawInfo((const ImageInfo *) NULL,(const DrawInfo *) NULL);
3222  (void) QueryColorCompliance("#ffffff",AllCompliance,&draw_info->fill,
3223  exception);
3224  (void) QueryColorCompliance("#ffffff",AllCompliance,&draw_info->stroke,
3225  exception);
3226  (void) FormatLocaleString(ellipse,MagickPathExtent,"ellipse %g,%g,%g,%g,"
3227  "0.0,360.0",image->columns/2.0,image->rows/2.0,image->columns/2.0-x,
3228  image->rows/2.0-y);
3229  draw_info->primitive=AcquireString(ellipse);
3230  (void) DrawImage(oval_image,draw_info,exception);
3231  draw_info=DestroyDrawInfo(draw_info);
3232  blur_image=BlurImage(oval_image,radius,sigma,exception);
3233  oval_image=DestroyImage(oval_image);
3234  if (blur_image == (Image *) NULL)
3235  {
3236  canvas=DestroyImage(canvas);
3237  return((Image *) NULL);
3238  }
3239  blur_image->alpha_trait=UndefinedPixelTrait;
3240  (void) CompositeImage(canvas,blur_image,IntensityCompositeOp,MagickTrue,
3241  0,0,exception);
3242  blur_image=DestroyImage(blur_image);
3243  vignette_image=MergeImageLayers(canvas,FlattenLayer,exception);
3244  canvas=DestroyImage(canvas);
3245  if (vignette_image != (Image *) NULL)
3246  (void) TransformImageColorspace(vignette_image,image->colorspace,exception);
3247  return(vignette_image);
3248 }
3249 
3250 /*
3251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3252 % %
3253 % %
3254 % %
3255 % W a v e I m a g e %
3256 % %
3257 % %
3258 % %
3259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3260 %
3261 % WaveImage() creates a "ripple" effect in the image by shifting the pixels
3262 % vertically along a sine wave whose amplitude and wavelength is specified
3263 % by the given parameters.
3264 %
3265 % The format of the WaveImage method is:
3266 %
3267 % Image *WaveImage(const Image *image,const double amplitude,
3268 % const double wave_length,const PixelInterpolateMethod method,
3269 % ExceptionInfo *exception)
3270 %
3271 % A description of each parameter follows:
3272 %
3273 % o image: the image.
3274 %
3275 % o amplitude, wave_length: Define the amplitude and wave length of the
3276 % sine wave.
3277 %
3278 % o interpolate: the pixel interpolation method.
3279 %
3280 % o exception: return any errors or warnings in this structure.
3281 %
3282 */
3283 MagickExport Image *WaveImage(const Image *image,const double amplitude,
3284  const double wave_length,const PixelInterpolateMethod method,
3285  ExceptionInfo *exception)
3286 {
3287 #define WaveImageTag "Wave/Image"
3288 
3289  CacheView
3290  *canvas_image_view,
3291  *wave_view;
3292 
3293  float
3294  *sine_map;
3295 
3296  Image
3297  *canvas_image,
3298  *wave_image;
3299 
3301  status;
3302 
3304  progress;
3305 
3306  register ssize_t
3307  i;
3308 
3309  ssize_t
3310  y;
3311 
3312  /*
3313  Initialize wave image attributes.
3314  */
3315  assert(image != (Image *) NULL);
3316  assert(image->signature == MagickCoreSignature);
3317  if (image->debug != MagickFalse)
3318  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3319  assert(exception != (ExceptionInfo *) NULL);
3320  assert(exception->signature == MagickCoreSignature);
3321  canvas_image=CloneImage(image,0,0,MagickTrue,exception);
3322  if (canvas_image == (Image *) NULL)
3323  return((Image *) NULL);
3324  if ((canvas_image->alpha_trait == UndefinedPixelTrait) &&
3325  (canvas_image->background_color.alpha != OpaqueAlpha))
3326  (void) SetImageAlpha(canvas_image,OpaqueAlpha,exception);
3327  wave_image=CloneImage(canvas_image,canvas_image->columns,(size_t)
3328  (canvas_image->rows+2.0*fabs(amplitude)),MagickTrue,exception);
3329  if (wave_image == (Image *) NULL)
3330  {
3331  canvas_image=DestroyImage(canvas_image);
3332  return((Image *) NULL);
3333  }
3334  if (SetImageStorageClass(wave_image,DirectClass,exception) == MagickFalse)
3335  {
3336  canvas_image=DestroyImage(canvas_image);
3337  wave_image=DestroyImage(wave_image);
3338  return((Image *) NULL);
3339  }
3340  /*
3341  Allocate sine map.
3342  */
3343  sine_map=(float *) AcquireQuantumMemory((size_t) wave_image->columns,
3344  sizeof(*sine_map));
3345  if (sine_map == (float *) NULL)
3346  {
3347  canvas_image=DestroyImage(canvas_image);
3348  wave_image=DestroyImage(wave_image);
3349  ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
3350  }
3351  for (i=0; i < (ssize_t) wave_image->columns; i++)
3352  sine_map[i]=(float) fabs(amplitude)+amplitude*sin((double)
3353  ((2.0*MagickPI*i)/wave_length));
3354  /*
3355  Wave image.
3356  */
3357  status=MagickTrue;
3358  progress=0;
3359  canvas_image_view=AcquireVirtualCacheView(canvas_image,exception);
3360  wave_view=AcquireAuthenticCacheView(wave_image,exception);
3361  (void) SetCacheViewVirtualPixelMethod(canvas_image_view,
3363 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3364  #pragma omp parallel for schedule(static) shared(progress,status) \
3365  magick_number_threads(canvas_image,wave_image,wave_image->rows,1)
3366 #endif
3367  for (y=0; y < (ssize_t) wave_image->rows; y++)
3368  {
3369  register const Quantum
3370  *magick_restrict p;
3371 
3372  register Quantum
3373  *magick_restrict q;
3374 
3375  register ssize_t
3376  x;
3377 
3378  if (status == MagickFalse)
3379  continue;
3380  p=GetCacheViewVirtualPixels(canvas_image_view,0,y,canvas_image->columns,1,
3381  exception);
3382  q=QueueCacheViewAuthenticPixels(wave_view,0,y,wave_image->columns,1,
3383  exception);
3384  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
3385  {
3386  status=MagickFalse;
3387  continue;
3388  }
3389  for (x=0; x < (ssize_t) wave_image->columns; x++)
3390  {
3391  status=InterpolatePixelChannels(canvas_image,canvas_image_view,
3392  wave_image,method,(double) x,(double) (y-sine_map[x]),q,exception);
3393  if (status == MagickFalse)
3394  break;
3395  p+=GetPixelChannels(canvas_image);
3396  q+=GetPixelChannels(wave_image);
3397  }
3398  if (SyncCacheViewAuthenticPixels(wave_view,exception) == MagickFalse)
3399  status=MagickFalse;
3400  if (image->progress_monitor != (MagickProgressMonitor) NULL)
3401  {
3403  proceed;
3404 
3405 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3406  #pragma omp atomic
3407 #endif
3408  progress++;
3409  proceed=SetImageProgress(canvas_image,WaveImageTag,progress,
3410  canvas_image->rows);
3411  if (proceed == MagickFalse)
3412  status=MagickFalse;
3413  }
3414  }
3415  wave_view=DestroyCacheView(wave_view);
3416  canvas_image_view=DestroyCacheView(canvas_image_view);
3417  canvas_image=DestroyImage(canvas_image);
3418  sine_map=(float *) RelinquishMagickMemory(sine_map);
3419  if (status == MagickFalse)
3420  wave_image=DestroyImage(wave_image);
3421  return(wave_image);
3422 }
3423 
3424 /*
3425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3426 % %
3427 % %
3428 % %
3429 % W a v e l e t D e n o i s e I m a g e %
3430 % %
3431 % %
3432 % %
3433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3434 %
3435 % WaveletDenoiseImage() removes noise from the image using a wavelet
3436 % transform. The wavelet transform is a fast hierarchical scheme for
3437 % processing an image using a set of consecutive lowpass and high_pass filters,
3438 % followed by a decimation. This results in a decomposition into different
3439 % scales which can be regarded as different “frequency bands”, determined by
3440 % the mother wavelet. Adapted from dcraw.c by David Coffin.
3441 %
3442 % The format of the WaveletDenoiseImage method is:
3443 %
3444 % Image *WaveletDenoiseImage(const Image *image,const double threshold,
3445 % const double softness,ExceptionInfo *exception)
3446 %
3447 % A description of each parameter follows:
3448 %
3449 % o image: the image.
3450 %
3451 % o threshold: set the threshold for smoothing.
3452 %
3453 % o softness: attenuate the smoothing threshold.
3454 %
3455 % o exception: return any errors or warnings in this structure.
3456 %
3457 */
3458 
3459 static inline void HatTransform(const float *magick_restrict pixels,
3460  const size_t stride,const size_t extent,const size_t scale,float *kernel)
3461 {
3462  const float
3463  *magick_restrict p,
3464  *magick_restrict q,
3465  *magick_restrict r;
3466 
3467  register ssize_t
3468  i;
3469 
3470  p=pixels;
3471  q=pixels+scale*stride;
3472  r=pixels+scale*stride;
3473  for (i=0; i < (ssize_t) scale; i++)
3474  {
3475  kernel[i]=0.25f*(*p+(*p)+(*q)+(*r));
3476  p+=stride;
3477  q-=stride;
3478  r+=stride;
3479  }
3480  for ( ; i < (ssize_t) (extent-scale); i++)
3481  {
3482  kernel[i]=0.25f*(2.0f*(*p)+*(p-scale*stride)+*(p+scale*stride));
3483  p+=stride;
3484  }
3485  q=p-scale*stride;
3486  r=pixels+stride*(extent-2);
3487  for ( ; i < (ssize_t) extent; i++)
3488  {
3489  kernel[i]=0.25f*(*p+(*p)+(*q)+(*r));
3490  p+=stride;
3491  q+=stride;
3492  r-=stride;
3493  }
3494 }
3495 
3497  const double threshold,const double softness,ExceptionInfo *exception)
3498 {
3499  CacheView
3500  *image_view,
3501  *noise_view;
3502 
3503  float
3504  *kernel,
3505  *pixels;
3506 
3507  Image
3508  *noise_image;
3509 
3511  status;
3512 
3514  number_pixels;
3515 
3516  MemoryInfo
3517  *pixels_info;
3518 
3519  ssize_t
3520  channel;
3521 
3522  static const float
3523  noise_levels[] = { 0.8002f, 0.2735f, 0.1202f, 0.0585f, 0.0291f, 0.0152f,
3524  0.0080f, 0.0044f };
3525 
3526  /*
3527  Initialize noise image attributes.
3528  */
3529  assert(image != (const Image *) NULL);
3530  assert(image->signature == MagickCoreSignature);
3531  if (image->debug != MagickFalse)
3532  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3533  assert(exception != (ExceptionInfo *) NULL);
3534  assert(exception->signature == MagickCoreSignature);
3535 #if defined(MAGICKCORE_OPENCL_SUPPORT)
3536  noise_image=AccelerateWaveletDenoiseImage(image,threshold,exception);
3537  if (noise_image != (Image *) NULL)
3538  return(noise_image);
3539 #endif
3540  noise_image=CloneImage(image,0,0,MagickTrue,exception);
3541  if (noise_image == (Image *) NULL)
3542  return((Image *) NULL);
3543  if (SetImageStorageClass(noise_image,DirectClass,exception) == MagickFalse)
3544  {
3545  noise_image=DestroyImage(noise_image);
3546  return((Image *) NULL);
3547  }
3549  ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
3550  pixels_info=AcquireVirtualMemory(3*image->columns,image->rows*
3551  sizeof(*pixels));
3552  kernel=(float *) AcquireQuantumMemory(MagickMax(image->rows,image->columns)+1,
3553  GetOpenMPMaximumThreads()*sizeof(*kernel));
3554  if ((pixels_info == (MemoryInfo *) NULL) || (kernel == (float *) NULL))
3555  {
3556  if (kernel != (float *) NULL)
3557  kernel=(float *) RelinquishMagickMemory(kernel);
3558  if (pixels_info != (MemoryInfo *) NULL)
3559  pixels_info=RelinquishVirtualMemory(pixels_info);
3560  ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
3561  }
3562  pixels=(float *) GetVirtualMemoryBlob(pixels_info);
3563  status=MagickTrue;
3564  number_pixels=(MagickSizeType) image->columns*image->rows;
3565  image_view=AcquireAuthenticCacheView(image,exception);
3566  noise_view=AcquireAuthenticCacheView(noise_image,exception);
3567  for (channel=0; channel < (ssize_t) GetPixelChannels(image); channel++)
3568  {
3569  register ssize_t
3570  i;
3571 
3572  size_t
3573  high_pass,
3574  low_pass;
3575 
3576  ssize_t
3577  level,
3578  y;
3579 
3580  PixelChannel
3581  pixel_channel;
3582 
3583  PixelTrait
3584  traits;
3585 
3586  if (status == MagickFalse)
3587  continue;
3588  traits=GetPixelChannelTraits(image,(PixelChannel) channel);
3589  if (traits == UndefinedPixelTrait)
3590  continue;
3591  pixel_channel=GetPixelChannelChannel(image,channel);
3592  if ((pixel_channel != RedPixelChannel) &&
3593  (pixel_channel != GreenPixelChannel) &&
3594  (pixel_channel != BluePixelChannel))
3595  continue;
3596  /*
3597  Copy channel from image to wavelet pixel array.
3598  */
3599  i=0;
3600  for (y=0; y < (ssize_t) image->rows; y++)
3601  {
3602  register const Quantum
3603  *magick_restrict p;
3604 
3605  ssize_t
3606  x;
3607 
3608  p=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3609  if (p == (const Quantum *) NULL)
3610  {
3611  status=MagickFalse;
3612  break;
3613  }
3614  for (x=0; x < (ssize_t) image->columns; x++)
3615  {
3616  pixels[i++]=(float) p[channel];
3617  p+=GetPixelChannels(image);
3618  }
3619  }
3620  /*
3621  Low pass filter outputs are called approximation kernel & high pass
3622  filters are referred to as detail kernel. The detail kernel
3623  have high values in the noisy parts of the signal.
3624  */
3625  high_pass=0;
3626  for (level=0; level < 5; level++)
3627  {
3628  double
3629  magnitude;
3630 
3631  ssize_t
3632  x,
3633  y;
3634 
3635  low_pass=(size_t) (number_pixels*((level & 0x01)+1));
3636 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3637  #pragma omp parallel for schedule(static,1) \
3638  magick_number_threads(image,image,image->rows,1)
3639 #endif
3640  for (y=0; y < (ssize_t) image->rows; y++)
3641  {
3642  const int
3643  id = GetOpenMPThreadId();
3644 
3645  register float
3646  *magick_restrict p,
3647  *magick_restrict q;
3648 
3649  register ssize_t
3650  x;
3651 
3652  p=kernel+id*image->columns;
3653  q=pixels+y*image->columns;
3654  HatTransform(q+high_pass,1,image->columns,(size_t) (1UL << level),p);
3655  q+=low_pass;
3656  for (x=0; x < (ssize_t) image->columns; x++)
3657  *q++=(*p++);
3658  }
3659 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3660  #pragma omp parallel for schedule(static,1) \
3661  magick_number_threads(image,image,image->columns,1)
3662 #endif
3663  for (x=0; x < (ssize_t) image->columns; x++)
3664  {
3665  const int
3666  id = GetOpenMPThreadId();
3667 
3668  register float
3669  *magick_restrict p,
3670  *magick_restrict q;
3671 
3672  register ssize_t
3673  y;
3674 
3675  p=kernel+id*image->rows;
3676  q=pixels+x+low_pass;
3677  HatTransform(q,image->columns,image->rows,(size_t) (1UL << level),p);
3678  for (y=0; y < (ssize_t) image->rows; y++)
3679  {
3680  *q=(*p++);
3681  q+=image->columns;
3682  }
3683  }
3684  /*
3685  To threshold, each coefficient is compared to a threshold value and
3686  attenuated / shrunk by some factor.
3687  */
3688  magnitude=threshold*noise_levels[level];
3689  for (i=0; i < (ssize_t) number_pixels; ++i)
3690  {
3691  pixels[high_pass+i]-=pixels[low_pass+i];
3692  if (pixels[high_pass+i] < -magnitude)
3693  pixels[high_pass+i]+=magnitude-softness*magnitude;
3694  else
3695  if (pixels[high_pass+i] > magnitude)
3696  pixels[high_pass+i]-=magnitude-softness*magnitude;
3697  else
3698  pixels[high_pass+i]*=softness;
3699  if (high_pass != 0)
3700  pixels[i]+=pixels[high_pass+i];
3701  }
3702  high_pass=low_pass;
3703  }
3704  /*
3705  Reconstruct image from the thresholded wavelet kernel.
3706  */
3707  i=0;
3708  for (y=0; y < (ssize_t) image->rows; y++)
3709  {
3711  sync;
3712 
3713  register Quantum
3714  *magick_restrict q;
3715 
3716  register ssize_t
3717  x;
3718 
3719  ssize_t
3720  offset;
3721 
3722  q=GetCacheViewAuthenticPixels(noise_view,0,y,noise_image->columns,1,
3723  exception);
3724  if (q == (Quantum *) NULL)
3725  {
3726  status=MagickFalse;
3727  break;
3728  }
3729  offset=GetPixelChannelOffset(noise_image,pixel_channel);
3730  for (x=0; x < (ssize_t) image->columns; x++)
3731  {
3733  pixel;
3734 
3735  pixel=(MagickRealType) pixels[i]+pixels[low_pass+i];
3736  q[offset]=ClampToQuantum(pixel);
3737  i++;
3738  q+=GetPixelChannels(noise_image);
3739  }
3740  sync=SyncCacheViewAuthenticPixels(noise_view,exception);
3741  if (sync == MagickFalse)
3742  status=MagickFalse;
3743  }
3744  if (image->progress_monitor != (MagickProgressMonitor) NULL)
3745  {
3747  proceed;
3748 
3750  channel,GetPixelChannels(image));
3751  if (proceed == MagickFalse)
3752  status=MagickFalse;
3753  }
3754  }
3755  noise_view=DestroyCacheView(noise_view);
3756  image_view=DestroyCacheView(image_view);
3757  kernel=(float *) RelinquishMagickMemory(kernel);
3758  pixels_info=RelinquishVirtualMemory(pixels_info);
3759  if (status == MagickFalse)
3760  noise_image=DestroyImage(noise_image);
3761  return(noise_image);
3762 }
double psi
Definition: geometry.h:106
size_t rows
Definition: image.h:172
#define magick_restrict
Definition: MagickCore.h:41
MagickExport Image * ResizeImage(const Image *image, const size_t columns, const size_t rows, const FilterType filter, ExceptionInfo *exception)
Definition: resize.c:3705
MagickExport Image * BlurImage(const Image *image, const double radius, const double sigma, ExceptionInfo *exception)
Definition: effect.c:770
#define ColorMatrixImageTag
PixelInfo fill
Definition: draw.h:214
MagickDoubleType MagickRealType
Definition: magick-type.h:124
MagickExport MagickBooleanType NegateImage(Image *image, const MagickBooleanType grayscale, ExceptionInfo *exception)
Definition: enhance.c:3905
PixelIntensityMethod intensity
Definition: image.h:222
MagickExport CacheView * DestroyCacheView(CacheView *cache_view)
Definition: cache-view.c:252
MagickExport Image * MotionBlurImage(const Image *image, const double radius, const double sigma, const double angle, ExceptionInfo *exception)
Definition: effect.c:2009
#define TransparentAlpha
Definition: image.h:26
MagickExport Image * TintImage(const Image *image, const char *blend, const PixelInfo *tint, ExceptionInfo *exception)
static ssize_t GetPixelChannelOffset(const Image *magick_restrict image, const PixelChannel channel)
char * primitive
Definition: draw.h:204
double x2
Definition: image.h:107
PixelInfo * colormap
Definition: image.h:179
MagickExport MemoryInfo * RelinquishVirtualMemory(MemoryInfo *memory_info)
Definition: memory.c:1190
MagickProgressMonitor progress_monitor
Definition: image.h:303
static Quantum GetPixelAlpha(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
GravityType gravity
Definition: draw.h:285
MagickExport MagickBooleanType TransformImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: colorspace.c:1515
FilterType filter
Definition: image.h:219
PixelTrait alpha_trait
Definition: pixel.h:178
MagickExport Image * WaveletDenoiseImage(const Image *image, const double threshold, const double softness, ExceptionInfo *exception)
static PixelTrait GetPixelAlphaTraits(const Image *magick_restrict image)
static Quantum GetPixelRed(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
MagickExport Image * ColorMatrixImage(const Image *image, const KernelInfo *color_matrix, ExceptionInfo *exception)
MagickExport Image * FlopImage(const Image *image, ExceptionInfo *exception)
Definition: transform.c:1320
size_t height
Definition: morphology.h:108
#define SteganoImageTag
PixelInfo border_color
Definition: image.h:179
PixelInterpolateMethod
Definition: pixel.h:110
MagickExport MemoryInfo * AcquireVirtualMemory(const size_t count, const size_t quantum)
Definition: memory.c:670
PixelInfo stroke
Definition: draw.h:214
size_t signature
Definition: exception.h:123
static size_t GetOpenMPMaximumThreads(void)
double rho
Definition: geometry.h:106
MagickExport Image * PolaroidImage(const Image *image, const DrawInfo *draw_info, const char *caption, const double angle, const PixelInterpolateMethod method, ExceptionInfo *exception)
MagickExport MagickBooleanType GetOneCacheViewVirtualPixelInfo(const CacheView *cache_view, const ssize_t x, const ssize_t y, PixelInfo *pixel, ExceptionInfo *exception)
Definition: cache-view.c:846
MagickExport MagickBooleanType SetImageArtifact(Image *image, const char *artifact, const char *value)
Definition: artifact.c:445
#define OpaqueAlpha
Definition: image.h:25
MagickPrivate double GenerateDifferentialNoise(RandomInfo *, const Quantum, const NoiseType, const double)
Definition: gem.c:1455
static Quantum GetPixelChannel(const Image *magick_restrict image, const PixelChannel channel, const Quantum *magick_restrict pixel)
static void HatTransform(const float *magick_restrict pixels, const size_t stride, const size_t extent, const size_t scale, float *kernel)
MagickExport MagickBooleanType InterpolatePixelChannels(const Image *magick_restrict source, const CacheView_ *source_view, const Image *magick_restrict destination, const PixelInterpolateMethod method, const double x, const double y, Quantum *pixel, ExceptionInfo *exception)
Definition: pixel.c:4915
MagickRealType red
Definition: pixel.h:190
MagickExport MagickBooleanType SetImageAlpha(Image *image, const Quantum alpha, ExceptionInfo *exception)
Definition: image.c:2315
static RandomInfo ** DestroyRandomInfoThreadSet(RandomInfo **random_info)
static PixelTrait GetPixelChannelTraits(const Image *magick_restrict image, const PixelChannel channel)
#define MagickPI
Definition: image-private.h:40
MagickExport Image * SepiaToneImage(const Image *image, const double threshold, ExceptionInfo *exception)
#define TintImageTag
MagickExport ssize_t FormatLocaleString(char *magick_restrict string, const size_t length, const char *magick_restrict format,...)
Definition: locale.c:499
static void SetPixelViaPixelInfo(const Image *magick_restrict image, const PixelInfo *magick_restrict pixel_info, Quantum *magick_restrict pixel)
static MagickBooleanType IsGrayColorspace(const ColorspaceType colorspace)
MagickExport Image * MergeImageLayers(Image *image, const LayerMethod method, ExceptionInfo *exception)
Definition: layer.c:1924
static Quantum PlasmaPixel(RandomInfo *magick_restrict random_info, const double pixel, const double noise)
#define MAGICKCORE_QUANTUM_DEPTH
Definition: magick-type.h:32
MagickExport const Quantum * GetCacheViewVirtualPixels(const CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:651
MagickExport MagickBooleanType GrayscaleImage(Image *image, const PixelIntensityMethod method, ExceptionInfo *exception)
Definition: enhance.c:2462
static RandomInfo ** AcquireRandomInfoThreadSet(void)
NoiseType
MagickRealType alpha
Definition: pixel.h:190
MagickExport MagickBooleanType PlasmaImage(Image *image, const SegmentInfo *segment, size_t attenuate, size_t depth, ExceptionInfo *exception)
#define MagickEpsilon
Definition: magick-type.h:114
double sigma
Definition: geometry.h:106
ClassType storage_class
Definition: image.h:154
MagickExport MagickBooleanType CompositeImage(Image *image, const Image *composite, const CompositeOperator compose, const MagickBooleanType clip_to_self, const ssize_t x_offset, const ssize_t y_offset, ExceptionInfo *exception)
Definition: composite.c:528
size_t width
Definition: geometry.h:130
MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type, const MagickSizeType size)
Definition: resource.c:188
Definition: log.h:52
ssize_t MagickOffsetType
Definition: magick-type.h:133
MagickExport unsigned long GetRandomSecretKey(const RandomInfo *random_info)
Definition: random.c:741
MagickExport void GetPixelInfo(const Image *image, PixelInfo *pixel)
Definition: pixel.c:2170
static Quantum ClampToQuantum(const MagickRealType quantum)
Definition: quantum.h:85
Definition: image.h:151
MagickExport RandomInfo * DestroyRandomInfo(RandomInfo *random_info)
Definition: random.c:274
MagickExport Image * ImplodeImage(const Image *image, const double amount, const PixelInterpolateMethod method, ExceptionInfo *exception)
MagickExport MagickBooleanType ContrastImage(Image *image, const MagickBooleanType sharpen, ExceptionInfo *exception)
Definition: enhance.c:1398
double x
Definition: geometry.h:123
#define MagickCoreSignature
MagickExport Quantum * GetCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:299
MagickExport ssize_t FormatMagickCaption(Image *image, DrawInfo *draw_info, const MagickBooleanType split, TypeMetric *metrics, char **caption, ExceptionInfo *exception)
Definition: annotate.c:588
MagickExport Image * GetFirstImageInList(const Image *images)
Definition: list.c:561
#define BlueShiftImageTag
MagickExport MagickBooleanType SetImageAlphaChannel(Image *image, const AlphaChannelOption alpha_type, ExceptionInfo *exception)
Definition: channel.c:974
MagickBooleanType
Definition: magick-type.h:169
unsigned int MagickStatusType
Definition: magick-type.h:125
MagickExport char * AcquireString(const char *source)
Definition: string.c:129
MagickExport MagickBooleanType AnnotateImage(Image *image, const DrawInfo *draw_info, ExceptionInfo *exception)
Definition: annotate.c:222
double x1
Definition: image.h:107
double descent
Definition: draw.h:372
MagickExport const Quantum * GetVirtualPixels(const Image *image, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache.c:3234
MagickExport MagickBooleanType NormalizeImage(Image *image, ExceptionInfo *exception)
Definition: enhance.c:4095
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:634
MagickExport Image * AddNoiseImage(const Image *image, const NoiseType noise_type, const double attenuate, ExceptionInfo *exception)
static double DegreesToRadians(const double degrees)
Definition: image-private.h:53
double y
Definition: geometry.h:123
static int GetOpenMPThreadId(void)
#define StereoImageTag
MagickExport Image * VignetteImage(const Image *image, const double radius, const double sigma, const ssize_t x, const ssize_t y, ExceptionInfo *exception)
RectangleInfo page
Definition: image.h:212
#define ImplodeImageTag
size_t MagickSizeType
Definition: magick-type.h:134
#define MagickPathExtent
MagickExport Image * ShadowImage(const Image *image, const double alpha, const double sigma, const ssize_t x_offset, const ssize_t y_offset, ExceptionInfo *exception)
static Quantum GetPixelGreen(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
static void GetPixelInfoPixel(const Image *magick_restrict image, const Quantum *magick_restrict pixel, PixelInfo *magick_restrict pixel_info)
MagickExport MagickBooleanType DrawImage(Image *image, const DrawInfo *draw_info, ExceptionInfo *exception)
Definition: draw.c:4438
PixelTrait alpha_trait
Definition: image.h:280
MagickRealType blue
Definition: pixel.h:190
MagickExport ChannelType SetPixelChannelMask(Image *image, const ChannelType channel_mask)
Definition: pixel.c:6278
static Quantum GetPixelBlack(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
MagickExport ChannelType SetImageChannelMask(Image *image, const ChannelType channel_mask)
Definition: image.c:2478
MagickExport Quantum * QueueCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:977
#define WaveImageTag
MagickExport MagickRealType GetPixelInfoIntensity(const Image *magick_restrict image, const PixelInfo *magick_restrict pixel)
Definition: pixel.c:2224
MagickExport Image * SketchImage(const Image *image, const double radius, const double sigma, const double angle, ExceptionInfo *exception)
MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(Image *image, const VirtualPixelMethod virtual_pixel_method, ExceptionInfo *exception)
Definition: image.c:3476
double y2
Definition: image.h:107
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1660
MagickExport Image * RotateImage(const Image *image, const double degrees, ExceptionInfo *exception)
Definition: distort.c:2853
size_t width
Definition: morphology.h:108
MagickExport MagickBooleanType SetImageBackgroundColor(Image *image, ExceptionInfo *exception)
Definition: image.c:2394
size_t signature
Definition: image.h:354
MagickExport RandomInfo * AcquireRandomInfo(void)
Definition: random.c:163
#define QuantumScale
Definition: magick-type.h:119
#define MorphImageTag
size_t columns
Definition: image.h:172
ssize_t x
Definition: geometry.h:134
MagickExport DrawInfo * CloneDrawInfo(const ImageInfo *image_info, const DrawInfo *draw_info)
Definition: draw.c:269
MagickExport Image * GetLastImageInList(const Image *images)
Definition: list.c:737
size_t height
Definition: geometry.h:130
MagickExport Image * SwirlImage(const Image *image, double degrees, const PixelInterpolateMethod method, ExceptionInfo *exception)
MagickExport MagickBooleanType QueryColorCompliance(const char *name, const ComplianceType compliance, PixelInfo *color, ExceptionInfo *exception)
Definition: color.c:2179
ChannelType
Definition: pixel.h:33
static void SetPixelBlue(const Image *magick_restrict image, const Quantum blue, Quantum *magick_restrict pixel)
MagickExport MagickBooleanType SetImageStorageClass(Image *image, const ClassType storage_class, ExceptionInfo *exception)
Definition: image.c:2594
ssize_t offset
Definition: image.h:206
#define SetBit(alpha, i, set)
MagickExport Image * DestroyImageList(Image *images)
Definition: list.c:462
PixelChannel
Definition: pixel.h:67
#define Colorize(pixel, blend_percentage, colorize)
MagickExport MagickBooleanType SetImageExtent(Image *image, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: image.c:2636
MagickExport Image * StereoAnaglyphImage(const Image *left_image, const Image *right_image, const ssize_t x_offset, const ssize_t y_offset, ExceptionInfo *exception)
#define MagickMax(x, y)
Definition: image-private.h:36
size_t colors
Definition: image.h:172
#define GetBit(alpha, i)
static size_t GetPixelChannels(const Image *magick_restrict image)
char filename[MagickPathExtent]
Definition: image.h:319
#define ColorizeImageTag
#define GetMagickModule()
Definition: log.h:28
MagickExport Image * MorphImages(const Image *image, const size_t number_frames, ExceptionInfo *exception)
static MagickBooleanType PlasmaImageProxy(Image *image, CacheView *image_view, CacheView *u_view, CacheView *v_view, RandomInfo *magick_restrict random_info, const SegmentInfo *magick_restrict segment, size_t attenuate, size_t depth, ExceptionInfo *exception)
double chi
Definition: geometry.h:106
#define ThrowImageException(severity, tag)
static PixelChannel GetPixelChannelChannel(const Image *magick_restrict image, const ssize_t offset)
static MagickRealType GetPixelInfoChannel(const PixelInfo *magick_restrict pixel_info, const PixelChannel channel)
MagickExport CacheView * AcquireVirtualCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:149
MagickExport MagickBooleanType SetCacheViewVirtualPixelMethod(CacheView *magick_restrict cache_view, const VirtualPixelMethod virtual_pixel_method)
Definition: cache-view.c:1060
MagickExport char * InterpretImageProperties(ImageInfo *image_info, Image *image, const char *embed_text, ExceptionInfo *exception)
Definition: property.c:3414
char * geometry
Definition: draw.h:204
MagickExport MagickBooleanType SyncAuthenticPixels(Image *image, ExceptionInfo *exception)
Definition: cache.c:5438
unsigned short Quantum
Definition: magick-type.h:86
double xi
Definition: geometry.h:106
static MagickBooleanType IsPixelInfoGray(const PixelInfo *magick_restrict pixel)
MagickExport Image * BorderImage(const Image *image, const RectangleInfo *border_info, const CompositeOperator compose, ExceptionInfo *exception)
Definition: decorate.c:103
MagickExport MagickBooleanType SetImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: colorspace.c:1324
MagickExport Image * SteganoImage(const Image *image, const Image *watermark, ExceptionInfo *exception)
MagickExport DrawInfo * DestroyDrawInfo(DrawInfo *draw_info)
Definition: draw.c:882
MagickExport Image * GetNextImageInList(const Image *images)
Definition: list.c:771
MagickRealType black
Definition: pixel.h:190
MagickExport char * DestroyString(char *string)
Definition: string.c:823
MagickExport Quantum * QueueAuthenticPixels(Image *image, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache.c:4304
MagickExport double GetPseudoRandomValue(RandomInfo *magick_restrict random_info)
Definition: random.c:610
MagickExport MagickStatusType ParseGeometry(const char *geometry, GeometryInfo *geometry_info)
Definition: geometry.c:853
static void SetPixelChannel(const Image *magick_restrict image, const PixelChannel channel, const Quantum quantum, Quantum *magick_restrict pixel)
MagickExport void AppendImageToList(Image **images, const Image *append)
Definition: list.c:78
#define SwirlImageTag
MagickExport Image * CharcoalImage(const Image *image, const double radius, const double sigma, ExceptionInfo *exception)
static void SetPixelAlpha(const Image *magick_restrict image, const Quantum alpha, Quantum *magick_restrict pixel)
MagickExport MagickBooleanType ConcatenateString(char **magick_restrict destination, const char *magick_restrict source)
Definition: string.c:492
char * text
Definition: draw.h:255
static RandomInfo * random_info
Definition: resource.c:113
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1123
MagickExport Image * WaveImage(const Image *image, const double amplitude, const double wave_length, const PixelInterpolateMethod method, ExceptionInfo *exception)
double ascent
Definition: draw.h:372
MagickExport MagickBooleanType ClampImage(Image *image, ExceptionInfo *exception)
Definition: threshold.c:1085
MagickRealType green
Definition: pixel.h:190
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
Definition: monitor.h:26
MagickExport Image * StereoImage(const Image *left_image, const Image *right_image, ExceptionInfo *exception)
MagickExport char * CloneString(char **destination, const char *source)
Definition: string.c:286
#define SepiaToneImageTag
static void SetPixelRed(const Image *magick_restrict image, const Quantum red, Quantum *magick_restrict pixel)
MagickExport Image * TrimImage(const Image *image, ExceptionInfo *exception)
Definition: transform.c:2402
MagickExport Image * BlueShiftImage(const Image *image, const double factor, ExceptionInfo *exception)
#define MagickExport
MagickExport MagickBooleanType SyncCacheViewAuthenticPixels(CacheView *magick_restrict cache_view, ExceptionInfo *exception)
Definition: cache-view.c:1100
ssize_t y
Definition: geometry.h:134
MagickExport MagickBooleanType SolarizeImage(Image *image, const double threshold, ExceptionInfo *exception)
MagickExport Image * ColorizeImage(const Image *image, const char *blend, const PixelInfo *colorize, ExceptionInfo *exception)
MagickExport CacheView * AcquireAuthenticCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:112
ColorspaceType colorspace
Definition: pixel.h:175
double y1
Definition: image.h:107
MagickExport Image * EdgeImage(const Image *image, const double radius, ExceptionInfo *exception)
Definition: effect.c:1185
static Quantum GetPixelBlue(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
PixelTrait
Definition: pixel.h:134
#define AddNoiseImageTag
MagickExport void * GetVirtualMemoryBlob(const MemoryInfo *memory_info)
Definition: memory.c:1051
MagickExport MagickRealType GetPixelIntensity(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
Definition: pixel.c:2358
PixelInfo background_color
Definition: image.h:179
MagickExport size_t GetImageListLength(const Image *images)
Definition: list.c:696
#define SolarizeImageTag
MagickExport Image * DestroyImage(Image *image)
Definition: image.c:1159
MagickExport Image * CloneImage(const Image *image, const size_t columns, const size_t rows, const MagickBooleanType detach, ExceptionInfo *exception)
Definition: image.c:774
ColorspaceType colorspace
Definition: image.h:157
#define QuantumRange
Definition: magick-type.h:87
MagickExport MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
Definition: monitor.c:136
MagickRealType * values
Definition: morphology.h:116
MagickBooleanType debug
Definition: image.h:334
static void SetPixelGreen(const Image *magick_restrict image, const Quantum green, Quantum *magick_restrict pixel)
size_t depth
Definition: image.h:172
MagickPrivate MagickBooleanType TransformImage(Image **, const char *, const char *, ExceptionInfo *)
Definition: transform.c:2039