root / ImageMagick / trunk / magick / image.c

Revision 12706, 152.7 kB (checked in by cristy, 2 days ago)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                     IIIII  M   M   AAA    GGGG  EEEEE                       %
7%                       I    MM MM  A   A  G      E                           %
8%                       I    M M M  AAAAA  G  GG  EEE                         %
9%                       I    M   M  A   A  G   G  E                           %
10%                     IIIII  M   M  A   A   GGGG  EEEEE                       %
11%                                                                             %
12%                                                                             %
13%                           MagickCore Image Methods                          %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                                 July 1992                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41  Include declarations.
42*/
43#include "magick/studio.h"
44#include "magick/animate.h"
45#include "magick/artifact.h"
46#include "magick/blob.h"
47#include "magick/blob-private.h"
48#include "magick/cache.h"
49#include "magick/cache-private.h"
50#include "magick/cache-view.h"
51#include "magick/client.h"
52#include "magick/color.h"
53#include "magick/color-private.h"
54#include "magick/colorspace.h"
55#include "magick/colorspace-private.h"
56#include "magick/composite.h"
57#include "magick/composite-private.h"
58#include "magick/compress.h"
59#include "magick/constitute.h"
60#include "magick/deprecate.h"
61#include "magick/display.h"
62#include "magick/draw.h"
63#include "magick/enhance.h"
64#include "magick/exception.h"
65#include "magick/exception-private.h"
66#include "magick/gem.h"
67#include "magick/geometry.h"
68#include "magick/list.h"
69#include "magick/image-private.h"
70#include "magick/magic.h"
71#include "magick/magick.h"
72#include "magick/memory_.h"
73#include "magick/module.h"
74#include "magick/monitor.h"
75#include "magick/monitor-private.h"
76#include "magick/option.h"
77#include "magick/paint.h"
78#include "magick/pixel-private.h"
79#include "magick/profile.h"
80#include "magick/property.h"
81#include "magick/quantize.h"
82#include "magick/random_.h"
83#include "magick/segment.h"
84#include "magick/semaphore.h"
85#include "magick/signature-private.h"
86#include "magick/statistic.h"
87#include "magick/string_.h"
88#include "magick/threshold.h"
89#include "magick/timer.h"
90#include "magick/utility.h"
91#include "magick/version.h"
92#include "magick/xwindow-private.h"
93
94/*
95  Constant declaration.
96*/
97const char
98  *BackgroundColor = "#ffffff"/* white */
99  *BorderColor = "#dfdfdf"/* gray */
100  *DefaultTileFrame = "15x15+3+3",
101  *DefaultTileGeometry = "120x120+4+3>",
102  *DefaultTileLabel = "%f\n%wx%h\n%b",
103  *ForegroundColor = "#000"/* black */
104  *LoadImageTag = "Load/Image",
105  *LoadImagesTag = "Load/Images",
106  *MatteColor = "#bdbdbd"/* gray */
107  *PSDensityGeometry = "72.0x72.0",
108  *PSPageGeometry = "612x792",
109  *SaveImageTag = "Save/Image",
110  *SaveImagesTag = "Save/Images",
111  *TransparentColor = "#00000000"/* transparent black */
112
113const double
114  DefaultResolution = 72.0;
115
116/*
117%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
118%                                                                             %
119%                                                                             %
120%                                                                             %
121%   A c q u i r e I m a g e                                                   %
122%                                                                             %
123%                                                                             %
124%                                                                             %
125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126%
127%  AcquireImage() returns a pointer to an image structure initialized to
128%  default values.
129%
130%  The format of the AcquireImage method is:
131%
132%      Image *AcquireImage(const ImageInfo *image_info)
133%
134%  A description of each parameter follows:
135%
136%    o image_info: Many of the image default values are set from this
137%      structure.  For example, filename, compression, depth, background color,
138%      and others.
139%
140*/
141MagickExport Image *AcquireImage(const ImageInfo *image_info)
142{
143  const char
144    *option;
145
146  Image
147    *image;
148
149  MagickStatusType
150    flags;
151
152  /*
153    Allocate image structure.
154  */
155  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
156  image=(Image *) AcquireMagickMemory(sizeof(*image));
157  if (image == (Image *) NULL)
158    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
159  (void) ResetMagickMemory(image,0,sizeof(*image));
160  /*
161    Initialize Image structure.
162  */
163  (void) CopyMagickString(image->magick,"MIFF",MaxTextExtent);
164  image->storage_class=DirectClass;
165  image->depth=MAGICKCORE_QUANTUM_DEPTH;
166  image->colorspace=RGBColorspace;
167  image->interlace=NoInterlace;
168  image->ticks_per_second=UndefinedTicksPerSecond;
169  image->compose=OverCompositeOp;
170  image->blur=1.0;
171  GetExceptionInfo(&image->exception);
172  (void) QueryColorDatabase(BackgroundColor,&image->background_color,
173    &image->exception);
174  (void) QueryColorDatabase(BorderColor,&image->border_color,&image->exception);
175  (void) QueryColorDatabase(MatteColor,&image->matte_color,&image->exception);
176  (void) QueryColorDatabase(TransparentColor,&image->transparent_color,
177    &image->exception);
178  image->x_resolution=DefaultResolution;
179  image->y_resolution=DefaultResolution;
180  image->units=PixelsPerInchResolution;
181  GetTimerInfo(&image->timer);
182  (void) GetCacheInfo(&image->cache);
183  image->blob=CloneBlobInfo((BlobInfo *) NULL);
184  image->debug=IsEventLogging();
185  image->reference_count=1;
186  image->semaphore=AllocateSemaphoreInfo();
187  image->signature=MagickSignature;
188  if (image_info == (ImageInfo *) NULL)
189    return(image);
190  /*
191    Transfer image info.
192  */
193  SetBlobExempt(image,image_info->file != (FILE *) NULL ? MagickTrue :
194    MagickFalse);
195  (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent);
196  (void) CopyMagickString(image->magick_filename,image_info->filename,
197    MaxTextExtent);
198  (void) CopyMagickString(image->magick,image_info->magick,MaxTextExtent);
199  if (image_info->size != (char *) NULL)
200    {
201      (void) ParseAbsoluteGeometry(image_info->size,&image->extract_info);
202      image->columns=image->extract_info.width;
203      image->rows=image->extract_info.height;
204      image->offset=image->extract_info.x;
205      image->extract_info.x=0;
206      image->extract_info.y=0;
207    }
208  if (image_info->extract != (char *) NULL)
209    {
210      RectangleInfo
211        geometry;
212
213      flags=ParseAbsoluteGeometry(image_info->extract,&geometry);
214      if (((flags & XValue) != 0) || ((flags & YValue) != 0))
215        {
216          image->extract_info=geometry;
217          Swap(image->columns,image->extract_info.width);
218          Swap(image->rows,image->extract_info.height);
219        }
220    }
221  image->compression=image_info->compression;
222  image->quality=image_info->quality;
223  image->endian=image_info->endian;
224  image->interlace=image_info->interlace;
225  image->units=image_info->units;
226  if (image_info->density != (char *) NULL)
227    {
228      GeometryInfo
229        geometry_info;
230
231      flags=ParseGeometry(image_info->density,&geometry_info);
232      image->x_resolution=geometry_info.rho;
233      image->y_resolution=geometry_info.sigma;
234      if ((flags & SigmaValue) == 0)
235        image->y_resolution=image->x_resolution;
236    }
237  if (image_info->page != (char *) NULL)
238    {
239      char
240        *geometry;
241
242      image->page=image->extract_info;
243      geometry=GetPageGeometry(image_info->page);
244      (void) ParseAbsoluteGeometry(geometry,&image->page);
245      geometry=DestroyString(geometry);
246    }
247  if (image_info->depth != 0)
248    image->depth=image_info->depth;
249  image->dither=image_info->dither;
250  image->background_color=image_info->background_color;
251  image->border_color=image_info->border_color;
252  image->matte_color=image_info->matte_color;
253  image->transparent_color=image_info->transparent_color;
254  option=GetImageOption(image_info,"tile-offset");
255  if (option != (const char *) NULL)
256    {
257      char
258        *geometry;
259
260      geometry=GetPageGeometry(option);
261      flags=ParseAbsoluteGeometry(geometry,&image->tile_offset);
262      geometry=DestroyString(geometry);
263    }
264  image->progress_monitor=image_info->progress_monitor;
265  image->client_data=image_info->client_data;
266  if (image_info->cache != (void *) NULL)
267    CloneCacheMethods(image->cache,image_info->cache);
268  (void) SetImageVirtualPixelMethod(image,image_info->virtual_pixel_method);
269  return(image);
270}
271
272/*
273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274%                                                                             %
275%                                                                             %
276%                                                                             %
277%   A c q u i r e I m a g e C o l o r m a p                                   %
278%                                                                             %
279%                                                                             %
280%                                                                             %
281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282%
283%  AcquireImageColormap() allocates an image colormap and initializes
284%  it to a linear gray colorspace.  If the image already has a colormap,
285%  it is replaced.  AcquireImageColormap() returns MagickTrue if successful,
286%  otherwise MagickFalse if there is not enough memory.
287%
288%  The format of the AcquireImageColormap method is:
289%
290%      MagickBooleanType AcquireImageColormap(Image *image,
291%        const unsigned long colors)
292%
293%  A description of each parameter follows:
294%
295%    o image: the image.
296%
297%    o colors: the number of colors in the image colormap.
298%
299*/
300
301static inline unsigned long MagickMax(const unsigned long x,
302  const unsigned long y)
303{
304  if (x > y)
305    return(x);
306  return(y);
307}
308
309static inline unsigned long MagickMin(const unsigned long x,
310  const unsigned long y)
311{
312  if (x < y)
313    return(x);
314  return(y);
315}
316
317MagickExport MagickBooleanType AcquireImageColormap(Image *image,
318  const unsigned long colors)
319{
320  register long
321    i;
322
323  size_t
324    length;
325
326  /*
327    Allocate image colormap.
328  */
329  assert(image != (Image *) NULL);
330  assert(image->signature == MagickSignature);
331  if (image->debug != MagickFalse)
332    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
333  image->colors=MagickMin(colors,MaxColormapSize);
334  length=(size_t) colors;
335  if (image->colormap == (PixelPacket *) NULL)
336    image->colormap=(PixelPacket *) AcquireQuantumMemory(length,
337      sizeof(*image->colormap));
338  else
339    image->colormap=(PixelPacket *) ResizeQuantumMemory(image->colormap,length,
340      sizeof(*image->colormap));
341  if (image->colormap == (PixelPacket *) NULL)
342    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
343      image->filename);
344  #pragma omp parallel for schedule(static,64)
345  for (i=0; i < (long) image->colors; i++)
346  {
347    unsigned long
348      pixel;
349
350    pixel=(unsigned long) (i*(QuantumRange/MagickMax(colors-1,1)));
351    image->colormap[i].red=(Quantum) pixel;
352    image->colormap[i].green=(Quantum) pixel;
353    image->colormap[i].blue=(Quantum) pixel;
354    image->colormap[i].opacity=OpaqueOpacity;
355  }
356  return(SetImageStorageClass(image,PseudoClass));
357}
358
359/*
360%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361%                                                                             %
362%                                                                             %
363%                                                                             %
364%   A c q u i r e I m a g e I n f o                                           %
365%                                                                             %
366%                                                                             %
367%                                                                             %
368%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369%
370%  AcquireImageInfo() allocates the ImageInfo structure.
371%
372%  The format of the AcquireImageInfo method is:
373%
374%      ImageInfo *AcquireImageInfo(void)
375%
376*/
377MagickExport ImageInfo *AcquireImageInfo(void)
378{
379  ImageInfo
380    *image_info;
381
382  image_info=(ImageInfo *) AcquireMagickMemory(sizeof(*image_info));
383  if (image_info == (ImageInfo *) NULL)
384    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
385  GetImageInfo(image_info);
386  return(image_info);
387}
388
389/*
390%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391%                                                                             %
392%                                                                             %
393%                                                                             %
394%   A c q u i r e N e x t I m a g e                                           %
395%                                                                             %
396%                                                                             %
397%                                                                             %
398%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399%
400%  AcquireNextImage() initializes the next image in a sequence to
401%  default values.  The next member of image points to the newly allocated
402%  image.  If there is a memory shortage, next is assigned NULL.
403%
404%  The format of the AcquireNextImage method is:
405%
406%      void AcquireNextImage(const ImageInfo *image_info,Image *image)
407%
408%  A description of each parameter follows:
409%
410%    o image_info: Many of the image default values are set from this
411%      structure.  For example, filename, compression, depth, background color,
412%      and others.
413%
414%    o image: the image.
415%
416*/
417MagickExport void AcquireNextImage(const ImageInfo *image_info,Image *image)
418{
419  /*
420    Allocate image structure.
421  */
422  assert(image != (Image *) NULL);
423  assert(image->signature == MagickSignature);
424  if (image->debug != MagickFalse)
425    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
426  image->next=AcquireImage(image_info);
427  if (GetNextImageInList(image) == (Image *) NULL)
428    return;
429  (void) CopyMagickString(GetNextImageInList(image)->filename,image->filename,
430    MaxTextExtent);
431  if (image_info != (ImageInfo *) NULL)
432    (void) CopyMagickString(GetNextImageInList(image)->filename,
433      image_info->filename,MaxTextExtent);
434  DestroyBlob(GetNextImageInList(image));
435  image->next->blob=ReferenceBlob(image->blob);
436  image->next->endian=image->endian;
437  image->next->scene=image->scene+1;
438  image->next->previous=image;
439}
440
441/*
442%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443%                                                                             %
444%                                                                             %
445%                                                                             %
446%     A p p e n d I m a g e s                                                 %
447%                                                                             %
448%                                                                             %
449%                                                                             %
450%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451%
452%  AppendImages() takes all images from the current image pointer to the end
453%  of the image list and appends them to each other top-to-bottom if the
454%  stack parameter is true, otherwise left-to-right.
455%
456%  The format of the AppendImage method is:
457%
458%      Image *AppendImages(const Image *image,const MagickBooleanType stack,
459%        ExceptionInfo *exception)
460%
461%  A description of each parameter follows:
462%
463%    o image: the image sequence.
464%
465%    o stack: A value other than 0 stacks the images top-to-bottom.
466%
467%    o exception: Return any errors or warnings in this structure.
468%
469*/
470MagickExport Image *AppendImages(const Image *image,
471  const MagickBooleanType stack,ExceptionInfo *exception)
472{
473#define AppendImageTag  "Append/Image"
474
475  Image
476    *append_image;
477
478  long
479    n,
480    y;
481
482  MagickBooleanType
483    matte,
484    proceed;
485
486  register const Image
487    *next;
488
489  register long
490    i;
491
492  unsigned long
493    height,
494    number_images,
495    width;
496
497  ViewInfo
498    **append_view,
499    **image_view;
500
501  volatile MagickBooleanType
502    status;
503
504  /*
505    Ensure the image have the same column width.
506  */
507  assert(image != (Image *) NULL);
508  assert(image->signature == MagickSignature);
509  if (image->debug != MagickFalse)
510    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
511  assert(exception != (ExceptionInfo *) NULL);
512  assert(exception->signature == MagickSignature);
513  matte=image->matte;
514  number_images=1;
515  width=image->columns;
516  height=image->rows;
517  next=GetNextImageInList(image);
518  for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
519  {
520    if (next->matte != MagickFalse)
521      matte=MagickTrue;
522    number_images++;
523    if (stack != MagickFalse)
524      {
525        if (next->columns > width)
526          width=next->columns;
527        height+=next->rows;
528        continue;
529      }
530    width+=next->columns;
531    if (next->rows > height)
532      height=next->rows;
533  }
534  /*
535    Initialize append next attributes.
536  */
537  append_image=CloneImage(image,width,height,MagickTrue,exception);
538  if (append_image == (Image *) NULL)
539    return((Image *) NULL);
540  if (SetImageStorageClass(append_image,DirectClass) == MagickFalse)
541    {
542      InheritException(exception,&append_image->exception);
543      append_image=DestroyImage(append_image);
544      return((Image *) NULL);
545    }
546  append_image->matte=matte;
547  (void) SetImageBackgroundColor(append_image);
548  status=MagickTrue;
549  i=0;
550  append_view=AcquireCacheViewThreadSet(append_image);
551  if (stack != MagickFalse)
552    {
553      /*
554        Stack top-to-bottom.
555      */
556      for (n=0; n < (long) number_images; n++)
557      {
558        image_view=AcquireCacheViewThreadSet(image);
559        #pragma omp parallel for schedule(static,64)
560        for (y=0; y < (long) image->rows; y++)
561        {
562          const IndexPacket
563            *indexes;
564
565          IndexPacket
566            *append_indexes;
567
568          register const PixelPacket
569            *p;
570
571          register long
572            id,
573            x;
574
575          register PixelPacket
576            *q;
577
578    if (status == MagickFalse)
579      continue;
580          id=GetCacheViewThreadId();
581          p=AcquireCacheViewPixels(image_view[id],0,y,image->columns,1,
582            exception);
583          q=SetCacheViewPixels(append_view[id],0,i+y,append_image->columns,1);
584          if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
585            {
586              status=MagickFalse;
587              continue;
588            }
589          indexes=AcquireCacheViewIndexes(image_view[id]);
590          append_indexes=GetCacheViewIndexes(append_view[id]);
591          for (x=0; x < (long) image->columns; x++)
592          {
593            q->red=p->red;
594            q->green=p->green;
595            q->blue=p->blue;
596            q->opacity=p->opacity;
597            if (append_image->colorspace == CMYKColorspace)
598              append_indexes[x]=indexes[x];
599            p++;
600            q++;
601          }
602          if (SyncCacheViewPixels(append_view[id]) == MagickFalse)
603            continue;
604        }
605        image_view=DestroyCacheViewThreadSet(image_view);
606        proceed=SetImageProgress(image,AppendImageTag,n,number_images);
607        if (proceed == MagickFalse)
608          break;
609        i+=image->rows;
610        image=GetNextImageInList(image);
611      }
612      append_view=DestroyCacheViewThreadSet(append_view);
613      if (status == MagickFalse)
614        append_image=DestroyImage(append_image);
615      return(append_image);
616    }
617  /*
618    Stack left-to-right.
619  */
620  for (n=0; n < (long) number_images; n++)
621  {
622    image_view=AcquireCacheViewThreadSet(image);
623    #pragma omp parallel for schedule(static,64)
624    for (y=0; y < (long) image->rows; y++)
625    {
626      const IndexPacket
627        *indexes;
628
629      IndexPacket
630        *append_indexes;
631
632      register const PixelPacket
633        *p;
634
635      register long
636        id,
637        x;
638
639      register PixelPacket
640        *q;
641
642    if (status == MagickFalse)
643      continue;
644      id=GetCacheViewThreadId();
645      p=AcquireCacheViewPixels(image_view[id],0,y,image->columns,1,exception);
646      q=SetCacheViewPixels(append_view[id],i,y,image->columns,1);
647      if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
648        {
649          status=MagickFalse;
650          continue;
651        }
652      indexes=AcquireCacheViewIndexes(image_view[id]);
653      append_indexes=GetCacheViewIndexes(append_view[id]);
654      for (x=0; x < (long) image->columns; x++)
655      {
656        q->red=p->red;
657        q->green=p->green;
658        q->blue=p->blue;
659        q->opacity=p->opacity;
660        if (append_image->colorspace == CMYKColorspace)
661          append_indexes[x]=indexes[x];
662        p++;
663        q++;
664      }
665      if (SyncCacheViewPixels(append_view[id]) == MagickFalse)
666        continue;
667    }
668    image_view=DestroyCacheViewThreadSet(image_view);
669    proceed=SetImageProgress(image,AppendImageTag,n,number_images);
670    if (proceed == MagickFalse)
671      break;
672    i+=image->columns;
673    image=GetNextImageInList(image);
674  }
675  append_view=DestroyCacheViewThreadSet(append_view);
676  if (status == MagickFalse)
677    append_image=DestroyImage(append_image);
678  return(append_image);
679}
680
681/*
682%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683%                                                                             %
684%                                                                             %
685%                                                                             %
686%     A v e r a g e I m a g e s                                               %
687%                                                                             %
688%                                                                             %
689%                                                                             %
690%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
691%
692%  AverageImages() takes a set of images and averages them together.  Each
693%  image in the set must have the same width and height.  AverageImages()
694%  returns a single image with each corresponding pixel component of each
695%  image averaged.   On failure, a NULL image is returned and exception
696%  describes the reason for the failure.
697%
698%  The format of the AverageImages method is:
699%
700%      Image *AverageImages(Image *image,ExceptionInfo *exception)
701%
702%  A description of each parameter follows:
703%
704%    o image: the image sequence.
705%
706%    o exception: Return any errors or warnings in this structure.
707%
708*/
709
710static MagickPixelPacket **DestroyPixelThreadSet(MagickPixelPacket **pixels)
711{
712  register long
713    i;
714
715  assert(pixels != (MagickPixelPacket **) NULL);
716  for (i=0; i < (long) GetCacheViewMaximumThreads(); i++)
717    if (pixels[i] != (MagickPixelPacket *) NULL)
718      pixels[i]=(MagickPixelPacket *) RelinquishMagickMemory(pixels[i]);
719  return((MagickPixelPacket **) RelinquishMagickMemory(pixels));
720}
721
722static MagickPixelPacket **AcquirePixelThreadSet(const Image *image)
723{
724  register long
725    i,
726    j;
727
728  MagickPixelPacket
729    **pixels;
730
731  pixels=(MagickPixelPacket **) AcquireQuantumMemory(
732    GetCacheViewMaximumThreads(),sizeof(*pixels));
733  if (pixels == (MagickPixelPacket **) NULL)
734    return((MagickPixelPacket **) NULL);
735  (void) ResetMagickMemory(pixels,0,GetCacheViewMaximumThreads()*
736    sizeof(*pixels));
737  for (i=0; i < (long) GetCacheViewMaximumThreads(); i++)
738  {
739    pixels[i]=(MagickPixelPacket *) AcquireQuantumMemory(image->columns,
740      sizeof(**pixels));
741    if (pixels[i] == (MagickPixelPacket *) NULL)
742      return(DestroyPixelThreadSet(pixels));
743    for (j=0; j < (long) image->columns; j++)
744      GetMagickPixelPacket(image,&pixels[i][j]);
745  }
746  return(pixels);
747}
748
749MagickExport Image *AverageImages(const Image *image,ExceptionInfo *exception)
750{
751#define AverageImageTag  "Average/Image"
752
753  const Image
754    *next;
755
756  Image
757    *average_image;
758
759  long
760    progress,
761    y;
762
763  MagickPixelPacket
764    **average_pixel,
765    zero;
766
767  unsigned long
768    number_images;
769
770  ViewInfo
771    **average_view;
772
773  volatile MagickBooleanType
774    status;
775
776  /*
777    Ensure the image are the same size.
778  */
779  assert(image != (Image *) NULL);
780  assert(image->signature == MagickSignature);
781  if (image->debug != MagickFalse)
782    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
783  assert(exception != (ExceptionInfo *) NULL);
784  assert(exception->signature == MagickSignature);
785  for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
786    if ((next->columns != image->columns) || (next->rows != image->rows))
787      ThrowImageException(OptionError,"ImageWidthsOrHeightsDiffer");
788  /*
789    Initialize average next attributes.
790  */
791  average_image=CloneImage(image,image->columns,image->rows,MagickTrue,
792    exception);
793  if (average_image == (Image *) NULL)
794    return((Image *) NULL);
795  if (SetImageStorageClass(average_image,DirectClass) == MagickFalse)
796    {
797      InheritException(exception,&average_image->exception);
798      average_image=DestroyImage(average_image);
799      return((Image *) NULL);
800    }
801  average_pixel=AcquirePixelThreadSet(image);
802  if (average_pixel == (MagickPixelPacket **) NULL)
803    {
804      average_image=DestroyImage(average_image);
805      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
806    }
807  /*
808    Average image pixels.
809  */
810  status=MagickTrue;
811  progress=0;
812  GetMagickPixelPacket(image,&zero);
813  number_images=GetImageListLength(image);
814  average_view=AcquireCacheViewThreadSet(average_image);
815  #pragma omp parallel for schedule(static,64)
816  for (y=0; y < (long) average_image->rows; y++)
817  {
818    const Image
819      *next;
820
821    IndexPacket
822      *average_indexes;
823
824    MagickPixelPacket
825      pixel;
826
827    register long
828      i,
829      id,
830      x;
831
832    register PixelPacket
833      *q;
834
835    ViewInfo
836      *image_view;
837
838    if (status == MagickFalse)
839      continue;
840    id=GetCacheViewThreadId();
841    q=SetCacheViewPixels(average_view[id],0,y,average_image->columns,1);
842    if (q == (PixelPacket *) NULL)
843      {
844        status=MagickFalse;
845        continue;
846      }
847    pixel=zero;
848    average_indexes=GetCacheViewIndexes(average_view[id]);
849    for (x=0; x < (long) average_image->columns; x++)
850      average_pixel[id][x]=zero;
851    next=image;
852    for (i=0; i < (long) number_images; i++)
853    {
854      register const IndexPacket
855        *indexes;
856
857      register const PixelPacket
858        *p;
859
860      image_view=AcquireCacheView(next);
861      p=AcquireCacheViewPixels(image_view,0,y,next->columns,1,exception);
862      if (p == (const PixelPacket *) NULL)
863        {
864          image_view=DestroyCacheView(image_view);
865          break;
866        }
867      indexes=AcquireCacheViewIndexes(image_view);
868      for (x=0; x < (long) next->columns; x++)
869      {
870        SetMagickPixelPacket(next,p,indexes+x,&pixel);
871        average_pixel[id][x].red+=QuantumScale*pixel.red;
872        average_pixel[id][x].green+=QuantumScale*pixel.green;
873        average_pixel[id][x].blue+=QuantumScale*pixel.blue;
874        average_pixel[id][x].opacity+=QuantumScale*pixel.opacity;
875        if (average_image->colorspace == CMYKColorspace)
876          average_pixel[id][x].index+=QuantumScale*pixel.index;
877        p++;
878      }
879      image_view=DestroyCacheView(image_view);
880      next=GetNextImageInList(next);
881    }
882    for (x=0; x < (long) average_image->columns; x++)
883    {
884      average_pixel[id][x].red=(MagickRealType) QuantumRange*
885        average_pixel[id][x].red/number_images;
886      average_pixel[id][x].green=(MagickRealType) QuantumRange*
887        average_pixel[id][x].green/number_images;
888      average_pixel[id][x].blue=(MagickRealType) QuantumRange*
889        average_pixel[id][x].blue/number_images;
890      average_pixel[id][x].opacity=(MagickRealType) QuantumRange*
891        average_pixel[id][x].opacity/number_images;
892      if (average_image->colorspace == CMYKColorspace)
893        average_pixel[id][x].index=(MagickRealType) QuantumRange*
894          average_pixel[id][x].index/number_images;
895      SetPixelPacket(average_image,&average_pixel[id][x],q,average_indexes+x);
896      q++;
897    }
898    if (SyncCacheViewPixels(average_view[id]) == MagickFalse)
899      status=MagickFalse;
900    if (image->progress_monitor != (MagickProgressMonitor) NULL)
901      {
902        MagickBooleanType
903          proceed;
904
905        #pragma omp critical
906        proceed=SetImageProgress(image,AverageImageTag,progress++,
907          average_image->rows);
908        if (proceed == MagickFalse)
909          status=MagickFalse;
910      }
911  }
912  average_view=DestroyCacheViewThreadSet(average_view);
913  average_pixel=DestroyPixelThreadSet(average_pixel);
914  if (status == MagickFalse)
915    average_image=DestroyImage(average_image);
916  return(average_image);
917}
918
919/*
920%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
921%                                                                             %
922%                                                                             %
923%                                                                             %
924%   C a t c h I m a g e E x c e p t i o n                                     %
925%                                                                             %
926%                                                                             %
927%                                                                             %
928%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
929%
930%  CatchImageException() returns if no exceptions are found in the image
931%  sequence, otherwise it determines the most severe exception and reports
932%  it as a warning or error depending on the severity.
933%
934%  The format of the CatchImageException method is:
935%
936%      ExceptionType CatchImageException(Image *image)
937%
938%  A description of each parameter follows:
939%
940%    o image: An image sequence.
941%
942*/
943MagickExport ExceptionType CatchImageException(Image *image)
944{
945  ExceptionInfo
946    *exception;
947
948  ExceptionType
949    severity;
950
951  assert(image != (const Image *) NULL);
952  assert(image->signature == MagickSignature);
953  if (image->debug != MagickFalse)
954    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
955  exception=AcquireExceptionInfo();
956  GetImageException(image,exception);
957  CatchException(exception);
958  severity=exception->severity;
959  exception=DestroyExceptionInfo(exception);
960  return(severity);
961}
962
963/*
964%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965%                                                                             %
966%                                                                             %
967%                                                                             %
968%   C l i p I m a g e P a t h                                                 %
969%                                                                             %
970%                                                                             %
971%                                                                             %
972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973%
974%  ClipImagePath() sets the image clip mask based any clipping path information
975%  if it exists.
976%
977%  The format of the ClipImagePath method is:
978%
979%      MagickBooleanType ClipImagePath(Image *image,const char *pathname,
980%        const MagickBooleanType inside)
981%
982%  A description of each parameter follows:
983%
984%    o image: the image.
985%
986%    o pathname: name of clipping path resource. If name is preceded by #, use
987%      clipping path numbered by name.
988%
989%    o inside: if non-zero, later operations take effect inside clipping path.
990%      Otherwise later operations take effect outside clipping path.
991%
992*/
993
994MagickExport MagickBooleanType ClipImage(Image *image)
995{
996  return(ClipImagePath(image,"#1",MagickTrue));</