root / ImageMagick / branches / ImageMagick-6.3.5 / magick / effect.c

Revision 8037, 115.6 kB (checked in by cristy, 14 months ago)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                   EEEEE  FFFFF  FFFFF  EEEEE  CCCC  TTTTT                   %
7%                   E      F      F      E     C        T                     %
8%                   EEE    FFF    FFF    EEE   C        T                     %
9%                   E      F      F      E     C        T                     %
10%                   EEEEE  F      F      EEEEE  CCCC    T                     %
11%                                                                             %
12%                                                                             %
13%                      ImageMagick Image Effects Methods                      %
14%                                                                             %
15%                               Software Design                               %
16%                                 John Cristy                                 %
17%                                 October 1996                                %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2007 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41  Include declarations.
42*/
43#include "magick/studio.h"
44#include "magick/property.h"
45#include "magick/blob.h"
46#include "magick/cache-view.h"
47#include "magick/color.h"
48#include "magick/color-private.h"
49#include "magick/colorspace.h"
50#include "magick/constitute.h"
51#include "magick/decorate.h"
52#include "magick/draw.h"
53#include "magick/enhance.h"
54#include "magick/exception.h"
55#include "magick/exception-private.h"
56#include "magick/effect.h"
57#include "magick/fx.h"
58#include "magick/gem.h"
59#include "magick/geometry.h"
60#include "magick/image-private.h"
61#include "magick/list.h"
62#include "magick/log.h"
63#include "magick/memory_.h"
64#include "magick/monitor.h"
65#include "magick/montage.h"
66#include "magick/pixel-private.h"
67#include "magick/property.h"
68#include "magick/quantize.h"
69#include "magick/quantum.h"
70#include "magick/random_.h"
71#include "magick/resize.h"
72#include "magick/resource_.h"
73#include "magick/segment.h"
74#include "magick/shear.h"
75#include "magick/signature.h"
76#include "magick/string_.h"
77#include "magick/transform.h"
78#include "magick/threshold.h"
79
80/*
81%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82%                                                                             %
83%                                                                             %
84%                                                                             %
85%     A d a p t i v e B l u r I m a g e                                       %
86%                                                                             %
87%                                                                             %
88%                                                                             %
89%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
90%
91%  AdaptiveBlurImage() adaptively blurs the image by blurring less
92%  intensely near image edges and more intensely far from edges.  We blur the
93%  image with a Gaussian operator of the given radius and standard deviation
94%  (sigma).  For reasonable results, radius should be larger than sigma.  Use a
95%  radius of 0 and AdaptiveBlurImage() selects a suitable radius for you.
96%
97%  The format of the AdaptiveBlurImage method is:
98%
99%      Image *AdaptiveBlurImage(const Image *image,const double radius,
100%        const double sigma,ExceptionInfo *exception)
101%      Image *AdaptiveBlurImageChannel(const Image *image,
102%        const ChannelType channel,double radius,const double sigma,
103%        ExceptionInfo *exception)
104%
105%  A description of each parameter follows:
106%
107%    o image: The image.
108%
109%    o channel: The channel type.
110%
111%    o radius: The radius of the Gaussian, in pixels, not counting the center
112%      pixel.
113%
114%    o sigma: The standard deviation of the Laplacian, in pixels.
115%
116%    o exception: Return any errors or warnings in this structure.
117%
118*/
119
120MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
121  const double sigma,ExceptionInfo *exception)
122{
123  Image
124    *blur_image;
125
126  blur_image=AdaptiveBlurImageChannel(image,DefaultChannels,radius,sigma,
127    exception);
128  return(blur_image);
129}
130
131MagickExport Image *AdaptiveBlurImageChannel(const Image *image,
132  const ChannelType channel,const double radius,const double sigma,
133  ExceptionInfo *exception)
134{
135#define AdaptiveBlurImageTag  "Convolve/Image"
136
137  double
138    **kernel;
139
140  Image
141    *blur_image,
142    *edge_image,
143    *gaussian_image;
144
145  IndexPacket
146    *indexes,
147    *blur_indexes;
148
149  long
150    j,
151    u,
152    v,
153    y;
154
155  MagickBooleanType
156    status;
157
158  MagickPixelPacket
159    pixel;
160
161  MagickRealType
162    alpha,
163    gamma,
164    normalize;
165
166  register const double
167    *k;
168
169  register const PixelPacket
170    *p,
171    *r;
172
173  register long
174    i,
175    x;
176
177  register PixelPacket
178    *q;
179
180  unsigned long
181    width;
182
183  assert(image != (const Image *) NULL);
184  assert(image->signature == MagickSignature);
185  if (image->debug != MagickFalse)
186    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
187  assert(exception != (ExceptionInfo *) NULL);
188  assert(exception->signature == MagickSignature);
189  blur_image=CloneImage(image,0,0,MagickTrue,exception);
190  if (blur_image == (Image *) NULL)
191    return((Image *) NULL);
192  if (fabs(sigma) <= MagickEpsilon)
193    return(blur_image);
194  if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
195    {
196      InheritException(exception,&blur_image->exception);
197      blur_image=DestroyImage(blur_image);
198      return((Image *) NULL);
199    }
200  /*
201    Edge detect the image brighness channel, level, blur, and level again.
202  */
203  edge_image=EdgeImage(image,radius,exception);
204  if (edge_image == (Image *) NULL)
205    {
206      blur_image=DestroyImage(blur_image);
207      return((Image *) NULL);
208    }
209  (void) LevelImage(edge_image,"20%,95%");
210  gaussian_image=GaussianBlurImage(edge_image,radius,sigma,exception);
211  if (gaussian_image != (Image *) NULL)
212    {
213      edge_image=DestroyImage(edge_image);
214      edge_image=gaussian_image;
215    }
216  (void) LevelImage(edge_image,"10%,95%");
217  /*
218    Create a set of kernels from maximum (radius,sigma) to minimum.
219  */
220  width=GetOptimalKernelWidth2D(radius,sigma);
221  kernel=(double **) AcquireQuantumMemory((size_t) width,sizeof(*kernel));
222  if (kernel == (double **) NULL)
223    {
224      edge_image=DestroyImage(edge_image);
225      blur_image=DestroyImage(blur_image);
226      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
227    }
228  (void) ResetMagickMemory(kernel,0,(size_t) width*sizeof(*kernel));
229  for (i=0; i < (long) width; i+=2)
230  {
231    kernel[i]=(double *) AcquireQuantumMemory((size_t) (width-i),(width-i)*
232      sizeof(**kernel));
233    if (kernel[i] == (double *) NULL)
234      break;
235    j=0;
236    normalize=0.0;
237    for (v=(-((long) (width-i)/2)); v <= (long) ((width-i)/2); v++)
238    {
239      for (u=(-((long) (width-i)/2)); u <= (long) ((width-i)/2); u++)
240      {
241        alpha=exp(-((double) u*u+v*v)/(2.0*sigma*sigma));
242        kernel[i][j]=(double) (alpha/(2.0*MagickPI*sigma*sigma));
243        if (((width-i) < 3) || (u != 0) || (v != 0))
244          normalize+=kernel[i][j];
245        j++;
246      }
247    }
248    kernel[i][j/2]=(double) ((-2.0)*normalize);
249    normalize=0.0;
250    for (j=0; j < (long) ((width-i)*(width-i)); j++)
251      normalize+=kernel[i][j];
252    if (fabs(normalize) <= MagickEpsilon)
253      normalize=1.0;
254    normalize=1.0/normalize;
255    for (j=0; j < (long) ((width-i)*(width-i)); j++)
256      kernel[i][j]=(double) (normalize*kernel[i][j]);
257  }
258  if (i < (long) width)
259    {
260      for (i-=2; i >= 0; i-=2)
261        kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
262      kernel=(double **) RelinquishMagickMemory(kernel);
263      edge_image=DestroyImage(edge_image);
264      blur_image=DestroyImage(blur_image);
265      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
266    }
267  /*
268    Adaptively blur image.
269  */
270  for (y=0; y < (long) blur_image->rows; y++)
271  {
272    r=AcquireImagePixels(edge_image,0,y,edge_image->columns,1,exception);
273    q=GetImagePixels(blur_image,0,y,blur_image->columns,1);
274    if ((r == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
275      break;
276    indexes=GetIndexes(image);
277    blur_indexes=GetIndexes(blur_image);
278    for (x=0; x < (long) blur_image->columns; x++)
279    {
280      GetMagickPixelPacket(image,&pixel);
281      gamma=0.0;
282      i=(long) (width*QuantumScale*PixelIntensity(r)+0.5);
283      if ((i & 0x01) != 0)
284        i--;
285      p=AcquireImagePixels(image,x-((long) (width-i)/2L),y-(long)
286        ((width-i)/2L),width-i,width-i,exception);
287      if (p == (const PixelPacket *) NULL)
288        break;
289      k=kernel[i];
290      for (v=0; v < (long) (width-i); v++)
291      {
292        for (u=0; u < (long) (width-i); u++)
293        {
294          alpha=1.0;
295          if (((channel & OpacityChannel) != 0) &&
296              (image->matte != MagickFalse))
297            alpha=QuantumScale*((MagickRealType) QuantumRange-p->opacity);
298          if ((channel & RedChannel) != 0)
299            pixel.red+=(*k)*alpha*p->red;
300          if ((channel & GreenChannel) != 0)
301            pixel.green+=(*k)*alpha*p->green;
302          if ((channel & BlueChannel) != 0)
303            pixel.blue+=(*k)*alpha*p->blue;
304          if ((channel & OpacityChannel) != 0)
305            pixel.opacity+=(*k)*p->opacity;
306          if (((channel & IndexChannel) != 0) &&
307              (image->colorspace == CMYKColorspace))
308            pixel.index+=(*k)*alpha*indexes[x+(width-i)*v+u];
309          gamma+=(*k)*alpha;
310          k++;
311          p++;
312        }
313      }
314      gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
315      if ((channel & RedChannel) != 0)
316        q->red=RoundToQuantum(gamma*pixel.red+image->bias);
317      if ((channel & GreenChannel) != 0)
318        q->green=RoundToQuantum(gamma*pixel.green+image->bias);
319      if ((channel & BlueChannel) != 0)
320        q->blue=RoundToQuantum(gamma*pixel.blue+image->bias);
321      if ((channel & OpacityChannel) != 0)
322        q->opacity=RoundToQuantum(pixel.opacity+image->bias);
323      if (((channel & IndexChannel) != 0) &&
324          (image->colorspace == CMYKColorspace))
325        blur_indexes[x]=RoundToQuantum(gamma*pixel.index+image->bias);
326      q++;
327      r++;
328    }
329    if (SyncImagePixels(blur_image) == MagickFalse)
330      break;
331    if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
332        (QuantumTick(y,image->rows) != MagickFalse))
333      {
334        status=image->progress_monitor(AdaptiveBlurImageTag,y,image->rows,
335          image->client_data);
336        if (status == MagickFalse)
337          break;
338      }
339  }
340  edge_image=DestroyImage(edge_image);
341  for (i=0; i < (long) width;  i+=2)
342    kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
343  kernel=(double **) RelinquishMagickMemory(kernel);
344  return(blur_image);
345}
346
347/*
348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349%                                                                             %
350%                                                                             %
351%                                                                             %
352%     A d a p t i v e S h a r p e n I m a g e                                 %
353%                                                                             %
354%                                                                             %
355%                                                                             %
356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
357%
358%  AdaptiveSharpenImage() adaptively sharpens the image by sharpening more
359%  intensely near image edges and less intensely far from edges. We sharpen the
360%  image with a Gaussian operator of the given radius and standard deviation
361%  (sigma).  For reasonable results, radius should be larger than sigma.  Use a
362%  radius of 0 and AdaptiveSharpenImage() selects a suitable radius for you.
363%
364%  The format of the AdaptiveSharpenImage method is:
365%
366%      Image *AdaptiveSharpenImage(const Image *image,const double radius,
367%        const double sigma,ExceptionInfo *exception)
368%      Image *AdaptiveSharpenImageChannel(const Image *image,
369%        const ChannelType channel,double radius,const double sigma,
370%        ExceptionInfo *exception)
371%
372%  A description of each parameter follows:
373%
374%    o image: The image.
375%
376%    o channel: The channel type.
377%
378%    o radius: The radius of the Gaussian, in pixels, not counting the center
379%      pixel.
380%
381%    o sigma: The standard deviation of the Laplacian, in pixels.
382%
383%    o exception: Return any errors or warnings in this structure.
384%
385*/
386
387MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
388  const double sigma,ExceptionInfo *exception)
389{
390  Image
391    *sharp_image;
392
393  sharp_image=AdaptiveSharpenImageChannel(image,DefaultChannels,radius,sigma,
394    exception);
395  return(sharp_image);
396}
397
398MagickExport Image *AdaptiveSharpenImageChannel(const Image *image,
399  const ChannelType channel,const double radius,const double sigma,
400  ExceptionInfo *exception)
401{
402#define AdaptiveSharpenImageTag  "Convolve/Image"
403
404  double
405    **kernel;
406
407  Image
408    *blur_image,
409    *edge_image,
410    *sharp_image;
411
412  IndexPacket
413    *indexes,
414    *sharp_indexes;
415
416  long
417    j,
418    u,
419    v,
420    y;
421
422  MagickBooleanType
423    status;
424
425  MagickPixelPacket
426    pixel;
427
428  MagickRealType
429    alpha,
430    gamma,
431    normalize;
432
433  register const double
434    *k;
435
436  register const PixelPacket
437    *p,
438    *r;
439
440  register long
441    i,
442    x;
443
444  register PixelPacket
445    *q;
446
447  unsigned long
448    width;
449
450  assert(image != (const Image *) NULL);
451  assert(image->signature == MagickSignature);
452  if (image->debug != MagickFalse)
453    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
454  assert(exception != (ExceptionInfo *) NULL);
455  assert(exception->signature == MagickSignature);
456  sharp_image=CloneImage(image,0,0,MagickTrue,exception);
457  if (sharp_image == (Image *) NULL)
458    return((Image *) NULL);
459  if (SetImageStorageClass(sharp_image,DirectClass) == MagickFalse)
460    {
461      InheritException(exception,&sharp_image->exception);
462      sharp_image=DestroyImage(sharp_image);
463      return((Image *) NULL);
464    }
465  /*
466    Edge detect the image brighness channel, level, blur, and level again.
467  */
468  edge_image=EdgeImage(image,radius,exception);
469  if (edge_image == (Image *) NULL)
470    {
471      sharp_image=DestroyImage(sharp_image);
472      return((Image *) NULL);
473    }
474  (void) LevelImage(edge_image,"20%,95%");
475  blur_image=GaussianBlurImage(edge_image,radius,sigma,exception);
476  if (blur_image != (Image *) NULL)
477    {
478      edge_image=DestroyImage(edge_image);
479      edge_image=blur_image;
480    }
481  (void) LevelImage(edge_image,"10%,95%");
482  /*
483    Create a set of kernels from maximum (radius,sigma) to minimum.
484  */
485  width=GetOptimalKernelWidth2D(radius,sigma);
486  kernel=(double **) AcquireQuantumMemory((size_t) width,sizeof(*kernel));
487  if (kernel == (double **) NULL)
488    {
489      edge_image=DestroyImage(edge_image);
490      sharp_image=DestroyImage(sharp_image);
491      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
492    }
493  (void) ResetMagickMemory(kernel,0,(size_t) width*sizeof(*kernel));
494  for (i=0; i < (long) width; i+=2)
495  {
496    kernel[i]=(double *) AcquireQuantumMemory((size_t) (width-i),(width-i)*
497      sizeof(**kernel));
498    if (kernel[i] == (double *) NULL)
499      break;
500    j=0;
501    normalize=0.0;
502    for (v=(-((long) (width-i)/2)); v <= (long) ((width-i)/2); v++)
503    {
504      for (u=(-((long) (width-i)/2)); u <= (long) ((width-i)/2); u++)
505      {
506        alpha=exp(-((double) u*u+v*v)/(2.0*sigma*sigma));
507        kernel[i][j]=(double) (-alpha/(2.0*MagickPI*sigma*sigma));
508        if (((width-i) < 3) || (u != 0) || (v != 0))
509          normalize+=kernel[i][j];
510        j++;
511      }
512    }
513    kernel[i][j/2]=(double) ((-2.0)*normalize);
514    normalize=0.0;
515    for (j=0; j < (long) ((width-i)*(width-i)); j++)
516      normalize+=kernel[i][j];
517    if (fabs(normalize) <= MagickEpsilon)
518      normalize=1.0;
519    normalize=1.0/normalize;
520    for (j=0; j < (long) ((width-i)*(width-i)); j++)
521      kernel[i][j]=(double) (normalize*kernel[i][j]);
522  }
523  if (i < (long) width)
524    {
525      for (i-=2; i >= 0; i-=2)
526        kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
527      kernel=(double **) RelinquishMagickMemory(kernel);
528      edge_image=DestroyImage(edge_image);
529      sharp_image=DestroyImage(sharp_image);
530      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
531    }
532  /*
533    Adaptively sharpen image.
534  */
535  for (y=0; y < (long) sharp_image->rows; y++)
536  {
537    r=AcquireImagePixels(edge_image,0,y,edge_image->columns,1,exception);
538    q=GetImagePixels(sharp_image,0,y,sharp_image->columns,1);
539    if ((r == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
540      break;
541    indexes=GetIndexes(image);
542    sharp_indexes=GetIndexes(sharp_image);
543    for (x=0; x < (long) sharp_image->columns; x++)
544    {
545      GetMagickPixelPacket(image,&pixel);
546      gamma=0.0;
547      i=(long) (width*QuantumScale*(QuantumRange-PixelIntensity(r))+0.5);
548      if ((i & 0x01) != 0)
549        i--;
550      p=AcquireImagePixels(image,x-((long) (width-i)/2L),y-(long)
551        ((width-i)/2L),width-i,width-i,exception);
552      if (p == (const PixelPacket *) NULL)
553        break;
554      k=kernel[i];
555      for (v=0; v < (long) (width-i); v++)
556      {
557        for (u=0; u < (long) (width-i); u++)
558        {
559          alpha=1.0;
560          if (((channel & OpacityChannel) != 0) &&
561              (image->matte != MagickFalse))
562            alpha=QuantumScale*((MagickRealType) QuantumRange-p->opacity);
563          if ((channel & RedChannel) != 0)
564            pixel.red+=(*k)*alpha*p->red;
565          if ((channel & GreenChannel) != 0)
566            pixel.green+=(*k)*alpha*p->green;
567          if ((channel & BlueChannel) != 0)
568            pixel.blue+=(*k)*alpha*p->blue;
569          if ((channel & OpacityChannel) != 0)
570            pixel.opacity+=(*k)*p->opacity;
571          if (((channel & IndexChannel) != 0) &&
572              (image->colorspace == CMYKColorspace))
573            pixel.index+=(*k)*alpha*indexes[x+(width-i)*v+u];
574          gamma+=(*k)*alpha;
575          k++;
576          p++;
577        }
578      }
579      gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
580      if ((channel & RedChannel) != 0)
581        q->red=RoundToQuantum(gamma*pixel.red+image->bias);
582      if ((channel & GreenChannel) != 0)
583        q->green=RoundToQuantum(gamma*pixel.green+image->bias);
584      if ((channel & BlueChannel) != 0)
585        q->blue=RoundToQuantum(gamma*pixel.blue+image->bias);
586      if ((channel & OpacityChannel) != 0)
587        q->opacity=RoundToQuantum(pixel.opacity+image->bias);
588      if (((channel & IndexChannel) != 0) &&
589          (image->colorspace == CMYKColorspace))
590        sharp_indexes[x]=RoundToQuantum(gamma*pixel.index+image->bias);
591      q++;
592      r++;
593    }
594    if (SyncImagePixels(sharp_image) == MagickFalse)
595      break;
596    if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
597        (QuantumTick(y,image->rows) != MagickFalse))
598      {
599        status=image->progress_monitor(AdaptiveSharpenImageTag,y,image->rows,
600          image->client_data);
601        if (status == MagickFalse)
602          break;
603      }
604  }
605  edge_image=DestroyImage(edge_image);
606  for (i=0; i < (long) width;  i+=2)
607    kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
608  kernel=(double **) RelinquishMagickMemory(kernel);
609  return(sharp_image);
610}
611
612/*
613%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
614%                                                                             %
615%                                                                             %
616%                                                                             %
617%     A d d N o i s e I m a g e                                               %
618%                                                                             %
619%                                                                             %
620%                                                                             %
621%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
622%
623%  AddNoiseImage() adds random noise to the image.
624%
625%  The format of the AddNoiseImage method is:
626%
627%      Image *AddNoiseImage(const Image *image,const NoiseType noise_type,
628%        ExceptionInfo *exception)
629%      Image *AddNoiseImageChannel(const Image *image,const ChannelType channel,
630%        const NoiseType noise_type,ExceptionInfo *exception)
631%
632%  A description of each parameter follows:
633%
634%    o image: The image.
635%
636%    o channel: The channel type.
637%
638%    o noise_type:  The type of noise: Uniform, Gaussian, Multiplicative,
639%      Impulse, Laplacian, or Poisson.
640%
641%    o exception: Return any errors or warnings in this structure.
642%
643*/
644
645static Quantum GenerateNoise(const Quantum pixel,const NoiseType noise_type,
646  const MagickRealType attenuate)
647{
648#define NoiseEpsilon  (attenuate*1.0e-5)
649#define SigmaUniform  ScaleCharToQuantum((unsigned char) (attenuate*4.0+0.5))
650#define SigmaGaussian  ScaleCharToQuantum((unsigned char) (attenuate*4.0+0.5))
651#define SigmaImpulse  (attenuate*0.10)
652#define SigmaLaplacian ScaleCharToQuantum((unsigned char) (attenuate*10.0+0.5))
653#define SigmaMultiplicativeGaussian \
654  ScaleCharToQuantum((unsigned char) (attenuate*1.0+0.5))
655#define SigmaPoisson  (attenuate*0.05)
656#define TauGaussian  ScaleCharToQuantum((unsigned char) (attenuate*20.0+0.5))
657
658  MagickRealType
659    alpha,
660    beta,
661    noise,
662    sigma;
663
664  alpha=GetRandomValue();
665  if (alpha == 0.0)
666    alpha=1.0;
667  switch (noise_type)
668  {
669    case UniformNoise:
670    default:
671    {
672      noise=(MagickRealType) pixel+SigmaUniform*(alpha-0.5);
673      break;
674    }
675    case GaussianNoise:
676    {
677      MagickRealType
678        tau;
679
680      beta=GetRandomValue();
681      sigma=sqrt(-2.0*log((double) alpha))*cos((double) (2.0*MagickPI*beta));
682      tau=sqrt(-2.0*log((double) alpha))*sin((double) (2.0*MagickPI*beta));
683      noise=(MagickRealType) pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
684        TauGaussian*tau;
685      break;
686    }
687    case MultiplicativeGaussianNoise:
688    {
689      if (alpha <= NoiseEpsilon)
690        sigma=(MagickRealType) QuantumRange;
691      else
692        sigma=sqrt(-2.0*log((double) alpha));
693      beta=GetRandomValue();
694      noise=(MagickRealType) pixel+pixel*SigmaMultiplicativeGaussian*sigma/2.0*
695        cos((double) (2.0*MagickPI*beta));
696      break;
697    }
698    case ImpulseNoise:
699    {
700      if (alpha < (SigmaImpulse/2.0))
701        noise=0.0;
702       else
703         if (alpha >= (1.0-(SigmaImpulse/2.0)))
704           noise=(MagickRealType) QuantumRange;
705         else
706           noise=(MagickRealType) pixel;
707      break;
708    }
709    case LaplacianNoise:
710    {
711      if (alpha <= 0.5)
712        {
713          if (alpha <= NoiseEpsilon)
714            noise=(MagickRealType) pixel-(MagickRealType) QuantumRange;
715          else
716            noise=(MagickRealType) pixel+ScaleCharToQuantum((unsigned char)
717              (SigmaLaplacian*log((double) (2.0*alpha))+0.5));
718          break;
719        }
720      beta=1.0-alpha;
721      if (beta <= (0.5*NoiseEpsilon))
722        noise=(MagickRealType) (pixel+QuantumRange);
723      else
724        noise=(MagickRealType) pixel-ScaleCharToQuantum((unsigned char)
725          (SigmaLaplacian*log((double) (2.0*beta))+0.5));
726      break;
727    }
728    case PoissonNoise:
729    {
730      MagickRealType
731        poisson;
732
733      register long
734        i;
735
736      poisson=exp(-SigmaPoisson*(double) ScaleQuantumToChar(pixel));
737      for (i=0; alpha > poisson; i++)
738      {
739        beta=GetRandomValue();
740        alpha=alpha*beta;
741      }
742      noise=(MagickRealType) ScaleCharToQuantum((unsigned char)
743        (i/SigmaPoisson));
744      break;
745    }
746    case RandomNoise:
747    {
748      noise=(MagickRealType) QuantumRange*GetRandomValue();
749      break;
750    }
751  }
752  return(RoundToQuantum(noise));
753}
754
755MagickExport Image *AddNoiseImage(const Image *image,const NoiseType noise_type,
756  ExceptionInfo *exception)
757{
758  Image
759    *noise_image;
760
761  noise_image=AddNoiseImageChannel(image,DefaultChannels,noise_type,exception);
762  return(noise_image);
763}
764
765MagickExport Image *AddNoiseImageChannel(const Image *image,
766  const ChannelType channel,const NoiseType noise_type,ExceptionInfo *exception)
767{
768#define AddNoiseImageTag  "AddNoise/Image"
769
770  const char
771    *option;
772
773  Image
774    *noise_image;
775
776  long
777    y;
778
779  MagickBooleanType
780    status;
781
782  MagickRealType
783    attenuate;
784
785  register const IndexPacket
786    *indexes;
787
788  register const PixelPacket
789    *pixels;
790
791  register IndexPacket
792    *noise_indexes;
793
794  register long
795    x;
796
797  register PixelPacket
798    *noise_pixels;
799
800  /*
801    Initialize noise image attributes.
802  */
803  assert(image != (const Image *) NULL);
804  assert(image->signature == MagickSignature);
805  if (image->debug != MagickFalse)
806    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
807  assert(exception != (ExceptionInfo *) NULL);
808  assert(exception->signature == MagickSignature);
809  noise_image=CloneImage(image,0,0,MagickTrue,exception);
810  if (noise_image == (Image *) NULL)
811    return((Image *) NULL);
812  if (SetImageStorageClass(noise_image,DirectClass) == MagickFalse)
813    {
814      InheritException(exception,&noise_image->exception);
815      noise_image=DestroyImage(noise_image);
816      return((Image *) NULL);
817    }
818  /*
819    Add noise in each row.
820  */
821  attenuate=1.0;
822  option=GetImageProperty(image,"attenuate");
823  if (option != (char *) NULL)
824    attenuate=atof(option);
825  for (y=0; y < (long) image->rows; y++)
826  {
827    pixels=AcquireImagePixels(image,0,y,image->columns,1,exception);
828    noise_pixels=GetImagePixels(noise_image,0,y,noise_image->columns,1);
829    if ((pixels == (PixelPacket *) NULL) ||
830        (noise_pixels == (PixelPacket *) NULL))
831      break;
832    indexes=AcquireIndexes(image);
833    noise_indexes=GetIndexes(noise_image);
834    for (x=0; x < (long) image->columns; x++)
835    {
836      if ((channel & RedChannel) != 0)
837        noise_pixels[x].red=GenerateNoise(pixels[x].red,noise_type,attenuate);
838      if ((channel & GreenChannel) != 0)
839        noise_pixels[x].green=GenerateNoise(pixels[x].green,noise_type,
840          attenuate);
841      if ((channel & BlueChannel) != 0)
842        noise_pixels[x].blue=GenerateNoise(pixels[x].blue,noise_type,attenuate);
843      if ((channel & OpacityChannel) != 0)
844        noise_pixels[x].opacity=GenerateNoise(pixels[x].opacity,noise_type,
845          attenuate);
846      if (((channel & IndexChannel) != 0) &&
847          (image->colorspace == CMYKColorspace))
848        noise_indexes[x]=(IndexPacket) GenerateNoise(indexes[x],noise_type,
849          attenuate);
850    }
851    if (SyncImagePixels(noise_image) == MagickFalse)
852      break;
853    if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
854        (QuantumTick(y,image->rows) != MagickFalse))
855      {
856        status=image->progress_monitor(AddNoiseImageTag,y,image->rows,
857          image->client_data);
858        if (status == MagickFalse)
859          break;
860      }
861  }
862  return(noise_image);
863}
864
865/*
866%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
867%                                                                             %
868%                                                                             %
869%                                                                             %
870%     B l u r I m a g e                                                       %
871%                                                                             %
872%                                                                             %
873%                                                                             %
874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875%
876%  BlurImage() blurs an image.  We convolve the image with a Gaussian operator
877%  of the given radius and standard deviation (sigma).  For reasonable results,
878%  the radius should be larger than sigma.  Use a radius of 0 and BlurImage()
879%  selects a suitable radius for you.
880%
881%  BlurImage() differs from GaussianBlurImage() in that it uses a separable
882%  kernel which is faster but mathematically equivalent to the non-separable
883%  kernel.
884%
885%  The format of the BlurImage method is:
886%
887%      Image *BlurImage(const Image *image,const double radius,
888%        const double sigma,ExceptionInfo *exception)
889%      Image *BlurImageChannel(const Image *image,const ChannelType channel,
890%        const double radius,const double sigma,ExceptionInfo *exception)
891%
892%  A description of each parameter follows:
893%
894%    o image: The image.
895%
896%    o channel: The channel type.
897%
898%    o radius: The radius of the Gaussian, in pixels, not counting the center
899%      pixel.
900%
901%    o sigma: The standard deviation of the Gaussian, in pixels.
902%
903%    o exception: Return any errors or warnings in this structure.
904%
905*/
906
907MagickExport Image *BlurImage(const Image *image,const double radius,
908  const double sigma,ExceptionInfo *exception)
909{
910  Image
911    *blur_image;
912
913  blur_image=BlurImageChannel(image,DefaultChannels,radius,sigma,exception);
914  return(blur_image);
915}
916
917static double *GetBlurKernel(unsigned long width,const MagickRealType sigma)
918{
919#define KernelRank 3
920
921  double
922    *kernel;
923
924  long
925    bias;
926
927  MagickRealType
928    alpha,
929    normalize;
930
931  register long
932    i;
933
934  /*
935    Generate a 1-D convolution kernel.
936  */
937  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
938  kernel=(double *) AcquireQuantumMemory((size_t) width,sizeof(*kernel));
939  if (kernel == (double *) NULL)
940    return(0);
941  (void) ResetMagickMemory(kernel,0,(size_t) width*sizeof(*kernel));
942  bias=KernelRank*(long) width/2;
943  for (i=(-bias); i <= bias; i++)
944  {
945    alpha=exp((-((double) (i*i))/(double) (2.0*KernelRank*KernelRank*
946      sigma*sigma)));
947    kernel[(i+bias)/KernelRank]+=(double) (alpha/(MagickSQ2PI*sigma));
948  }
949  normalize=0.0;
950  for (i=0; i < (long) width; i++)
951    normalize+=kernel[i];
952  for (i=0; i < (long) width; i++)
953    kernel[i]/=normalize;
954  return(kernel);
955}
956
957MagickExport Image *BlurImageChannel(const Image *image,
958  const ChannelType channel,const double radius,const double sigma,
959  ExceptionInfo *exception)
960{
961#define BlurImageTag  "Blur/Image"
962
963  double
964    *kernel;
965
966  Image
967    *blur_image;
968
969  IndexPacket
970    *blur_indexes;
971
972  long
973    y;
974
975  MagickBooleanType
976    status;
977
978  MagickPixelPacket
979    pixel;
980
981  MagickOffsetType
982    offset;
983
984  MagickRealType
985    alpha,
986    gamma;
987
988  register const IndexPacket
989    *indexes;
990
991  register const PixelPacket
992    *pixels;
993
994  register const double
995    *k;
996
997  register long
998    i,
999    x;
1000
1001  register PixelPacket
1002    *blur_pixels;
1003
1004  unsigned long
1005    width;
1006
1007  ViewInfo
1008    *image_view;
1009
1010  /*
1011    Initialize blur image attributes.
1012  */
1013  assert(image != (Image *) NULL);
1014  assert(image->signature == MagickSignature);
1015  if (image->debug != MagickFalse)
1016    (void) LogMagickEvent(TraceEvent,GetMagickM