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

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