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