~ubuntu-branches/ubuntu/oneiric/imagemagick/oneiric-updates

« back to all changes in this revision

Viewing changes to magick/effect.c

  • Committer: Bazaar Package Importer
  • Author(s): Nelson A. de Oliveira
  • Date: 2010-06-20 19:59:55 UTC
  • mfrom: (6.2.8 sid)
  • Revision ID: james.westby@ubuntu.com-20100620195955-n3eq0yenhycw888i
Tags: 7:6.6.2.6-1
* New upstream release;
* Change Recommends on ufraw to ufraw-batch (Closes: #579775);
* Fix FTBFS when using dash to run the configure script, by setting
  CONFIG_SHELL=/bin/bash (Closes: #582073, #583024). Thank you, Niko Tyni!

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
%                                 October 1996                                %
18
18
%                                                                             %
19
19
%                                                                             %
20
 
%  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
 
20
%  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
21
21
%  dedicated to making software imaging solutions freely available.           %
22
22
%                                                                             %
23
23
%  You may not use this file except in compliance with the License.  You may  %
41
41
  Include declarations.
42
42
*/
43
43
#include "magick/studio.h"
44
 
#include "magick/property.h"
 
44
#include "magick/accelerate.h"
45
45
#include "magick/blob.h"
46
46
#include "magick/cache-view.h"
47
47
#include "magick/color.h"
64
64
#include "magick/monitor.h"
65
65
#include "magick/monitor-private.h"
66
66
#include "magick/montage.h"
 
67
#include "magick/morphology.h"
67
68
#include "magick/paint.h"
68
69
#include "magick/pixel-private.h"
69
70
#include "magick/property.h"
141
142
#define AdaptiveBlurImageTag  "Convolve/Image"
142
143
#define MagickSigma  (fabs(sigma) <= MagickEpsilon ? 1.0 : sigma)
143
144
 
 
145
  CacheView
 
146
    *blur_view,
 
147
    *edge_view,
 
148
    *image_view;
 
149
 
144
150
  double
145
 
    **kernel;
 
151
    **kernel,
 
152
    normalize;
146
153
 
147
154
  Image
148
155
    *blur_image,
149
156
    *edge_image,
150
157
    *gaussian_image;
151
158
 
152
 
  long
153
 
    j,
154
 
    progress,
155
 
    y;
156
 
 
157
159
  MagickBooleanType
158
160
    status;
159
161
 
 
162
  MagickOffsetType
 
163
    progress;
 
164
 
160
165
  MagickPixelPacket
161
166
    bias;
162
167
 
163
 
  MagickRealType
164
 
    alpha,
165
 
    normalize;
166
 
 
167
 
  register long
168
 
    i,
 
168
  register ssize_t
 
169
    i;
 
170
 
 
171
  size_t
 
172
    width;
 
173
 
 
174
  ssize_t
 
175
    j,
 
176
    k,
169
177
    u,
170
 
    v;
171
 
 
172
 
  unsigned long
173
 
    width;
174
 
 
175
 
  CacheView
176
 
    *blur_view,
177
 
    *edge_view,
178
 
    *image_view;
 
178
    v,
 
179
    y;
179
180
 
180
181
  assert(image != (const Image *) NULL);
181
182
  assert(image->signature == MagickSignature);
223
224
      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
224
225
    }
225
226
  (void) ResetMagickMemory(kernel,0,(size_t) width*sizeof(*kernel));
226
 
  for (i=0; i < (long) width; i+=2)
 
227
  for (i=0; i < (ssize_t) width; i+=2)
227
228
  {
228
229
    kernel[i]=(double *) AcquireQuantumMemory((size_t) (width-i),(width-i)*
229
230
      sizeof(**kernel));
230
231
    if (kernel[i] == (double *) NULL)
231
232
      break;
232
 
    j=0;
233
 
    for (v=(-((long) (width-i)/2)); v <= (long) ((width-i)/2); v++)
 
233
    normalize=0.0;
 
234
    j=(ssize_t) (width-i)/2;
 
235
    k=0;
 
236
    for (v=(-j); v <= j; v++)
234
237
    {
235
 
      for (u=(-((long) (width-i)/2)); u <= (long) ((width-i)/2); u++)
 
238
      for (u=(-j); u <= j; u++)
236
239
      {
237
 
        alpha=exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma));
238
 
        kernel[i][j]=(double) (alpha/(2.0*MagickPI*MagickSigma*MagickSigma));
239
 
        j++;
 
240
        kernel[i][k]=exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma))/
 
241
          (2.0*MagickPI*MagickSigma*MagickSigma);
 
242
        normalize+=kernel[i][k];
 
243
        k++;
240
244
      }
241
245
    }
242
 
    normalize=0.0;
243
 
    for (j=0; j < (long) ((width-i)*(width-i)); j++)
244
 
      normalize+=kernel[i][j];
245
246
    if (fabs(normalize) <= MagickEpsilon)
246
247
      normalize=1.0;
247
248
    normalize=1.0/normalize;
248
 
    for (j=0; j < (long) ((width-i)*(width-i)); j++)
249
 
      kernel[i][j]=(double) (normalize*kernel[i][j]);
 
249
    for (k=0; k < (j*j); k++)
 
250
      kernel[i][k]=normalize*kernel[i][k];
250
251
  }
251
 
  if (i < (long) width)
 
252
  if (i < (ssize_t) width)
252
253
    {
253
254
      for (i-=2; i >= 0; i-=2)
254
255
        kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
270
271
#if defined(MAGICKCORE_OPENMP_SUPPORT)
271
272
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
272
273
#endif
273
 
  for (y=0; y < (long) blur_image->rows; y++)
 
274
  for (y=0; y < (ssize_t) blur_image->rows; y++)
274
275
  {
275
276
    register const IndexPacket
276
 
      *__restrict indexes;
 
277
      *restrict indexes;
277
278
 
278
279
    register const PixelPacket
279
 
      *__restrict p,
280
 
      *__restrict r;
 
280
      *restrict p,
 
281
      *restrict r;
281
282
 
282
283
    register IndexPacket
283
 
      *__restrict blur_indexes;
 
284
      *restrict blur_indexes;
284
285
 
285
 
    register long
 
286
    register ssize_t
286
287
      x;
287
288
 
288
289
    register PixelPacket
289
 
      *__restrict q;
 
290
      *restrict q;
290
291
 
291
292
    if (status == MagickFalse)
292
293
      continue;
299
300
        continue;
300
301
      }
301
302
    blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
302
 
    for (x=0; x < (long) blur_image->columns; x++)
 
303
    for (x=0; x < (ssize_t) blur_image->columns; x++)
303
304
    {
304
305
      MagickPixelPacket
305
306
        pixel;
309
310
        gamma;
310
311
 
311
312
      register const double
312
 
        *__restrict k;
 
313
        *restrict k;
313
314
 
314
 
      register long
 
315
      register ssize_t
315
316
        i,
316
317
        u,
317
318
        v;
318
319
 
319
320
      gamma=0.0;
320
 
      i=(long) (width*QuantumScale*PixelIntensity(r)+0.5);
 
321
      i=(ssize_t) ceil((double) width*QuantumScale*PixelIntensity(r)-0.5);
321
322
      if (i < 0)
322
323
        i=0;
323
324
      else
324
 
        if (i > (long) width)
325
 
          i=(long) width;
 
325
        if (i > (ssize_t) width)
 
326
          i=(ssize_t) width;
326
327
      if ((i & 0x01) != 0)
327
328
        i--;
328
 
      p=GetCacheViewVirtualPixels(image_view,x-((long) (width-i)/2L),y-(long)
 
329
      p=GetCacheViewVirtualPixels(image_view,x-((ssize_t) (width-i)/2L),y-(ssize_t)
329
330
        ((width-i)/2L),width-i,width-i,exception);
330
331
      if (p == (const PixelPacket *) NULL)
331
332
        break;
332
333
      indexes=GetCacheViewVirtualIndexQueue(image_view);
333
334
      pixel=bias;
334
335
      k=kernel[i];
335
 
      for (v=0; v < (long) (width-i); v++)
 
336
      for (v=0; v < (ssize_t) (width-i); v++)
336
337
      {
337
 
        for (u=0; u < (long) (width-i); u++)
 
338
        for (u=0; u < (ssize_t) (width-i); u++)
338
339
        {
339
340
          alpha=1.0;
340
341
          if (((channel & OpacityChannel) != 0) &&
341
342
              (image->matte != MagickFalse))
342
 
            alpha=(MagickRealType) (QuantumScale*(QuantumRange-p->opacity));
 
343
            alpha=(MagickRealType) (QuantumScale*GetAlphaPixelComponent(p));
343
344
          if ((channel & RedChannel) != 0)
344
 
            pixel.red+=(*k)*alpha*p->red;
 
345
            pixel.red+=(*k)*alpha*GetRedPixelComponent(p);
345
346
          if ((channel & GreenChannel) != 0)
346
 
            pixel.green+=(*k)*alpha*p->green;
 
347
            pixel.green+=(*k)*alpha*GetGreenPixelComponent(p);
347
348
          if ((channel & BlueChannel) != 0)
348
 
            pixel.blue+=(*k)*alpha*p->blue;
 
349
            pixel.blue+=(*k)*alpha*GetBluePixelComponent(p);
349
350
          if ((channel & OpacityChannel) != 0)
350
 
            pixel.opacity+=(*k)*p->opacity;
 
351
            pixel.opacity+=(*k)*GetOpacityPixelComponent(p);
351
352
          if (((channel & IndexChannel) != 0) &&
352
353
              (image->colorspace == CMYKColorspace))
353
354
            pixel.index+=(*k)*alpha*indexes[x+(width-i)*v+u];
358
359
      }
359
360
      gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
360
361
      if ((channel & RedChannel) != 0)
361
 
        q->red=RoundToQuantum(gamma*pixel.red);
 
362
        q->red=ClampToQuantum(gamma*GetRedPixelComponent(&pixel));
362
363
      if ((channel & GreenChannel) != 0)
363
 
        q->green=RoundToQuantum(gamma*pixel.green);
 
364
        q->green=ClampToQuantum(gamma*GetGreenPixelComponent(&pixel));
364
365
      if ((channel & BlueChannel) != 0)
365
 
        q->blue=RoundToQuantum(gamma*pixel.blue);
 
366
        q->blue=ClampToQuantum(gamma*GetBluePixelComponent(&pixel));
366
367
      if ((channel & OpacityChannel) != 0)
367
 
        q->opacity=RoundToQuantum(pixel.opacity);
 
368
        SetOpacityPixelComponent(q,ClampOpacityPixelComponent(&pixel));
368
369
      if (((channel & IndexChannel) != 0) &&
369
370
          (image->colorspace == CMYKColorspace))
370
 
        blur_indexes[x]=RoundToQuantum(gamma*pixel.index);
 
371
        blur_indexes[x]=ClampToQuantum(gamma*GetIndexPixelComponent(&pixel));
371
372
      q++;
372
373
      r++;
373
374
    }
392
393
  edge_view=DestroyCacheView(edge_view);
393
394
  image_view=DestroyCacheView(image_view);
394
395
  edge_image=DestroyImage(edge_image);
395
 
  for (i=0; i < (long) width;  i+=2)
 
396
  for (i=0; i < (ssize_t) width;  i+=2)
396
397
    kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
397
398
  kernel=(double **) RelinquishMagickMemory(kernel);
398
399
  if (status == MagickFalse)
458
459
#define AdaptiveSharpenImageTag  "Convolve/Image"
459
460
#define MagickSigma  (fabs(sigma) <= MagickEpsilon ? 1.0 : sigma)
460
461
 
 
462
  CacheView
 
463
    *sharp_view,
 
464
    *edge_view,
 
465
    *image_view;
 
466
 
461
467
  double
462
 
    **kernel;
 
468
    **kernel,
 
469
    normalize;
463
470
 
464
471
  Image
465
472
    *sharp_image,
466
473
    *edge_image,
467
474
    *gaussian_image;
468
475
 
469
 
  long
470
 
    j,
471
 
    progress,
472
 
    y;
473
 
 
474
476
  MagickBooleanType
475
477
    status;
476
478
 
 
479
  MagickOffsetType
 
480
    progress;
 
481
 
477
482
  MagickPixelPacket
478
483
    bias;
479
484
 
480
 
  MagickRealType
481
 
    alpha,
482
 
    normalize;
483
 
 
484
 
  register long
485
 
    i,
 
485
  register ssize_t
 
486
    i;
 
487
 
 
488
  size_t
 
489
    width;
 
490
 
 
491
  ssize_t
 
492
    j,
 
493
    k,
486
494
    u,
487
 
    v;
488
 
 
489
 
  unsigned long
490
 
    width;
491
 
 
492
 
  CacheView
493
 
    *sharp_view,
494
 
    *edge_view,
495
 
    *image_view;
 
495
    v,
 
496
    y;
496
497
 
497
498
  assert(image != (const Image *) NULL);
498
499
  assert(image->signature == MagickSignature);
540
541
      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
541
542
    }
542
543
  (void) ResetMagickMemory(kernel,0,(size_t) width*sizeof(*kernel));
543
 
  for (i=0; i < (long) width; i+=2)
 
544
  for (i=0; i < (ssize_t) width; i+=2)
544
545
  {
545
546
    kernel[i]=(double *) AcquireQuantumMemory((size_t) (width-i),(width-i)*
546
547
      sizeof(**kernel));
547
548
    if (kernel[i] == (double *) NULL)
548
549
      break;
549
 
    j=0;
550
 
    for (v=(-((long) (width-i)/2)); v <= (long) ((width-i)/2); v++)
 
550
    normalize=0.0;
 
551
    j=(ssize_t) (width-i)/2;
 
552
    k=0;
 
553
    for (v=(-j); v <= j; v++)
551
554
    {
552
 
      for (u=(-((long) (width-i)/2)); u <= (long) ((width-i)/2); u++)
 
555
      for (u=(-j); u <= j; u++)
553
556
      {
554
 
        alpha=exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma));
555
 
        kernel[i][j]=(double) (-alpha/(2.0*MagickPI*MagickSigma*MagickSigma));
556
 
        j++;
 
557
        kernel[i][k]=(-exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma))/
 
558
          (2.0*MagickPI*MagickSigma*MagickSigma));
 
559
        normalize+=kernel[i][k];
 
560
        k++;
557
561
      }
558
562
    }
559
 
    normalize=0.0;
560
 
    for (j=0; j < (long) ((width-i)*(width-i)); j++)
561
 
      normalize+=kernel[i][j];
562
563
    if (fabs(normalize) <= MagickEpsilon)
563
564
      normalize=1.0;
564
565
    normalize=1.0/normalize;
565
 
    for (j=0; j < (long) ((width-i)*(width-i)); j++)
566
 
      kernel[i][j]=(double) (normalize*kernel[i][j]);
 
566
    for (k=0; k < (j*j); k++)
 
567
      kernel[i][k]=normalize*kernel[i][k];
567
568
  }
568
 
  if (i < (long) width)
 
569
  if (i < (ssize_t) width)
569
570
    {
570
571
      for (i-=2; i >= 0; i-=2)
571
572
        kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
587
588
#if defined(MAGICKCORE_OPENMP_SUPPORT)
588
589
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
589
590
#endif
590
 
  for (y=0; y < (long) sharp_image->rows; y++)
 
591
  for (y=0; y < (ssize_t) sharp_image->rows; y++)
591
592
  {
592
593
    register const IndexPacket
593
 
      *__restrict indexes;
 
594
      *restrict indexes;
594
595
 
595
596
    register const PixelPacket
596
 
      *__restrict p,
597
 
      *__restrict r;
 
597
      *restrict p,
 
598
      *restrict r;
598
599
 
599
600
    register IndexPacket
600
 
      *__restrict sharp_indexes;
 
601
      *restrict sharp_indexes;
601
602
 
602
 
    register long
 
603
    register ssize_t
603
604
      x;
604
605
 
605
606
    register PixelPacket
606
 
      *__restrict q;
 
607
      *restrict q;
607
608
 
608
609
    if (status == MagickFalse)
609
610
      continue;
616
617
        continue;
617
618
      }
618
619
    sharp_indexes=GetCacheViewAuthenticIndexQueue(sharp_view);
619
 
    for (x=0; x < (long) sharp_image->columns; x++)
 
620
    for (x=0; x < (ssize_t) sharp_image->columns; x++)
620
621
    {
621
622
      MagickPixelPacket
622
623
        pixel;
626
627
        gamma;
627
628
 
628
629
      register const double
629
 
        *__restrict k;
 
630
        *restrict k;
630
631
 
631
 
      register long
 
632
      register ssize_t
632
633
        i,
633
634
        u,
634
635
        v;
635
636
 
636
637
      gamma=0.0;
637
 
      i=(long) (width*(QuantumRange-QuantumScale*PixelIntensity(r))+0.5);
 
638
      i=(ssize_t) ceil((double) width*(QuantumRange-QuantumScale*
 
639
        PixelIntensity(r))-0.5);
638
640
      if (i < 0)
639
641
        i=0;
640
642
      else
641
 
        if (i > (long) width)
642
 
          i=(long) width;
 
643
        if (i > (ssize_t) width)
 
644
          i=(ssize_t) width;
643
645
      if ((i & 0x01) != 0)
644
646
        i--;
645
 
      p=GetCacheViewVirtualPixels(image_view,x-((long) (width-i)/2L),y-(long)
 
647
      p=GetCacheViewVirtualPixels(image_view,x-((ssize_t) (width-i)/2L),y-(ssize_t)
646
648
        ((width-i)/2L),width-i,width-i,exception);
647
649
      if (p == (const PixelPacket *) NULL)
648
650
        break;
649
651
      indexes=GetCacheViewVirtualIndexQueue(image_view);
650
652
      k=kernel[i];
651
653
      pixel=bias;
652
 
      for (v=0; v < (long) (width-i); v++)
 
654
      for (v=0; v < (ssize_t) (width-i); v++)
653
655
      {
654
 
        for (u=0; u < (long) (width-i); u++)
 
656
        for (u=0; u < (ssize_t) (width-i); u++)
655
657
        {
656
658
          alpha=1.0;
657
659
          if (((channel & OpacityChannel) != 0) &&
658
660
              (image->matte != MagickFalse))
659
 
            alpha=(MagickRealType) (QuantumScale*(QuantumRange-p->opacity));
 
661
            alpha=(MagickRealType) (QuantumScale*GetAlphaPixelComponent(p));
660
662
          if ((channel & RedChannel) != 0)
661
 
            pixel.red+=(*k)*alpha*p->red;
 
663
            pixel.red+=(*k)*alpha*GetRedPixelComponent(p);
662
664
          if ((channel & GreenChannel) != 0)
663
 
            pixel.green+=(*k)*alpha*p->green;
 
665
            pixel.green+=(*k)*alpha*GetGreenPixelComponent(p);
664
666
          if ((channel & BlueChannel) != 0)
665
 
            pixel.blue+=(*k)*alpha*p->blue;
 
667
            pixel.blue+=(*k)*alpha*GetBluePixelComponent(p);
666
668
          if ((channel & OpacityChannel) != 0)
667
 
            pixel.opacity+=(*k)*p->opacity;
 
669
            pixel.opacity+=(*k)*GetOpacityPixelComponent(p);
668
670
          if (((channel & IndexChannel) != 0) &&
669
671
              (image->colorspace == CMYKColorspace))
670
672
            pixel.index+=(*k)*alpha*indexes[x+(width-i)*v+u];
675
677
      }
676
678
      gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
677
679
      if ((channel & RedChannel) != 0)
678
 
        q->red=RoundToQuantum(gamma*pixel.red);
 
680
        q->red=ClampToQuantum(gamma*GetRedPixelComponent(&pixel));
679
681
      if ((channel & GreenChannel) != 0)
680
 
        q->green=RoundToQuantum(gamma*pixel.green);
 
682
        q->green=ClampToQuantum(gamma*GetGreenPixelComponent(&pixel));
681
683
      if ((channel & BlueChannel) != 0)
682
 
        q->blue=RoundToQuantum(gamma*pixel.blue);
 
684
        q->blue=ClampToQuantum(gamma*GetBluePixelComponent(&pixel));
683
685
      if ((channel & OpacityChannel) != 0)
684
 
        q->opacity=RoundToQuantum(pixel.opacity);
 
686
        SetOpacityPixelComponent(q,ClampOpacityPixelComponent(&pixel));
685
687
      if (((channel & IndexChannel) != 0) &&
686
688
          (image->colorspace == CMYKColorspace))
687
 
        sharp_indexes[x]=RoundToQuantum(gamma*pixel.index);
 
689
        sharp_indexes[x]=ClampToQuantum(gamma*GetIndexPixelComponent(&pixel));
688
690
      q++;
689
691
      r++;
690
692
    }
709
711
  edge_view=DestroyCacheView(edge_view);
710
712
  image_view=DestroyCacheView(image_view);
711
713
  edge_image=DestroyImage(edge_image);
712
 
  for (i=0; i < (long) width;  i+=2)
 
714
  for (i=0; i < (ssize_t) width;  i+=2)
713
715
    kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
714
716
  kernel=(double **) RelinquishMagickMemory(kernel);
715
717
  if (status == MagickFalse)
769
771
  return(blur_image);
770
772
}
771
773
 
772
 
static double *GetBlurKernel(unsigned long width,const MagickRealType sigma)
 
774
static double *GetBlurKernel(const size_t width,const double sigma)
773
775
{
774
 
#define KernelRank 3
775
 
 
776
776
  double
777
 
    *kernel;
778
 
 
779
 
  long
780
 
    bias;
781
 
 
782
 
  MagickRealType
783
 
    alpha,
 
777
    *kernel,
784
778
    normalize;
785
779
 
786
 
  register long
 
780
  ssize_t
 
781
    j,
 
782
    k;
 
783
 
 
784
  register ssize_t
787
785
    i;
788
786
 
789
787
  /*
793
791
  kernel=(double *) AcquireQuantumMemory((size_t) width,sizeof(*kernel));
794
792
  if (kernel == (double *) NULL)
795
793
    return(0);
796
 
  (void) ResetMagickMemory(kernel,0,(size_t) width*sizeof(*kernel));
797
 
  bias=KernelRank*(long) width/2;
798
 
  for (i=(-bias); i <= bias; i++)
 
794
  normalize=0.0;
 
795
  j=(ssize_t) width/2;
 
796
  i=0;
 
797
  for (k=(-j); k <= j; k++)
799
798
  {
800
 
    alpha=exp((-((double) (i*i))/(double) (2.0*KernelRank*KernelRank*
801
 
      MagickSigma*MagickSigma)));
802
 
    kernel[(i+bias)/KernelRank]+=(double) (alpha/(MagickSQ2PI*sigma));
 
799
    kernel[i]=exp(-((double) k*k)/(2.0*MagickSigma*MagickSigma))/
 
800
      (MagickSQ2PI*MagickSigma);
 
801
    normalize+=kernel[i];
 
802
    i++;
803
803
  }
804
 
  normalize=0.0;
805
 
  for (i=0; i < (long) width; i++)
806
 
    normalize+=kernel[i];
807
 
  for (i=0; i < (long) width; i++)
 
804
  for (i=0; i < (ssize_t) width; i++)
808
805
    kernel[i]/=normalize;
809
806
  return(kernel);
810
807
}
815
812
{
816
813
#define BlurImageTag  "Blur/Image"
817
814
 
 
815
  CacheView
 
816
    *blur_view,
 
817
    *image_view;
 
818
 
818
819
  double
819
820
    *kernel;
820
821
 
821
822
  Image
822
823
    *blur_image;
823
824
 
824
 
  long
825
 
    progress,
 
825
  MagickBooleanType
 
826
    status;
 
827
 
 
828
  MagickOffsetType
 
829
    progress;
 
830
 
 
831
  MagickPixelPacket
 
832
    bias;
 
833
 
 
834
  register ssize_t
 
835
    i;
 
836
 
 
837
  size_t
 
838
    width;
 
839
 
 
840
  ssize_t
826
841
    x,
827
842
    y;
828
843
 
829
 
  MagickBooleanType
830
 
    status;
831
 
 
832
 
  MagickPixelPacket
833
 
    bias;
834
 
 
835
 
  register long
836
 
    i;
837
 
 
838
 
  unsigned long
839
 
    width;
840
 
 
841
 
  CacheView
842
 
    *blur_view,
843
 
    *image_view;
844
 
 
845
844
  /*
846
845
    Initialize blur image attributes.
847
846
  */
879
878
        *k;
880
879
 
881
880
      (void) LogMagickEvent(TransformEvent,GetMagickModule(),
882
 
        "  BlurImage with %ld kernel:",width);
 
881
        "  BlurImage with %.20g kernel:",(double) width);
883
882
      message=AcquireString("");
884
883
      k=kernel;
885
 
      for (i=0; i < (long) width; i++)
 
884
      for (i=0; i < (ssize_t) width; i++)
886
885
      {
887
886
        *message='\0';
888
 
        (void) FormatMagickString(format,MaxTextExtent,"%ld: ",i);
 
887
        (void) FormatMagickString(format,MaxTextExtent,"%.20g: ",(double) i);
889
888
        (void) ConcatenateString(&message,format);
890
889
        (void) FormatMagickString(format,MaxTextExtent,"%g ",*k++);
891
890
        (void) ConcatenateString(&message,format);
905
904
#if defined(MAGICKCORE_OPENMP_SUPPORT)
906
905
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
907
906
#endif
908
 
  for (y=0; y < (long) blur_image->rows; y++)
 
907
  for (y=0; y < (ssize_t) blur_image->rows; y++)
909
908
  {
910
909
    register const IndexPacket
911
 
      *__restrict indexes;
 
910
      *restrict indexes;
912
911
 
913
912
    register const PixelPacket
914
 
      *__restrict p;
 
913
      *restrict p;
915
914
 
916
915
    register IndexPacket
917
 
      *__restrict blur_indexes;
 
916
      *restrict blur_indexes;
918
917
 
919
 
    register long
 
918
    register ssize_t
920
919
      x;
921
920
 
922
921
    register PixelPacket
923
 
      *__restrict q;
 
922
      *restrict q;
924
923
 
925
924
    if (status == MagickFalse)
926
925
      continue;
927
 
    p=GetCacheViewVirtualPixels(image_view,-((long) width/2L),y,image->columns+
 
926
    p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y,image->columns+
928
927
      width,1,exception);
929
928
    q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
930
929
      exception);
935
934
      }
936
935
    indexes=GetCacheViewVirtualIndexQueue(image_view);
937
936
    blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
938
 
    for (x=0; x < (long) blur_image->columns; x++)
 
937
    for (x=0; x < (ssize_t) blur_image->columns; x++)
939
938
    {
940
939
      MagickPixelPacket
941
940
        pixel;
942
941
 
943
942
      register const double
944
 
        *__restrict k;
 
943
        *restrict k;
945
944
 
946
945
      register const PixelPacket
947
 
        *__restrict kernel_pixels;
 
946
        *restrict kernel_pixels;
948
947
 
949
 
      register long
 
948
      register ssize_t
950
949
        i;
951
950
 
952
951
      pixel=bias;
954
953
      kernel_pixels=p;
955
954
      if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
956
955
        {
957
 
          for (i=0; i < (long) width; i++)
 
956
          for (i=0; i < (ssize_t) width; i++)
958
957
          {
959
958
            pixel.red+=(*k)*kernel_pixels->red;
960
959
            pixel.green+=(*k)*kernel_pixels->green;
963
962
            kernel_pixels++;
964
963
          }
965
964
          if ((channel & RedChannel) != 0)
966
 
            q->red=RoundToQuantum(pixel.red);
 
965
            SetRedPixelComponent(q,ClampRedPixelComponent(&pixel));
967
966
          if ((channel & GreenChannel) != 0)
968
 
            q->green=RoundToQuantum(pixel.green);
 
967
            SetGreenPixelComponent(q,ClampGreenPixelComponent(&pixel));
969
968
          if ((channel & BlueChannel) != 0)
970
 
            q->blue=RoundToQuantum(pixel.blue);
 
969
            SetBluePixelComponent(q,ClampBluePixelComponent(&pixel));
971
970
          if ((channel & OpacityChannel) != 0)
972
971
            {
973
972
              k=kernel;
974
973
              kernel_pixels=p;
975
 
              for (i=0; i < (long) width; i++)
 
974
              for (i=0; i < (ssize_t) width; i++)
976
975
              {
977
976
                pixel.opacity+=(*k)*kernel_pixels->opacity;
978
977
                k++;
979
978
                kernel_pixels++;
980
979
              }
981
 
              q->opacity=RoundToQuantum(pixel.opacity);
 
980
              SetOpacityPixelComponent(q,ClampOpacityPixelComponent(&pixel));
982
981
            }
983
982
          if (((channel & IndexChannel) != 0) &&
984
983
              (image->colorspace == CMYKColorspace))
985
984
            {
986
985
              register const IndexPacket
987
 
                *__restrict kernel_indexes;
 
986
                *restrict kernel_indexes;
988
987
 
989
988
              k=kernel;
990
989
              kernel_indexes=indexes;
991
 
              for (i=0; i < (long) width; i++)
 
990
              for (i=0; i < (ssize_t) width; i++)
992
991
              {
993
992
                pixel.index+=(*k)*(*kernel_indexes);
994
993
                k++;
995
994
                kernel_indexes++;
996
995
              }
997
 
              blur_indexes[x]=RoundToQuantum(pixel.index);
 
996
              blur_indexes[x]=ClampToQuantum(pixel.index);
998
997
            }
999
998
        }
1000
999
      else
1004
1003
            gamma;
1005
1004
 
1006
1005
          gamma=0.0;
1007
 
          for (i=0; i < (long) width; i++)
 
1006
          for (i=0; i < (ssize_t) width; i++)
1008
1007
          {
1009
 
            alpha=(MagickRealType) (QuantumScale*(QuantumRange-
1010
 
              kernel_pixels->opacity));
 
1008
            alpha=(MagickRealType) (QuantumScale*
 
1009
              GetAlphaPixelComponent(kernel_pixels));
1011
1010
            pixel.red+=(*k)*alpha*kernel_pixels->red;
1012
1011
            pixel.green+=(*k)*alpha*kernel_pixels->green;
1013
1012
            pixel.blue+=(*k)*alpha*kernel_pixels->blue;
1017
1016
          }
1018
1017
          gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
1019
1018
          if ((channel & RedChannel) != 0)
1020
 
            q->red=RoundToQuantum(gamma*pixel.red);
 
1019
            q->red=ClampToQuantum(gamma*GetRedPixelComponent(&pixel));
1021
1020
          if ((channel & GreenChannel) != 0)
1022
 
            q->green=RoundToQuantum(gamma*pixel.green);
 
1021
            q->green=ClampToQuantum(gamma*GetGreenPixelComponent(&pixel));
1023
1022
          if ((channel & BlueChannel) != 0)
1024
 
            q->blue=RoundToQuantum(gamma*pixel.blue);
 
1023
            q->blue=ClampToQuantum(gamma*GetBluePixelComponent(&pixel));
1025
1024
          if ((channel & OpacityChannel) != 0)
1026
1025
            {
1027
1026
              k=kernel;
1028
1027
              kernel_pixels=p;
1029
 
              for (i=0; i < (long) width; i++)
 
1028
              for (i=0; i < (ssize_t) width; i++)
1030
1029
              {
1031
1030
                pixel.opacity+=(*k)*kernel_pixels->opacity;
1032
1031
                k++;
1033
1032
                kernel_pixels++;
1034
1033
              }
1035
 
              q->opacity=RoundToQuantum(pixel.opacity);
 
1034
              SetOpacityPixelComponent(q,ClampOpacityPixelComponent(&pixel));
1036
1035
            }
1037
1036
          if (((channel & IndexChannel) != 0) &&
1038
1037
              (image->colorspace == CMYKColorspace))
1039
1038
            {
1040
1039
              register const IndexPacket
1041
 
                *__restrict kernel_indexes;
 
1040
                *restrict kernel_indexes;
1042
1041
 
1043
1042
              k=kernel;
1044
1043
              kernel_pixels=p;
1045
1044
              kernel_indexes=indexes;
1046
 
              for (i=0; i < (long) width; i++)
 
1045
              for (i=0; i < (ssize_t) width; i++)
1047
1046
              {
1048
 
                alpha=(MagickRealType) (QuantumScale*(QuantumRange-
1049
 
                  kernel_pixels->opacity));
 
1047
                alpha=(MagickRealType) (QuantumScale*
 
1048
                  GetAlphaPixelComponent(kernel_pixels));
1050
1049
                pixel.index+=(*k)*alpha*(*kernel_indexes);
1051
1050
                k++;
1052
1051
                kernel_pixels++;
1053
1052
                kernel_indexes++;
1054
1053
              }
1055
 
              blur_indexes[x]=RoundToQuantum(gamma*pixel.index);
 
1054
              blur_indexes[x]=ClampToQuantum(gamma*
 
1055
                GetIndexPixelComponent(&pixel));
1056
1056
            }
1057
1057
        }
1058
1058
      p++;
1084
1084
#if defined(MAGICKCORE_OPENMP_SUPPORT)
1085
1085
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
1086
1086
#endif
1087
 
  for (x=0; x < (long) blur_image->columns; x++)
 
1087
  for (x=0; x < (ssize_t) blur_image->columns; x++)
1088
1088
  {
1089
1089
    register const IndexPacket
1090
 
      *__restrict indexes;
 
1090
      *restrict indexes;
1091
1091
 
1092
1092
    register const PixelPacket
1093
 
      *__restrict p;
 
1093
      *restrict p;
1094
1094
 
1095
1095
    register IndexPacket
1096
 
      *__restrict blur_indexes;
 
1096
      *restrict blur_indexes;
1097
1097
 
1098
 
    register long
 
1098
    register ssize_t
1099
1099
      y;
1100
1100
 
1101
1101
    register PixelPacket
1102
 
      *__restrict q;
 
1102
      *restrict q;
1103
1103
 
1104
1104
    if (status == MagickFalse)
1105
1105
      continue;
1106
 
    p=GetCacheViewVirtualPixels(image_view,x,-((long) width/2L),1,image->rows+
 
1106
    p=GetCacheViewVirtualPixels(image_view,x,-((ssize_t) width/2L),1,image->rows+
1107
1107
      width,exception);
1108
1108
    q=GetCacheViewAuthenticPixels(blur_view,x,0,1,blur_image->rows,exception);
1109
1109
    if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
1113
1113
      }
1114
1114
    indexes=GetCacheViewVirtualIndexQueue(image_view);
1115
1115
    blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
1116
 
    for (y=0; y < (long) blur_image->rows; y++)
 
1116
    for (y=0; y < (ssize_t) blur_image->rows; y++)
1117
1117
    {
1118
1118
      MagickPixelPacket
1119
1119
        pixel;
1120
1120
 
1121
1121
      register const double
1122
 
        *__restrict k;
 
1122
        *restrict k;
1123
1123
 
1124
1124
      register const PixelPacket
1125
 
        *__restrict kernel_pixels;
 
1125
        *restrict kernel_pixels;
1126
1126
 
1127
 
      register long
 
1127
      register ssize_t
1128
1128
        i;
1129
1129
 
1130
1130
      pixel=bias;
1132
1132
      kernel_pixels=p;
1133
1133
      if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
1134
1134
        {
1135
 
          for (i=0; i < (long) width; i++)
 
1135
          for (i=0; i < (ssize_t) width; i++)
1136
1136
          {
1137
1137
            pixel.red+=(*k)*kernel_pixels->red;
1138
1138
            pixel.green+=(*k)*kernel_pixels->green;
1141
1141
            kernel_pixels++;
1142
1142
          }
1143
1143
          if ((channel & RedChannel) != 0)
1144
 
            q->red=RoundToQuantum(pixel.red);
 
1144
            SetRedPixelComponent(q,ClampRedPixelComponent(&pixel));
1145
1145
          if ((channel & GreenChannel) != 0)
1146
 
            q->green=RoundToQuantum(pixel.green);
 
1146
            SetGreenPixelComponent(q,ClampGreenPixelComponent(&pixel));
1147
1147
          if ((channel & BlueChannel) != 0)
1148
 
            q->blue=RoundToQuantum(pixel.blue);
 
1148
            SetBluePixelComponent(q,ClampBluePixelComponent(&pixel));
1149
1149
          if ((channel & OpacityChannel) != 0)
1150
1150
            {
1151
1151
              k=kernel;
1152
1152
              kernel_pixels=p;
1153
 
              for (i=0; i < (long) width; i++)
 
1153
              for (i=0; i < (ssize_t) width; i++)
1154
1154
              {
1155
1155
                pixel.opacity+=(*k)*kernel_pixels->opacity;
1156
1156
                k++;
1157
1157
                kernel_pixels++;
1158
1158
              }
1159
 
              q->opacity=RoundToQuantum(pixel.opacity);
 
1159
              SetOpacityPixelComponent(q,ClampOpacityPixelComponent(&pixel));
1160
1160
            }
1161
1161
          if (((channel & IndexChannel) != 0) &&
1162
1162
              (image->colorspace == CMYKColorspace))
1163
1163
            {
1164
1164
              register const IndexPacket
1165
 
                *__restrict kernel_indexes;
 
1165
                *restrict kernel_indexes;
1166
1166
 
1167
1167
              k=kernel;
1168
1168
              kernel_indexes=indexes;
1169
 
              for (i=0; i < (long) width; i++)
 
1169
              for (i=0; i < (ssize_t) width; i++)
1170
1170
              {
1171
1171
                pixel.index+=(*k)*(*kernel_indexes);
1172
1172
                k++;
1173
1173
                kernel_indexes++;
1174
1174
              }
1175
 
              blur_indexes[y]=RoundToQuantum(pixel.index);
 
1175
              blur_indexes[y]=ClampToQuantum(pixel.index);
1176
1176
            }
1177
1177
        }
1178
1178
      else
1182
1182
            gamma;
1183
1183
 
1184
1184
          gamma=0.0;
1185
 
          for (i=0; i < (long) width; i++)
 
1185
          for (i=0; i < (ssize_t) width; i++)
1186
1186
          {
1187
 
            alpha=(MagickRealType) (QuantumScale*(QuantumRange-
1188
 
              kernel_pixels->opacity));
 
1187
            alpha=(MagickRealType) (QuantumScale*
 
1188
              GetAlphaPixelComponent(kernel_pixels));
1189
1189
            pixel.red+=(*k)*alpha*kernel_pixels->red;
1190
1190
            pixel.green+=(*k)*alpha*kernel_pixels->green;
1191
1191
            pixel.blue+=(*k)*alpha*kernel_pixels->blue;
1195
1195
          }
1196
1196
          gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
1197
1197
          if ((channel & RedChannel) != 0)
1198
 
            q->red=RoundToQuantum(gamma*pixel.red);
 
1198
            q->red=ClampToQuantum(gamma*GetRedPixelComponent(&pixel));
1199
1199
          if ((channel & GreenChannel) != 0)
1200
 
            q->green=RoundToQuantum(gamma*pixel.green);
 
1200
            q->green=ClampToQuantum(gamma*GetGreenPixelComponent(&pixel));
1201
1201
          if ((channel & BlueChannel) != 0)
1202
 
            q->blue=RoundToQuantum(gamma*pixel.blue);
 
1202
            q->blue=ClampToQuantum(gamma*GetBluePixelComponent(&pixel));
1203
1203
          if ((channel & OpacityChannel) != 0)
1204
1204
            {
1205
1205
              k=kernel;
1206
1206
              kernel_pixels=p;
1207
 
              for (i=0; i < (long) width; i++)
 
1207
              for (i=0; i < (ssize_t) width; i++)
1208
1208
              {
1209
1209
                pixel.opacity+=(*k)*kernel_pixels->opacity;
1210
1210
                k++;
1211
1211
                kernel_pixels++;
1212
1212
              }
1213
 
              q->opacity=RoundToQuantum(pixel.opacity);
 
1213
              SetOpacityPixelComponent(q,ClampOpacityPixelComponent(&pixel));
1214
1214
            }
1215
1215
          if (((channel & IndexChannel) != 0) &&
1216
1216
              (image->colorspace == CMYKColorspace))
1217
1217
            {
1218
1218
              register const IndexPacket
1219
 
                *__restrict kernel_indexes;
 
1219
                *restrict kernel_indexes;
1220
1220
 
1221
1221
              k=kernel;
1222
1222
              kernel_pixels=p;
1223
1223
              kernel_indexes=indexes;
1224
 
              for (i=0; i < (long) width; i++)
 
1224
              for (i=0; i < (ssize_t) width; i++)
1225
1225
              {
1226
 
                alpha=(MagickRealType) (QuantumScale*(QuantumRange-
1227
 
                  kernel_pixels->opacity));
 
1226
                alpha=(MagickRealType) (QuantumScale*
 
1227
                  GetAlphaPixelComponent(kernel_pixels));
1228
1228
                pixel.index+=(*k)*alpha*(*kernel_indexes);
1229
1229
                k++;
1230
1230
                kernel_pixels++;
1231
1231
                kernel_indexes++;
1232
1232
              }
1233
 
              blur_indexes[y]=RoundToQuantum(gamma*pixel.index);
 
1233
              blur_indexes[y]=ClampToQuantum(gamma*
 
1234
                GetIndexPixelComponent(&pixel));
1234
1235
            }
1235
1236
        }
1236
1237
      p++;
1266
1267
%                                                                             %
1267
1268
%                                                                             %
1268
1269
%                                                                             %
 
1270
%     C o n v o l v e I m a g e                                               %
 
1271
%                                                                             %
 
1272
%                                                                             %
 
1273
%                                                                             %
 
1274
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1275
%
 
1276
%  ConvolveImage() applies a custom convolution kernel to the image.
 
1277
%
 
1278
%  The format of the ConvolveImage method is:
 
1279
%
 
1280
%      Image *ConvolveImage(const Image *image,const size_t order,
 
1281
%        const double *kernel,ExceptionInfo *exception)
 
1282
%      Image *ConvolveImageChannel(const Image *image,const ChannelType channel,
 
1283
%        const size_t order,const double *kernel,
 
1284
%        ExceptionInfo *exception)
 
1285
%
 
1286
%  A description of each parameter follows:
 
1287
%
 
1288
%    o image: the image.
 
1289
%
 
1290
%    o channel: the channel type.
 
1291
%
 
1292
%    o order: the number of columns and rows in the filter kernel.
 
1293
%
 
1294
%    o kernel: An array of double representing the convolution kernel.
 
1295
%
 
1296
%    o exception: return any errors or warnings in this structure.
 
1297
%
 
1298
*/
 
1299
 
 
1300
MagickExport Image *ConvolveImage(const Image *image,const size_t order,
 
1301
  const double *kernel,ExceptionInfo *exception)
 
1302
{
 
1303
  Image
 
1304
    *convolve_image;
 
1305
 
 
1306
  convolve_image=ConvolveImageChannel(image,DefaultChannels,order,kernel,
 
1307
    exception);
 
1308
  return(convolve_image);
 
1309
}
 
1310
 
 
1311
MagickExport Image *ConvolveImageChannel(const Image *image,
 
1312
  const ChannelType channel,const size_t order,const double *kernel,
 
1313
  ExceptionInfo *exception)
 
1314
{
 
1315
#define ConvolveImageTag  "Convolve/Image"
 
1316
 
 
1317
  CacheView
 
1318
    *convolve_view,
 
1319
    *image_view;
 
1320
 
 
1321
  double
 
1322
    *normal_kernel;
 
1323
 
 
1324
  Image
 
1325
    *convolve_image;
 
1326
 
 
1327
  MagickBooleanType
 
1328
    status;
 
1329
 
 
1330
  MagickOffsetType
 
1331
    progress;
 
1332
 
 
1333
  MagickPixelPacket
 
1334
    bias;
 
1335
 
 
1336
  MagickRealType
 
1337
    gamma;
 
1338
 
 
1339
  register ssize_t
 
1340
    i;
 
1341
 
 
1342
  size_t
 
1343
    width;
 
1344
 
 
1345
  ssize_t
 
1346
    y;
 
1347
 
 
1348
  /*
 
1349
    Initialize convolve image attributes.
 
1350
  */
 
1351
  assert(image != (Image *) NULL);
 
1352
  assert(image->signature == MagickSignature);
 
1353
  if (image->debug != MagickFalse)
 
1354
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
1355
  assert(exception != (ExceptionInfo *) NULL);
 
1356
  assert(exception->signature == MagickSignature);
 
1357
  width=order;
 
1358
  if ((width % 2) == 0)
 
1359
    ThrowImageException(OptionError,"KernelWidthMustBeAnOddNumber");
 
1360
  convolve_image=CloneImage(image,0,0,MagickTrue,exception);
 
1361
  if (convolve_image == (Image *) NULL)
 
1362
    return((Image *) NULL);
 
1363
  if (SetImageStorageClass(convolve_image,DirectClass) == MagickFalse)
 
1364
    {
 
1365
      InheritException(exception,&convolve_image->exception);
 
1366
      convolve_image=DestroyImage(convolve_image);
 
1367
      return((Image *) NULL);
 
1368
    }
 
1369
  if (image->debug != MagickFalse)
 
1370
    {
 
1371
      char
 
1372
        format[MaxTextExtent],
 
1373
        *message;
 
1374
 
 
1375
      ssize_t
 
1376
        u,
 
1377
        v;
 
1378
 
 
1379
      register const double
 
1380
        *k;
 
1381
 
 
1382
      (void) LogMagickEvent(TransformEvent,GetMagickModule(),
 
1383
        "  ConvolveImage with %.20gx%.20g kernel:",(double) width,(double)
 
1384
        width);
 
1385
      message=AcquireString("");
 
1386
      k=kernel;
 
1387
      for (v=0; v < (ssize_t) width; v++)
 
1388
      {
 
1389
        *message='\0';
 
1390
        (void) FormatMagickString(format,MaxTextExtent,"%.20g: ",(double) v);
 
1391
        (void) ConcatenateString(&message,format);
 
1392
        for (u=0; u < (ssize_t) width; u++)
 
1393
        {
 
1394
          (void) FormatMagickString(format,MaxTextExtent,"%g ",*k++);
 
1395
          (void) ConcatenateString(&message,format);
 
1396
        }
 
1397
        (void) LogMagickEvent(TransformEvent,GetMagickModule(),"%s",message);
 
1398
      }
 
1399
      message=DestroyString(message);
 
1400
    }
 
1401
  /*
 
1402
    Normalize kernel.
 
1403
  */
 
1404
  normal_kernel=(double *) AcquireQuantumMemory(width*width,
 
1405
    sizeof(*normal_kernel));
 
1406
  if (normal_kernel == (double *) NULL)
 
1407
    {
 
1408
      convolve_image=DestroyImage(convolve_image);
 
1409
      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
 
1410
    }
 
1411
  gamma=0.0;
 
1412
  for (i=0; i < (ssize_t) (width*width); i++)
 
1413
    gamma+=kernel[i];
 
1414
  gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
 
1415
  for (i=0; i < (ssize_t) (width*width); i++)
 
1416
    normal_kernel[i]=gamma*kernel[i];
 
1417
  /*
 
1418
    Convolve image.
 
1419
  */
 
1420
  status=MagickTrue;
 
1421
  progress=0;
 
1422
  GetMagickPixelPacket(image,&bias);
 
1423
  SetMagickPixelPacketBias(image,&bias);
 
1424
  image_view=AcquireCacheView(image);
 
1425
  convolve_view=AcquireCacheView(convolve_image);
 
1426
#if defined(MAGICKCORE_OPENMP_SUPPORT)
 
1427
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
 
1428
#endif
 
1429
  for (y=0; y < (ssize_t) image->rows; y++)
 
1430
  {
 
1431
    MagickBooleanType
 
1432
      sync;
 
1433
 
 
1434
    register const IndexPacket
 
1435
      *restrict indexes;
 
1436
 
 
1437
    register const PixelPacket
 
1438
      *restrict p;
 
1439
 
 
1440
    register IndexPacket
 
1441
      *restrict convolve_indexes;
 
1442
 
 
1443
    register ssize_t
 
1444
      x;
 
1445
 
 
1446
    register PixelPacket
 
1447
      *restrict q;
 
1448
 
 
1449
    if (status == MagickFalse)
 
1450
      continue;
 
1451
    p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t) (width/
 
1452
      2L),image->columns+width,width,exception);
 
1453
    q=GetCacheViewAuthenticPixels(convolve_view,0,y,convolve_image->columns,1,
 
1454
      exception);
 
1455
    if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
 
1456
      {
 
1457
        status=MagickFalse;
 
1458
        continue;
 
1459
      }
 
1460
    indexes=GetCacheViewVirtualIndexQueue(image_view);
 
1461
    convolve_indexes=GetCacheViewAuthenticIndexQueue(convolve_view);
 
1462
    for (x=0; x < (ssize_t) image->columns; x++)
 
1463
    {
 
1464
      ssize_t
 
1465
        v;
 
1466
 
 
1467
      MagickPixelPacket
 
1468
        pixel;
 
1469
 
 
1470
      register const double
 
1471
        *restrict k;
 
1472
 
 
1473
      register const PixelPacket
 
1474
        *restrict kernel_pixels;
 
1475
 
 
1476
      register ssize_t
 
1477
        u;
 
1478
 
 
1479
      pixel=bias;
 
1480
      k=normal_kernel;
 
1481
      kernel_pixels=p;
 
1482
      if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
 
1483
        {
 
1484
          for (v=0; v < (ssize_t) width; v++)
 
1485
          {
 
1486
            for (u=0; u < (ssize_t) width; u++)
 
1487
            {
 
1488
              pixel.red+=(*k)*kernel_pixels[u].red;
 
1489
              pixel.green+=(*k)*kernel_pixels[u].green;
 
1490
              pixel.blue+=(*k)*kernel_pixels[u].blue;
 
1491
              k++;
 
1492
            }
 
1493
            kernel_pixels+=image->columns+width;
 
1494
          }
 
1495
          if ((channel & RedChannel) != 0)
 
1496
            SetRedPixelComponent(q,ClampRedPixelComponent(&pixel));
 
1497
          if ((channel & GreenChannel) != 0)
 
1498
            SetGreenPixelComponent(q,ClampGreenPixelComponent(&pixel));
 
1499
          if ((channel & BlueChannel) != 0)
 
1500
            SetBluePixelComponent(q,ClampBluePixelComponent(&pixel));
 
1501
          if ((channel & OpacityChannel) != 0)
 
1502
            {
 
1503
              k=normal_kernel;
 
1504
              kernel_pixels=p;
 
1505
              for (v=0; v < (ssize_t) width; v++)
 
1506
              {
 
1507
                for (u=0; u < (ssize_t) width; u++)
 
1508
                {
 
1509
                  pixel.opacity+=(*k)*kernel_pixels[u].opacity;
 
1510
                  k++;
 
1511
                }
 
1512
                kernel_pixels+=image->columns+width;
 
1513
              }
 
1514
              SetOpacityPixelComponent(q,ClampOpacityPixelComponent(&pixel));
 
1515
            }
 
1516
          if (((channel & IndexChannel) != 0) &&
 
1517
              (image->colorspace == CMYKColorspace))
 
1518
            {
 
1519
              register const IndexPacket
 
1520
                *restrict kernel_indexes;
 
1521
 
 
1522
              k=normal_kernel;
 
1523
              kernel_indexes=indexes;
 
1524
              for (v=0; v < (ssize_t) width; v++)
 
1525
              {
 
1526
                for (u=0; u < (ssize_t) width; u++)
 
1527
                {
 
1528
                  pixel.index+=(*k)*kernel_indexes[u];
 
1529
                  k++;
 
1530
                }
 
1531
                kernel_indexes+=image->columns+width;
 
1532
              }
 
1533
              convolve_indexes[x]=ClampToQuantum(pixel.index);
 
1534
            }
 
1535
        }
 
1536
      else
 
1537
        {
 
1538
          MagickRealType
 
1539
            alpha,
 
1540
            gamma;
 
1541
 
 
1542
          gamma=0.0;
 
1543
          for (v=0; v < (ssize_t) width; v++)
 
1544
          {
 
1545
            for (u=0; u < (ssize_t) width; u++)
 
1546
            {
 
1547
              alpha=(MagickRealType) (QuantumScale*(QuantumRange-
 
1548
                kernel_pixels[u].opacity));
 
1549
              pixel.red+=(*k)*alpha*kernel_pixels[u].red;
 
1550
              pixel.green+=(*k)*alpha*kernel_pixels[u].green;
 
1551
              pixel.blue+=(*k)*alpha*kernel_pixels[u].blue;
 
1552
              gamma+=(*k)*alpha;
 
1553
              k++;
 
1554
            }
 
1555
            kernel_pixels+=image->columns+width;
 
1556
          }
 
1557
          gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
 
1558
          if ((channel & RedChannel) != 0)
 
1559
            q->red=ClampToQuantum(gamma*GetRedPixelComponent(&pixel));
 
1560
          if ((channel & GreenChannel) != 0)
 
1561
            q->green=ClampToQuantum(gamma*GetGreenPixelComponent(&pixel));
 
1562
          if ((channel & BlueChannel) != 0)
 
1563
            q->blue=ClampToQuantum(gamma*GetBluePixelComponent(&pixel));
 
1564
          if ((channel & OpacityChannel) != 0)
 
1565
            {
 
1566
              k=normal_kernel;
 
1567
              kernel_pixels=p;
 
1568
              for (v=0; v < (ssize_t) width; v++)
 
1569
              {
 
1570
                for (u=0; u < (ssize_t) width; u++)
 
1571
                {
 
1572
                  pixel.opacity+=(*k)*kernel_pixels[u].opacity;
 
1573
                  k++;
 
1574
                }
 
1575
                kernel_pixels+=image->columns+width;
 
1576
              }
 
1577
              SetOpacityPixelComponent(q,ClampOpacityPixelComponent(&pixel));
 
1578
            }
 
1579
          if (((channel & IndexChannel) != 0) &&
 
1580
              (image->colorspace == CMYKColorspace))
 
1581
            {
 
1582
              register const IndexPacket
 
1583
                *restrict kernel_indexes;
 
1584
 
 
1585
              k=normal_kernel;
 
1586
              kernel_pixels=p;
 
1587
              kernel_indexes=indexes;
 
1588
              for (v=0; v < (ssize_t) width; v++)
 
1589
              {
 
1590
                for (u=0; u < (ssize_t) width; u++)
 
1591
                {
 
1592
                  alpha=(MagickRealType) (QuantumScale*(QuantumRange-
 
1593
                    kernel_pixels[u].opacity));
 
1594
                  pixel.index+=(*k)*alpha*kernel_indexes[u];
 
1595
                  k++;
 
1596
                }
 
1597
                kernel_pixels+=image->columns+width;
 
1598
                kernel_indexes+=image->columns+width;
 
1599
              }
 
1600
              convolve_indexes[x]=ClampToQuantum(gamma*
 
1601
                GetIndexPixelComponent(&pixel));
 
1602
            }
 
1603
        }
 
1604
      p++;
 
1605
      q++;
 
1606
    }
 
1607
    sync=SyncCacheViewAuthenticPixels(convolve_view,exception);
 
1608
    if (sync == MagickFalse)
 
1609
      status=MagickFalse;
 
1610
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
 
1611
      {
 
1612
        MagickBooleanType
 
1613
          proceed;
 
1614
 
 
1615
#if defined(MAGICKCORE_OPENMP_SUPPORT)
 
1616
  #pragma omp critical (MagickCore_ConvolveImageChannel)
 
1617
#endif
 
1618
        proceed=SetImageProgress(image,ConvolveImageTag,progress++,image->rows);
 
1619
        if (proceed == MagickFalse)
 
1620
          status=MagickFalse;
 
1621
      }
 
1622
  }
 
1623
  convolve_image->type=image->type;
 
1624
  convolve_view=DestroyCacheView(convolve_view);
 
1625
  image_view=DestroyCacheView(image_view);
 
1626
  normal_kernel=(double *) RelinquishMagickMemory(normal_kernel);
 
1627
  if (status == MagickFalse)
 
1628
    convolve_image=DestroyImage(convolve_image);
 
1629
  return(convolve_image);
 
1630
}
 
1631
 
 
1632
/*
 
1633
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1634
%                                                                             %
 
1635
%                                                                             %
 
1636
%                                                                             %
1269
1637
%     D e s p e c k l e I m a g e                                             %
1270
1638
%                                                                             %
1271
1639
%                                                                             %
1289
1657
 
1290
1658
static Quantum **DestroyPixelThreadSet(Quantum **pixels)
1291
1659
{
1292
 
  register long
 
1660
  register ssize_t
1293
1661
    i;
1294
1662
 
1295
1663
  assert(pixels != (Quantum **) NULL);
1296
 
  for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
 
1664
  for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
1297
1665
    if (pixels[i] != (Quantum *) NULL)
1298
1666
      pixels[i]=(Quantum *) RelinquishMagickMemory(pixels[i]);
1299
1667
  pixels=(Quantum **) RelinquishAlignedMemory(pixels);
1302
1670
 
1303
1671
static Quantum **AcquirePixelThreadSet(const size_t count)
1304
1672
{
1305
 
  register long
 
1673
  register ssize_t
1306
1674
    i;
1307
1675
 
1308
1676
  Quantum
1309
1677
    **pixels;
1310
1678
 
1311
 
  unsigned long
 
1679
  size_t
1312
1680
    number_threads;
1313
1681
 
1314
1682
  number_threads=GetOpenMPMaximumThreads();
1316
1684
  if (pixels == (Quantum **) NULL)
1317
1685
    return((Quantum **) NULL);
1318
1686
  (void) ResetMagickMemory(pixels,0,number_threads*sizeof(*pixels));
1319
 
  for (i=0; i < (long) number_threads; i++)
 
1687
  for (i=0; i < (ssize_t) number_threads; i++)
1320
1688
  {
1321
1689
    pixels[i]=(Quantum *) AcquireQuantumMemory(count,sizeof(**pixels));
1322
1690
    if (pixels[i] == (Quantum *) NULL)
1325
1693
  return(pixels);
1326
1694
}
1327
1695
 
1328
 
static void Hull(const long x_offset,const long y_offset,
1329
 
  const unsigned long columns,const unsigned long rows,Quantum *f,Quantum *g,
 
1696
static void Hull(const ssize_t x_offset,const ssize_t y_offset,
 
1697
  const size_t columns,const size_t rows,Quantum *f,Quantum *g,
1330
1698
  const int polarity)
1331
1699
{
1332
 
  long
 
1700
  ssize_t
1333
1701
    y;
1334
1702
 
1335
1703
  MagickRealType
1336
1704
    v;
1337
1705
 
1338
 
  register long
 
1706
  register ssize_t
1339
1707
    x;
1340
1708
 
1341
1709
  register Quantum
1348
1716
  assert(g != (Quantum *) NULL);
1349
1717
  p=f+(columns+2);
1350
1718
  q=g+(columns+2);
1351
 
  r=p+(y_offset*((long) columns+2)+x_offset);
1352
 
  for (y=0; y < (long) rows; y++)
 
1719
  r=p+(y_offset*((ssize_t) columns+2)+x_offset);
 
1720
  for (y=0; y < (ssize_t) rows; y++)
1353
1721
  {
1354
1722
    p++;
1355
1723
    q++;
1356
1724
    r++;
1357
1725
    if (polarity > 0)
1358
 
      for (x=(long) columns; x != 0; x--)
 
1726
      for (x=(ssize_t) columns; x != 0; x--)
1359
1727
      {
1360
1728
        v=(MagickRealType) (*p);
1361
1729
        if ((MagickRealType) *r >= (v+(MagickRealType) ScaleCharToQuantum(2)))
1366
1734
        r++;
1367
1735
      }
1368
1736
    else
1369
 
      for (x=(long) columns; x != 0; x--)
 
1737
      for (x=(ssize_t) columns; x != 0; x--)
1370
1738
      {
1371
1739
        v=(MagickRealType) (*p);
1372
1740
        if ((MagickRealType) *r <= (v-(MagickRealType) ScaleCharToQuantum(2)))
1373
 
          v-=(long) ScaleCharToQuantum(1);
 
1741
          v-=(ssize_t) ScaleCharToQuantum(1);
1374
1742
        *q=(Quantum) v;
1375
1743
        p++;
1376
1744
        q++;
1382
1750
  }
1383
1751
  p=f+(columns+2);
1384
1752
  q=g+(columns+2);
1385
 
  r=q+(y_offset*((long) columns+2)+x_offset);
1386
 
  s=q-(y_offset*((long) columns+2)+x_offset);
1387
 
  for (y=0; y < (long) rows; y++)
 
1753
  r=q+(y_offset*((ssize_t) columns+2)+x_offset);
 
1754
  s=q-(y_offset*((ssize_t) columns+2)+x_offset);
 
1755
  for (y=0; y < (ssize_t) rows; y++)
1388
1756
  {
1389
1757
    p++;
1390
1758
    q++;
1391
1759
    r++;
1392
1760
    s++;
1393
1761
    if (polarity > 0)
1394
 
      for (x=(long) columns; x != 0; x--)
 
1762
      for (x=(ssize_t) columns; x != 0; x--)
1395
1763
      {
1396
1764
        v=(MagickRealType) (*q);
1397
1765
        if (((MagickRealType) *s >=
1405
1773
        s++;
1406
1774
      }
1407
1775
    else
1408
 
      for (x=(long) columns; x != 0; x--)
 
1776
      for (x=(ssize_t) columns; x != 0; x--)
1409
1777
      {
1410
1778
        v=(MagickRealType) (*q);
1411
1779
        if (((MagickRealType) *s <=
1436
1804
  Image
1437
1805
    *despeckle_image;
1438
1806
 
1439
 
  long
 
1807
  ssize_t
1440
1808
    channel;
1441
1809
 
1442
1810
  MagickBooleanType
1443
1811
    status;
1444
1812
 
1445
1813
  Quantum
1446
 
    **buffers,
1447
 
    **pixels;
 
1814
    **restrict buffers,
 
1815
    **restrict pixels;
1448
1816
 
1449
1817
  size_t
1450
1818
    length;
1451
1819
 
1452
 
  static const int
 
1820
  static const ssize_t
1453
1821
    X[4] = {0, 1, 1,-1},
1454
1822
    Y[4] = {1, 0, 1, 1};
1455
1823
 
1498
1866
#endif
1499
1867
  for (channel=0; channel <= 3; channel++)
1500
1868
  {
1501
 
    long
 
1869
    ssize_t
1502
1870
      j,
1503
1871
      y;
1504
1872
 
1505
 
    register long
 
1873
    register ssize_t
1506
1874
      i,
1507
1875
      id,
1508
1876
      x;
1517
1885
    pixel=pixels[id];
1518
1886
    (void) ResetMagickMemory(pixel,0,length*sizeof(*pixel));
1519
1887
    buffer=buffers[id];
1520
 
    j=(long) image->columns+2;
1521
 
    for (y=0; y < (long) image->rows; y++)
 
1888
    j=(ssize_t) image->columns+2;
 
1889
    for (y=0; y < (ssize_t) image->rows; y++)
1522
1890
    {
1523
1891
      register const PixelPacket
1524
 
        *__restrict p;
 
1892
        *restrict p;
1525
1893
 
1526
1894
      p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1527
1895
      if (p == (const PixelPacket *) NULL)
1528
1896
        break;
1529
1897
      j++;
1530
 
      for (x=0; x < (long) image->columns; x++)
 
1898
      for (x=0; x < (ssize_t) image->columns; x++)
1531
1899
      {
1532
1900
        switch (channel)
1533
1901
        {
1534
 
          case 0: pixel[j]=p->red; break;
1535
 
          case 1: pixel[j]=p->green; break;
1536
 
          case 2: pixel[j]=p->blue; break;
1537
 
          case 3: pixel[j]=p->opacity; break;
 
1902
          case 0: pixel[j]=GetRedPixelComponent(p); break;
 
1903
          case 1: pixel[j]=GetGreenPixelComponent(p); break;
 
1904
          case 2: pixel[j]=GetBluePixelComponent(p); break;
 
1905
          case 3: pixel[j]=GetOpacityPixelComponent(p); break;
1538
1906
          default: break;
1539
1907
        }
1540
1908
        p++;
1550
1918
      Hull(-X[i],-Y[i],image->columns,image->rows,pixel,buffer,-1);
1551
1919
      Hull(X[i],Y[i],image->columns,image->rows,pixel,buffer,-1);
1552
1920
    }
1553
 
    j=(long) image->columns+2;
1554
 
    for (y=0; y < (long) image->rows; y++)
 
1921
    j=(ssize_t) image->columns+2;
 
1922
    for (y=0; y < (ssize_t) image->rows; y++)
1555
1923
    {
1556
1924
      MagickBooleanType
1557
1925
        sync;
1558
1926
 
1559
1927
      register PixelPacket
1560
 
        *__restrict q;
 
1928
        *restrict q;
1561
1929
 
1562
1930
      q=GetCacheViewAuthenticPixels(despeckle_view,0,y,despeckle_image->columns,
1563
1931
        1,exception);
1564
1932
      if (q == (PixelPacket *) NULL)
1565
1933
        break;
1566
1934
      j++;
1567
 
      for (x=0; x < (long) image->columns; x++)
 
1935
      for (x=0; x < (ssize_t) image->columns; x++)
1568
1936
      {
1569
1937
        switch (channel)
1570
1938
        {
1593
1961
#if defined(MAGICKCORE_OPENMP_SUPPORT)
1594
1962
  #pragma omp critical (MagickCore_DespeckleImage)
1595
1963
#endif
1596
 
        proceed=SetImageProgress(image,DespeckleImageTag,channel,3);
 
1964
        proceed=SetImageProgress(image,DespeckleImageTag,(MagickOffsetType)
 
1965
          channel,3);
1597
1966
        if (proceed == MagickFalse)
1598
1967
          status=MagickFalse;
1599
1968
      }
1646
2015
  double
1647
2016
    *kernel;
1648
2017
 
1649
 
  register long
 
2018
  register ssize_t
1650
2019
    i;
1651
2020
 
1652
 
  unsigned long
 
2021
  size_t
1653
2022
    width;
1654
2023
 
1655
2024
  assert(image != (const Image *) NULL);
1662
2031
  kernel=(double *) AcquireQuantumMemory((size_t) width,width*sizeof(*kernel));
1663
2032
  if (kernel == (double *) NULL)
1664
2033
    ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
1665
 
  for (i=0; i < (long) (width*width); i++)
 
2034
  for (i=0; i < (ssize_t) (width*width); i++)
1666
2035
    kernel[i]=(-1.0);
1667
2036
  kernel[i/2]=(double) (width*width-1.0);
1668
2037
  edge_image=ConvolveImage(image,width,kernel,exception);
1712
2081
  Image
1713
2082
    *emboss_image;
1714
2083
 
1715
 
  long
1716
 
    j;
1717
 
 
1718
 
  MagickRealType
1719
 
    alpha;
1720
 
 
1721
 
  register long
1722
 
    i,
 
2084
  ssize_t
 
2085
    j,
 
2086
    k,
1723
2087
    u,
1724
2088
    v;
1725
2089
 
1726
 
  unsigned long
 
2090
  register ssize_t
 
2091
    i;
 
2092
 
 
2093
  size_t
1727
2094
    width;
1728
2095
 
1729
2096
  assert(image != (Image *) NULL);
1736
2103
  kernel=(double *) AcquireQuantumMemory((size_t) width,width*sizeof(*kernel));
1737
2104
  if (kernel == (double *) NULL)
1738
2105
    ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
 
2106
  j=(ssize_t) width/2;
 
2107
  k=j;
1739
2108
  i=0;
1740
 
  j=(long) width/2;
1741
 
  for (v=(-((long) width/2)); v <= (long) (width/2); v++)
 
2109
  for (v=(-j); v <= j; v++)
1742
2110
  {
1743
 
    for (u=(-((long) width/2)); u <= (long) (width/2); u++)
 
2111
    for (u=(-j); u <= j; u++)
1744
2112
    {
1745
 
      alpha=exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma));
1746
 
      kernel[i]=(double) (((u < 0) || (v < 0) ? -8.0 : 8.0)*alpha/
1747
 
        (2.0*MagickPI*MagickSigma*MagickSigma));
1748
 
      if (u != j)
 
2113
      kernel[i]=((u < 0) || (v < 0) ? -8.0 : 8.0)*
 
2114
        exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma))/
 
2115
        (2.0*MagickPI*MagickSigma*MagickSigma);
 
2116
      if (u != k)
1749
2117
        kernel[i]=0.0;
1750
2118
      i++;
1751
2119
    }
1752
 
    j--;
 
2120
    k--;
1753
2121
  }
1754
2122
  emboss_image=ConvolveImage(image,width,kernel,exception);
1755
2123
  if (emboss_image != (Image *) NULL)
1763
2131
%                                                                             %
1764
2132
%                                                                             %
1765
2133
%                                                                             %
 
2134
%     F i l t e r I m a g e                                                   %
 
2135
%                                                                             %
 
2136
%                                                                             %
 
2137
%                                                                             %
 
2138
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2139
%
 
2140
%  FilterImage() applies a custom convolution kernel to the image.
 
2141
%
 
2142
%  The format of the FilterImage method is:
 
2143
%
 
2144
%      Image *FilterImage(const Image *image,const KernelInfo *kernel,
 
2145
%        ExceptionInfo *exception)
 
2146
%      Image *FilterImageChannel(const Image *image,const ChannelType channel,
 
2147
%        const KernelInfo *kernel,ExceptionInfo *exception)
 
2148
%
 
2149
%  A description of each parameter follows:
 
2150
%
 
2151
%    o image: the image.
 
2152
%
 
2153
%    o channel: the channel type.
 
2154
%
 
2155
%    o kernel: the filtering kernel.
 
2156
%
 
2157
%    o exception: return any errors or warnings in this structure.
 
2158
%
 
2159
*/
 
2160
 
 
2161
MagickExport Image *FilterImage(const Image *image,const KernelInfo *kernel,
 
2162
  ExceptionInfo *exception)
 
2163
{
 
2164
  Image
 
2165
    *filter_image;
 
2166
 
 
2167
  filter_image=FilterImageChannel(image,DefaultChannels,kernel,exception);
 
2168
  return(filter_image);
 
2169
}
 
2170
 
 
2171
MagickExport Image *FilterImageChannel(const Image *image,
 
2172
  const ChannelType channel,const KernelInfo *kernel,ExceptionInfo *exception)
 
2173
{
 
2174
#define FilterImageTag  "Filter/Image"
 
2175
 
 
2176
  CacheView
 
2177
    *filter_view,
 
2178
    *image_view;
 
2179
 
 
2180
  Image
 
2181
    *filter_image;
 
2182
 
 
2183
  MagickBooleanType
 
2184
    status;
 
2185
 
 
2186
  MagickOffsetType
 
2187
    progress;
 
2188
 
 
2189
  MagickPixelPacket
 
2190
    bias;
 
2191
 
 
2192
  ssize_t
 
2193
    y;
 
2194
 
 
2195
  /*
 
2196
    Initialize filter image attributes.
 
2197
  */
 
2198
  assert(image != (Image *) NULL);
 
2199
  assert(image->signature == MagickSignature);
 
2200
  if (image->debug != MagickFalse)
 
2201
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
2202
  assert(exception != (ExceptionInfo *) NULL);
 
2203
  assert(exception->signature == MagickSignature);
 
2204
  if ((kernel->width % 2) == 0)
 
2205
    ThrowImageException(OptionError,"KernelWidthMustBeAnOddNumber");
 
2206
  filter_image=CloneImage(image,0,0,MagickTrue,exception);
 
2207
  if (filter_image == (Image *) NULL)
 
2208
    return((Image *) NULL);
 
2209
  if (SetImageStorageClass(filter_image,DirectClass) == MagickFalse)
 
2210
    {
 
2211
      InheritException(exception,&filter_image->exception);
 
2212
      filter_image=DestroyImage(filter_image);
 
2213
      return((Image *) NULL);
 
2214
    }
 
2215
  if (image->debug != MagickFalse)
 
2216
    {
 
2217
      char
 
2218
        format[MaxTextExtent],
 
2219
        *message;
 
2220
 
 
2221
      ssize_t
 
2222
        u,
 
2223
        v;
 
2224
 
 
2225
      register const double
 
2226
        *k;
 
2227
 
 
2228
      (void) LogMagickEvent(TransformEvent,GetMagickModule(),
 
2229
        "  FilterImage with %.20gx%.20g kernel:",(double) kernel->width,(double)
 
2230
        kernel->height);
 
2231
      message=AcquireString("");
 
2232
      k=kernel->values;
 
2233
      for (v=0; v < (ssize_t) kernel->height; v++)
 
2234
      {
 
2235
        *message='\0';
 
2236
        (void) FormatMagickString(format,MaxTextExtent,"%.20g: ",(double) v);
 
2237
        (void) ConcatenateString(&message,format);
 
2238
        for (u=0; u < (ssize_t) kernel->width; u++)
 
2239
        {
 
2240
          (void) FormatMagickString(format,MaxTextExtent,"%g ",*k++);
 
2241
          (void) ConcatenateString(&message,format);
 
2242
        }
 
2243
        (void) LogMagickEvent(TransformEvent,GetMagickModule(),"%s",message);
 
2244
      }
 
2245
      message=DestroyString(message);
 
2246
    }
 
2247
  status=AccelerateConvolveImage(image,kernel,filter_image,exception);
 
2248
  if (status == MagickTrue)
 
2249
    return(filter_image);
 
2250
  /*
 
2251
    Filter image.
 
2252
  */
 
2253
  status=MagickTrue;
 
2254
  progress=0;
 
2255
  GetMagickPixelPacket(image,&bias);
 
2256
  SetMagickPixelPacketBias(image,&bias);
 
2257
  image_view=AcquireCacheView(image);
 
2258
  filter_view=AcquireCacheView(filter_image);
 
2259
#if defined(MAGICKCORE_OPENMP_SUPPORT)
 
2260
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
 
2261
#endif
 
2262
  for (y=0; y < (ssize_t) image->rows; y++)
 
2263
  {
 
2264
    MagickBooleanType
 
2265
      sync;
 
2266
 
 
2267
    register const IndexPacket
 
2268
      *restrict indexes;
 
2269
 
 
2270
    register const PixelPacket
 
2271
      *restrict p;
 
2272
 
 
2273
    register IndexPacket
 
2274
      *restrict filter_indexes;
 
2275
 
 
2276
    register ssize_t
 
2277
      x;
 
2278
 
 
2279
    register PixelPacket
 
2280
      *restrict q;
 
2281
 
 
2282
    if (status == MagickFalse)
 
2283
      continue;
 
2284
    p=GetCacheViewVirtualPixels(image_view,-((ssize_t) kernel->width/2L),
 
2285
      y-(ssize_t) (kernel->height/2L),image->columns+kernel->width,kernel->height,
 
2286
      exception);
 
2287
    q=GetCacheViewAuthenticPixels(filter_view,0,y,filter_image->columns,1,
 
2288
      exception);
 
2289
    if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
 
2290
      {
 
2291
        status=MagickFalse;
 
2292
        continue;
 
2293
      }
 
2294
    indexes=GetCacheViewVirtualIndexQueue(image_view);
 
2295
    filter_indexes=GetCacheViewAuthenticIndexQueue(filter_view);
 
2296
    for (x=0; x < (ssize_t) image->columns; x++)
 
2297
    {
 
2298
      ssize_t
 
2299
        v;
 
2300
 
 
2301
      MagickPixelPacket
 
2302
        pixel;
 
2303
 
 
2304
      register const double
 
2305
        *restrict k;
 
2306
 
 
2307
      register const PixelPacket
 
2308
        *restrict kernel_pixels;
 
2309
 
 
2310
      register ssize_t
 
2311
        u;
 
2312
 
 
2313
      pixel=bias;
 
2314
      k=kernel->values;
 
2315
      kernel_pixels=p;
 
2316
      if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
 
2317
        {
 
2318
          for (v=0; v < (ssize_t) kernel->width; v++)
 
2319
          {
 
2320
            for (u=0; u < (ssize_t) kernel->height; u++)
 
2321
            {
 
2322
              pixel.red+=(*k)*kernel_pixels[u].red;
 
2323
              pixel.green+=(*k)*kernel_pixels[u].green;
 
2324
              pixel.blue+=(*k)*kernel_pixels[u].blue;
 
2325
              k++;
 
2326
            }
 
2327
            kernel_pixels+=image->columns+kernel->width;
 
2328
          }
 
2329
          if ((channel & RedChannel) != 0)
 
2330
            SetRedPixelComponent(q,ClampRedPixelComponent(&pixel));
 
2331
          if ((channel & GreenChannel) != 0)
 
2332
            SetGreenPixelComponent(q,ClampGreenPixelComponent(&pixel));
 
2333
          if ((channel & BlueChannel) != 0)
 
2334
            SetBluePixelComponent(q,ClampBluePixelComponent(&pixel));
 
2335
          if ((channel & OpacityChannel) != 0)
 
2336
            {
 
2337
              k=kernel->values;
 
2338
              kernel_pixels=p;
 
2339
              for (v=0; v < (ssize_t) kernel->width; v++)
 
2340
              {
 
2341
                for (u=0; u < (ssize_t) kernel->height; u++)
 
2342
                {
 
2343
                  pixel.opacity+=(*k)*kernel_pixels[u].opacity;
 
2344
                  k++;
 
2345
                }
 
2346
                kernel_pixels+=image->columns+kernel->width;
 
2347
              }
 
2348
              SetOpacityPixelComponent(q,ClampOpacityPixelComponent(&pixel));
 
2349
            }
 
2350
          if (((channel & IndexChannel) != 0) &&
 
2351
              (image->colorspace == CMYKColorspace))
 
2352
            {
 
2353
              register const IndexPacket
 
2354
                *restrict kernel_indexes;
 
2355
 
 
2356
              k=kernel->values;
 
2357
              kernel_indexes=indexes;
 
2358
              for (v=0; v < (ssize_t) kernel->width; v++)
 
2359
              {
 
2360
                for (u=0; u < (ssize_t) kernel->height; u++)
 
2361
                {
 
2362
                  pixel.index+=(*k)*kernel_indexes[u];
 
2363
                  k++;
 
2364
                }
 
2365
                kernel_indexes+=image->columns+kernel->width;
 
2366
              }
 
2367
              filter_indexes[x]=ClampToQuantum(pixel.index);
 
2368
            }
 
2369
        }
 
2370
      else
 
2371
        {
 
2372
          MagickRealType
 
2373
            alpha,
 
2374
            gamma;
 
2375
 
 
2376
          gamma=0.0;
 
2377
          for (v=0; v < (ssize_t) kernel->width; v++)
 
2378
          {
 
2379
            for (u=0; u < (ssize_t) kernel->height; u++)
 
2380
            {
 
2381
              alpha=(MagickRealType) (QuantumScale*(QuantumRange-
 
2382
                kernel_pixels[u].opacity));
 
2383
              pixel.red+=(*k)*alpha*kernel_pixels[u].red;
 
2384
              pixel.green+=(*k)*alpha*kernel_pixels[u].green;
 
2385
              pixel.blue+=(*k)*alpha*kernel_pixels[u].blue;
 
2386
              gamma+=(*k)*alpha;
 
2387
              k++;
 
2388
            }
 
2389
            kernel_pixels+=image->columns+kernel->width;
 
2390
          }
 
2391
          gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
 
2392
          if ((channel & RedChannel) != 0)
 
2393
            q->red=ClampToQuantum(gamma*GetRedPixelComponent(&pixel));
 
2394
          if ((channel & GreenChannel) != 0)
 
2395
            q->green=ClampToQuantum(gamma*GetGreenPixelComponent(&pixel));
 
2396
          if ((channel & BlueChannel) != 0)
 
2397
            q->blue=ClampToQuantum(gamma*GetBluePixelComponent(&pixel));
 
2398
          if ((channel & OpacityChannel) != 0)
 
2399
            {
 
2400
              k=kernel->values;
 
2401
              kernel_pixels=p;
 
2402
              for (v=0; v < (ssize_t) kernel->width; v++)
 
2403
              {
 
2404
                for (u=0; u < (ssize_t) kernel->height; u++)
 
2405
                {
 
2406
                  pixel.opacity+=(*k)*kernel_pixels[u].opacity;
 
2407
                  k++;
 
2408
                }
 
2409
                kernel_pixels+=image->columns+kernel->width;
 
2410
              }
 
2411
              SetOpacityPixelComponent(q,ClampOpacityPixelComponent(&pixel));
 
2412
            }
 
2413
          if (((channel & IndexChannel) != 0) &&
 
2414
              (image->colorspace == CMYKColorspace))
 
2415
            {
 
2416
              register const IndexPacket
 
2417
                *restrict kernel_indexes;
 
2418
 
 
2419
              k=kernel->values;
 
2420
              kernel_pixels=p;
 
2421
              kernel_indexes=indexes;
 
2422
              for (v=0; v < (ssize_t) kernel->width; v++)
 
2423
              {
 
2424
                for (u=0; u < (ssize_t) kernel->height; u++)
 
2425
                {
 
2426
                  alpha=(MagickRealType) (QuantumScale*(QuantumRange-
 
2427
                    kernel_pixels[u].opacity));
 
2428
                  pixel.index+=(*k)*alpha*kernel_indexes[u];
 
2429
                  k++;
 
2430
                }
 
2431
                kernel_pixels+=image->columns+kernel->width;
 
2432
                kernel_indexes+=image->columns+kernel->width;
 
2433
              }
 
2434
              filter_indexes[x]=ClampToQuantum(gamma*
 
2435
                GetIndexPixelComponent(&pixel));
 
2436
            }
 
2437
        }
 
2438
      p++;
 
2439
      q++;
 
2440
    }
 
2441
    sync=SyncCacheViewAuthenticPixels(filter_view,exception);
 
2442
    if (sync == MagickFalse)
 
2443
      status=MagickFalse;
 
2444
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
 
2445
      {
 
2446
        MagickBooleanType
 
2447
          proceed;
 
2448
 
 
2449
#if defined(MAGICKCORE_OPENMP_SUPPORT)
 
2450
  #pragma omp critical (MagickCore_FilterImageChannel)
 
2451
#endif
 
2452
        proceed=SetImageProgress(image,FilterImageTag,progress++,image->rows);
 
2453
        if (proceed == MagickFalse)
 
2454
          status=MagickFalse;
 
2455
      }
 
2456
  }
 
2457
  filter_image->type=image->type;
 
2458
  filter_view=DestroyCacheView(filter_view);
 
2459
  image_view=DestroyCacheView(image_view);
 
2460
  if (status == MagickFalse)
 
2461
    filter_image=DestroyImage(filter_image);
 
2462
  return(filter_image);
 
2463
}
 
2464
 
 
2465
/*
 
2466
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2467
%                                                                             %
 
2468
%                                                                             %
 
2469
%                                                                             %
1766
2470
%     G a u s s i a n B l u r I m a g e                                       %
1767
2471
%                                                                             %
1768
2472
%                                                                             %
1818
2522
  Image
1819
2523
    *blur_image;
1820
2524
 
1821
 
  MagickRealType
1822
 
    alpha;
1823
 
 
1824
 
  register long
1825
 
    i,
 
2525
  ssize_t
 
2526
    j,
1826
2527
    u,
1827
2528
    v;
1828
2529
 
1829
 
  unsigned long
 
2530
  register ssize_t
 
2531
    i;
 
2532
 
 
2533
  size_t
1830
2534
    width;
1831
2535
 
1832
2536
  assert(image != (const Image *) NULL);
1839
2543
  kernel=(double *) AcquireQuantumMemory((size_t) width,width*sizeof(*kernel));
1840
2544
  if (kernel == (double *) NULL)
1841
2545
    ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
 
2546
  j=(ssize_t) width/2;
1842
2547
  i=0;
1843
 
  for (v=(-((long) width/2)); v <= (long) (width/2); v++)
 
2548
  for (v=(-j); v <= j; v++)
1844
2549
  {
1845
 
    for (u=(-((long) width/2)); u <= (long) (width/2); u++)
1846
 
    {
1847
 
      alpha=exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma));
1848
 
      kernel[i]=(double) (alpha/(2.0*MagickPI*MagickSigma*MagickSigma));
1849
 
      i++;
1850
 
    }
 
2550
    for (u=(-j); u <= j; u++)
 
2551
      kernel[i++]=exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma))/
 
2552
        (2.0*MagickPI*MagickSigma*MagickSigma);
1851
2553
  }
1852
2554
  blur_image=ConvolveImageChannel(image,channel,width,kernel,exception);
1853
2555
  kernel=(double *) RelinquishMagickMemory(kernel);
1893
2595
 
1894
2596
typedef struct _MedianListNode
1895
2597
{
1896
 
  unsigned long
 
2598
  size_t
1897
2599
    next[9],
1898
2600
    count,
1899
2601
    signature;
1901
2603
 
1902
2604
typedef struct _MedianSkipList
1903
2605
{
1904
 
  long
 
2606
  ssize_t
1905
2607
    level;
1906
2608
 
1907
2609
  MedianListNode
1910
2612
 
1911
2613
typedef struct _MedianPixelList
1912
2614
{
1913
 
  unsigned long
 
2615
  size_t
1914
2616
    center,
1915
2617
    seed,
1916
2618
    signature;
1921
2623
 
1922
2624
static MedianPixelList *DestroyMedianPixelList(MedianPixelList *pixel_list)
1923
2625
{
1924
 
  register long
 
2626
  register ssize_t
1925
2627
    i;
1926
2628
 
1927
2629
  if (pixel_list == (MedianPixelList *) NULL)
1937
2639
static MedianPixelList **DestroyMedianPixelListThreadSet(
1938
2640
  MedianPixelList **pixel_list)
1939
2641
{
1940
 
  register long
 
2642
  register ssize_t
1941
2643
    i;
1942
2644
 
1943
2645
  assert(pixel_list != (MedianPixelList **) NULL);
1944
 
  for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
 
2646
  for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
1945
2647
    if (pixel_list[i] != (MedianPixelList *) NULL)
1946
2648
      pixel_list[i]=DestroyMedianPixelList(pixel_list[i]);
1947
2649
  pixel_list=(MedianPixelList **) RelinquishAlignedMemory(pixel_list);
1948
2650
  return(pixel_list);
1949
2651
}
1950
2652
 
1951
 
static MedianPixelList *AcquireMedianPixelList(const unsigned long width)
 
2653
static MedianPixelList *AcquireMedianPixelList(const size_t width)
1952
2654
{
1953
2655
  MedianPixelList
1954
2656
    *pixel_list;
1955
2657
 
1956
 
  register long
 
2658
  register ssize_t
1957
2659
    i;
1958
2660
 
1959
2661
  pixel_list=(MedianPixelList *) AcquireAlignedMemory(1,sizeof(*pixel_list));
1975
2677
}
1976
2678
 
1977
2679
static MedianPixelList **AcquireMedianPixelListThreadSet(
1978
 
  const unsigned long width)
 
2680
  const size_t width)
1979
2681
{
1980
 
  register long
 
2682
  register ssize_t
1981
2683
    i;
1982
2684
 
1983
2685
  MedianPixelList
1984
2686
    **pixel_list;
1985
2687
 
1986
 
  unsigned long
 
2688
  size_t
1987
2689
    number_threads;
1988
2690
 
1989
2691
  number_threads=GetOpenMPMaximumThreads();
1992
2694
  if (pixel_list == (MedianPixelList **) NULL)
1993
2695
    return((MedianPixelList **) NULL);
1994
2696
  (void) ResetMagickMemory(pixel_list,0,number_threads*sizeof(*pixel_list));
1995
 
  for (i=0; i < (long) number_threads; i++)
 
2697
  for (i=0; i < (ssize_t) number_threads; i++)
1996
2698
  {
1997
2699
    pixel_list[i]=AcquireMedianPixelList(width);
1998
2700
    if (pixel_list[i] == (MedianPixelList *) NULL)
2002
2704
}
2003
2705
 
2004
2706
static void AddNodeMedianPixelList(MedianPixelList *pixel_list,
2005
 
  const long channel,const unsigned long color)
 
2707
  const ssize_t channel,const size_t color)
2006
2708
{
2007
 
  register long
 
2709
  register ssize_t
2008
2710
    level;
2009
2711
 
2010
2712
  register MedianSkipList
2011
2713
    *list;
2012
2714
 
2013
 
  unsigned long
 
2715
  size_t
2014
2716
    search,
2015
2717
    update[9];
2016
2718
 
2021
2723
  list->nodes[color].signature=pixel_list->signature;
2022
2724
  list->nodes[color].count=1;
2023
2725
  /*
2024
 
    Determine where it belongs in the list.
 
2726
    Determine where it bessize_ts in the list.
2025
2727
  */
2026
2728
  search=65536UL;
2027
2729
  for (level=list->level; level >= 0; level--)
2067
2769
  MagickPixelPacket
2068
2770
    pixel;
2069
2771
 
2070
 
  register long
 
2772
  register ssize_t
2071
2773
    channel;
2072
2774
 
2073
2775
  register MedianSkipList
2074
2776
    *list;
2075
2777
 
2076
 
  unsigned long
 
2778
  size_t
2077
2779
    center,
2078
2780
    color,
2079
2781
    count;
2111
2813
  const PixelPacket *pixel,const IndexPacket *indexes,
2112
2814
  MedianPixelList *pixel_list)
2113
2815
{
2114
 
  unsigned long
 
2816
  size_t
2115
2817
    signature;
2116
2818
 
2117
2819
  unsigned short
2155
2857
  int
2156
2858
    level;
2157
2859
 
2158
 
  register long
 
2860
  register ssize_t
2159
2861
    channel;
2160
2862
 
2161
2863
  register MedianListNode
2183
2885
{
2184
2886
#define MedianFilterImageTag  "MedianFilter/Image"
2185
2887
 
 
2888
  CacheView
 
2889
    *image_view,
 
2890
    *median_view;
 
2891
 
2186
2892
  Image
2187
2893
    *median_image;
2188
2894
 
2189
 
  long
2190
 
    progress,
2191
 
    y;
2192
 
 
2193
2895
  MagickBooleanType
2194
2896
    status;
2195
2897
 
 
2898
  MagickOffsetType
 
2899
    progress;
 
2900
 
2196
2901
  MedianPixelList
2197
 
    **pixel_list;
 
2902
    **restrict pixel_list;
2198
2903
 
2199
 
  unsigned long
 
2904
  size_t
2200
2905
    width;
2201
2906
 
2202
 
  CacheView
2203
 
    *image_view,
2204
 
    *median_view;
 
2907
  ssize_t
 
2908
    y;
2205
2909
 
2206
2910
  /*
2207
2911
    Initialize median image attributes.
2241
2945
#if defined(MAGICKCORE_OPENMP_SUPPORT)
2242
2946
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
2243
2947
#endif
2244
 
  for (y=0; y < (long) median_image->rows; y++)
 
2948
  for (y=0; y < (ssize_t) median_image->rows; y++)
2245
2949
  {
2246
2950
    register const IndexPacket
2247
 
      *__restrict indexes;
 
2951
      *restrict indexes;
2248
2952
 
2249
2953
    register const PixelPacket
2250
 
      *__restrict p;
 
2954
      *restrict p;
2251
2955
 
2252
2956
    register IndexPacket
2253
 
      *__restrict median_indexes;
 
2957
      *restrict median_indexes;
2254
2958
 
2255
 
    register long
 
2959
    register ssize_t
2256
2960
      id,
2257
2961
      x;
2258
2962
 
2259
2963
    register PixelPacket
2260
 
      *__restrict q;
 
2964
      *restrict q;
2261
2965
 
2262
2966
    if (status == MagickFalse)
2263
2967
      continue;
2264
 
    p=GetCacheViewVirtualPixels(image_view,-((long) width/2L),y-(long) (width/
 
2968
    p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t) (width/
2265
2969
      2L),image->columns+width,width,exception);
2266
2970
    q=QueueCacheViewAuthenticPixels(median_view,0,y,median_image->columns,1,
2267
2971
      exception);
2273
2977
    indexes=GetCacheViewVirtualIndexQueue(image_view);
2274
2978
    median_indexes=GetCacheViewAuthenticIndexQueue(median_view);
2275
2979
    id=GetOpenMPThreadId();
2276
 
    for (x=0; x < (long) median_image->columns; x++)
 
2980
    for (x=0; x < (ssize_t) median_image->columns; x++)
2277
2981
    {
2278
2982
      MagickPixelPacket
2279
2983
        pixel;
2280
2984
 
2281
2985
      register const PixelPacket
2282
 
        *__restrict r;
 
2986
        *restrict r;
2283
2987
 
2284
2988
      register const IndexPacket
2285
 
        *__restrict s;
 
2989
        *restrict s;
2286
2990
 
2287
 
      register long
 
2991
      register ssize_t
2288
2992
        u,
2289
2993
        v;
2290
2994
 
2291
2995
      r=p;
2292
2996
      s=indexes+x;
2293
2997
      ResetMedianPixelList(pixel_list[id]);
2294
 
      for (v=0; v < (long) width; v++)
 
2998
      for (v=0; v < (ssize_t) width; v++)
2295
2999
      {
2296
 
        for (u=0; u < (long) width; u++)
 
3000
        for (u=0; u < (ssize_t) width; u++)
2297
3001
          InsertMedianPixelList(image,r+u,s+u,pixel_list[id]);
2298
3002
        r+=image->columns+width;
2299
3003
        s+=image->columns+width;
2370
3074
%
2371
3075
*/
2372
3076
 
2373
 
static double *GetMotionBlurKernel(unsigned long width,
2374
 
  const MagickRealType sigma)
 
3077
static double *GetMotionBlurKernel(const size_t width,const double sigma)
2375
3078
{
2376
 
#define KernelRank 3
2377
 
 
2378
3079
  double
2379
 
    *kernel;
2380
 
 
2381
 
  long
2382
 
    bias;
2383
 
 
2384
 
  MagickRealType
2385
 
    alpha,
 
3080
    *kernel,
2386
3081
    normalize;
2387
3082
 
2388
 
  register long
 
3083
  register ssize_t
2389
3084
    i;
2390
3085
 
2391
3086
  /*
2392
 
    Generate a 1-D convolution kernel.
 
3087
   Generate a 1-D convolution kernel.
2393
3088
  */
2394
3089
  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2395
3090
  kernel=(double *) AcquireQuantumMemory((size_t) width,sizeof(*kernel));
2396
3091
  if (kernel == (double *) NULL)
2397
3092
    return(kernel);
2398
 
  (void) ResetMagickMemory(kernel,0,(size_t) width*sizeof(*kernel));
2399
 
  bias=(long) (KernelRank*width);
2400
 
  for (i=0; i < (long) bias; i++)
 
3093
  normalize=0.0;
 
3094
  for (i=0; i < (ssize_t) width; i++)
2401
3095
  {
2402
 
    alpha=exp((-((double) (i*i))/(double) (2.0*KernelRank*KernelRank*
2403
 
      MagickSigma*MagickSigma)));
2404
 
    kernel[i/KernelRank]+=(double) alpha/(MagickSQ2PI*sigma);
 
3096
    kernel[i]=exp((-((double) i*i)/(double) (2.0*MagickSigma*MagickSigma)))/
 
3097
      (MagickSQ2PI*MagickSigma);
 
3098
    normalize+=kernel[i];
2405
3099
  }
2406
 
  normalize=0.0;
2407
 
  for (i=0; i < (long) width; i++)
2408
 
    normalize+=kernel[i];
2409
 
  for (i=0; i < (long) width; i++)
 
3100
  for (i=0; i < (ssize_t) width; i++)
2410
3101
    kernel[i]/=normalize;
2411
3102
  return(kernel);
2412
3103
}
2426
3117
  const ChannelType channel,const double radius,const double sigma,
2427
3118
  const double angle,ExceptionInfo *exception)
2428
3119
{
2429
 
  typedef struct _OffsetInfo
2430
 
  {
2431
 
    long
2432
 
      x,
2433
 
      y;
2434
 
  } OffsetInfo;
 
3120
  CacheView
 
3121
    *blur_view,
 
3122
    *image_view;
2435
3123
 
2436
3124
  double
2437
3125
    *kernel;
2439
3127
  Image
2440
3128
    *blur_image;
2441
3129
 
2442
 
  long
2443
 
    progress,
2444
 
    y;
2445
 
 
2446
3130
  MagickBooleanType
2447
3131
    status;
2448
3132
 
 
3133
  MagickOffsetType
 
3134
    progress;
 
3135
 
2449
3136
  MagickPixelPacket
2450
3137
    bias;
2451
3138
 
2455
3142
  PointInfo
2456
3143
    point;
2457
3144
 
2458
 
  register long
 
3145
  register ssize_t
2459
3146
    i;
2460
3147
 
2461
 
  unsigned long
 
3148
  size_t
2462
3149
    width;
2463
3150
 
2464
 
  CacheView
2465
 
    *blur_view,
2466
 
    *image_view;
 
3151
  ssize_t
 
3152
    y;
2467
3153
 
2468
3154
  assert(image != (Image *) NULL);
2469
3155
  assert(image->signature == MagickSignature);
2497
3183
    }
2498
3184
  point.x=(double) width*sin(DegreesToRadians(angle));
2499
3185
  point.y=(double) width*cos(DegreesToRadians(angle));
2500
 
  for (i=0; i < (long) width; i++)
 
3186
  for (i=0; i < (ssize_t) width; i++)
2501
3187
  {
2502
 
    offset[i].x=(long) ((i*point.y)/hypot(point.x,point.y)+0.5);
2503
 
    offset[i].y=(long) ((i*point.x)/hypot(point.x,point.y)+0.5);
 
3188
    offset[i].x=(ssize_t) ceil((double) (i*point.y)/hypot(point.x,point.y)-0.5);
 
3189
    offset[i].y=(ssize_t) ceil((double) (i*point.x)/hypot(point.x,point.y)-0.5);
2504
3190
  }
2505
3191
  /*
2506
3192
    Motion blur image.
2510
3196
  GetMagickPixelPacket(image,&bias);
2511
3197
  image_view=AcquireCacheView(image);
2512
3198
  blur_view=AcquireCacheView(blur_image);
2513
 
#if defined(MAGICKCORE_OPENMP_SUPPORT)
 
3199
#if defined(MAGICKCORE_OPENMP_SUPPORT) 
2514
3200
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
2515
3201
#endif
2516
 
  for (y=0; y < (long) image->rows; y++)
 
3202
  for (y=0; y < (ssize_t) image->rows; y++)
2517
3203
  {
2518
3204
    register IndexPacket
2519
 
      *__restrict blur_indexes;
 
3205
      *restrict blur_indexes;
2520
3206
 
2521
 
    register long
 
3207
    register ssize_t
2522
3208
      x;
2523
3209
 
2524
3210
    register PixelPacket
2525
 
      *__restrict q;
 
3211
      *restrict q;
2526
3212
 
2527
3213
    if (status == MagickFalse)
2528
3214
      continue;
2534
3220
        continue;
2535
3221
      }
2536
3222
    blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
2537
 
    for (x=0; x < (long) image->columns; x++)
 
3223
    for (x=0; x < (ssize_t) image->columns; x++)
2538
3224
    {
2539
3225
      MagickPixelPacket
2540
3226
        qixel;
2543
3229
        pixel;
2544
3230
 
2545
3231
      register double
2546
 
        *__restrict k;
 
3232
        *restrict k;
2547
3233
 
2548
 
      register long
 
3234
      register ssize_t
2549
3235
        i;
2550
3236
 
2551
3237
      register const IndexPacket
2552
 
        *__restrict indexes;
 
3238
        *restrict indexes;
2553
3239
 
2554
3240
      k=kernel;
2555
3241
      qixel=bias;
2556
3242
      if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
2557
3243
        {
2558
 
          for (i=0; i < (long) width; i++)
 
3244
          for (i=0; i < (ssize_t) width; i++)
2559
3245
          {
2560
3246
            (void) GetOneCacheViewVirtualPixel(image_view,x+offset[i].x,y+
2561
3247
              offset[i].y,&pixel,exception);
2571
3257
            k++;
2572
3258
          }
2573
3259
          if ((channel & RedChannel) != 0)
2574
 
            q->red=RoundToQuantum(qixel.red);
 
3260
            q->red=ClampToQuantum(qixel.red);
2575
3261
          if ((channel & GreenChannel) != 0)
2576
 
            q->green=RoundToQuantum(qixel.green);
 
3262
            q->green=ClampToQuantum(qixel.green);
2577
3263
          if ((channel & BlueChannel) != 0)
2578
 
            q->blue=RoundToQuantum(qixel.blue);
 
3264
            q->blue=ClampToQuantum(qixel.blue);
2579
3265
          if ((channel & OpacityChannel) != 0)
2580
 
            q->opacity=RoundToQuantum(qixel.opacity);
 
3266
            q->opacity=ClampToQuantum(qixel.opacity);
2581
3267
          if (((channel & IndexChannel) != 0) &&
2582
3268
              (image->colorspace == CMYKColorspace))
2583
 
            blur_indexes[x]=(IndexPacket) RoundToQuantum(qixel.index);
 
3269
            blur_indexes[x]=(IndexPacket) ClampToQuantum(qixel.index);
2584
3270
        }
2585
3271
      else
2586
3272
        {
2590
3276
 
2591
3277
          alpha=0.0;
2592
3278
          gamma=0.0;
2593
 
          for (i=0; i < (long) width; i++)
 
3279
          for (i=0; i < (ssize_t) width; i++)
2594
3280
          {
2595
3281
            (void) GetOneCacheViewVirtualPixel(image_view,x+offset[i].x,y+
2596
3282
              offset[i].y,&pixel,exception);
2597
 
            alpha=(MagickRealType) (QuantumScale*(QuantumRange-pixel.opacity));
 
3283
            alpha=(MagickRealType) (QuantumScale*
 
3284
              GetAlphaPixelComponent(&pixel));
2598
3285
            qixel.red+=(*k)*alpha*pixel.red;
2599
3286
            qixel.green+=(*k)*alpha*pixel.green;
2600
3287
            qixel.blue+=(*k)*alpha*pixel.blue;
2609
3296
          }
2610
3297
          gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
2611
3298
          if ((channel & RedChannel) != 0)
2612
 
            q->red=RoundToQuantum(gamma*qixel.red);
 
3299
            q->red=ClampToQuantum(gamma*qixel.red);
2613
3300
          if ((channel & GreenChannel) != 0)
2614
 
            q->green=RoundToQuantum(gamma*qixel.green);
 
3301
            q->green=ClampToQuantum(gamma*qixel.green);
2615
3302
          if ((channel & BlueChannel) != 0)
2616
 
            q->blue=RoundToQuantum(gamma*qixel.blue);
 
3303
            q->blue=ClampToQuantum(gamma*qixel.blue);
2617
3304
          if ((channel & OpacityChannel) != 0)
2618
 
            q->opacity=RoundToQuantum(qixel.opacity);
 
3305
            q->opacity=ClampToQuantum(qixel.opacity);
2619
3306
          if (((channel & IndexChannel) != 0) &&
2620
3307
              (image->colorspace == CMYKColorspace))
2621
 
            blur_indexes[x]=(IndexPacket) RoundToQuantum(gamma*qixel.index);
 
3308
            blur_indexes[x]=(IndexPacket) ClampToQuantum(gamma*qixel.index);
2622
3309
        }
2623
3310
      q++;
2624
3311
    }
2629
3316
        MagickBooleanType
2630
3317
          proceed;
2631
3318
 
2632
 
#if defined(MAGICKCORE_OPENMP_SUPPORT)
 
3319
#if defined(MAGICKCORE_OPENMP_SUPPORT) 
2633
3320
  #pragma omp critical (MagickCore_MotionBlurImageChannel)
2634
3321
#endif
2635
3322
        proceed=SetImageProgress(image,BlurImageTag,progress++,image->rows);
2704
3391
  ImageInfo
2705
3392
    *preview_info;
2706
3393
 
2707
 
  long
 
3394
  ssize_t
2708
3395
    y;
2709
3396
 
2710
3397
  MagickBooleanType
2719
3406
  RectangleInfo
2720
3407
    geometry;
2721
3408
 
2722
 
  register long
 
3409
  register ssize_t
2723
3410
    i,
2724
3411
    x;
2725
3412
 
2726
 
  unsigned long
 
3413
  size_t
2727
3414
    colors;
2728
3415
 
2729
3416
  /*
2781
3468
      }
2782
3469
      case RollPreview:
2783
3470
      {
2784
 
        x=(long) ((i+1)*thumbnail->columns)/NumberTiles;
2785
 
        y=(long) ((i+1)*thumbnail->rows)/NumberTiles;
 
3471
        x=(ssize_t) ((i+1)*thumbnail->columns)/NumberTiles;
 
3472
        y=(ssize_t) ((i+1)*thumbnail->rows)/NumberTiles;
2786
3473
        preview_image=RollImage(thumbnail,x,y,exception);
2787
 
        (void) FormatMagickString(label,MaxTextExtent,"roll %ldx%ld",x,y);
 
3474
        (void) FormatMagickString(label,MaxTextExtent,"roll %+.20gx%+.20g",
 
3475
          (double) x,(double) y);
2788
3476
        break;
2789
3477
      }
2790
3478
      case HuePreview:
2803
3491
        preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2804
3492
        if (preview_image == (Image *) NULL)
2805
3493
          break;
2806
 
        (void) FormatMagickString(factor,MaxTextExtent,"100,%g",2.0*percentage);
 
3494
        (void) FormatMagickString(factor,MaxTextExtent,"100,%g",
 
3495
          2.0*percentage);
2807
3496
        (void) ModulateImage(preview_image,factor);
2808
3497
        (void) FormatMagickString(label,MaxTextExtent,"modulate %s",factor);
2809
3498
        break;
2835
3524
        if (preview_image != (Image *) NULL)
2836
3525
          for (x=0; x < i; x++)
2837
3526
            (void) ContrastImage(preview_image,MagickTrue);
2838
 
        (void) FormatMagickString(label,MaxTextExtent,"contrast (%ld)",i+1);
 
3527
        (void) FormatMagickString(label,MaxTextExtent,"contrast (%.20g)",
 
3528
          (double) i+1);
2839
3529
        break;
2840
3530
      }
2841
3531
      case DullPreview:
2845
3535
          break;
2846
3536
        for (x=0; x < i; x++)
2847
3537
          (void) ContrastImage(preview_image,MagickFalse);
2848
 
        (void) FormatMagickString(label,MaxTextExtent,"+contrast (%ld)",i+1);
 
3538
        (void) FormatMagickString(label,MaxTextExtent,"+contrast (%.20g)",
 
3539
          (double) i+1);
2849
3540
        break;
2850
3541
      }
2851
3542
      case GrayscalePreview:
2858
3549
        quantize_info.colorspace=GRAYColorspace;
2859
3550
        (void) QuantizeImage(&quantize_info,preview_image);
2860
3551
        (void) FormatMagickString(label,MaxTextExtent,
2861
 
          "-colorspace gray -colors %ld",colors);
 
3552
          "-colorspace gray -colors %.20g",(double) colors);
2862
3553
        break;
2863
3554
      }
2864
3555
      case QuantizePreview:
2869
3560
        colors<<=1;
2870
3561
        quantize_info.number_colors=colors;
2871
3562
        (void) QuantizeImage(&quantize_info,preview_image);
2872
 
        (void) FormatMagickString(label,MaxTextExtent,"colors %ld",colors);
 
3563
        (void) FormatMagickString(label,MaxTextExtent,"colors %.20g",(double)
 
3564
          colors);
2873
3565
        break;
2874
3566
      }
2875
3567
      case DespecklePreview:
2885
3577
        preview_image=DespeckleImage(thumbnail,exception);
2886
3578
        if (preview_image == (Image *) NULL)
2887
3579
          break;
2888
 
        (void) FormatMagickString(label,MaxTextExtent,"despeckle (%ld)",i+1);
 
3580
        (void) FormatMagickString(label,MaxTextExtent,"despeckle (%.20g)",
 
3581
          (double) i+1);
2889
3582
        break;
2890
3583
      }
2891
3584
      case ReduceNoisePreview:
2941
3634
      case SharpenPreview:
2942
3635
      {
2943
3636
        preview_image=SharpenImage(thumbnail,radius,sigma,exception);
2944
 
        (void) FormatMagickString(label,MaxTextExtent,"sharpen %gx%g",radius,
2945
 
          sigma);
 
3637
        (void) FormatMagickString(label,MaxTextExtent,"sharpen %gx%g",
 
3638
          radius,sigma);
2946
3639
        break;
2947
3640
      }
2948
3641
      case BlurPreview:
2972
3665
      case SpreadPreview:
2973
3666
      {
2974
3667
        preview_image=SpreadImage(thumbnail,radius,exception);
2975
 
        (void) FormatMagickString(label,MaxTextExtent,"spread %g",radius+0.5);
 
3668
        (void) FormatMagickString(label,MaxTextExtent,"spread %g",
 
3669
          radius+0.5);
2976
3670
        break;
2977
3671
      }
2978
3672
      case SolarizePreview:
2991
3685
        degrees+=10.0;
2992
3686
        preview_image=ShadeImage(thumbnail,MagickTrue,degrees,degrees,
2993
3687
          exception);
2994
 
        (void) FormatMagickString(label,MaxTextExtent,"shade %gx%g",degrees,
2995
 
          degrees);
 
3688
        (void) FormatMagickString(label,MaxTextExtent,"shade %gx%g",
 
3689
          degrees,degrees);
2996
3690
        break;
2997
3691
      }
2998
3692
      case RaisePreview:
3000
3694
        preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3001
3695
        if (preview_image == (Image *) NULL)
3002
3696
          break;
3003
 
        geometry.width=(unsigned long) (2*i+2);
3004
 
        geometry.height=(unsigned long) (2*i+2);
 
3697
        geometry.width=(size_t) (2*i+2);
 
3698
        geometry.height=(size_t) (2*i+2);
3005
3699
        geometry.x=i/2;
3006
3700
        geometry.y=i/2;
3007
3701
        (void) RaiseImage(preview_image,&geometry,MagickTrue);
3008
 
        (void) FormatMagickString(label,MaxTextExtent,"raise %lux%lu%+ld%+ld",
3009
 
          geometry.width,geometry.height,geometry.x,geometry.y);
 
3702
        (void) FormatMagickString(label,MaxTextExtent,
 
3703
          "raise %.20gx%.20g%+.20g%+.20g",(double) geometry.width,(double)
 
3704
          geometry.height,(double) geometry.x,(double) geometry.y);
3010
3705
        break;
3011
3706
      }
3012
3707
      case SegmentPreview:
3039
3734
      {
3040
3735
        degrees+=5.0f;
3041
3736
        preview_image=WaveImage(thumbnail,0.5*degrees,2.0*degrees,exception);
3042
 
        (void) FormatMagickString(label,MaxTextExtent,"wave %gx%g",0.5*degrees,
3043
 
          2.0*degrees);
 
3737
        (void) FormatMagickString(label,MaxTextExtent,"wave %gx%g",
 
3738
          0.5*degrees,2.0*degrees);
3044
3739
        break;
3045
3740
      }
3046
3741
      case OilPaintPreview:
3053
3748
      {
3054
3749
        preview_image=CharcoalImage(thumbnail,(double) radius,(double) sigma,
3055
3750
          exception);
3056
 
        (void) FormatMagickString(label,MaxTextExtent,"charcoal %gx%g",radius,
3057
 
          sigma);
 
3751
        (void) FormatMagickString(label,MaxTextExtent,"charcoal %gx%g",
 
3752
          radius,sigma);
3058
3753
        break;
3059
3754
      }
3060
3755
      case JPEGPreview:
3071
3766
        preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3072
3767
        if (preview_image == (Image *) NULL)
3073
3768
          break;
3074
 
        preview_info->quality=(unsigned long) percentage;
3075
 
        (void) FormatMagickString(factor,MaxTextExtent,"%lu",
 
3769
        preview_info->quality=(size_t) percentage;
 
3770
        (void) FormatMagickString(factor,MaxTextExtent,"%.20g",(double)
3076
3771
          preview_info->quality);
3077
3772
        file=AcquireUniqueFileResource(filename);
3078
3773
        if (file != -1)
3101
3796
            1024.0/1024.0);
3102
3797
        else
3103
3798
          if (GetBlobSize(preview_image) >= 1024)
3104
 
            (void) FormatMagickString(label,MaxTextExtent,"quality %s\n%gkb ",
3105
 
              factor,(double) ((MagickOffsetType) GetBlobSize(preview_image))/
3106
 
              1024.0);
 
3799
            (void) FormatMagickString(label,MaxTextExtent,
 
3800
              "quality %s\n%gkb ",factor,(double) ((MagickOffsetType)
 
3801
              GetBlobSize(preview_image))/1024.0);
3107
3802
          else
3108
 
            (void) FormatMagickString(label,MaxTextExtent,"quality %s\n%lub ",
3109
 
              factor,(unsigned long) GetBlobSize(thumbnail));
 
3803
            (void) FormatMagickString(label,MaxTextExtent,"quality %s\n%.20gb ",
 
3804
              factor,(double) GetBlobSize(thumbnail));
3110
3805
        break;
3111
3806
      }
3112
3807
    }
3119
3814
    (void) DeleteImageProperty(preview_image,"label");
3120
3815
    (void) SetImageProperty(preview_image,"label",label);
3121
3816
    AppendImageToList(&images,preview_image);
3122
 
    proceed=SetImageProgress(image,PreviewImageTag,i,NumberTiles);
 
3817
    proceed=SetImageProgress(image,PreviewImageTag,(MagickOffsetType) i,
 
3818
      NumberTiles);
3123
3819
    if (proceed == MagickFalse)
3124
3820
      break;
3125
3821
  }
3204
3900
MagickExport Image *RadialBlurImageChannel(const Image *image,
3205
3901
  const ChannelType channel,const double angle,ExceptionInfo *exception)
3206
3902
{
 
3903
  CacheView
 
3904
    *blur_view,
 
3905
    *image_view;
 
3906
 
3207
3907
  Image
3208
3908
    *blur_image;
3209
3909
 
3210
 
  long
3211
 
    progress,
3212
 
    y;
3213
 
 
3214
3910
  MagickBooleanType
3215
3911
    status;
3216
3912
 
 
3913
  MagickOffsetType
 
3914
    progress;
 
3915
 
3217
3916
  MagickPixelPacket
3218
3917
    bias;
3219
3918
 
3227
3926
  PointInfo
3228
3927
    blur_center;
3229
3928
 
3230
 
  register long
 
3929
  register ssize_t
3231
3930
    i;
3232
3931
 
3233
 
  unsigned long
 
3932
  size_t
3234
3933
    n;
3235
3934
 
3236
 
  CacheView
3237
 
    *blur_view,
3238
 
    *image_view;
 
3935
  ssize_t
 
3936
    y;
3239
3937
 
3240
3938
  /*
3241
3939
    Allocate blur image.
3258
3956
  blur_center.x=(double) image->columns/2.0;
3259
3957
  blur_center.y=(double) image->rows/2.0;
3260
3958
  blur_radius=hypot(blur_center.x,blur_center.y);
3261
 
  n=(unsigned long) fabs(4.0*DegreesToRadians(angle)*sqrt((double) blur_radius)+
 
3959
  n=(size_t) fabs(4.0*DegreesToRadians(angle)*sqrt((double) blur_radius)+
3262
3960
    2UL);
3263
3961
  theta=DegreesToRadians(angle)/(MagickRealType) (n-1);
3264
3962
  cos_theta=(MagickRealType *) AcquireQuantumMemory((size_t) n,
3272
3970
      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
3273
3971
    }
3274
3972
  offset=theta*(MagickRealType) (n-1)/2.0;
3275
 
  for (i=0; i < (long) n; i++)
 
3973
  for (i=0; i < (ssize_t) n; i++)
3276
3974
  {
3277
3975
    cos_theta[i]=cos((double) (theta*i-offset));
3278
3976
    sin_theta[i]=sin((double) (theta*i-offset));
3288
3986
#if defined(MAGICKCORE_OPENMP_SUPPORT)
3289
3987
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
3290
3988
#endif
3291
 
  for (y=0; y < (long) blur_image->rows; y++)
 
3989
  for (y=0; y < (ssize_t) blur_image->rows; y++)
3292
3990
  {
3293
3991
    register const IndexPacket
3294
 
      *__restrict indexes;
 
3992
      *restrict indexes;
3295
3993
 
3296
3994
    register IndexPacket
3297
 
      *__restrict blur_indexes;
 
3995
      *restrict blur_indexes;
3298
3996
 
3299
 
    register long
 
3997
    register ssize_t
3300
3998
      x;
3301
3999
 
3302
4000
    register PixelPacket
3303
 
      *__restrict q;
 
4001
      *restrict q;
3304
4002
 
3305
4003
    if (status == MagickFalse)
3306
4004
      continue;
3312
4010
        continue;
3313
4011
      }
3314
4012
    blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
3315
 
    for (x=0; x < (long) blur_image->columns; x++)
 
4013
    for (x=0; x < (ssize_t) blur_image->columns; x++)
3316
4014
    {
3317
4015
      MagickPixelPacket
3318
4016
        qixel;
3327
4025
      PointInfo
3328
4026
        center;
3329
4027
 
3330
 
      register long
 
4028
      register ssize_t
3331
4029
        i;
3332
4030
 
3333
 
      unsigned long
 
4031
      size_t
3334
4032
        step;
3335
4033
 
3336
4034
      center.x=(double) x-blur_center.x;
3340
4038
        step=1;
3341
4039
      else
3342
4040
        {
3343
 
          step=(unsigned long) (blur_radius/radius);
 
4041
          step=(size_t) (blur_radius/radius);
3344
4042
          if (step == 0)
3345
4043
            step=1;
3346
4044
          else
3351
4049
      qixel=bias;
3352
4050
      if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
3353
4051
        {
3354
 
          for (i=0; i < (long) n; i+=step)
 
4052
          for (i=0; i < (ssize_t) n; i+=(ssize_t) step)
3355
4053
          {
3356
 
            (void) GetOneCacheViewVirtualPixel(image_view,(long) (blur_center.x+
3357
 
              center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),(long) (
3358
 
              blur_center.y+center.x*sin_theta[i]+center.y*cos_theta[i]+0.5),
3359
 
              &pixel,exception);
 
4054
            (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t)
 
4055
              (blur_center.x+center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),
 
4056
              (ssize_t) (blur_center.y+center.x*sin_theta[i]+center.y*
 
4057
              cos_theta[i]+0.5),&pixel,exception);
3360
4058
            qixel.red+=pixel.red;
3361
4059
            qixel.green+=pixel.green;
3362
4060
            qixel.blue+=pixel.blue;
3371
4069
          normalize=1.0/(fabs((double) normalize) <= MagickEpsilon ? 1.0 :
3372
4070
            normalize);
3373
4071
          if ((channel & RedChannel) != 0)
3374
 
            q->red=RoundToQuantum(normalize*qixel.red);
 
4072
            q->red=ClampToQuantum(normalize*qixel.red);
3375
4073
          if ((channel & GreenChannel) != 0)
3376
 
            q->green=RoundToQuantum(normalize*qixel.green);
 
4074
            q->green=ClampToQuantum(normalize*qixel.green);
3377
4075
          if ((channel & BlueChannel) != 0)
3378
 
            q->blue=RoundToQuantum(normalize*qixel.blue);
 
4076
            q->blue=ClampToQuantum(normalize*qixel.blue);
3379
4077
          if ((channel & OpacityChannel) != 0)
3380
 
            q->opacity=RoundToQuantum(normalize*qixel.opacity);
 
4078
            q->opacity=ClampToQuantum(normalize*qixel.opacity);
3381
4079
          if (((channel & IndexChannel) != 0) &&
3382
4080
              (image->colorspace == CMYKColorspace))
3383
 
            blur_indexes[x]=(IndexPacket) RoundToQuantum(normalize*qixel.index);
 
4081
            blur_indexes[x]=(IndexPacket) ClampToQuantum(normalize*qixel.index);
3384
4082
        }
3385
4083
      else
3386
4084
        {
3390
4088
 
3391
4089
          alpha=1.0;
3392
4090
          gamma=0.0;
3393
 
          for (i=0; i < (long) n; i+=step)
 
4091
          for (i=0; i < (ssize_t) n; i+=(ssize_t) step)
3394
4092
          {
3395
 
            (void) GetOneCacheViewVirtualPixel(image_view,(long) (blur_center.x+
3396
 
              center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),(long) (
3397
 
              blur_center.y+center.x*sin_theta[i]+center.y*cos_theta[i]+0.5),
3398
 
              &pixel,exception);
3399
 
            alpha=(MagickRealType) (QuantumScale*(QuantumRange-pixel.opacity));
 
4093
            (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t)
 
4094
              (blur_center.x+center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),
 
4095
              (ssize_t) (blur_center.y+center.x*sin_theta[i]+center.y*
 
4096
              cos_theta[i]+0.5),&pixel,exception);
 
4097
            alpha=(MagickRealType) (QuantumScale*
 
4098
              GetAlphaPixelComponent(&pixel));
3400
4099
            qixel.red+=alpha*pixel.red;
3401
4100
            qixel.green+=alpha*pixel.green;
3402
4101
            qixel.blue+=alpha*pixel.blue;
3413
4112
          normalize=1.0/(fabs((double) normalize) <= MagickEpsilon ? 1.0 :
3414
4113
            normalize);
3415
4114
          if ((channel & RedChannel) != 0)
3416
 
            q->red=RoundToQuantum(gamma*qixel.red);
 
4115
            q->red=ClampToQuantum(gamma*qixel.red);
3417
4116
          if ((channel & GreenChannel) != 0)
3418
 
            q->green=RoundToQuantum(gamma*qixel.green);
 
4117
            q->green=ClampToQuantum(gamma*qixel.green);
3419
4118
          if ((channel & BlueChannel) != 0)
3420
 
            q->blue=RoundToQuantum(gamma*qixel.blue);
 
4119
            q->blue=ClampToQuantum(gamma*qixel.blue);
3421
4120
          if ((channel & OpacityChannel) != 0)
3422
 
            q->opacity=RoundToQuantum(normalize*qixel.opacity);
 
4121
            q->opacity=ClampToQuantum(normalize*qixel.opacity);
3423
4122
          if (((channel & IndexChannel) != 0) &&
3424
4123
              (image->colorspace == CMYKColorspace))
3425
 
            blur_indexes[x]=(IndexPacket) RoundToQuantum(gamma*qixel.index);
 
4124
            blur_indexes[x]=(IndexPacket) ClampToQuantum(gamma*qixel.index);
3426
4125
        }
3427
4126
      q++;
3428
4127
    }
3486
4185
  MagickPixelPacket
3487
4186
    pixel;
3488
4187
 
3489
 
  register long
 
4188
  register ssize_t
3490
4189
    channel;
3491
4190
 
3492
4191
  register MedianSkipList
3493
4192
    *list;
3494
4193
 
3495
 
  unsigned long
 
4194
  size_t
3496
4195
    center,
3497
4196
    color,
3498
4197
    count,
3541
4240
{
3542
4241
#define ReduceNoiseImageTag  "ReduceNoise/Image"
3543
4242
 
 
4243
  CacheView
 
4244
    *image_view,
 
4245
    *noise_view;
 
4246
 
3544
4247
  Image
3545
4248
    *noise_image;
3546
4249
 
3547
 
  long
3548
 
    progress,
3549
 
    y;
3550
 
 
3551
4250
  MagickBooleanType
3552
4251
    status;
3553
4252
 
 
4253
  MagickOffsetType
 
4254
    progress;
 
4255
 
3554
4256
  MedianPixelList
3555
 
    **pixel_list;
 
4257
    **restrict pixel_list;
3556
4258
 
3557
 
  unsigned long
 
4259
  size_t
3558
4260
    width;
3559
4261
 
3560
 
  CacheView
3561
 
    *image_view,
3562
 
    *noise_view;
 
4262
  ssize_t
 
4263
    y;
3563
4264
 
3564
4265
  /*
3565
4266
    Initialize noise image attributes.
3599
4300
#if defined(MAGICKCORE_OPENMP_SUPPORT)
3600
4301
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
3601
4302
#endif
3602
 
  for (y=0; y < (long) noise_image->rows; y++)
 
4303
  for (y=0; y < (ssize_t) noise_image->rows; y++)
3603
4304
  {
3604
4305
    register const IndexPacket
3605
 
      *__restrict indexes;
 
4306
      *restrict indexes;
3606
4307
 
3607
4308
    register const PixelPacket
3608
 
      *__restrict p;
 
4309
      *restrict p;
3609
4310
 
3610
4311
    register IndexPacket
3611
 
      *__restrict noise_indexes;
 
4312
      *restrict noise_indexes;
3612
4313
 
3613
 
    register long
 
4314
    register ssize_t
3614
4315
      id,
3615
4316
      x;
3616
4317
 
3617
4318
    register PixelPacket
3618
 
      *__restrict q;
 
4319
      *restrict q;
3619
4320
 
3620
4321
    if (status == MagickFalse)
3621
4322
      continue;
3622
 
    p=GetCacheViewVirtualPixels(image_view,-((long) width/2L),y-(long) (width/
 
4323
    p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t) (width/
3623
4324
      2L),image->columns+width,width,exception);
3624
4325
    q=QueueCacheViewAuthenticPixels(noise_view,0,y,noise_image->columns,1,
3625
4326
      exception);
3631
4332
    indexes=GetCacheViewVirtualIndexQueue(image_view);
3632
4333
    noise_indexes=GetCacheViewAuthenticIndexQueue(noise_view);
3633
4334
    id=GetOpenMPThreadId();
3634
 
    for (x=0; x < (long) noise_image->columns; x++)
 
4335
    for (x=0; x < (ssize_t) noise_image->columns; x++)
3635
4336
    {
3636
4337
      MagickPixelPacket
3637
4338
        pixel;
3638
4339
 
3639
4340
      register const PixelPacket
3640
 
        *__restrict r;
 
4341
        *restrict r;
3641
4342
 
3642
4343
      register const IndexPacket
3643
 
        *__restrict s;
 
4344
        *restrict s;
3644
4345
 
3645
 
      register long
 
4346
      register ssize_t
3646
4347
        u,
3647
4348
        v;
3648
4349
 
3649
4350
      r=p;
3650
4351
      s=indexes+x;
3651
4352
      ResetMedianPixelList(pixel_list[id]);
3652
 
      for (v=0; v < (long) width; v++)
 
4353
      for (v=0; v < (ssize_t) width; v++)
3653
4354
      {
3654
 
        for (u=0; u < (long) width; u++)
 
4355
        for (u=0; u < (ssize_t) width; u++)
3655
4356
          InsertMedianPixelList(image,r+u,s+u,pixel_list[id]);
3656
4357
        r+=image->columns+width;
3657
4358
        s+=image->columns+width;
3749
4450
{
3750
4451
#define SelectiveBlurImageTag  "SelectiveBlur/Image"
3751
4452
 
 
4453
  CacheView
 
4454
    *blur_view,
 
4455
    *image_view;
 
4456
 
3752
4457
  double
3753
 
    alpha,
3754
4458
    *kernel;
3755
4459
 
3756
4460
  Image
3757
4461
    *blur_image;
3758
4462
 
3759
 
  long
3760
 
    progress,
3761
 
    v,
3762
 
    y;
3763
 
 
3764
4463
  MagickBooleanType
3765
4464
    status;
3766
4465
 
 
4466
  MagickOffsetType
 
4467
    progress;
 
4468
 
3767
4469
  MagickPixelPacket
3768
4470
    bias;
3769
4471
 
3770
 
  register long
3771
 
    i,
3772
 
    u;
 
4472
  register ssize_t
 
4473
    i;
3773
4474
 
3774
 
  unsigned long
 
4475
  size_t
3775
4476
    width;
3776
4477
 
3777
 
  CacheView
3778
 
    *blur_view,
3779
 
    *image_view;
 
4478
  ssize_t
 
4479
    j,
 
4480
    u,
 
4481
    v,
 
4482
    y;
3780
4483
 
3781
4484
  /*
3782
4485
    Initialize blur image attributes.
3791
4494
  kernel=(double *) AcquireQuantumMemory((size_t) width,width*sizeof(*kernel));
3792
4495
  if (kernel == (double *) NULL)
3793
4496
    ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
 
4497
  j=(ssize_t) width/2;
3794
4498
  i=0;
3795
 
  for (v=(-((long) width/2)); v <= (long) (width/2); v++)
 
4499
  for (v=(-j); v <= j; v++)
3796
4500
  {
3797
 
    for (u=(-((long) width/2)); u <= (long) (width/2); u++)
3798
 
    {
3799
 
      alpha=exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma));
3800
 
      kernel[i]=(double) (alpha/(2.0*MagickPI*MagickSigma*MagickSigma));
3801
 
      i++;
3802
 
    }
 
4501
    for (u=(-j); u <= j; u++)
 
4502
      kernel[i++]=exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma))/
 
4503
        (2.0*MagickPI*MagickSigma*MagickSigma);
3803
4504
  }
3804
4505
  if (image->debug != MagickFalse)
3805
4506
    {
3807
4508
        format[MaxTextExtent],
3808
4509
        *message;
3809
4510
 
3810
 
      long
 
4511
      ssize_t
3811
4512
        u,
3812
4513
        v;
3813
4514
 
3815
4516
        *k;
3816
4517
 
3817
4518
      (void) LogMagickEvent(TransformEvent,GetMagickModule(),
3818
 
        "  SelectiveBlurImage with %ldx%ld kernel:",width,width);
 
4519
        "  SelectiveBlurImage with %.20gx%.20g kernel:",(double) width,(double)
 
4520
        width);
3819
4521
      message=AcquireString("");
3820
4522
      k=kernel;
3821
 
      for (v=0; v < (long) width; v++)
 
4523
      for (v=0; v < (ssize_t) width; v++)
3822
4524
      {
3823
4525
        *message='\0';
3824
 
        (void) FormatMagickString(format,MaxTextExtent,"%ld: ",v);
 
4526
        (void) FormatMagickString(format,MaxTextExtent,"%.20g: ",(double) v);
3825
4527
        (void) ConcatenateString(&message,format);
3826
 
        for (u=0; u < (long) width; u++)
 
4528
        for (u=0; u < (ssize_t) width; u++)
3827
4529
        {
3828
4530
          (void) FormatMagickString(format,MaxTextExtent,"%+f ",*k++);
3829
4531
          (void) ConcatenateString(&message,format);
3853
4555
#if defined(MAGICKCORE_OPENMP_SUPPORT)
3854
4556
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
3855
4557
#endif
3856
 
  for (y=0; y < (long) image->rows; y++)
 
4558
  for (y=0; y < (ssize_t) image->rows; y++)
3857
4559
  {
3858
4560
    MagickBooleanType
3859
4561
      sync;
3862
4564
      gamma;
3863
4565
 
3864
4566
    register const IndexPacket
3865
 
      *__restrict indexes;
 
4567
      *restrict indexes;
3866
4568
 
3867
4569
    register const PixelPacket
3868
 
      *__restrict p;
 
4570
      *restrict p;
3869
4571
 
3870
4572
    register IndexPacket
3871
 
      *__restrict blur_indexes;
 
4573
      *restrict blur_indexes;
3872
4574
 
3873
 
    register long
 
4575
    register ssize_t
3874
4576
      x;
3875
4577
 
3876
4578
    register PixelPacket
3877
 
      *__restrict q;
 
4579
      *restrict q;
3878
4580
 
3879
4581
    if (status == MagickFalse)
3880
4582
      continue;
3881
 
    p=GetCacheViewVirtualPixels(image_view,-((long) width/2L),y-(long) (width/
 
4583
    p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t) (width/
3882
4584
      2L),image->columns+width,width,exception);
3883
4585
    q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
3884
4586
      exception);
3889
4591
      }
3890
4592
    indexes=GetCacheViewVirtualIndexQueue(image_view);
3891
4593
    blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
3892
 
    for (x=0; x < (long) image->columns; x++)
 
4594
    for (x=0; x < (ssize_t) image->columns; x++)
3893
4595
    {
3894
 
      long
 
4596
      ssize_t
3895
4597
        j,
3896
4598
        v;
3897
4599
 
3899
4601
        pixel;
3900
4602
 
3901
4603
      register const double
3902
 
        *__restrict k;
 
4604
        *restrict k;
3903
4605
 
3904
 
      register long
 
4606
      register ssize_t
3905
4607
        u;
3906
4608
 
3907
4609
      pixel=bias;
3910
4612
      j=0;
3911
4613
      if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
3912
4614
        {
3913
 
          for (v=0; v < (long) width; v++)
 
4615
          for (v=0; v < (ssize_t) width; v++)
3914
4616
          {
3915
 
            for (u=0; u < (long) width; u++)
 
4617
            for (u=0; u < (ssize_t) width; u++)
3916
4618
            {
3917
4619
              if (SelectiveContrast(p+u+j,q,threshold) != MagickFalse)
3918
4620
                {
3923
4625
                  k++;
3924
4626
                }
3925
4627
            }
3926
 
            j+=image->columns+width;
 
4628
            j+=(ssize_t) (image->columns+width);
3927
4629
          }
3928
4630
          if (gamma != 0.0)
3929
4631
            {
3930
4632
              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
3931
4633
              if ((channel & RedChannel) != 0)
3932
 
                q->red=RoundToQuantum(gamma*pixel.red);
 
4634
                q->red=ClampToQuantum(gamma*GetRedPixelComponent(&pixel));
3933
4635
              if ((channel & GreenChannel) != 0)
3934
 
                q->green=RoundToQuantum(gamma*pixel.green);
 
4636
                q->green=ClampToQuantum(gamma*GetGreenPixelComponent(&pixel));
3935
4637
              if ((channel & BlueChannel) != 0)
3936
 
                q->blue=RoundToQuantum(gamma*pixel.blue);
 
4638
                q->blue=ClampToQuantum(gamma*GetBluePixelComponent(&pixel));
3937
4639
            }
3938
4640
          if ((channel & OpacityChannel) != 0)
3939
4641
            {
3940
4642
              gamma=0.0;
3941
4643
              j=0;
3942
 
              for (v=0; v < (long) width; v++)
 
4644
              for (v=0; v < (ssize_t) width; v++)
3943
4645
              {
3944
 
                for (u=0; u < (long) width; u++)
 
4646
                for (u=0; u < (ssize_t) width; u++)
3945
4647
                {
3946
4648
                  if (SelectiveContrast(p+u+j,q,threshold) != MagickFalse)
3947
4649
                    {
3950
4652
                      k++;
3951
4653
                    }
3952
4654
                }
3953
 
                j+=image->columns+width;
 
4655
                j+=(ssize_t) (image->columns+width);
3954
4656
              }
3955
4657
              if (gamma != 0.0)
3956
4658
                {
3957
4659
                  gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 :
3958
4660
                    gamma);
3959
 
                  q->opacity=RoundToQuantum(gamma*pixel.opacity);
 
4661
                  SetOpacityPixelComponent(q,ClampToQuantum(gamma*
 
4662
                    GetOpacityPixelComponent(&pixel)));
3960
4663
                }
3961
4664
            }
3962
4665
          if (((channel & IndexChannel) != 0) &&
3964
4667
            {
3965
4668
              gamma=0.0;
3966
4669
              j=0;
3967
 
              for (v=0; v < (long) width; v++)
 
4670
              for (v=0; v < (ssize_t) width; v++)
3968
4671
              {
3969
 
                for (u=0; u < (long) width; u++)
 
4672
                for (u=0; u < (ssize_t) width; u++)
3970
4673
                {
3971
4674
                  if (SelectiveContrast(p+u+j,q,threshold) != MagickFalse)
3972
4675
                    {
3975
4678
                      k++;
3976
4679
                    }
3977
4680
                }
3978
 
                j+=image->columns+width;
 
4681
                j+=(ssize_t) (image->columns+width);
3979
4682
              }
3980
4683
              if (gamma != 0.0)
3981
4684
                {
3982
4685
                  gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 :
3983
4686
                    gamma);
3984
 
                  blur_indexes[x]=RoundToQuantum(gamma*pixel.index);
 
4687
                  blur_indexes[x]=ClampToQuantum(gamma*
 
4688
                    GetIndexPixelComponent(&pixel));
3985
4689
                }
3986
4690
            }
3987
4691
        }
3990
4694
          MagickRealType
3991
4695
            alpha;
3992
4696
 
3993
 
          for (v=0; v < (long) width; v++)
 
4697
          for (v=0; v < (ssize_t) width; v++)
3994
4698
          {
3995
 
            for (u=0; u < (long) width; u++)
 
4699
            for (u=0; u < (ssize_t) width; u++)
3996
4700
            {
3997
4701
              if (SelectiveContrast(p+u+j,q,threshold) != MagickFalse)
3998
4702
                {
3999
 
                  alpha=(MagickRealType) (QuantumScale*(QuantumRange-
4000
 
                    (p+u+j)->opacity));
 
4703
                  alpha=(MagickRealType) (QuantumScale*
 
4704
                    GetAlphaPixelComponent(p+u+j));
4001
4705
                  pixel.red+=(*k)*alpha*(p+u+j)->red;
4002
4706
                  pixel.green+=(*k)*alpha*(p+u+j)->green;
4003
4707
                  pixel.blue+=(*k)*alpha*(p+u+j)->blue;
4006
4710
                  k++;
4007
4711
                }
4008
4712
            }
4009
 
            j+=image->columns+width;
 
4713
            j+=(ssize_t) (image->columns+width);
4010
4714
          }
4011
4715
          if (gamma != 0.0)
4012
4716
            {
4013
4717
              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
4014
4718
              if ((channel & RedChannel) != 0)
4015
 
                q->red=RoundToQuantum(gamma*pixel.red);
 
4719
                q->red=ClampToQuantum(gamma*GetRedPixelComponent(&pixel));
4016
4720
              if ((channel & GreenChannel) != 0)
4017
 
                q->green=RoundToQuantum(gamma*pixel.green);
 
4721
                q->green=ClampToQuantum(gamma*GetGreenPixelComponent(&pixel));
4018
4722
              if ((channel & BlueChannel) != 0)
4019
 
                q->blue=RoundToQuantum(gamma*pixel.blue);
 
4723
                q->blue=ClampToQuantum(gamma*GetBluePixelComponent(&pixel));
4020
4724
            }
4021
4725
          if ((channel & OpacityChannel) != 0)
4022
4726
            {
4023
4727
              gamma=0.0;
4024
4728
              j=0;
4025
 
              for (v=0; v < (long) width; v++)
 
4729
              for (v=0; v < (ssize_t) width; v++)
4026
4730
              {
4027
 
                for (u=0; u < (long) width; u++)
 
4731
                for (u=0; u < (ssize_t) width; u++)
4028
4732
                {
4029
4733
                  if (SelectiveContrast(p+u+j,q,threshold) != MagickFalse)
4030
4734
                    {
4033
4737
                      k++;
4034
4738
                    }
4035
4739
                }
4036
 
                j+=image->columns+width;
 
4740
                j+=(ssize_t) (image->columns+width);
4037
4741
              }
4038
4742
              if (gamma != 0.0)
4039
4743
                {
4040
4744
                  gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 :
4041
4745
                    gamma);
4042
 
                  q->opacity=RoundToQuantum(pixel.opacity);
 
4746
                  SetOpacityPixelComponent(q,
 
4747
                    ClampOpacityPixelComponent(&pixel));
4043
4748
                }
4044
4749
            }
4045
4750
          if (((channel & IndexChannel) != 0) &&
4047
4752
            {
4048
4753
              gamma=0.0;
4049
4754
              j=0;
4050
 
              for (v=0; v < (long) width; v++)
 
4755
              for (v=0; v < (ssize_t) width; v++)
4051
4756
              {
4052
 
                for (u=0; u < (long) width; u++)
 
4757
                for (u=0; u < (ssize_t) width; u++)
4053
4758
                {
4054
4759
                  if (SelectiveContrast(p+u+j,q,threshold) != MagickFalse)
4055
4760
                    {
4056
 
                      alpha=(MagickRealType) (QuantumScale*(QuantumRange-
4057
 
                        (p+u+j)->opacity));
 
4761
                      alpha=(MagickRealType) (QuantumScale*
 
4762
                        GetAlphaPixelComponent(p+u+j));
4058
4763
                      pixel.index+=(*k)*alpha*indexes[x+u+j];
4059
4764
                      gamma+=(*k);
4060
4765
                      k++;
4061
4766
                    }
4062
4767
                }
4063
 
                j+=image->columns+width;
 
4768
                j+=(ssize_t) (image->columns+width);
4064
4769
              }
4065
4770
              if (gamma != 0.0)
4066
4771
                {
4067
4772
                  gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 :
4068
4773
                    gamma);
4069
 
                  blur_indexes[x]=RoundToQuantum(gamma*pixel.index);
 
4774
                  blur_indexes[x]=ClampToQuantum(gamma*
 
4775
                    GetIndexPixelComponent(&pixel));
4070
4776
                }
4071
4777
            }
4072
4778
        }
4136
4842
{
4137
4843
#define ShadeImageTag  "Shade/Image"
4138
4844
 
 
4845
  CacheView
 
4846
    *image_view,
 
4847
    *shade_view;
 
4848
 
4139
4849
  Image
4140
4850
    *shade_image;
4141
4851
 
4142
 
  long
4143
 
    progress,
4144
 
    y;
4145
 
 
4146
4852
  MagickBooleanType
4147
4853
    status;
4148
4854
 
 
4855
  MagickOffsetType
 
4856
    progress;
 
4857
 
4149
4858
  PrimaryInfo
4150
4859
    light;
4151
4860
 
4152
 
  CacheView
4153
 
    *image_view,
4154
 
    *shade_view;
 
4861
  ssize_t
 
4862
    y;
4155
4863
 
4156
4864
  /*
4157
4865
    Initialize shaded image attributes.
4189
4897
#if defined(MAGICKCORE_OPENMP_SUPPORT)
4190
4898
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
4191
4899
#endif
4192
 
  for (y=0; y < (long) image->rows; y++)
 
4900
  for (y=0; y < (ssize_t) image->rows; y++)
4193
4901
  {
4194
4902
    MagickRealType
4195
4903
      distance,
4200
4908
      normal;
4201
4909
 
4202
4910
    register const PixelPacket
4203
 
      *__restrict p,
4204
 
      *__restrict s0,
4205
 
      *__restrict s1,
4206
 
      *__restrict s2;
 
4911
      *restrict p,
 
4912
      *restrict s0,
 
4913
      *restrict s1,
 
4914
      *restrict s2;
4207
4915
 
4208
 
    register long
 
4916
    register ssize_t
4209
4917
      x;
4210
4918
 
4211
4919
    register PixelPacket
4212
 
      *__restrict q;
 
4920
      *restrict q;
4213
4921
 
4214
4922
    if (status == MagickFalse)
4215
4923
      continue;
4228
4936
    s0=p+1;
4229
4937
    s1=s0+image->columns+2;
4230
4938
    s2=s1+image->columns+2;
4231
 
    for (x=0; x < (long) image->columns; x++)
 
4939
    for (x=0; x < (ssize_t) image->columns; x++)
4232
4940
    {
4233
4941
      /*
4234
4942
        Determine the surface normal and compute shading.
4261
4969
        }
4262
4970
      else
4263
4971
        {
4264
 
          q->red=RoundToQuantum(QuantumScale*shade*s1->red);
4265
 
          q->green=RoundToQuantum(QuantumScale*shade*s1->green);
4266
 
          q->blue=RoundToQuantum(QuantumScale*shade*s1->blue);
 
4972
          q->red=ClampToQuantum(QuantumScale*shade*s1->red);
 
4973
          q->green=ClampToQuantum(QuantumScale*shade*s1->green);
 
4974
          q->blue=ClampToQuantum(QuantumScale*shade*s1->blue);
4267
4975
        }
4268
4976
      q->opacity=s1->opacity;
4269
4977
      s0++;
4351
5059
  ExceptionInfo *exception)
4352
5060
{
4353
5061
  double
4354
 
    *kernel;
 
5062
    *kernel,
 
5063
    normalize;
4355
5064
 
4356
5065
  Image
4357
5066
    *sharp_image;
4358
5067
 
4359
 
  MagickRealType
4360
 
    alpha,
4361
 
    normalize;
4362
 
 
4363
 
  register long
4364
 
    i,
 
5068
  ssize_t
 
5069
    j,
4365
5070
    u,
4366
5071
    v;
4367
5072
 
4368
 
  unsigned long
 
5073
  register ssize_t
 
5074
    i;
 
5075
 
 
5076
  size_t
4369
5077
    width;
4370
5078
 
4371
5079
  assert(image != (const Image *) NULL);
4378
5086
  kernel=(double *) AcquireQuantumMemory((size_t) width*width,sizeof(*kernel));
4379
5087
  if (kernel == (double *) NULL)
4380
5088
    ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
 
5089
  normalize=0.0;
 
5090
  j=(ssize_t) width/2;
4381
5091
  i=0;
4382
 
  normalize=0.0;
4383
 
  for (v=(-((long) width/2)); v <= (long) (width/2); v++)
 
5092
  for (v=(-j); v <= j; v++)
4384
5093
  {
4385
 
    for (u=(-((long) width/2)); u <= (long) (width/2); u++)
 
5094
    for (u=(-j); u <= j; u++)
4386
5095
    {
4387
 
      alpha=exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma));
4388
 
      kernel[i]=(double) (-alpha/(2.0*MagickPI*MagickSigma*MagickSigma));
 
5096
      kernel[i]=(-exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma))/
 
5097
        (2.0*MagickPI*MagickSigma*MagickSigma));
4389
5098
      normalize+=kernel[i];
4390
5099
      i++;
4391
5100
    }
4429
5138
{
4430
5139
#define SpreadImageTag  "Spread/Image"
4431
5140
 
 
5141
  CacheView
 
5142
    *image_view;
 
5143
 
4432
5144
  Image
4433
5145
    *spread_image;
4434
5146
 
4435
 
  long
4436
 
    progress,
4437
 
    y;
4438
 
 
4439
5147
  MagickBooleanType
4440
5148
    status;
4441
5149
 
 
5150
  MagickOffsetType
 
5151
    progress;
 
5152
 
4442
5153
  MagickPixelPacket
4443
5154
    bias;
4444
5155
 
4445
5156
  RandomInfo
4446
 
    **random_info;
 
5157
    **restrict random_info;
4447
5158
 
4448
5159
  ResampleFilter
4449
 
    **resample_filter;
 
5160
    **restrict resample_filter;
4450
5161
 
4451
 
  unsigned long
 
5162
  size_t
4452
5163
    width;
4453
5164
 
4454
 
  CacheView
4455
 
    *image_view;
 
5165
  ssize_t
 
5166
    y;
4456
5167
 
4457
5168
  /*
4458
5169
    Initialize spread image attributes.
4480
5191
  progress=0;
4481
5192
  GetMagickPixelPacket(spread_image,&bias);
4482
5193
  width=GetOptimalKernelWidth1D(radius,0.5);
4483
 
  resample_filter=AcquireResampleFilterThreadSet(image,MagickTrue,exception);
 
5194
  resample_filter=AcquireResampleFilterThreadSet(image,
 
5195
    UndefinedVirtualPixelMethod,MagickTrue,exception);
4484
5196
  random_info=AcquireRandomInfoThreadSet();
4485
5197
  image_view=AcquireCacheView(spread_image);
4486
 
#if defined(MAGICKCORE_OPENMP_SUPPORT)
 
5198
#if defined(MAGICKCORE_OPENMP_SUPPORT) 
4487
5199
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
4488
5200
#endif
4489
 
  for (y=0; y < (long) spread_image->rows; y++)
 
5201
  for (y=0; y < (ssize_t) spread_image->rows; y++)
4490
5202
  {
4491
5203
    MagickPixelPacket
4492
5204
      pixel;
4493
5205
 
4494
5206
    register IndexPacket
4495
 
      *__restrict indexes;
 
5207
      *restrict indexes;
4496
5208
 
4497
 
    register long
 
5209
    register ssize_t
4498
5210
      id,
4499
5211
      x;
4500
5212
 
4501
5213
    register PixelPacket
4502
 
      *__restrict q;
 
5214
      *restrict q;
4503
5215
 
4504
5216
    if (status == MagickFalse)
4505
5217
      continue;
4513
5225
    indexes=GetCacheViewAuthenticIndexQueue(image_view);
4514
5226
    pixel=bias;
4515
5227
    id=GetOpenMPThreadId();
4516
 
    for (x=0; x < (long) spread_image->columns; x++)
 
5228
    for (x=0; x < (ssize_t) spread_image->columns; x++)
4517
5229
    {
4518
5230
      (void) ResamplePixelColor(resample_filter[id],(double) x+width*
4519
5231
        (GetPseudoRandomValue(random_info[id])-0.5),(double) y+width*
4528
5240
        MagickBooleanType
4529
5241
          proceed;
4530
5242
 
4531
 
#if defined(MAGICKCORE_OPENMP_SUPPORT)
 
5243
#if defined(MAGICKCORE_OPENMP_SUPPORT) 
4532
5244
  #pragma omp critical (MagickCore_SpreadImage)
4533
5245
#endif
4534
5246
        proceed=SetImageProgress(image,SpreadImageTag,progress++,image->rows);
4605
5317
{
4606
5318
#define SharpenImageTag  "Sharpen/Image"
4607
5319
 
 
5320
  CacheView
 
5321
    *image_view,
 
5322
    *unsharp_view;
 
5323
 
4608
5324
  Image
4609
5325
    *unsharp_image;
4610
5326
 
4611
 
  long
4612
 
    progress,
4613
 
    y;
4614
 
 
4615
5327
  MagickBooleanType
4616
5328
    status;
4617
5329
 
 
5330
  MagickOffsetType
 
5331
    progress;
 
5332
 
4618
5333
  MagickPixelPacket
4619
5334
    bias;
4620
5335
 
4621
5336
  MagickRealType
4622
5337
    quantum_threshold;
4623
5338
 
4624
 
  CacheView
4625
 
    *image_view,
4626
 
    *unsharp_view;
 
5339
  ssize_t
 
5340
    y;
4627
5341
 
4628
5342
  assert(image != (const Image *) NULL);
4629
5343
  assert(image->signature == MagickSignature);
4645
5359
#if defined(MAGICKCORE_OPENMP_SUPPORT)
4646
5360
  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
4647
5361
#endif
4648
 
  for (y=0; y < (long) image->rows; y++)
 
5362
  for (y=0; y < (ssize_t) image->rows; y++)
4649
5363
  {
4650
5364
    MagickPixelPacket
4651
5365
      pixel;
4652
5366
 
4653
5367
    register const IndexPacket
4654
 
      *__restrict indexes;
 
5368
      *restrict indexes;
4655
5369
 
4656
5370
    register const PixelPacket
4657
 
      *__restrict p;
 
5371
      *restrict p;
4658
5372
 
4659
5373
    register IndexPacket
4660
 
      *__restrict unsharp_indexes;
 
5374
      *restrict unsharp_indexes;
4661
5375
 
4662
 
    register long
 
5376
    register ssize_t
4663
5377
      x;
4664
5378
 
4665
5379
    register PixelPacket
4666
 
      *__restrict q;
 
5380
      *restrict q;
4667
5381
 
4668
5382
    if (status == MagickFalse)
4669
5383
      continue;
4678
5392
    indexes=GetCacheViewVirtualIndexQueue(image_view);
4679
5393
    unsharp_indexes=GetCacheViewAuthenticIndexQueue(unsharp_view);
4680
5394
    pixel=bias;
4681
 
    for (x=0; x < (long) image->columns; x++)
 
5395
    for (x=0; x < (ssize_t) image->columns; x++)
4682
5396
    {
4683
5397
      if ((channel & RedChannel) != 0)
4684
5398
        {
4685
5399
          pixel.red=p->red-(MagickRealType) q->red;
4686
5400
          if (fabs(2.0*pixel.red) < quantum_threshold)
4687
 
            pixel.red=(MagickRealType) p->red;
 
5401
            pixel.red=(MagickRealType) GetRedPixelComponent(p);
4688
5402
          else
4689
5403
            pixel.red=(MagickRealType) p->red+(pixel.red*amount);
4690
 
          q->red=RoundToQuantum(pixel.red);
 
5404
          SetRedPixelComponent(q,ClampRedPixelComponent(&pixel));
4691
5405
        }
4692
5406
      if ((channel & GreenChannel) != 0)
4693
5407
        {
4694
5408
          pixel.green=p->green-(MagickRealType) q->green;
4695
5409
          if (fabs(2.0*pixel.green) < quantum_threshold)
4696
 
            pixel.green=(MagickRealType) p->green;
 
5410
            pixel.green=(MagickRealType) GetGreenPixelComponent(p);
4697
5411
          else
4698
5412
            pixel.green=(MagickRealType) p->green+(pixel.green*amount);
4699
 
          q->green=RoundToQuantum(pixel.green);
 
5413
          SetGreenPixelComponent(q,ClampGreenPixelComponent(&pixel));
4700
5414
        }
4701
5415
      if ((channel & BlueChannel) != 0)
4702
5416
        {
4703
5417
          pixel.blue=p->blue-(MagickRealType) q->blue;
4704
5418
          if (fabs(2.0*pixel.blue) < quantum_threshold)
4705
 
            pixel.blue=(MagickRealType) p->blue;
 
5419
            pixel.blue=(MagickRealType) GetBluePixelComponent(p);
4706
5420
          else
4707
5421
            pixel.blue=(MagickRealType) p->blue+(pixel.blue*amount);
4708
 
          q->blue=RoundToQuantum(pixel.blue);
 
5422
          SetBluePixelComponent(q,ClampBluePixelComponent(&pixel));
4709
5423
        }
4710
5424
      if ((channel & OpacityChannel) != 0)
4711
5425
        {
4712
5426
          pixel.opacity=p->opacity-(MagickRealType) q->opacity;
4713
5427
          if (fabs(2.0*pixel.opacity) < quantum_threshold)
4714
 
            pixel.opacity=(MagickRealType) p->opacity;
 
5428
            pixel.opacity=(MagickRealType) GetOpacityPixelComponent(p);
4715
5429
          else
4716
5430
            pixel.opacity=p->opacity+(pixel.opacity*amount);
4717
 
          q->opacity=RoundToQuantum(pixel.opacity);
 
5431
          SetOpacityPixelComponent(q,ClampOpacityPixelComponent(&pixel));
4718
5432
        }
4719
5433
      if (((channel & IndexChannel) != 0) &&
4720
5434
          (image->colorspace == CMYKColorspace))
4725
5439
          else
4726
5440
            pixel.index=(MagickRealType) unsharp_indexes[x]+(pixel.index*
4727
5441
              amount);
4728
 
          unsharp_indexes[x]=RoundToQuantum(pixel.index);
 
5442
          unsharp_indexes[x]=ClampToQuantum(pixel.index);
4729
5443
        }
4730
5444
      p++;
4731
5445
      q++;