]> granicus.if.org Git - imagemagick/blob - magick/image.c
(no commit message)
[imagemagick] / magick / image.c
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-2009 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 \f
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/thread-private.h"
89 #include "magick/threshold.h"
90 #include "magick/timer.h"
91 #include "magick/utility.h"
92 #include "magick/version.h"
93 #include "magick/xwindow-private.h"
94 \f
95 /*
96   Constant declaration.
97 */
98 const char
99   BackgroundColor[] = "#ffffff",  /* white */
100   BorderColor[] = "#dfdfdf",  /* gray */
101   DefaultTileFrame[] = "15x15+3+3",
102   DefaultTileGeometry[] = "120x120+4+3>",
103   DefaultTileLabel[] = "%f\n%G\n%b",
104   ForegroundColor[] = "#000",  /* black */
105   LoadImageTag[] = "Load/Image",
106   LoadImagesTag[] = "Load/Images",
107   MatteColor[] = "#bdbdbd",  /* gray */
108   PSDensityGeometry[] = "72.0x72.0",
109   PSPageGeometry[] = "612x792",
110   SaveImageTag[] = "Save/Image",
111   SaveImagesTag[] = "Save/Images",
112   TransparentColor[] = "#00000000";  /* transparent black */
113
114 const double
115   DefaultResolution = 72.0;
116 \f
117 /*
118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119 %                                                                             %
120 %                                                                             %
121 %                                                                             %
122 %   A c q u i r e I m a g e                                                   %
123 %                                                                             %
124 %                                                                             %
125 %                                                                             %
126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127 %
128 %  AcquireImage() returns a pointer to an image structure initialized to
129 %  default values.
130 %
131 %  The format of the AcquireImage method is:
132 %
133 %      Image *AcquireImage(const ImageInfo *image_info)
134 %
135 %  A description of each parameter follows:
136 %
137 %    o image_info: Many of the image default values are set from this
138 %      structure.  For example, filename, compression, depth, background color,
139 %      and others.
140 %
141 */
142 MagickExport Image *AcquireImage(const ImageInfo *image_info)
143 {
144   Image
145     *image;
146
147   MagickStatusType
148     flags;
149
150   /*
151     Allocate image structure.
152   */
153   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
154   image=(Image *) AcquireMagickMemory(sizeof(*image));
155   if (image == (Image *) NULL)
156     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
157   (void) ResetMagickMemory(image,0,sizeof(*image));
158   /*
159     Initialize Image structure.
160   */
161   (void) CopyMagickString(image->magick,"MIFF",MaxTextExtent);
162   image->storage_class=DirectClass;
163   image->depth=MAGICKCORE_QUANTUM_DEPTH;
164   image->colorspace=RGBColorspace;
165   image->interlace=NoInterlace;
166   image->ticks_per_second=UndefinedTicksPerSecond;
167   image->compose=OverCompositeOp;
168   image->blur=1.0;
169   GetExceptionInfo(&image->exception);
170   (void) QueryColorDatabase(BackgroundColor,&image->background_color,
171     &image->exception);
172   (void) QueryColorDatabase(BorderColor,&image->border_color,&image->exception);
173   (void) QueryColorDatabase(MatteColor,&image->matte_color,&image->exception);
174   (void) QueryColorDatabase(TransparentColor,&image->transparent_color,
175     &image->exception);
176   image->x_resolution=DefaultResolution;
177   image->y_resolution=DefaultResolution;
178   image->units=PixelsPerInchResolution;
179   GetTimerInfo(&image->timer);
180   image->cache=AcquirePixelCache(0);
181   image->blob=CloneBlobInfo((BlobInfo *) NULL);
182   image->debug=IsEventLogging();
183   image->reference_count=1;
184   image->semaphore=AllocateSemaphoreInfo();
185   image->signature=MagickSignature;
186   if (image_info == (ImageInfo *) NULL)
187     return(image);
188   /*
189     Transfer image info.
190   */
191   SetBlobExempt(image,image_info->file != (FILE *) NULL ? MagickTrue :
192     MagickFalse);
193   (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent);
194   (void) CopyMagickString(image->magick_filename,image_info->filename,
195     MaxTextExtent);
196   (void) CopyMagickString(image->magick,image_info->magick,MaxTextExtent);
197   if (image_info->size != (char *) NULL)
198     {
199       (void) ParseAbsoluteGeometry(image_info->size,&image->extract_info);
200       image->columns=image->extract_info.width;
201       image->rows=image->extract_info.height;
202       image->offset=image->extract_info.x;
203       image->extract_info.x=0;
204       image->extract_info.y=0;
205     }
206   if (image_info->extract != (char *) NULL)
207     {
208       RectangleInfo
209         geometry;
210
211       flags=ParseAbsoluteGeometry(image_info->extract,&geometry);
212       if (((flags & XValue) != 0) || ((flags & YValue) != 0))
213         {
214           image->extract_info=geometry;
215           Swap(image->columns,image->extract_info.width);
216           Swap(image->rows,image->extract_info.height);
217         }
218     }
219   image->compression=image_info->compression;
220   image->quality=image_info->quality;
221   image->endian=image_info->endian;
222   image->interlace=image_info->interlace;
223   image->units=image_info->units;
224   if (image_info->density != (char *) NULL)
225     {
226       GeometryInfo
227         geometry_info;
228
229       flags=ParseGeometry(image_info->density,&geometry_info);
230       image->x_resolution=geometry_info.rho;
231       image->y_resolution=geometry_info.sigma;
232       if ((flags & SigmaValue) == 0)
233         image->y_resolution=image->x_resolution;
234     }
235   if (image_info->page != (char *) NULL)
236     {
237       char
238         *geometry;
239
240       image->page=image->extract_info;
241       geometry=GetPageGeometry(image_info->page);
242       (void) ParseAbsoluteGeometry(geometry,&image->page);
243       geometry=DestroyString(geometry);
244     }
245   if (image_info->depth != 0)
246     image->depth=image_info->depth;
247   image->dither=image_info->dither;
248   image->background_color=image_info->background_color;
249   image->border_color=image_info->border_color;
250   image->matte_color=image_info->matte_color;
251   image->transparent_color=image_info->transparent_color;
252   image->progress_monitor=image_info->progress_monitor;
253   image->client_data=image_info->client_data;
254   if (image_info->cache != (void *) NULL)
255     ClonePixelCacheMethods(image->cache,image_info->cache);
256   (void) SetImageVirtualPixelMethod(image,image_info->virtual_pixel_method);
257   return(image);
258 }
259 \f
260 /*
261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262 %                                                                             %
263 %                                                                             %
264 %                                                                             %
265 %   A c q u i r e I m a g e C o l o r m a p                                   %
266 %                                                                             %
267 %                                                                             %
268 %                                                                             %
269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270 %
271 %  AcquireImageColormap() allocates an image colormap and initializes
272 %  it to a linear gray colorspace.  If the image already has a colormap,
273 %  it is replaced.  AcquireImageColormap() returns MagickTrue if successful,
274 %  otherwise MagickFalse if there is not enough memory.
275 %
276 %  The format of the AcquireImageColormap method is:
277 %
278 %      MagickBooleanType AcquireImageColormap(Image *image,
279 %        const unsigned long colors)
280 %
281 %  A description of each parameter follows:
282 %
283 %    o image: the image.
284 %
285 %    o colors: the number of colors in the image colormap.
286 %
287 */
288
289 static inline unsigned long MagickMax(const unsigned long x,
290   const unsigned long y)
291 {
292   if (x > y)
293     return(x);
294   return(y);
295 }
296
297 static inline unsigned long MagickMin(const unsigned long x,
298   const unsigned long y)
299 {
300   if (x < y)
301     return(x);
302   return(y);
303 }
304
305 MagickExport MagickBooleanType AcquireImageColormap(Image *image,
306   const unsigned long colors)
307 {
308   register long
309     i;
310
311   size_t
312     length;
313
314   /*
315     Allocate image colormap.
316   */
317   assert(image != (Image *) NULL);
318   assert(image->signature == MagickSignature);
319   if (image->debug != MagickFalse)
320     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
321   image->colors=MagickMin(colors,MaxColormapSize);
322   length=(size_t) colors;
323   if (image->colormap == (PixelPacket *) NULL)
324     image->colormap=(PixelPacket *) AcquireQuantumMemory(length,
325       sizeof(*image->colormap));
326   else
327     image->colormap=(PixelPacket *) ResizeQuantumMemory(image->colormap,length,
328       sizeof(*image->colormap));
329   if (image->colormap == (PixelPacket *) NULL)
330     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
331       image->filename);
332   for (i=0; i < (long) image->colors; i++)
333   {
334     unsigned long
335       pixel;
336
337     pixel=(unsigned long) (i*(QuantumRange/MagickMax(colors-1,1)));
338     image->colormap[i].red=(Quantum) pixel;
339     image->colormap[i].green=(Quantum) pixel;
340     image->colormap[i].blue=(Quantum) pixel;
341     image->colormap[i].opacity=OpaqueOpacity;
342   }
343   return(SetImageStorageClass(image,PseudoClass));
344 }
345 \f
346 /*
347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
348 %                                                                             %
349 %                                                                             %
350 %                                                                             %
351 %   A c q u i r e I m a g e I n f o                                           %
352 %                                                                             %
353 %                                                                             %
354 %                                                                             %
355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
356 %
357 %  AcquireImageInfo() allocates the ImageInfo structure.
358 %
359 %  The format of the AcquireImageInfo method is:
360 %
361 %      ImageInfo *AcquireImageInfo(void)
362 %
363 */
364 MagickExport ImageInfo *AcquireImageInfo(void)
365 {
366   ImageInfo
367     *image_info;
368
369   image_info=(ImageInfo *) AcquireMagickMemory(sizeof(*image_info));
370   if (image_info == (ImageInfo *) NULL)
371     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
372   GetImageInfo(image_info);
373   return(image_info);
374 }
375 \f
376 /*
377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378 %                                                                             %
379 %                                                                             %
380 %                                                                             %
381 %   A c q u i r e N e x t I m a g e                                           %
382 %                                                                             %
383 %                                                                             %
384 %                                                                             %
385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386 %
387 %  AcquireNextImage() initializes the next image in a sequence to
388 %  default values.  The next member of image points to the newly allocated
389 %  image.  If there is a memory shortage, next is assigned NULL.
390 %
391 %  The format of the AcquireNextImage method is:
392 %
393 %      void AcquireNextImage(const ImageInfo *image_info,Image *image)
394 %
395 %  A description of each parameter follows:
396 %
397 %    o image_info: Many of the image default values are set from this
398 %      structure.  For example, filename, compression, depth, background color,
399 %      and others.
400 %
401 %    o image: the image.
402 %
403 */
404 MagickExport void AcquireNextImage(const ImageInfo *image_info,Image *image)
405 {
406   /*
407     Allocate image structure.
408   */
409   assert(image != (Image *) NULL);
410   assert(image->signature == MagickSignature);
411   if (image->debug != MagickFalse)
412     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
413   image->next=AcquireImage(image_info);
414   if (GetNextImageInList(image) == (Image *) NULL)
415     return;
416   (void) CopyMagickString(GetNextImageInList(image)->filename,image->filename,
417     MaxTextExtent);
418   if (image_info != (ImageInfo *) NULL)
419     (void) CopyMagickString(GetNextImageInList(image)->filename,
420       image_info->filename,MaxTextExtent);
421   DestroyBlob(GetNextImageInList(image));
422   image->next->blob=ReferenceBlob(image->blob);
423   image->next->endian=image->endian;
424   image->next->scene=image->scene+1;
425   image->next->previous=image;
426 }
427 \f
428 /*
429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430 %                                                                             %
431 %                                                                             %
432 %                                                                             %
433 %     A p p e n d I m a g e s                                                 %
434 %                                                                             %
435 %                                                                             %
436 %                                                                             %
437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438 %
439 %  AppendImages() takes all images from the current image pointer to the end
440 %  of the image list and appends them to each other top-to-bottom if the
441 %  stack parameter is true, otherwise left-to-right.
442 %
443 %  The current gravity setting now effects how the image is justified in the
444 %  final image.
445 %
446 %  The format of the AppendImages method is:
447 %
448 %      Image *AppendImages(const Image *image,const MagickBooleanType stack,
449 %        ExceptionInfo *exception)
450 %
451 %  A description of each parameter follows:
452 %
453 %    o image: the image sequence.
454 %
455 %    o stack: A value other than 0 stacks the images top-to-bottom.
456 %
457 %    o exception: return any errors or warnings in this structure.
458 %
459 */
460 MagickExport Image *AppendImages(const Image *image,
461   const MagickBooleanType stack,ExceptionInfo *exception)
462 {
463 #define AppendImageTag  "Append/Image"
464
465   CacheView
466     *append_view,
467     *image_view;
468
469   Image
470     *append_image;
471
472   long
473     n,
474     x_offset,
475     y,
476     y_offset;
477
478   MagickBooleanType
479     matte,
480     proceed,
481     status;
482
483   RectangleInfo
484     geometry;
485
486   register const Image
487     *next;
488
489   unsigned long
490     height,
491     number_images,
492     width;
493
494   /*
495     Ensure the image have the same column width.
496   */
497   assert(image != (Image *) NULL);
498   assert(image->signature == MagickSignature);
499   if (image->debug != MagickFalse)
500     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
501   assert(exception != (ExceptionInfo *) NULL);
502   assert(exception->signature == MagickSignature);
503   matte=image->matte;
504   number_images=1;
505   width=image->columns;
506   height=image->rows;
507   next=GetNextImageInList(image);
508   for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
509   {
510     if (next->matte != MagickFalse)
511       matte=MagickTrue;
512     number_images++;
513     if (stack != MagickFalse)
514       {
515         if (next->columns > width)
516           width=next->columns;
517         height+=next->rows;
518         continue;
519       }
520     width+=next->columns;
521     if (next->rows > height)
522       height=next->rows;
523   }
524   /*
525     Initialize append next attributes.
526   */
527   append_image=CloneImage(image,width,height,MagickTrue,exception);
528   if (append_image == (Image *) NULL)
529     return((Image *) NULL);
530   if (SetImageStorageClass(append_image,DirectClass) == MagickFalse)
531     {
532       InheritException(exception,&append_image->exception);
533       append_image=DestroyImage(append_image);
534       return((Image *) NULL);
535     }
536   append_image->matte=matte;
537   (void) SetImageBackgroundColor(append_image);
538   status=MagickTrue;
539   x_offset=0;
540   y_offset=0;
541   append_view=AcquireCacheView(append_image);
542   for (n=0; n < (long) number_images; n++)
543   {
544     SetGeometry(append_image,&geometry);
545     GravityAdjustGeometry(image->columns,image->rows,image->gravity,&geometry);
546     if (stack != MagickFalse)
547       x_offset-=geometry.x;
548     else
549       y_offset-=geometry.y;
550     image_view=AcquireCacheView(image);
551 #if defined(MAGICKCORE_OPENMP_SUPPORT)
552     #pragma omp parallel for schedule(dynamic,4) shared(status)
553 #endif
554     for (y=0; y < (long) image->rows; y++)
555     {
556       MagickBooleanType
557         sync;
558
559       register const IndexPacket
560         *__restrict indexes;
561
562       register const PixelPacket
563         *__restrict p;
564
565       register IndexPacket
566         *__restrict append_indexes;
567
568       register long
569         x;
570
571       register PixelPacket
572         *__restrict q;
573
574       if (status == MagickFalse)
575         continue;
576       p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
577       q=QueueCacheViewAuthenticPixels(append_view,x_offset,y+y_offset,
578         image->columns,1,exception);
579       if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
580         {
581           status=MagickFalse;
582           continue;
583         }
584       indexes=GetCacheViewVirtualIndexQueue(image_view);
585       append_indexes=GetCacheViewAuthenticIndexQueue(append_view);
586       for (x=0; x < (long) image->columns; x++)
587       {
588         q->red=p->red;
589         q->green=p->green;
590         q->blue=p->blue;
591         q->opacity=OpaqueOpacity;
592         if (image->matte != MagickFalse)
593           q->opacity=p->opacity;
594         if (image->colorspace == CMYKColorspace)
595           append_indexes[x]=indexes[x];
596         p++;
597         q++;
598       }
599       sync=SyncCacheViewAuthenticPixels(append_view,exception);
600       if (sync == MagickFalse)
601         continue;
602     }
603     image_view=DestroyCacheView(image_view);
604     proceed=SetImageProgress(image,AppendImageTag,n,number_images);
605     if (proceed == MagickFalse)
606       break;
607     if (stack == MagickFalse)
608       {
609         x_offset+=image->columns;
610         y_offset=0;
611       }
612     else
613       {
614         x_offset=0;
615         y_offset+=image->rows;
616       }
617     image=GetNextImageInList(image);
618   }
619   append_view=DestroyCacheView(append_view);
620   if (status == MagickFalse)
621     append_image=DestroyImage(append_image);
622   return(append_image);
623 }
624 \f
625 /*
626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627 %                                                                             %
628 %                                                                             %
629 %                                                                             %
630 %     A v e r a g e I m a g e s                                               %
631 %                                                                             %
632 %                                                                             %
633 %                                                                             %
634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635 %
636 %  AverageImages() takes a set of images and averages them together.  Each
637 %  image in the set must have the same width and height.  AverageImages()
638 %  returns a single image with each corresponding pixel component of each
639 %  image averaged.   On failure, a NULL image is returned and exception
640 %  describes the reason for the failure.
641 %
642 %  The format of the AverageImages method is:
643 %
644 %      Image *AverageImages(Image *image,ExceptionInfo *exception)
645 %
646 %  A description of each parameter follows:
647 %
648 %    o image: the image sequence.
649 %
650 %    o exception: return any errors or warnings in this structure.
651 %
652 */
653
654 static MagickPixelPacket **DestroyPixelThreadSet(MagickPixelPacket **pixels)
655 {
656   register long
657     i;
658
659   assert(pixels != (MagickPixelPacket **) NULL);
660   for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
661     if (pixels[i] != (MagickPixelPacket *) NULL)
662       pixels[i]=(MagickPixelPacket *) RelinquishMagickMemory(pixels[i]);
663   pixels=(MagickPixelPacket **) RelinquishAlignedMemory(pixels);
664   return(pixels);
665 }
666
667 static MagickPixelPacket **AcquirePixelThreadSet(const Image *image)
668 {
669   register long
670     i,
671     j;
672
673   MagickPixelPacket
674     **pixels;
675
676   unsigned long
677     number_threads;
678
679   number_threads=GetOpenMPMaximumThreads();
680   pixels=(MagickPixelPacket **) AcquireAlignedMemory(number_threads,
681     sizeof(*pixels));
682   if (pixels == (MagickPixelPacket **) NULL)
683     return((MagickPixelPacket **) NULL);
684   (void) ResetMagickMemory(pixels,0,number_threads*sizeof(*pixels));
685   for (i=0; i < (long) number_threads; i++)
686   {
687     pixels[i]=(MagickPixelPacket *) AcquireQuantumMemory(image->columns,
688       sizeof(**pixels));
689     if (pixels[i] == (MagickPixelPacket *) NULL)
690       return(DestroyPixelThreadSet(pixels));
691     for (j=0; j < (long) image->columns; j++)
692       GetMagickPixelPacket(image,&pixels[i][j]);
693   }
694   return(pixels);
695 }
696
697 MagickExport Image *AverageImages(const Image *image,ExceptionInfo *exception)
698 {
699 #define AverageImageTag  "Average/Image"
700
701   CacheView
702     *average_view;
703
704   const Image
705     *next;
706
707   Image
708     *average_image;
709
710   long
711     progress,
712     y;
713
714   MagickBooleanType
715     status;
716
717   MagickPixelPacket
718     **average_pixels,
719     zero;
720
721   unsigned long
722     number_images;
723
724   /*
725     Ensure the image are the same size.
726   */
727   assert(image != (Image *) NULL);
728   assert(image->signature == MagickSignature);
729   if (image->debug != MagickFalse)
730     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
731   assert(exception != (ExceptionInfo *) NULL);
732   assert(exception->signature == MagickSignature);
733   for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
734     if ((next->columns != image->columns) || (next->rows != image->rows))
735       ThrowImageException(OptionError,"ImageWidthsOrHeightsDiffer");
736   /*
737     Initialize average next attributes.
738   */
739   average_image=CloneImage(image,image->columns,image->rows,MagickTrue,
740     exception);
741   if (average_image == (Image *) NULL)
742     return((Image *) NULL);
743   if (SetImageStorageClass(average_image,DirectClass) == MagickFalse)
744     {
745       InheritException(exception,&average_image->exception);
746       average_image=DestroyImage(average_image);
747       return((Image *) NULL);
748     }
749   average_pixels=AcquirePixelThreadSet(image);
750   if (average_pixels == (MagickPixelPacket **) NULL)
751     {
752       average_image=DestroyImage(average_image);
753       ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
754     }
755   /*
756     Average image pixels.
757   */
758   status=MagickTrue;
759   progress=0;
760   GetMagickPixelPacket(image,&zero);
761   number_images=GetImageListLength(image);
762   average_view=AcquireCacheView(average_image);
763 #if defined(MAGICKCORE_OPENMP_SUPPORT)
764   #pragma omp parallel for schedule(dynamic) shared(progress,status)
765 #endif
766   for (y=0; y < (long) average_image->rows; y++)
767   {
768     CacheView
769       *image_view;
770
771     const Image
772       *next;
773
774     MagickPixelPacket
775       pixel;
776
777     register IndexPacket
778       *__restrict average_indexes;
779
780     register long
781       i,
782       x;
783
784     register MagickPixelPacket
785       *average_pixel;
786
787     register PixelPacket
788       *__restrict q;
789
790     if (status == MagickFalse)
791       continue;
792     q=QueueCacheViewAuthenticPixels(average_view,0,y,average_image->columns,1,
793       exception);
794     if (q == (PixelPacket *) NULL)
795       {
796         status=MagickFalse;
797         continue;
798       }
799     average_indexes=GetCacheViewAuthenticIndexQueue(average_view);
800     pixel=zero;
801     average_pixel=average_pixels[GetOpenMPThreadId()];
802     for (x=0; x < (long) average_image->columns; x++)
803       average_pixel[x]=zero;
804     next=image;
805     for (i=0; i < (long) number_images; i++)
806     {
807       register const IndexPacket
808         *indexes;
809
810       register const PixelPacket
811         *p;
812
813       image_view=AcquireCacheView(next);
814       p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
815       if (p == (const PixelPacket *) NULL)
816         {
817           image_view=DestroyCacheView(image_view);
818           break;
819         }
820       indexes=GetCacheViewVirtualIndexQueue(image_view);
821       for (x=0; x < (long) next->columns; x++)
822       {
823         SetMagickPixelPacket(next,p,indexes+x,&pixel);
824         average_pixel[x].red+=QuantumScale*pixel.red;
825         average_pixel[x].green+=QuantumScale*pixel.green;
826         average_pixel[x].blue+=QuantumScale*pixel.blue;
827         average_pixel[x].opacity+=QuantumScale*pixel.opacity;
828         if (average_image->colorspace == CMYKColorspace)
829           average_pixel[x].index+=QuantumScale*pixel.index;
830         p++;
831       }
832       image_view=DestroyCacheView(image_view);
833       next=GetNextImageInList(next);
834     }
835     for (x=0; x < (long) average_image->columns; x++)
836     {
837       average_pixel[x].red=(MagickRealType) (QuantumRange*
838         average_pixel[x].red/number_images);
839       average_pixel[x].green=(MagickRealType) (QuantumRange*
840         average_pixel[x].green/number_images);
841       average_pixel[x].blue=(MagickRealType) (QuantumRange*
842         average_pixel[x].blue/number_images);
843       average_pixel[x].opacity=(MagickRealType) (QuantumRange*
844         average_pixel[x].opacity/number_images);
845       if (average_image->colorspace == CMYKColorspace)
846         average_pixel[x].index=(MagickRealType) (QuantumRange*
847           average_pixel[x].index/number_images);
848       SetPixelPacket(average_image,&average_pixel[x],q,average_indexes+x);
849       q++;
850     }
851     if (SyncCacheViewAuthenticPixels(average_view,exception) == MagickFalse)
852       status=MagickFalse;
853     if (image->progress_monitor != (MagickProgressMonitor) NULL)
854       {
855         MagickBooleanType
856           proceed;
857
858 #if defined(MAGICKCORE_OPENMP_SUPPORT)
859         #pragma omp critical (MagickCore_AverageImages)
860 #endif
861         proceed=SetImageProgress(image,AverageImageTag,progress++,
862           average_image->rows);
863         if (proceed == MagickFalse)
864           status=MagickFalse;
865       }
866   }
867   average_view=DestroyCacheView(average_view);
868   average_pixels=DestroyPixelThreadSet(average_pixels);
869   if (status == MagickFalse)
870     average_image=DestroyImage(average_image);
871   return(average_image);
872 }
873 \f
874 /*
875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
876 %                                                                             %
877 %                                                                             %
878 %                                                                             %
879 %   C a t c h I m a g e E x c e p t i o n                                     %
880 %                                                                             %
881 %                                                                             %
882 %                                                                             %
883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
884 %
885 %  CatchImageException() returns if no exceptions are found in the image
886 %  sequence, otherwise it determines the most severe exception and reports
887 %  it as a warning or error depending on the severity.
888 %
889 %  The format of the CatchImageException method is:
890 %
891 %      ExceptionType CatchImageException(Image *image)
892 %
893 %  A description of each parameter follows:
894 %
895 %    o image: An image sequence.
896 %
897 */
898 MagickExport ExceptionType CatchImageException(Image *image)
899 {
900   ExceptionInfo
901     *exception;
902
903   ExceptionType
904     severity;
905
906   assert(image != (const Image *) NULL);
907   assert(image->signature == MagickSignature);
908   if (image->debug != MagickFalse)
909     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
910   exception=AcquireExceptionInfo();
911   GetImageException(image,exception);
912   CatchException(exception);
913   severity=exception->severity;
914   exception=DestroyExceptionInfo(exception);
915   return(severity);
916 }
917 \f
918 /*
919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
920 %                                                                             %
921 %                                                                             %
922 %                                                                             %
923 %   C l i p I m a g e P a t h                                                 %
924 %                                                                             %
925 %                                                                             %
926 %                                                                             %
927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
928 %
929 %  ClipImagePath() sets the image clip mask based any clipping path information
930 %  if it exists.
931 %
932 %  The format of the ClipImagePath method is:
933 %
934 %      MagickBooleanType ClipImagePath(Image *image,const char *pathname,
935 %        const MagickBooleanType inside)
936 %
937 %  A description of each parameter follows:
938 %
939 %    o image: the image.
940 %
941 %    o pathname: name of clipping path resource. If name is preceded by #, use
942 %      clipping path numbered by name.
943 %
944 %    o inside: if non-zero, later operations take effect inside clipping path.
945 %      Otherwise later operations take effect outside clipping path.
946 %
947 */
948
949 MagickExport MagickBooleanType ClipImage(Image *image)
950 {
951   return(ClipImagePath(image,"#1",MagickTrue));
952 }
953
954 MagickExport MagickBooleanType ClipImagePath(Image *image,const char *pathname,
955   const MagickBooleanType inside)
956 {
957 #define ClipImagePathTag  "ClipPath/Image"
958
959   char
960     *property;
961
962   const char
963     *value;
964
965   Image
966     *clip_mask;
967
968   ImageInfo
969     *image_info;
970
971   assert(image != (const Image *) NULL);
972   assert(image->signature == MagickSignature);
973   if (image->debug != MagickFalse)
974     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
975   assert(pathname != NULL);
976   property=AcquireString(pathname);
977   (void) FormatMagickString(property,MaxTextExtent,"8BIM:1999,2998:%s",
978     pathname);
979   value=GetImageProperty(image,property);
980   property=DestroyString(property);
981   if (value == (const char *) NULL)
982     {
983       ThrowFileException(&image->exception,OptionError,"NoClipPathDefined",
984         image->filename);
985       return(MagickFalse);
986     }
987   image_info=AcquireImageInfo();
988   (void) CopyMagickString(image_info->filename,image->filename,MaxTextExtent);
989   (void) ConcatenateMagickString(image_info->filename,pathname,MaxTextExtent);
990   clip_mask=BlobToImage(image_info,value,strlen(value),&image->exception);
991   image_info=DestroyImageInfo(image_info);
992   if (clip_mask == (Image *) NULL)
993     return(MagickFalse);
994   if (clip_mask->storage_class == PseudoClass)
995     {
996       (void) SyncImage(clip_mask);
997       if (SetImageStorageClass(clip_mask,DirectClass) == MagickFalse)
998         return(MagickFalse);
999     }
1000   if (inside == MagickFalse)
1001     (void) NegateImage(clip_mask,MagickFalse);
1002   (void) FormatMagickString(clip_mask->magick_filename,MaxTextExtent,
1003     "8BIM:1999,2998:%s\nPS",pathname);
1004   (void) SetImageClipMask(image,clip_mask);
1005   clip_mask=DestroyImage(clip_mask);
1006   return(MagickTrue);
1007 }
1008 \f
1009 /*
1010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1011 %                                                                             %
1012 %                                                                             %
1013 %                                                                             %
1014 %   C l o n e I m a g e                                                       %
1015 %                                                                             %
1016 %                                                                             %
1017 %                                                                             %
1018 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1019 %
1020 %  CloneImage() copies an image and returns the copy as a new image object.
1021 %  If the specified columns and rows is 0, an exact copy of the image is
1022 %  returned, otherwise the pixel data is undefined and must be initialized
1023 %  with the QueueAuthenticPixels() and SyncAuthenticPixels() methods.  On
1024 %  failure, a NULL image is returned and exception describes the reason for the
1025 %  failure.
1026 %
1027 %  The format of the CloneImage method is:
1028 %
1029 %      Image *CloneImage(const Image *image,const unsigned long columns,
1030 %        const unsigned long rows,const MagickBooleanType orphan,
1031 %        ExceptionInfo *exception)
1032 %
1033 %  A description of each parameter follows:
1034 %
1035 %    o image: the image.
1036 %
1037 %    o columns: the number of columns in the cloned image.
1038 %
1039 %    o rows: the number of rows in the cloned image.
1040 %
1041 %    o detach:  With a value other than 0, the cloned image is detached from
1042 %      its parent I/O stream.
1043 %
1044 %    o exception: return any errors or warnings in this structure.
1045 %
1046 */
1047 MagickExport Image *CloneImage(const Image *image,const unsigned long columns,
1048   const unsigned long rows,const MagickBooleanType detach,
1049   ExceptionInfo *exception)
1050 {
1051   Image
1052     *clone_image;
1053
1054   MagickRealType
1055     scale;
1056
1057   size_t
1058     length;
1059
1060   /*
1061     Clone the image.
1062   */
1063   assert(image != (const Image *) NULL);
1064   assert(image->signature == MagickSignature);
1065   if (image->debug != MagickFalse)
1066     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1067   assert(exception != (ExceptionInfo *) NULL);
1068   assert(exception->signature == MagickSignature);
1069   clone_image=(Image *) AcquireMagickMemory(sizeof(*clone_image));
1070   if (clone_image == (Image *) NULL)
1071     ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
1072   (void) ResetMagickMemory(clone_image,0,sizeof(*clone_image));
1073   clone_image->signature=MagickSignature;
1074   clone_image->storage_class=image->storage_class;
1075   clone_image->colorspace=image->colorspace;
1076   clone_image->matte=image->matte;
1077   clone_image->columns=image->columns;
1078   clone_image->rows=image->rows;
1079   clone_image->dither=image->dither;
1080   if (image->colormap != (PixelPacket *) NULL)
1081     {
1082       /*
1083         Allocate and copy the image colormap.
1084       */
1085       clone_image->colors=image->colors;
1086       length=(size_t) image->colors;
1087       clone_image->colormap=(PixelPacket *) AcquireQuantumMemory(length,
1088         sizeof(*clone_image->colormap));
1089       if (clone_image->colormap == (PixelPacket *) NULL)
1090         ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
1091       (void) CopyMagickMemory(clone_image->colormap,image->colormap,length*
1092         sizeof(*clone_image->colormap));
1093     }
1094   (void) CloneImageProfiles(clone_image,image);
1095   (void) CloneImageProperties(clone_image,image);
1096   (void) CloneImageArtifacts(clone_image,image);
1097   GetTimerInfo(&clone_image->timer);
1098   GetExceptionInfo(&clone_image->exception);
1099   InheritException(&clone_image->exception,&image->exception);
1100   if (image->ascii85 != (void *) NULL)
1101     Ascii85Initialize(clone_image);
1102   clone_image->magick_columns=image->magick_columns;
1103   clone_image->magick_rows=image->magick_rows;
1104   clone_image->type=image->type;
1105   (void) CopyMagickString(clone_image->magick_filename,image->magick_filename,
1106     MaxTextExtent);
1107   (void) CopyMagickString(clone_image->magick,image->magick,MaxTextExtent);
1108   (void) CopyMagickString(clone_image->filename,image->filename,MaxTextExtent);
1109   clone_image->progress_monitor=image->progress_monitor;
1110   clone_image->client_data=image->client_data;
1111   clone_image->reference_count=1;
1112   clone_image->next=NewImageList();
1113   clone_image->previous=NewImageList();
1114   clone_image->list=NewImageList();
1115   clone_image->clip_mask=NewImageList();
1116   clone_image->mask=NewImageList();
1117   if (detach == MagickFalse)
1118     clone_image->blob=ReferenceBlob(image->blob);
1119   else
1120     clone_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1121   clone_image->debug=IsEventLogging();
1122   clone_image->semaphore=AllocateSemaphoreInfo();
1123   if ((columns == 0) && (rows == 0))
1124     {
1125       if (image->montage != (char *) NULL)
1126         (void) CloneString(&clone_image->montage,image->montage);
1127       if (image->directory != (char *) NULL)
1128         (void) CloneString(&clone_image->directory,image->directory);
1129       if (image->clip_mask != (Image *) NULL)
1130         clone_image->clip_mask=CloneImage(image->clip_mask,0,0,MagickTrue,
1131           exception);
1132       if (image->mask != (Image *) NULL)
1133         clone_image->mask=CloneImage(image->mask,0,0,MagickTrue,exception);
1134       clone_image->cache=ReferencePixelCache(image->cache);
1135       return(clone_image);
1136     }
1137   scale=(MagickRealType) columns/(MagickRealType) image->columns;
1138   clone_image->page.width=(unsigned long) (scale*image->page.width+0.5);
1139   clone_image->page.x=(long) (scale*image->page.x+0.5);
1140   clone_image->tile_offset.x=(long) (scale*image->tile_offset.x+0.5);
1141   scale=(MagickRealType) rows/(MagickRealType) image->rows;
1142   clone_image->page.height=(unsigned long) (scale*image->page.height+0.5);
1143   clone_image->page.y=(long) (image->page.y*scale+0.5);
1144   clone_image->tile_offset.y=(long) (scale*image->tile_offset.y+0.5);
1145   clone_image->columns=columns;
1146   clone_image->rows=rows;
1147   clone_image->cache=ClonePixelCache(image->cache);
1148   return(clone_image);
1149 }
1150 \f
1151 /*
1152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1153 %                                                                             %
1154 %                                                                             %
1155 %                                                                             %
1156 %   C l o n e I m a g e I n f o                                               %
1157 %                                                                             %
1158 %                                                                             %
1159 %                                                                             %
1160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1161 %
1162 %  CloneImageInfo() makes a copy of the given image info structure.  If
1163 %  NULL is specified, a new image info structure is created initialized to
1164 %  default values.
1165 %
1166 %  The format of the CloneImageInfo method is:
1167 %
1168 %      ImageInfo *CloneImageInfo(const ImageInfo *image_info)
1169 %
1170 %  A description of each parameter follows:
1171 %
1172 %    o image_info: the image info.
1173 %
1174 */
1175 MagickExport ImageInfo *CloneImageInfo(const ImageInfo *image_info)
1176 {
1177   ImageInfo
1178     *clone_info;
1179
1180   clone_info=AcquireImageInfo();
1181   if (image_info == (ImageInfo *) NULL)
1182     return(clone_info);
1183   clone_info->compression=image_info->compression;
1184   clone_info->temporary=image_info->temporary;
1185   clone_info->adjoin=image_info->adjoin;
1186   clone_info->antialias=image_info->antialias;
1187   clone_info->scene=image_info->scene;
1188   clone_info->number_scenes=image_info->number_scenes;
1189   clone_info->depth=image_info->depth;
1190   if (image_info->size != (char *) NULL)
1191     (void) CloneString(&clone_info->size,image_info->size);
1192   if (image_info->extract != (char *) NULL)
1193     (void) CloneString(&clone_info->extract,image_info->extract);
1194   if (image_info->scenes != (char *) NULL)
1195     (void) CloneString(&clone_info->scenes,image_info->scenes);
1196   if (image_info->page != (char *) NULL)
1197     (void) CloneString(&clone_info->page,image_info->page);
1198   clone_info->interlace=image_info->interlace;
1199   clone_info->endian=image_info->endian;
1200   clone_info->units=image_info->units;
1201   clone_info->quality=image_info->quality;
1202   if (image_info->sampling_factor != (char *) NULL)
1203     (void) CloneString(&clone_info->sampling_factor,
1204       image_info->sampling_factor);
1205   if (image_info->server_name != (char *) NULL)
1206     (void) CloneString(&clone_info->server_name,image_info->server_name);
1207   if (image_info->font != (char *) NULL)
1208     (void) CloneString(&clone_info->font,image_info->font);
1209   if (image_info->texture != (char *) NULL)
1210     (void) CloneString(&clone_info->texture,image_info->texture);
1211   if (image_info->density != (char *) NULL)
1212     (void) CloneString(&clone_info->density,image_info->density);
1213   clone_info->pointsize=image_info->pointsize;
1214   clone_info->fuzz=image_info->fuzz;
1215   clone_info->pen=image_info->pen;
1216   clone_info->background_color=image_info->background_color;
1217   clone_info->border_color=image_info->border_color;
1218   clone_info->matte_color=image_info->matte_color;
1219   clone_info->transparent_color=image_info->transparent_color;
1220   clone_info->dither=image_info->dither;
1221   clone_info->monochrome=image_info->monochrome;
1222   clone_info->colors=image_info->colors;
1223   clone_info->colorspace=image_info->colorspace;
1224   clone_info->type=image_info->type;
1225   clone_info->orientation=image_info->orientation;
1226   clone_info->preview_type=image_info->preview_type;
1227   clone_info->group=image_info->group;
1228   clone_info->ping=image_info->ping;
1229   clone_info->verbose=image_info->verbose;
1230   if (image_info->view != (char *) NULL)
1231     (void) CloneString(&clone_info->view,image_info->view);
1232   if (image_info->authenticate != (char *) NULL)
1233     (void) CloneString(&clone_info->authenticate,image_info->authenticate);
1234   (void) CloneImageOptions(clone_info,image_info);
1235   clone_info->progress_monitor=image_info->progress_monitor;
1236   clone_info->client_data=image_info->client_data;
1237   clone_info->cache=image_info->cache;
1238   if (image_info->cache != (void *) NULL)
1239     clone_info->cache=ReferencePixelCache(image_info->cache);
1240   if (image_info->profile != (void *) NULL)
1241     clone_info->profile=(void *) CloneStringInfo((StringInfo *)
1242       image_info->profile);
1243   SetImageInfoFile(clone_info,image_info->file);
1244   SetImageInfoBlob(clone_info,image_info->blob,image_info->length);
1245   clone_info->stream=image_info->stream;
1246   clone_info->virtual_pixel_method=image_info->virtual_pixel_method;
1247   (void) CopyMagickString(clone_info->magick,image_info->magick,MaxTextExtent);
1248   (void) CopyMagickString(clone_info->unique,image_info->unique,MaxTextExtent);
1249   (void) CopyMagickString(clone_info->zero,image_info->zero,MaxTextExtent);
1250   (void) CopyMagickString(clone_info->filename,image_info->filename,
1251     MaxTextExtent);
1252   clone_info->subimage=image_info->scene;  /* deprecated */
1253   clone_info->subrange=image_info->number_scenes;  /* deprecated */
1254   clone_info->channel=image_info->channel;
1255   clone_info->debug=IsEventLogging();
1256   clone_info->signature=image_info->signature;
1257   return(clone_info);
1258 }
1259 \f
1260 /*
1261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1262 %                                                                             %
1263 %                                                                             %
1264 %                                                                             %
1265 %     C o m b i n e I m a g e s                                               %
1266 %                                                                             %
1267 %                                                                             %
1268 %                                                                             %
1269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1270 %
1271 %  CombineImages() combines one or more images into a single image.  The
1272 %  grayscale value of the pixels of each image in the sequence is assigned in
1273 %  order to the specified channels of the combined image.   The typical
1274 %  ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
1275 %
1276 %  The format of the CombineImages method is:
1277 %
1278 %      Image *CombineImages(const Image *image,const ChannelType channel,
1279 %        ExceptionInfo *exception)
1280 %
1281 %  A description of each parameter follows:
1282 %
1283 %    o image: the image.
1284 %
1285 %    o exception: return any errors or warnings in this structure.
1286 %
1287 */
1288 MagickExport Image *CombineImages(const Image *image,const ChannelType channel,
1289   ExceptionInfo *exception)
1290 {
1291 #define CombineImageTag  "Combine/Image"
1292
1293   CacheView
1294     *combine_view;
1295
1296   const Image
1297     *next;
1298
1299   Image
1300     *combine_image;
1301
1302   long
1303     progress,
1304     y;
1305
1306   MagickBooleanType
1307     status;
1308
1309   /*
1310     Ensure the image are the same size.
1311   */
1312   assert(image != (const Image *) NULL);
1313   assert(image->signature == MagickSignature);
1314   if (image->debug != MagickFalse)
1315     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1316   assert(exception != (ExceptionInfo *) NULL);
1317   assert(exception->signature == MagickSignature);
1318   for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1319   {
1320     if ((next->columns != image->columns) || (next->rows != image->rows))
1321       ThrowImageException(OptionError,"ImagesAreNotTheSameSize");
1322   }
1323   combine_image=CloneImage(image,0,0,MagickTrue,exception);
1324   if (combine_image == (Image *) NULL)
1325     return((Image *) NULL);
1326   if (SetImageStorageClass(combine_image,DirectClass) == MagickFalse)
1327     {
1328       InheritException(exception,&combine_image->exception);
1329       combine_image=DestroyImage(combine_image);
1330       return((Image *) NULL);
1331     }
1332   if ((channel & OpacityChannel) != 0)
1333     combine_image->matte=MagickTrue;
1334   (void) SetImageBackgroundColor(combine_image);
1335   /*
1336     Combine images.
1337   */
1338   status=MagickTrue;
1339   progress=0;
1340   combine_view=AcquireCacheView(combine_image);
1341 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1342   #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
1343 #endif
1344   for (y=0; y < (long) combine_image->rows; y++)
1345   {
1346     CacheView
1347       *image_view;
1348
1349     const Image
1350       *next;
1351
1352     PixelPacket
1353       *pixels;
1354
1355     register const PixelPacket
1356       *__restrict p;
1357
1358     register long
1359       x;
1360
1361     register PixelPacket
1362       *__restrict q;
1363
1364     if (status == MagickFalse)
1365       continue;
1366     pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns,
1367       1,exception);
1368     if (pixels == (PixelPacket *) NULL)
1369       {
1370         status=MagickFalse;
1371         continue;
1372       }
1373     next=image;
1374     if (((channel & RedChannel) != 0) && (next != (Image *) NULL))
1375       {
1376         image_view=AcquireCacheView(next);
1377         p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1378         if (p == (const PixelPacket *) NULL)
1379           continue;
1380         q=pixels;
1381         for (x=0; x < (long) combine_image->columns; x++)
1382         {
1383           q->red=PixelIntensityToQuantum(p);
1384           p++;
1385           q++;
1386         }
1387         image_view=DestroyCacheView(image_view);
1388         next=GetNextImageInList(next);
1389       }
1390     if (((channel & GreenChannel) != 0) && (next != (Image *) NULL))
1391       {
1392         image_view=AcquireCacheView(next);
1393         p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1394         if (p == (const PixelPacket *) NULL)
1395           continue;
1396         q=pixels;
1397         for (x=0; x < (long) combine_image->columns; x++)
1398         {
1399           q->green=PixelIntensityToQuantum(p);
1400           p++;
1401           q++;
1402         }
1403         image_view=DestroyCacheView(image_view);
1404         next=GetNextImageInList(next);
1405       }
1406     if (((channel & BlueChannel) != 0) && (next != (Image *) NULL))
1407       {
1408         image_view=AcquireCacheView(next);
1409         p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1410         if (p == (const PixelPacket *) NULL)
1411           continue;
1412         q=pixels;
1413         for (x=0; x < (long) combine_image->columns; x++)
1414         {
1415           q->blue=PixelIntensityToQuantum(p);
1416           p++;
1417           q++;
1418         }
1419         image_view=DestroyCacheView(image_view);
1420         next=GetNextImageInList(next);
1421       }
1422     if (((channel & OpacityChannel) != 0) && (next != (Image *) NULL))
1423       {
1424         image_view=AcquireCacheView(next);
1425         p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1426         if (p == (const PixelPacket *) NULL)
1427           continue;
1428         q=pixels;
1429         for (x=0; x < (long) combine_image->columns; x++)
1430         {
1431           q->opacity=PixelIntensityToQuantum(p);
1432           p++;
1433           q++;
1434         }
1435         image_view=DestroyCacheView(image_view);
1436         next=GetNextImageInList(next);
1437       }
1438     if (((channel & IndexChannel) != 0) &&
1439         (image->colorspace == CMYKColorspace) && (next != (Image *) NULL))
1440       {
1441         IndexPacket
1442           *indexes;
1443
1444         image_view=AcquireCacheView(next);
1445         p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1446         if (p == (const PixelPacket *) NULL)
1447           continue;
1448         indexes=GetCacheViewAuthenticIndexQueue(combine_view);
1449         for (x=0; x < (long) combine_image->columns; x++)
1450         {
1451           indexes[x]=PixelIntensityToQuantum(p);
1452           p++;
1453         }
1454         image_view=DestroyCacheView(image_view);
1455         next=GetNextImageInList(next);
1456       }
1457     if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse)
1458       status=MagickFalse;
1459     if (image->progress_monitor != (MagickProgressMonitor) NULL)
1460       {
1461         MagickBooleanType
1462           proceed;
1463
1464 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1465         #pragma omp critical (MagickCore_CombineImages)
1466 #endif
1467         proceed=SetImageProgress(image,CombineImageTag,progress++,
1468           combine_image->rows);
1469         if (proceed == MagickFalse)
1470           status=MagickFalse;
1471       }
1472   }
1473   combine_view=DestroyCacheView(combine_view);
1474   if (status == MagickFalse)
1475     combine_image=DestroyImage(combine_image);
1476   return(combine_image);
1477 }
1478 \f
1479 /*
1480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1481 %                                                                             %
1482 %                                                                             %
1483 %                                                                             %
1484 %     C y c l e C o l o r m a p I m a g e                                     %
1485 %                                                                             %
1486 %                                                                             %
1487 %                                                                             %
1488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1489 %
1490 %  CycleColormap() displaces an image's colormap by a given number of
1491 %  positions.  If you cycle the colormap a number of times you can produce
1492 %  a psychodelic effect.
1493 %
1494 %  The format of the CycleColormapImage method is:
1495 %
1496 %      MagickBooleanType CycleColormapImage(Image *image,const long displace)
1497 %
1498 %  A description of each parameter follows:
1499 %
1500 %    o image: the image.
1501 %
1502 %    o displace:  displace the colormap this amount.
1503 %
1504 */
1505 MagickExport MagickBooleanType CycleColormapImage(Image *image,
1506   const long displace)
1507 {
1508   CacheView
1509     *image_view;
1510
1511   ExceptionInfo
1512     *exception;
1513
1514   long
1515     y;
1516
1517   MagickBooleanType
1518     status;
1519
1520   assert(image != (Image *) NULL);
1521   assert(image->signature == MagickSignature);
1522   if (image->debug != MagickFalse)
1523     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1524   if (image->storage_class == DirectClass)
1525     (void) SetImageType(image,PaletteType);
1526   status=MagickTrue;
1527   exception=(&image->exception);
1528   image_view=AcquireCacheView(image);
1529 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1530   #pragma omp parallel for schedule(dynamic,4) shared(status)
1531 #endif
1532   for (y=0; y < (long) image->rows; y++)
1533   {
1534     long
1535       index;
1536
1537     register IndexPacket
1538       *__restrict indexes;
1539
1540     register long
1541       x;
1542
1543     register PixelPacket
1544       *__restrict q;
1545
1546     if (status == MagickFalse)
1547       continue;
1548     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1549     if (q == (PixelPacket *) NULL)
1550       {
1551         status=MagickFalse;
1552         continue;
1553       }
1554     indexes=GetCacheViewAuthenticIndexQueue(image_view);
1555     for (x=0; x < (long) image->columns; x++)
1556     {
1557       index=(long) (indexes[x]+displace) % image->colors;
1558       if (index < 0)
1559         index+=image->colors;
1560       indexes[x]=(IndexPacket) index;
1561       q->red=image->colormap[index].red;
1562       q->green=image->colormap[index].green;
1563       q->blue=image->colormap[index].blue;
1564       q++;
1565     }
1566     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1567       status=MagickFalse;
1568   }
1569   image_view=DestroyCacheView(image_view);
1570   return(status);
1571 }
1572 \f
1573 /*
1574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1575 %                                                                             %
1576 %                                                                             %
1577 %                                                                             %
1578 %   D e s t r o y I m a g e                                                   %
1579 %                                                                             %
1580 %                                                                             %
1581 %                                                                             %
1582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1583 %
1584 %  DestroyImage() dereferences an image, deallocating memory associated with
1585 %  the image if the reference count becomes zero.
1586 %
1587 %  The format of the DestroyImage method is:
1588 %
1589 %      Image *DestroyImage(Image *image)
1590 %
1591 %  A description of each parameter follows:
1592 %
1593 %    o image: the image.
1594 %
1595 */
1596 MagickExport Image *DestroyImage(Image *image)
1597 {
1598   MagickBooleanType
1599     destroy;
1600
1601   /*
1602     Dereference image.
1603   */
1604   assert(image != (Image *) NULL);
1605   assert(image->signature == MagickSignature);
1606   if (image->debug != MagickFalse)
1607     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1608   destroy=MagickFalse;
1609   (void) LockSemaphoreInfo(image->semaphore);
1610   image->reference_count--;
1611   if (image->reference_count == 0)
1612     destroy=MagickTrue;
1613   (void) UnlockSemaphoreInfo(image->semaphore);
1614   if (destroy == MagickFalse)
1615     return((Image *) NULL);
1616   /*
1617     Destroy image.
1618   */
1619   DestroyImagePixels(image);
1620   if (image->clip_mask != (Image *) NULL)
1621     image->clip_mask=DestroyImage(image->clip_mask);
1622   if (image->mask != (Image *) NULL)
1623     image->mask=DestroyImage(image->mask);
1624   if (image->montage != (char *) NULL)
1625     image->montage=DestroyString(image->montage);
1626   if (image->directory != (char *) NULL)
1627     image->directory=DestroyString(image->directory);
1628   if (image->colormap != (PixelPacket *) NULL)
1629     image->colormap=(PixelPacket *) RelinquishMagickMemory(image->colormap);
1630   if (image->geometry != (char *) NULL)
1631     image->geometry=DestroyString(image->geometry);
1632 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
1633   DestroyImageAttributes(image);
1634 #endif
1635   DestroyImageProfiles(image);
1636   DestroyImageProperties(image);
1637   DestroyImageArtifacts(image);
1638   if (image->ascii85 != (Ascii85Info*) NULL)
1639     image->ascii85=(Ascii85Info *) RelinquishMagickMemory(image->ascii85);
1640   DestroyBlob(image);
1641   (void) DestroyExceptionInfo(&image->exception);
1642   if (image->semaphore != (SemaphoreInfo *) NULL)
1643     DestroySemaphoreInfo(&image->semaphore);
1644   image->signature=(~MagickSignature);
1645   image=(Image *) RelinquishMagickMemory(image);
1646   return(image);
1647 }
1648 \f
1649 /*
1650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1651 %                                                                             %
1652 %                                                                             %
1653 %                                                                             %
1654 %   D e s t r o y I m a g e I n f o                                           %
1655 %                                                                             %
1656 %                                                                             %
1657 %                                                                             %
1658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1659 %
1660 %  DestroyImageInfo() deallocates memory associated with an ImageInfo
1661 %  structure.
1662 %
1663 %  The format of the DestroyImageInfo method is:
1664 %
1665 %      ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1666 %
1667 %  A description of each parameter follows:
1668 %
1669 %    o image_info: the image info.
1670 %
1671 */
1672 MagickExport ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1673 {
1674   assert(image_info != (ImageInfo *) NULL);
1675   assert(image_info->signature == MagickSignature);
1676   if (image_info->debug != MagickFalse)
1677     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1678       image_info->filename);
1679   if (image_info->size != (char *) NULL)
1680     image_info->size=DestroyString(image_info->size);
1681   if (image_info->extract != (char *) NULL)
1682     image_info->extract=DestroyString(image_info->extract);
1683   if (image_info->scenes != (char *) NULL)
1684     image_info->scenes=DestroyString(image_info->scenes);
1685   if (image_info->page != (char *) NULL)
1686     image_info->page=DestroyString(image_info->page);
1687   if (image_info->sampling_factor != (char *) NULL)
1688     image_info->sampling_factor=DestroyString(
1689       image_info->sampling_factor);
1690   if (image_info->server_name != (char *) NULL)
1691     image_info->server_name=DestroyString(
1692       image_info->server_name);
1693   if (image_info->font != (char *) NULL)
1694     image_info->font=DestroyString(image_info->font);
1695   if (image_info->texture != (char *) NULL)
1696     image_info->texture=DestroyString(image_info->texture);
1697   if (image_info->density != (char *) NULL)
1698     image_info->density=DestroyString(image_info->density);
1699   if (image_info->view != (char *) NULL)
1700     image_info->view=DestroyString(image_info->view);
1701   if (image_info->authenticate != (char *) NULL)
1702     image_info->authenticate=DestroyString(
1703       image_info->authenticate);
1704   DestroyImageOptions(image_info);
1705   if (image_info->cache != (void *) NULL)
1706     image_info->cache=DestroyPixelCache(image_info->cache);
1707   if (image_info->profile != (StringInfo *) NULL)
1708     image_info->profile=(void *) DestroyStringInfo((StringInfo *)
1709       image_info->profile);
1710   image_info->signature=(~MagickSignature);
1711   image_info=(ImageInfo *) RelinquishMagickMemory(image_info);
1712   return(image_info);
1713 }
1714 \f
1715 /*
1716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1717 %                                                                             %
1718 %                                                                             %
1719 %                                                                             %
1720 +   D i s a s s o c i a t e I m a g e S t r e a m                             %
1721 %                                                                             %
1722 %                                                                             %
1723 %                                                                             %
1724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725 %
1726 %  DisassociateImageStream() disassociates the image stream.
1727 %
1728 %  The format of the DisassociateImageStream method is:
1729 %
1730 %      MagickBooleanType DisassociateImageStream(const Image *image)
1731 %
1732 %  A description of each parameter follows:
1733 %
1734 %    o image: the image.
1735 %
1736 */
1737 MagickExport void DisassociateImageStream(Image *image)
1738 {
1739   assert(image != (const Image *) NULL);
1740   assert(image->signature == MagickSignature);
1741   if (image->debug != MagickFalse)
1742     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1743   (void) DetachBlob(image->blob);
1744 }
1745 \f
1746 /*
1747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1748 %                                                                             %
1749 %                                                                             %
1750 %                                                                             %
1751 %   G e t I m a g e A l p h a C h a n n e l                                   %
1752 %                                                                             %
1753 %                                                                             %
1754 %                                                                             %
1755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1756 %
1757 %  GetImageAlphaChannel() returns MagickFalse if the image alpha channel is
1758 %  not activated.  That is, the image is RGB rather than RGBA or CMYK rather
1759 %  than CMYKA.
1760 %
1761 %  The format of the GetImageAlphaChannel method is:
1762 %
1763 %      MagickBooleanType GetImageAlphaChannel(const Image *image)
1764 %
1765 %  A description of each parameter follows:
1766 %
1767 %    o image: the image.
1768 %
1769 */
1770 MagickExport MagickBooleanType GetImageAlphaChannel(const Image *image)
1771 {
1772   assert(image != (const Image *) NULL);
1773   if (image->debug != MagickFalse)
1774     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1775   assert(image->signature == MagickSignature);
1776   return(image->matte);
1777 }
1778 \f
1779 /*
1780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781 %                                                                             %
1782 %                                                                             %
1783 %                                                                             %
1784 %   G e t I m a g e C l i p M a s k                                           %
1785 %                                                                             %
1786 %                                                                             %
1787 %                                                                             %
1788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1789 %
1790 %  GetImageClipMask() returns the clip path associated with the image.
1791 %
1792 %  The format of the GetImageClipMask method is:
1793 %
1794 %      Image *GetImageClipMask(const Image *image,ExceptionInfo *exception)
1795 %
1796 %  A description of each parameter follows:
1797 %
1798 %    o image: the image.
1799 %
1800 */
1801 MagickExport Image *GetImageClipMask(const Image *image,
1802   ExceptionInfo *exception)
1803 {
1804   assert(image != (const Image *) NULL);
1805   if (image->debug != MagickFalse)
1806     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1807   assert(image->signature == MagickSignature);
1808   if (image->clip_mask == (Image *) NULL)
1809     return((Image *) NULL);
1810   return(CloneImage(image->clip_mask,0,0,MagickTrue,exception));
1811 }
1812 \f
1813 /*
1814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1815 %                                                                             %
1816 %                                                                             %
1817 %                                                                             %
1818 %   G e t I m a g e E x c e p t i o n                                         %
1819 %                                                                             %
1820 %                                                                             %
1821 %                                                                             %
1822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1823 %
1824 %  GetImageException() traverses an image sequence and returns any
1825 %  error more severe than noted by the exception parameter.
1826 %
1827 %  The format of the GetImageException method is:
1828 %
1829 %      void GetImageException(Image *image,ExceptionInfo *exception)
1830 %
1831 %  A description of each parameter follows:
1832 %
1833 %    o image: Specifies a pointer to a list of one or more images.
1834 %
1835 %    o exception: return the highest severity exception.
1836 %
1837 */
1838 MagickExport void GetImageException(Image *image,ExceptionInfo *exception)
1839 {
1840   register Image
1841     *next;
1842
1843   assert(image != (Image *) NULL);
1844   assert(image->signature == MagickSignature);
1845   if (image->debug != MagickFalse)
1846     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1847   assert(exception != (ExceptionInfo *) NULL);
1848   assert(exception->signature == MagickSignature);
1849   for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1850   {
1851     if (next->exception.severity == UndefinedException)
1852       continue;
1853     if (next->exception.severity > exception->severity)
1854       InheritException(exception,&next->exception);
1855     next->exception.severity=UndefinedException;
1856   }
1857 }
1858 \f
1859 /*
1860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1861 %                                                                             %
1862 %                                                                             %
1863 %                                                                             %
1864 %   G e t I m a g e I n f o                                                   %
1865 %                                                                             %
1866 %                                                                             %
1867 %                                                                             %
1868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1869 %
1870 %  GetImageInfo() initializes image_info to default values.
1871 %
1872 %  The format of the GetImageInfo method is:
1873 %
1874 %      void GetImageInfo(ImageInfo *image_info)
1875 %
1876 %  A description of each parameter follows:
1877 %
1878 %    o image_info: the image info.
1879 %
1880 */
1881 MagickExport void GetImageInfo(ImageInfo *image_info)
1882 {
1883   ExceptionInfo
1884     *exception;
1885
1886   /*
1887     File and image dimension members.
1888   */
1889   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1890   assert(image_info != (ImageInfo *) NULL);
1891   (void) ResetMagickMemory(image_info,0,sizeof(*image_info));
1892   image_info->adjoin=MagickTrue;
1893   image_info->interlace=NoInterlace;
1894   image_info->channel=DefaultChannels;
1895   image_info->quality=UndefinedCompressionQuality;
1896   image_info->antialias=MagickTrue;
1897   image_info->dither=MagickTrue;
1898   exception=AcquireExceptionInfo();
1899   (void) QueryColorDatabase(BackgroundColor,&image_info->background_color,
1900     exception);
1901   (void) QueryColorDatabase(BorderColor,&image_info->border_color,exception);
1902   (void) QueryColorDatabase(MatteColor,&image_info->matte_color,exception);
1903   (void) QueryColorDatabase(TransparentColor,&image_info->transparent_color,
1904     exception);
1905   exception=DestroyExceptionInfo(exception);
1906   image_info->debug=IsEventLogging();
1907   image_info->signature=MagickSignature;
1908 }
1909 \f
1910 /*
1911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1912 %                                                                             %
1913 %                                                                             %
1914 %                                                                             %
1915 %   G e t I m a g e M a s k                                                   %
1916 %                                                                             %
1917 %                                                                             %
1918 %                                                                             %
1919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1920 %
1921 %  GetImageMask() returns the mask associated with the image.
1922 %
1923 %  The format of the GetImageMask method is:
1924 %
1925 %      Image *GetImageMask(const Image *image,ExceptionInfo *exception)
1926 %
1927 %  A description of each parameter follows:
1928 %
1929 %    o image: the image.
1930 %
1931 */
1932 MagickExport Image *GetImageMask(const Image *image,ExceptionInfo *exception)
1933 {
1934   assert(image != (const Image *) NULL);
1935   if (image->debug != MagickFalse)
1936     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1937   assert(image->signature == MagickSignature);
1938   if (image->mask == (Image *) NULL)
1939     return((Image *) NULL);
1940   return(CloneImage(image->mask,0,0,MagickTrue,exception));
1941 }
1942 \f
1943 /*
1944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1945 %                                                                             %
1946 %                                                                             %
1947 %                                                                             %
1948 +   G e t I m a g e R e f e r e n c e C o u n t                               %
1949 %                                                                             %
1950 %                                                                             %
1951 %                                                                             %
1952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1953 %
1954 %  GetImageReferenceCount() returns the image reference count.
1955 %
1956 %  The format of the GetReferenceCount method is:
1957 %
1958 %      long GetImageReferenceCount(Image *image)
1959 %
1960 %  A description of each parameter follows:
1961 %
1962 %    o image: the image.
1963 %
1964 */
1965 MagickExport long GetImageReferenceCount(Image *image)
1966 {
1967   long
1968     reference_count;
1969
1970   assert(image != (Image *) NULL);
1971   assert(image->signature == MagickSignature);
1972   if (image->debug != MagickFalse)
1973     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1974   AcquireSemaphoreInfo(&image->semaphore);
1975   reference_count=image->reference_count;
1976   RelinquishSemaphoreInfo(image->semaphore);
1977   return(reference_count);
1978 }
1979 \f
1980 /*
1981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1982 %                                                                             %
1983 %                                                                             %
1984 %                                                                             %
1985 %   G e t I m a g e T y p e                                                   %
1986 %                                                                             %
1987 %                                                                             %
1988 %                                                                             %
1989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1990 %
1991 %  GetImageType() returns the potential type of image:
1992 %
1993 %        Bilevel         Grayscale        GrayscaleMatte
1994 %        Palette         PaletteMatte     TrueColor
1995 %        TrueColorMatte  ColorSeparation  ColorSeparationMatte
1996 %
1997 %  To ensure the image type matches its potential, use SetImageType():
1998 %
1999 %    (void) SetImageType(image,GetImageType(image));
2000 %
2001 %  The format of the GetImageType method is:
2002 %
2003 %      ImageType GetImageType(const Image *image,ExceptionInfo *exception)
2004 %
2005 %  A description of each parameter follows:
2006 %
2007 %    o image: the image.
2008 %
2009 %    o exception: return any errors or warnings in this structure.
2010 %
2011 */
2012 MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception)
2013 {
2014   assert(image != (Image *) NULL);
2015   assert(image->signature == MagickSignature);
2016   if (image->debug != MagickFalse)
2017     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2018   if (image->colorspace == CMYKColorspace)
2019     {
2020       if (image->matte == MagickFalse)
2021         return(ColorSeparationType);
2022       return(ColorSeparationMatteType);
2023     }
2024   if (IsMonochromeImage(image,exception) != MagickFalse)
2025     return(BilevelType);
2026   if (IsGrayImage(image,exception) != MagickFalse)
2027     {
2028       if (image->matte != MagickFalse)
2029         return(GrayscaleMatteType);
2030       return(GrayscaleType);
2031     }
2032   if (IsPaletteImage(image,exception) != MagickFalse)
2033     {
2034       if (image->matte != MagickFalse)
2035         return(PaletteMatteType);
2036       return(PaletteType);
2037     }
2038   if (image->matte != MagickFalse)
2039     return(TrueColorMatteType);
2040   return(TrueColorType);
2041 }
2042 \f
2043 /*
2044 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2045 %                                                                             %
2046 %                                                                             %
2047 %                                                                             %
2048 %   G e t I m a g e V i r t u a l P i x e l M e t h o d                       %
2049 %                                                                             %
2050 %                                                                             %
2051 %                                                                             %
2052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2053 %
2054 %  GetImageVirtualPixelMethod() gets the "virtual pixels" method for the
2055 %  image.  A virtual pixel is any pixel access that is outside the boundaries
2056 %  of the image cache.
2057 %
2058 %  The format of the GetImageVirtualPixelMethod() method is:
2059 %
2060 %      VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
2061 %
2062 %  A description of each parameter follows:
2063 %
2064 %    o image: the image.
2065 %
2066 */
2067 MagickExport VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
2068 {
2069   assert(image != (Image *) NULL);
2070   assert(image->signature == MagickSignature);
2071   if (image->debug != MagickFalse)
2072     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2073   return(GetPixelCacheVirtualMethod(image));
2074 }
2075 \f
2076 /*
2077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2078 %                                                                             %
2079 %                                                                             %
2080 %                                                                             %
2081 %  I n t e r p r e t I m a g e F i l e n a m e                                %
2082 %                                                                             %
2083 %                                                                             %
2084 %                                                                             %
2085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2086 %
2087 %  InterpretImageFilename() interprets embedded characters in an image filename.
2088 %  The filename length is returned.
2089 %
2090 %  The format of the InterpretImageFilename method is:
2091 %
2092 %      size_t InterpretImageFilename(const ImageInfo *image_info,
2093 %        Image *image,const char *format,int value,char *filename)
2094 %
2095 %  A description of each parameter follows.
2096 %
2097 %    o image_info: the image info..
2098 %
2099 %    o image: the image.
2100 %
2101 %    o format:  A filename describing the format to use to write the numeric
2102 %      argument. Only the first numeric format identifier is replaced.
2103 %
2104 %    o value:  Numeric value to substitute into format filename.
2105 %
2106 %    o filename:  return the formatted filename in this character buffer.
2107 %
2108 */
2109 MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
2110   Image *image,const char *format,int value,char *filename)
2111 {
2112   char
2113     *q;
2114
2115   int
2116     c;
2117
2118   MagickBooleanType
2119     canonical;
2120
2121   register const char
2122     *p;
2123
2124   canonical=MagickFalse;
2125   (void) CopyMagickString(filename,format,MaxTextExtent);
2126   for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
2127   {
2128     q=(char *) p+1;
2129     if (*q == '%')
2130       {
2131         p=q+1;
2132         continue;
2133       }
2134     if (*q == '0')
2135       {
2136         long
2137           value;
2138
2139         value=strtol(q,&q,10);
2140       }
2141     switch (*q)
2142     {
2143       case 'd':
2144       case 'o':
2145       case 'x':
2146       {
2147         q++;
2148         c=(*q);
2149         *q='\0';
2150         (void) FormatMagickString(filename+(p-format),(size_t) (MaxTextExtent-
2151           (p-format)),p,value);
2152         *q=c;
2153         (void) ConcatenateMagickString(filename,q,MaxTextExtent);
2154         canonical=MagickTrue;
2155         if (*(q-1) != '%')
2156           break;
2157         p++;
2158         break;
2159       }
2160       case '[':
2161       {
2162         char
2163           pattern[MaxTextExtent];
2164
2165         const char
2166           *value;
2167
2168         long
2169           depth;
2170
2171         register char
2172           *r;
2173
2174         register long
2175           i;
2176
2177         /*
2178           Image option.
2179         */
2180         if (strchr(p,']') == (char *) NULL)
2181           break;
2182         depth=1;
2183         r=q+1;
2184         for (i=0; (i < (MaxTextExtent-1L)) && (*r != '\0'); i++)
2185         {
2186           if (*r == '[')
2187             depth++;
2188           if (*r == ']')
2189             depth--;
2190           if (depth <= 0)
2191             break;
2192           pattern[i]=(*r++);
2193         }
2194         pattern[i]='\0';
2195         if (LocaleNCompare(pattern,"filename:",9) != 0)
2196           break;
2197         value=(const char *) NULL;
2198         if ((image_info != (const ImageInfo *) NULL) &&
2199             (image != (const Image *) NULL))
2200           value=GetMagickProperty(image_info,image,pattern);
2201         else
2202           if (image != (Image *) NULL)
2203             value=GetImageProperty(image,pattern);
2204           else
2205             if (image_info != (ImageInfo *) NULL)
2206               value=GetImageOption(image_info,pattern);
2207         if (value == (const char *) NULL)
2208           break;
2209         q--;
2210         c=(*q);
2211         *q='\0';
2212         (void) CopyMagickString(filename+(p-format),value,(size_t)
2213           (MaxTextExtent-(p-format)));
2214         *q=c;
2215         (void) ConcatenateMagickString(filename,r+1,MaxTextExtent);
2216         canonical=MagickTrue;
2217         if (*(q-1) != '%')
2218           break;
2219         p++;
2220         break;
2221       }
2222       default:
2223         break;
2224     }
2225   }
2226   for (q=filename; *q != '\0'; q++)
2227     if ((*q == '%') && (*(q+1) == '%'))
2228       (void) CopyMagickString(q,q+1,(size_t) (MaxTextExtent-(q-filename)));
2229   if (canonical == MagickFalse)
2230     (void) CopyMagickString(filename,format,MaxTextExtent);
2231   return(strlen(filename));
2232 }
2233 \f
2234 /*
2235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2236 %                                                                             %
2237 %                                                                             %
2238 %                                                                             %
2239 %   I s H i g h D y n a m i c R a n g e I m a g e                             %
2240 %                                                                             %
2241 %                                                                             %
2242 %                                                                             %
2243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2244 %
2245 %  IsHighDynamicRangeImage() returns MagickTrue if any pixel component is
2246 %  non-integer or exceeds the bounds of the quantum depth (e.g. for Q16
2247 %  0..65535.
2248 %
2249 %  The format of the IsHighDynamicRangeImage method is:
2250 %
2251 %      MagickBooleanType IsHighDynamicRangeImage(const Image *image,
2252 %        ExceptionInfo *exception)
2253 %
2254 %  A description of each parameter follows:
2255 %
2256 %    o image: the image.
2257 %
2258 %    o exception: return any errors or warnings in this structure.
2259 %
2260 */
2261 MagickExport MagickBooleanType IsHighDynamicRangeImage(const Image *image,
2262   ExceptionInfo *exception)
2263 {
2264 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2265   (void) image;
2266   (void) exception;
2267   return(MagickFalse);
2268 #else
2269   CacheView
2270     *image_view;
2271
2272   long
2273     y;
2274
2275   MagickBooleanType
2276     status;
2277
2278   MagickPixelPacket
2279     zero;
2280
2281   assert(image != (Image *) NULL);
2282   assert(image->signature == MagickSignature);
2283   if (image->debug != MagickFalse)
2284     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2285   status=MagickTrue;
2286   GetMagickPixelPacket(image,&zero);
2287   image_view=AcquireCacheView(image);
2288 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2289   #pragma omp parallel for schedule(dynamic,4) shared(status)
2290 #endif
2291   for (y=0; y < (long) image->rows; y++)
2292   {
2293     MagickPixelPacket
2294       pixel;
2295
2296     register const IndexPacket
2297       *indexes;
2298
2299     register const PixelPacket
2300       *p;
2301
2302     register long
2303       x;
2304
2305     if (status == MagickFalse)
2306       continue;
2307     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
2308     if (p == (const PixelPacket *) NULL)
2309       {
2310         status=MagickFalse;
2311         continue;
2312       }
2313     indexes=GetCacheViewVirtualIndexQueue(image_view);
2314     pixel=zero;
2315     for (x=0; x < (long) image->columns; x++)
2316     {
2317       SetMagickPixelPacket(image,p,indexes+x,&pixel);
2318       if ((pixel.red < 0.0) || (pixel.red > QuantumRange) ||
2319           (pixel.red != (QuantumAny) pixel.red))
2320         break;
2321       if ((pixel.green < 0.0) || (pixel.green > QuantumRange) ||
2322           (pixel.green != (QuantumAny) pixel.green))
2323         break;
2324       if ((pixel.blue < 0.0) || (pixel.blue > QuantumRange) ||
2325           (pixel.blue != (QuantumAny) pixel.blue))
2326         break;
2327       if (pixel.matte != MagickFalse)
2328         {
2329           if ((pixel.opacity < 0.0) || (pixel.opacity > QuantumRange) ||
2330               (pixel.opacity != (QuantumAny) pixel.opacity))
2331             break;
2332         }
2333       if (pixel.colorspace == CMYKColorspace)
2334         {
2335           if ((pixel.index < 0.0) || (pixel.index > QuantumRange) ||
2336               (pixel.index != (QuantumAny) pixel.index))
2337             break;
2338         }
2339       p++;
2340     }
2341     if (x < (long) image->columns)
2342       status=MagickFalse;
2343   }
2344   image_view=DestroyCacheView(image_view);
2345   return(status != MagickFalse ? MagickFalse : MagickTrue);
2346 #endif
2347 }
2348 \f
2349 /*
2350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2351 %                                                                             %
2352 %                                                                             %
2353 %                                                                             %
2354 %     I s I m a g e O b j e c t                                               %
2355 %                                                                             %
2356 %                                                                             %
2357 %                                                                             %
2358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2359 %
2360 %  IsImageObject() returns MagickTrue if the image sequence contains a valid
2361 %  set of image objects.
2362 %
2363 %  The format of the IsImageObject method is:
2364 %
2365 %      MagickBooleanType IsImageObject(const Image *image)
2366 %
2367 %  A description of each parameter follows:
2368 %
2369 %    o image: the image.
2370 %
2371 */
2372 MagickExport MagickBooleanType IsImageObject(const Image *image)
2373 {
2374   register const Image
2375     *p;
2376
2377   assert(image != (Image *) NULL);
2378   if (image->debug != MagickFalse)
2379     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2380   for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
2381     if (p->signature != MagickSignature)
2382       return(MagickFalse);
2383   return(MagickTrue);
2384 }
2385 \f
2386 /*
2387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2388 %                                                                             %
2389 %                                                                             %
2390 %                                                                             %
2391 %     I s T a i n t I m a g e                                                 %
2392 %                                                                             %
2393 %                                                                             %
2394 %                                                                             %
2395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2396 %
2397 %  IsTaintImage() returns MagickTrue any pixel in the image has been altered
2398 %  since it was first constituted.
2399 %
2400 %  The format of the IsTaintImage method is:
2401 %
2402 %      MagickBooleanType IsTaintImage(const Image *image)
2403 %
2404 %  A description of each parameter follows:
2405 %
2406 %    o image: the image.
2407 %
2408 */
2409 MagickExport MagickBooleanType IsTaintImage(const Image *image)
2410 {
2411   char
2412     magick[MaxTextExtent],
2413     filename[MaxTextExtent];
2414
2415   register const Image
2416     *p;
2417
2418   assert(image != (Image *) NULL);
2419   if (image->debug != MagickFalse)
2420     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2421   assert(image->signature == MagickSignature);
2422   (void) CopyMagickString(magick,image->magick,MaxTextExtent);
2423   (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2424   for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
2425   {
2426     if (p->taint != MagickFalse)
2427       return(MagickTrue);
2428     if (LocaleCompare(p->magick,magick) != 0)
2429       return(MagickTrue);
2430     if (LocaleCompare(p->filename,filename) != 0)
2431       return(MagickTrue);
2432   }
2433   return(MagickFalse);
2434 }
2435 \f
2436 /*
2437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2438 %                                                                             %
2439 %                                                                             %
2440 %                                                                             %
2441 %   M o d i f y I m a g e                                                     %
2442 %                                                                             %
2443 %                                                                             %
2444 %                                                                             %
2445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2446 %
2447 %  ModifyImage() ensures that there is only a single reference to the image
2448 %  to be modified, updating the provided image pointer to point to a clone of
2449 %  the original image if necessary.
2450 %
2451 %  The format of the ModifyImage method is:
2452 %
2453 %      MagickBooleanType ModifyImage(Image *image,ExceptionInfo *exception)
2454 %
2455 %  A description of each parameter follows:
2456 %
2457 %    o image: the image.
2458 %
2459 %    o exception: return any errors or warnings in this structure.
2460 %
2461 */
2462 MagickExport MagickBooleanType ModifyImage(Image **image,
2463   ExceptionInfo *exception)
2464 {
2465   Image
2466     *clone_image;
2467
2468   assert(image != (Image **) NULL);
2469   assert(*image != (Image *) NULL);
2470   assert((*image)->signature == MagickSignature);
2471   if ((*image)->debug != MagickFalse)
2472     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
2473   if (GetImageReferenceCount(*image) <= 1)
2474     return(MagickTrue);
2475   clone_image=CloneImage(*image,0,0,MagickTrue,exception);
2476   AcquireSemaphoreInfo(&(*image)->semaphore);
2477   (*image)->reference_count--;
2478   RelinquishSemaphoreInfo((*image)->semaphore);
2479   *image=clone_image;
2480   return(MagickTrue);
2481 }
2482 \f
2483 /*
2484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2485 %                                                                             %
2486 %                                                                             %
2487 %                                                                             %
2488 %   N e w M a g i c k I m a g e                                               %
2489 %                                                                             %
2490 %                                                                             %
2491 %                                                                             %
2492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2493 %
2494 %  NewMagickImage() creates a blank image canvas of the specified size and
2495 %  background color.
2496 %
2497 %  The format of the NewMagickImage method is:
2498 %
2499 %      Image *NewMagickImage(const ImageInfo *image_info,
2500 %        const unsigned long width,const unsigned long height,
2501 %        const MagickPixelPacket *background)
2502 %
2503 %  A description of each parameter follows:
2504 %
2505 %    o image: the image.
2506 %
2507 %    o width: the image width.
2508 %
2509 %    o height: the image height.
2510 %
2511 %    o background: the image color.
2512 %
2513 */
2514 MagickExport Image *NewMagickImage(const ImageInfo *image_info,
2515   const unsigned long width,const unsigned long height,
2516   const MagickPixelPacket *background)
2517 {
2518   CacheView
2519     *image_view;
2520
2521   ExceptionInfo
2522     *exception;
2523
2524   Image
2525     *image;
2526
2527   long
2528     y;
2529
2530   MagickBooleanType
2531     status;
2532
2533   assert(image_info != (const ImageInfo *) NULL);
2534   if (image_info->debug != MagickFalse)
2535     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2536   assert(image_info->signature == MagickSignature);
2537   assert(background != (const MagickPixelPacket *) NULL);
2538   image=AcquireImage(image_info);
2539   image->columns=width;
2540   image->rows=height;
2541   image->colorspace=background->colorspace;
2542   image->matte=background->matte;
2543   image->fuzz=background->fuzz;
2544   image->depth=background->depth;
2545   status=MagickTrue;
2546   exception=(&image->exception);
2547   image_view=AcquireCacheView(image);
2548   for (y=0; y < (long) image->rows; y++)
2549   {
2550     register IndexPacket
2551       *__restrict indexes;
2552
2553     register long
2554       x;
2555
2556     register PixelPacket
2557       *__restrict q;
2558
2559     q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2560     if (q == (PixelPacket *) NULL)
2561       {
2562         status=MagickFalse;
2563         continue;
2564       }
2565     indexes=GetCacheViewAuthenticIndexQueue(image_view);
2566     for (x=0; x < (long) image->columns; x++)
2567     {
2568       SetPixelPacket(image,background,q,indexes+x);
2569       q++;
2570     }
2571     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2572       status=MagickFalse;
2573     if (status == MagickFalse)
2574       break;
2575   }
2576   image_view=DestroyCacheView(image_view);
2577   if (status == MagickFalse)
2578     image=DestroyImage(image);
2579   return(image);
2580 }
2581 \f
2582 /*
2583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2584 %                                                                             %
2585 %                                                                             %
2586 %                                                                             %
2587 %   R e f e r e n c e I m a g e                                               %
2588 %                                                                             %
2589 %                                                                             %
2590 %                                                                             %
2591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2592 %
2593 %  ReferenceImage() increments the reference count associated with an image
2594 %  returning a pointer to the image.
2595 %
2596 %  The format of the ReferenceImage method is:
2597 %
2598 %      Image *ReferenceImage(Image *image)
2599 %
2600 %  A description of each parameter follows:
2601 %
2602 %    o image: the image.
2603 %
2604 */
2605 MagickExport Image *ReferenceImage(Image *image)
2606 {
2607   assert(image != (Image *) NULL);
2608   if (image->debug != MagickFalse)
2609     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2610   assert(image->signature == MagickSignature);
2611   (void) LockSemaphoreInfo(image->semaphore);
2612   image->reference_count++;
2613   (void) UnlockSemaphoreInfo(image->semaphore);
2614   return(image);
2615 }
2616 \f
2617 /*
2618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2619 %                                                                             %
2620 %                                                                             %
2621 %                                                                             %
2622 %   R e s e t I m a g e P a g e                                               %
2623 %                                                                             %
2624 %                                                                             %
2625 %                                                                             %
2626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2627 %
2628 %  ResetImagePage() resets the image page canvas and position.
2629 %
2630 %  The format of the ResetImagePage method is:
2631 %
2632 %      MagickBooleanType ResetImagePage(Image *image,const char *page)
2633 %
2634 %  A description of each parameter follows:
2635 %
2636 %    o image: the image.
2637 %
2638 %    o page: the relative page specification.
2639 %
2640 */
2641 MagickExport MagickBooleanType ResetImagePage(Image *image,const char *page)
2642 {
2643   MagickStatusType
2644     flags;
2645
2646   RectangleInfo
2647     geometry;
2648
2649   assert(image != (Image *) NULL);
2650   assert(image->signature == MagickSignature);
2651   if (image->debug != MagickFalse)
2652     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2653   flags=ParseAbsoluteGeometry(page,&geometry);
2654   if ((flags & WidthValue) != 0)
2655     {
2656       if ((flags & HeightValue) == 0)
2657         geometry.height=geometry.width;
2658       image->page.width=geometry.width;
2659       image->page.height=geometry.height;
2660     }
2661   if ((flags & AspectValue) != 0)
2662     {
2663       if ((flags & XValue) != 0)
2664         image->page.x+=geometry.x;
2665       if ((flags & YValue) != 0)
2666         image->page.y+=geometry.y;
2667     }
2668   else
2669     {
2670       if ((flags & XValue) != 0)
2671         {
2672           image->page.x=geometry.x;
2673           if ((image->page.width == 0) && (geometry.x > 0))
2674             image->page.width=image->columns+geometry.x;
2675         }
2676       if ((flags & YValue) != 0)
2677         {
2678           image->page.y=geometry.y;
2679           if ((image->page.height == 0) && (geometry.y > 0))
2680             image->page.height=image->rows+geometry.y;
2681         }
2682     }
2683   return(MagickTrue);
2684 }
2685 \f
2686 /*
2687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2688 %                                                                             %
2689 %                                                                             %
2690 %                                                                             %
2691 %     S e p a r a t e I m a g e C h a n n e l                                 %
2692 %                                                                             %
2693 %                                                                             %
2694 %                                                                             %
2695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2696 %
2697 %  SeparateImageChannel() separates a channel from the image and returns it as
2698 %  a grayscale image.  A channel is a particular color component of each pixel
2699 %  in the image.
2700 %
2701 %  The format of the SeparateImageChannel method is:
2702 %
2703 %      MagickBooleanType SeparateImageChannel(Image *image,
2704 %        const ChannelType channel)
2705 %
2706 %  A description of each parameter follows:
2707 %
2708 %    o image: the image.
2709 %
2710 %    o channel: Identify which channel to extract: RedChannel, GreenChannel,
2711 %      BlueChannel, OpacityChannel, CyanChannel, MagentaChannel,
2712 %      YellowChannel, or BlackChannel.
2713 %
2714 */
2715 MagickExport MagickBooleanType SeparateImageChannel(Image *image,
2716   const ChannelType channel)
2717 {
2718 #define SeparateImageTag  "Separate/Image"
2719
2720   CacheView
2721     *image_view;
2722
2723   ExceptionInfo
2724     *exception;
2725
2726   long
2727     progress,
2728     y;
2729
2730   MagickBooleanType
2731     status;
2732
2733   assert(image != (Image *) NULL);
2734   assert(image->signature == MagickSignature);
2735   if (image->debug != MagickFalse)
2736     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2737   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2738     return(MagickFalse);
2739   /*
2740     Separate image channels.
2741   */
2742   status=MagickTrue;
2743   if ( channel == GrayChannels )
2744     image->matte=MagickTrue;
2745   progress=0;
2746   exception=(&image->exception);
2747   image_view=AcquireCacheView(image);
2748 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2749   #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
2750 #endif
2751   for (y=0; y < (long) image->rows; y++)
2752   {
2753     register IndexPacket
2754       *__restrict indexes;
2755
2756     register long
2757       x;
2758
2759     register PixelPacket
2760       *__restrict q;
2761
2762     if (status == MagickFalse)
2763       continue;
2764     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2765     if (q == (PixelPacket *) NULL)
2766       {
2767         status=MagickFalse;
2768         continue;
2769       }
2770     indexes=GetCacheViewAuthenticIndexQueue(image_view);
2771     switch (channel)
2772     {
2773       case RedChannel:
2774       {
2775         for (x=0; x < (long) image->columns; x++)
2776         {
2777           q->green=q->red;
2778           q->blue=q->red;
2779           q++;
2780         }
2781         break;
2782       }
2783       case GreenChannel:
2784       {
2785         for (x=0; x < (long) image->columns; x++)
2786         {
2787           q->red=q->green;
2788           q->blue=q->green;
2789           q++;
2790         }
2791         break;
2792       }
2793       case BlueChannel:
2794       {
2795         for (x=0; x < (long) image->columns; x++)
2796         {
2797           q->red=q->blue;
2798           q->green=q->blue;
2799           q++;
2800         }
2801         break;
2802       }
2803       case OpacityChannel:
2804       {
2805         for (x=0; x < (long) image->columns; x++)
2806         {
2807           q->red=q->opacity;
2808           q->green=q->opacity;
2809           q->blue=q->opacity;
2810           q++;
2811         }
2812         break;
2813       }
2814       case BlackChannel:
2815       {
2816         if ((image->storage_class != PseudoClass) &&
2817             (image->colorspace != CMYKColorspace))
2818           break;
2819         for (x=0; x < (long) image->columns; x++)
2820         {
2821           q->red=indexes[x];
2822           q->green=indexes[x];
2823           q->blue=indexes[x];
2824           q++;
2825         }
2826         break;
2827       }
2828       case TrueAlphaChannel:
2829       {
2830         for (x=0; x < (long) image->columns; x++)
2831         {
2832           q->red=(Quantum) (QuantumRange-q->opacity);
2833           q->green=(Quantum) (QuantumRange-q->opacity);
2834           q->blue=(Quantum) (QuantumRange-q->opacity);
2835           q++;
2836         }
2837         break;
2838       }
2839       case GrayChannels:
2840       {
2841         for (x=0; x < (long) image->columns; x++)
2842         {
2843           q->opacity=(Quantum) (QuantumRange-PixelIntensityToQuantum(q));
2844           q++;
2845         }
2846         break;
2847       }
2848       default:
2849         break;
2850     }
2851     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2852       status=MagickFalse;
2853     if (image->progress_monitor != (MagickProgressMonitor) NULL)
2854       {
2855         MagickBooleanType
2856           proceed;
2857
2858 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2859         #pragma omp critical (MagickCore_SeparateImageChannel)
2860 #endif
2861         proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows);
2862         if (proceed == MagickFalse)
2863           status=MagickFalse;
2864       }
2865   }
2866   image_view=DestroyCacheView(image_view);
2867   if ( channel != GrayChannels )
2868     image->matte=MagickFalse;
2869   (void) SetImageColorspace(image,RGBColorspace);
2870   return(status);
2871 }
2872 \f
2873 /*
2874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2875 %                                                                             %
2876 %                                                                             %
2877 %                                                                             %
2878 %     S e p a r a t e I m a g e s                                             %
2879 %                                                                             %
2880 %                                                                             %
2881 %                                                                             %
2882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2883 %
2884 %  SeparateImages() returns a separate grayscale image for each channel
2885 %  specified.
2886 %
2887 %  The format of the SeparateImages method is:
2888 %
2889 %      MagickBooleanType SeparateImages(const Image *image,
2890 %        const ChannelType channel,ExceptionInfo *exception)
2891 %
2892 %  A description of each parameter follows:
2893 %
2894 %    o image: the image.
2895 %
2896 %    o channel: Identify which channels to extract: RedChannel, GreenChannel,
2897 %      BlueChannel, OpacityChannel, CyanChannel, MagentaChannel,
2898 %      YellowChannel, or BlackChannel.
2899 %
2900 %    o exception: return any errors or warnings in this structure.
2901 %
2902 */
2903 MagickExport Image *SeparateImages(const Image *image,const ChannelType channel,
2904   ExceptionInfo *exception)
2905 {
2906   Image
2907     *images,
2908     *separate_image;
2909
2910   assert(image != (Image *) NULL);
2911   assert(image->signature == MagickSignature);
2912   if (image->debug != MagickFalse)
2913     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2914   images=NewImageList();
2915   if ((channel & RedChannel) != 0)
2916     {
2917       separate_image=CloneImage(image,0,0,MagickTrue,exception);
2918       (void) SeparateImageChannel(separate_image,RedChannel);
2919       AppendImageToList(&images,separate_image);
2920     }
2921   if ((channel & GreenChannel) != 0)
2922     {
2923       separate_image=CloneImage(image,0,0,MagickTrue,exception);
2924       (void) SeparateImageChannel(separate_image,GreenChannel);
2925       AppendImageToList(&images,separate_image);
2926     }
2927   if ((channel & BlueChannel) != 0)
2928     {
2929       separate_image=CloneImage(image,0,0,MagickTrue,exception);
2930       (void) SeparateImageChannel(separate_image,BlueChannel);
2931       AppendImageToList(&images,separate_image);
2932     }
2933   if (((channel & BlackChannel) != 0) && (image->colorspace == CMYKColorspace))
2934     {
2935       separate_image=CloneImage(image,0,0,MagickTrue,exception);
2936       (void) SeparateImageChannel(separate_image,BlackChannel);
2937       AppendImageToList(&images,separate_image);
2938     }
2939   if ((channel & OpacityChannel) != 0)
2940     {
2941       separate_image=CloneImage(image,0,0,MagickTrue,exception);
2942       (void) SeparateImageChannel(separate_image,OpacityChannel);
2943       AppendImageToList(&images,separate_image);
2944     }
2945   return(images);
2946 }
2947 \f
2948 /*
2949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2950 %                                                                             %
2951 %                                                                             %
2952 %                                                                             %
2953 %   S e t I m a g e A l p h a C h a n n e l                                   %
2954 %                                                                             %
2955 %                                                                             %
2956 %                                                                             %
2957 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2958 %
2959 %  SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha
2960 %  channel.
2961 %
2962 %  The format of the SetImageAlphaChannel method is:
2963 %
2964 %      MagickBooleanType SetImageAlphaChannel(Image *image,
2965 %        const AlphaChannelType alpha_type)
2966 %
2967 %  A description of each parameter follows:
2968 %
2969 %    o image: the image.
2970 %
2971 %    o alpha_type:  The alpha channel type: ActivateAlphaChannel,
2972 %      CopyAlphaChannel, DeactivateAlphaChannel, ExtractAlphaChannel,
2973 %      OpaqueAlphaChannel, ResetAlphaChannel, SetAlphaChannel,
2974 %      ShapeAlphaChannel, and TransparentAlphaChannel.
2975 %
2976 */
2977 MagickExport MagickBooleanType SetImageAlphaChannel(Image *image,
2978   const AlphaChannelType alpha_type)
2979 {
2980   MagickBooleanType
2981     status;
2982
2983   assert(image != (Image *) NULL);
2984   if (image->debug != MagickFalse)
2985     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2986   assert(image->signature == MagickSignature);
2987   status=MagickFalse;
2988   switch (alpha_type)
2989   {
2990     case ActivateAlphaChannel:
2991     {
2992       image->matte=MagickTrue;
2993       break;
2994     }
2995     case BackgroundAlphaChannel:
2996     {
2997       CacheView
2998         *image_view;
2999
3000       ExceptionInfo
3001         *exception;
3002
3003       IndexPacket
3004         index;
3005
3006       long
3007         y;
3008
3009       MagickBooleanType
3010         status;
3011
3012       MagickPixelPacket
3013         background;
3014
3015       PixelPacket
3016         pixel;
3017
3018       /*
3019         Set transparent pixels to background color.
3020       */
3021       if (image->matte == MagickFalse)
3022         break;
3023       if (SetImageStorageClass(image,DirectClass) == MagickFalse)
3024         break;
3025       GetMagickPixelPacket(image,&background);
3026       SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *)
3027         NULL,&background);
3028       if (image->colorspace == CMYKColorspace)
3029         ConvertRGBToCMYK(&background);
3030       index=0;
3031       SetPixelPacket(image,&background,&pixel,&index);
3032       status=MagickTrue;
3033       exception=(&image->exception);
3034       image_view=AcquireCacheView(image);
3035       #if defined(MAGICKCORE_OPENMP_SUPPORT)
3036         #pragma omp parallel for schedule(dynamic,4) shared(status)
3037       #endif
3038       for (y=0; y < (long) image->rows; y++)
3039       {
3040         register IndexPacket
3041           *__restrict indexes;
3042
3043         register long
3044           x;
3045
3046         register PixelPacket
3047           *__restrict q;
3048
3049         if (status == MagickFalse)
3050           continue;
3051         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3052           exception);
3053         if (q == (PixelPacket *) NULL)
3054           {
3055             status=MagickFalse;
3056             continue;
3057           }
3058         for (x=0; x < (long) image->columns; x++)
3059         {
3060           if (q->opacity == TransparentOpacity)
3061             {
3062               q->red=pixel.red;
3063               q->green=pixel.green;
3064               q->blue=pixel.blue;
3065             }
3066           q++;
3067         }
3068         if (image->colorspace == CMYKColorspace)
3069           {
3070             indexes=GetCacheViewAuthenticIndexQueue(image_view);
3071             for (x=0; x < (long) image->columns; x++)
3072               indexes[x]=index;
3073           }
3074         if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3075           status=MagickFalse;
3076       }
3077       image_view=DestroyCacheView(image_view);
3078       return(status);
3079     }
3080     case DeactivateAlphaChannel:
3081     {
3082       image->matte=MagickFalse;
3083       break;
3084     }
3085     case ShapeAlphaChannel:
3086     case CopyAlphaChannel:
3087     {
3088       /*
3089         Special usage case for SeparateImageChannel(): copy grayscale color to
3090         the alpha channel.
3091       */
3092       status=SeparateImageChannel(image,GrayChannels);
3093       image->matte=MagickTrue; /* make sure transparency is now on! */
3094       if (alpha_type == ShapeAlphaChannel)
3095         {
3096           MagickPixelPacket
3097             background;
3098
3099           /*
3100             Reset all color channels to background color.
3101           */
3102           GetMagickPixelPacket(image,&background);
3103           SetMagickPixelPacket(image,&(image->background_color),(IndexPacket *)
3104             NULL,&background);
3105           (void) LevelImageColors(image,DefaultChannels,&background,&background,
3106             MagickTrue);
3107         }
3108       break;
3109     }
3110     case ExtractAlphaChannel:
3111     {
3112       status=SeparateImageChannel(image,TrueAlphaChannel);
3113       image->matte=MagickFalse;
3114       break;
3115     }
3116     case ResetAlphaChannel:
3117     case OpaqueAlphaChannel:
3118     {
3119       status=SetImageOpacity(image,OpaqueOpacity);
3120       image->matte=MagickTrue;
3121       break;
3122     }
3123     case TransparentAlphaChannel:
3124     {
3125       status=SetImageOpacity(image,TransparentOpacity);
3126       image->matte=MagickTrue;
3127       break;
3128     }
3129     case SetAlphaChannel:
3130     {
3131       if (image->matte == MagickFalse)
3132         {
3133           status=SetImageOpacity(image,OpaqueOpacity);
3134           image->matte=MagickTrue;
3135         }
3136       break;
3137     }
3138     case UndefinedAlphaChannel:
3139       break;
3140   }
3141   return(status);
3142 }
3143 \f
3144 /*
3145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3146 %                                                                             %
3147 %                                                                             %
3148 %                                                                             %
3149 %   S e t I m a g e B a c k g r o u n d C o l o r                             %
3150 %                                                                             %
3151 %                                                                             %
3152 %                                                                             %
3153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3154 %
3155 %  SetImageBackgroundColor() initializes the image pixels to the image
3156 %  background color.  The background color is defined by the background_color
3157 %  member of the image structure.
3158 %
3159 %  The format of the SetImage method is:
3160 %
3161 %      MagickBooleanType SetImageBackgroundColor(Image *image)
3162 %
3163 %  A description of each parameter follows:
3164 %
3165 %    o image: the image.
3166 %
3167 */
3168 MagickExport MagickBooleanType SetImageBackgroundColor(Image *image)
3169 {
3170   CacheView
3171     *image_view;
3172
3173   ExceptionInfo
3174     *exception;
3175
3176   IndexPacket
3177     index;
3178
3179   long
3180     y;
3181
3182   MagickBooleanType
3183     status;
3184
3185   MagickPixelPacket
3186     background;
3187
3188   PixelPacket
3189     pixel;
3190
3191   assert(image != (Image *) NULL);
3192   if (image->debug != MagickFalse)
3193     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3194   assert(image->signature == MagickSignature);
3195   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
3196     return(MagickFalse);
3197   if (image->background_color.opacity != OpaqueOpacity)
3198     image->matte=MagickTrue;
3199   GetMagickPixelPacket(image,&background);
3200   SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *)
3201     NULL,&background);
3202   if (image->colorspace == CMYKColorspace)
3203     ConvertRGBToCMYK(&background);
3204   index=0;
3205   SetPixelPacket(image,&background,&pixel,&index);
3206   /*
3207     Set image background color.
3208   */
3209   status=MagickTrue;
3210   exception=(&image->exception);
3211   image_view=AcquireCacheView(image);
3212 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3213   #pragma omp parallel for schedule(dynamic,4) shared(status)
3214 #endif
3215   for (y=0; y < (long) image->rows; y++)
3216   {
3217     register IndexPacket
3218       *__restrict indexes;
3219
3220     register long
3221       x;
3222
3223     register PixelPacket
3224       *__restrict q;
3225
3226     if (status == MagickFalse)
3227       continue;
3228     q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3229     if (q == (PixelPacket *) NULL)
3230       {
3231         status=MagickFalse;
3232         continue;
3233       }
3234     for (x=0; x < (long) image->columns; x++)
3235       *q++=pixel;
3236     if (image->colorspace == CMYKColorspace)
3237       {
3238         indexes=GetCacheViewAuthenticIndexQueue(image_view);
3239         for (x=0; x < (long) image->columns; x++)
3240           indexes[x]=index;
3241       }
3242     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3243       status=MagickFalse;
3244   }
3245   image_view=DestroyCacheView(image_view);
3246   return(status);
3247 }
3248 \f
3249 /*
3250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3251 %                                                                             %
3252 %                                                                             %
3253 %                                                                             %
3254 %   S e t I m a g e S t o r a g e C l a s s                                   %
3255 %                                                                             %
3256 %                                                                             %
3257 %                                                                             %
3258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3259 %
3260 %  SetImageStorageClass() sets the image class: DirectClass for true color
3261 %  images or PseudoClass for colormapped images.
3262 %
3263 %  The format of the SetImageStorageClass method is:
3264 %
3265 %      MagickBooleanType SetImageStorageClass(Image *image,
3266 %        const ClassType storage_class)
3267 %
3268 %  A description of each parameter follows:
3269 %
3270 %    o image: the image.
3271 %
3272 %    o storage_class:  The image class.
3273 %
3274 */
3275 MagickExport MagickBooleanType SetImageStorageClass(Image *image,
3276   const ClassType storage_class)
3277 {
3278   Cache
3279     cache;
3280
3281   if (image->storage_class == storage_class)
3282     return(MagickTrue);
3283   image->storage_class=storage_class;
3284   cache=GetImagePixelCache(image,MagickTrue,&image->exception);
3285   return(cache == (Cache) NULL ? MagickFalse : MagickTrue);
3286 }
3287 \f
3288 /*
3289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3290 %                                                                             %
3291 %                                                                             %
3292 %                                                                             %
3293 %   S e t I m a g e C l i p M a s k                                           %
3294 %                                                                             %
3295 %                                                                             %
3296 %                                                                             %
3297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3298 %
3299 %  SetImageClipMask() associates a clip path with the image.  The clip path
3300 %  must be the same dimensions as the image.  Set any pixel component of
3301 %  the clip path to TransparentOpacity to prevent that corresponding image
3302 %  pixel component from being updated when SyncAuthenticPixels() is applied.
3303 %
3304 %  The format of the SetImageClipMask method is:
3305 %
3306 %      MagickBooleanType SetImageClipMask(Image *image,const Image *clip_mask)
3307 %
3308 %  A description of each parameter follows:
3309 %
3310 %    o image: the image.
3311 %
3312 %    o clip_mask: the image clip path.
3313 %
3314 */
3315 MagickExport MagickBooleanType SetImageClipMask(Image *image,
3316   const Image *clip_mask)
3317 {
3318   assert(image != (Image *) NULL);
3319   if (image->debug != MagickFalse)
3320     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3321   assert(image->signature == MagickSignature);
3322   if (clip_mask != (const Image *) NULL)
3323     if ((clip_mask->columns != image->columns) ||
3324         (clip_mask->rows != image->rows))
3325       ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename);
3326   if (image->clip_mask != (Image *) NULL)
3327     image->clip_mask=DestroyImage(image->clip_mask);
3328   image->clip_mask=NewImageList();
3329   if (clip_mask == (Image *) NULL)
3330     return(MagickTrue);
3331   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
3332     return(MagickFalse);
3333   image->clip_mask=CloneImage(clip_mask,0,0,MagickTrue,&image->exception);
3334   if (image->clip_mask == (Image *) NULL)
3335     return(MagickFalse);
3336   return(MagickTrue);
3337 }
3338 \f
3339 /*
3340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3341 %                                                                             %
3342 %                                                                             %
3343 %                                                                             %
3344 %   S e t I m a g e E x t e n t                                               %
3345 %                                                                             %
3346 %                                                                             %
3347 %                                                                             %
3348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3349 %
3350 %  SetImageExtent() sets the image size (i.e. columns & rows).
3351 %
3352 %  The format of the SetImageExtent method is:
3353 %
3354 %      MagickBooleanType SetImageExtent(Image *image,
3355 %        const unsigned long columns,const unsigned long rows)
3356 %
3357 %  A description of each parameter follows:
3358 %
3359 %    o image: the image.
3360 %
3361 %    o columns:  The image width in pixels.
3362 %
3363 %    o rows:  The image height in pixels.
3364 %
3365 */
3366 MagickExport MagickBooleanType SetImageExtent(Image *image,
3367   const unsigned long columns,const unsigned long rows)
3368 {
3369   Cache
3370     cache;
3371
3372   if ((columns != 0) && (rows != 0))
3373     {
3374       image->columns=columns;
3375       image->rows=rows;
3376     }
3377   cache=GetImagePixelCache(image,MagickTrue,&image->exception);
3378   return(cache == (Cache) NULL ? MagickFalse : MagickTrue);
3379 }
3380 \f
3381 /*
3382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3383 %                                                                             %
3384 %                                                                             %
3385 %                                                                             %
3386 +   S e t I m a g e I n f o                                                   %
3387 %                                                                             %
3388 %                                                                             %
3389 %                                                                             %
3390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3391 %
3392 %  SetImageInfo() initializes the `magick' field of the ImageInfo structure.
3393 %  It is set to a type of image format based on the prefix or suffix of the
3394 %  filename.  For example, `ps:image' returns PS indicating a Postscript image.
3395 %  JPEG is returned for this filename: `image.jpg'.  The filename prefix has
3396 %  precendence over the suffix.  Use an optional index enclosed in brackets
3397 %  after a file name to specify a desired scene of a multi-resolution image
3398 %  format like Photo CD (e.g. img0001.pcd[4]).  A True (non-zero) return value
3399 %  indicates success.
3400 %
3401 %  The format of the SetImageInfo method is:
3402 %
3403 %      MagickBooleanType SetImageInfo(ImageInfo *image_info,
3404 %        const MagickBooleanType rectify,ExceptionInfo *exception)
3405 %
3406 %  A description of each parameter follows:
3407 %
3408 %    o image_info: the image info..
3409 %
3410 %    o rectify: an unsigned value other than zero rectifies the attribute for
3411 %      multi-frame support (user may want multi-frame but image format may not
3412 %      support it).
3413 %
3414 %    o exception: return any errors or warnings in this structure.
3415 %
3416 */
3417 MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info,
3418   const MagickBooleanType rectify,ExceptionInfo *exception)
3419 {
3420   char
3421     extension[MaxTextExtent],
3422     filename[MaxTextExtent],
3423     magic[MaxTextExtent],
3424     *q,
3425     subimage[MaxTextExtent];
3426
3427   const MagicInfo
3428     *magic_info;
3429
3430   const MagickInfo
3431     *magick_info;
3432
3433   ExceptionInfo
3434     *sans_exception;
3435
3436   Image
3437     *image;
3438
3439   MagickBooleanType
3440     status;
3441
3442   register const char
3443     *p;
3444
3445   ssize_t
3446     count;
3447
3448   unsigned char
3449     magick[2*MaxTextExtent];
3450
3451   /*
3452     Look for 'image.format' in filename.
3453   */
3454   assert(image_info != (ImageInfo *) NULL);
3455   assert(image_info->signature == MagickSignature);
3456   if (image_info->debug != MagickFalse)
3457     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3458       image_info->filename);
3459   *subimage='\0';
3460   GetPathComponent(image_info->filename,SubimagePath,subimage);
3461   if (*subimage != '\0')
3462     {
3463       /*
3464         Look for scene specification (e.g. img0001.pcd[4]).
3465       */
3466       if (IsSceneGeometry(subimage,MagickFalse) == MagickFalse)
3467         {
3468           if (IsGeometry(subimage) != MagickFalse)
3469             (void) CloneString(&image_info->extract,subimage);
3470         }
3471       else
3472         {
3473           unsigned long
3474             first,
3475             last;
3476
3477           (void) CloneString(&image_info->scenes,subimage);
3478           image_info->scene=(unsigned long) atol(image_info->scenes);
3479           image_info->number_scenes=image_info->scene;
3480           p=image_info->scenes;
3481           for (q=(char *) image_info->scenes; *q != '\0'; p++)
3482           {
3483             while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
3484               p++;
3485             first=(unsigned long) strtol(p,&q,10);
3486             last=first;
3487             while (isspace((int) ((unsigned char) *q)) != 0)
3488               q++;
3489             if (*q == '-')
3490               last=(unsigned long) strtol(q+1,&q,10);
3491             if (first > last)
3492               Swap(first,last);
3493             if (first < image_info->scene)
3494               image_info->scene=first;
3495             if (last > image_info->number_scenes)
3496               image_info->number_scenes=last;
3497             p=q;
3498           }
3499           image_info->number_scenes-=image_info->scene-1;
3500           image_info->subimage=image_info->scene;
3501           image_info->subrange=image_info->number_scenes;
3502         }
3503     }
3504   *extension='\0';
3505   GetPathComponent(image_info->filename,ExtensionPath,extension);
3506 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3507   if (*extension != '\0')
3508     if ((LocaleCompare(extension,"gz") == 0) ||
3509         (LocaleCompare(extension,"Z") == 0) ||
3510         (LocaleCompare(extension,"wmz") == 0))
3511       {
3512         char
3513           path[MaxTextExtent];
3514
3515         (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
3516         path[strlen(path)-strlen(extension)-1]='\0';
3517         GetPathComponent(path,ExtensionPath,extension);
3518       }
3519 #endif
3520 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3521   if (*extension != '\0')
3522     if (LocaleCompare(extension,"bz2") == 0)
3523       {
3524         char
3525           path[MaxTextExtent];
3526
3527         (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
3528         path[strlen(path)-strlen(extension)-1]='\0';
3529         GetPathComponent(path,ExtensionPath,extension);
3530       }
3531 #endif
3532   image_info->affirm=MagickFalse;
3533   sans_exception=AcquireExceptionInfo();
3534   if (*extension != '\0')
3535     {
3536       MagickFormatType
3537         format_type;
3538
3539       register long
3540         i;
3541
3542       static const char
3543         *format_type_formats[] =
3544         {
3545           "AUTOTRACE",
3546           "BROWSE",
3547           "DCRAW",
3548           "EDIT",
3549           "EPHEMERAL",
3550           "LAUNCH",
3551           "MPEG:DECODE",
3552           "MPEG:ENCODE",
3553           "PRINT",
3554           "PS:ALPHA",
3555           "PS:CMYK",
3556           "PS:COLOR",
3557           "PS:GRAY",
3558           "PS:MONO",
3559           "SCAN",
3560           "SHOW",
3561           "WIN",
3562           (char *) NULL
3563         };
3564
3565       /*
3566         User specified image format.
3567       */
3568       (void) CopyMagickString(magic,extension,MaxTextExtent);
3569       LocaleUpper(magic);
3570       /*
3571         Look for explicit image formats.
3572       */
3573       format_type=UndefinedFormatType;
3574       i=0;
3575       while ((format_type != UndefinedFormatType) &&
3576              (format_type_formats[i] != (char *) NULL))
3577       {
3578         if ((*magic == *format_type_formats[i]) &&
3579             (LocaleCompare(magic,format_type_formats[i]) == 0))
3580           format_type=ExplicitFormatType;
3581         i++;
3582       }
3583       magick_info=GetMagickInfo(magic,sans_exception);
3584       if ((magick_info != (const MagickInfo *) NULL) &&
3585           (magick_info->format_type != UndefinedFormatType))
3586         format_type=magick_info->format_type;
3587       if (format_type == UndefinedFormatType)
3588         (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3589       else
3590         if (format_type == ExplicitFormatType)
3591           {
3592             image_info->affirm=MagickTrue;
3593             (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3594           }
3595       if (LocaleCompare(magic,"RGB") == 0)
3596         image_info->affirm=MagickFalse;  /* maybe SGI disguised as RGB */
3597     }
3598   /*
3599     Look for explicit 'format:image' in filename.
3600   */
3601   *magic='\0';
3602   GetPathComponent(image_info->filename,MagickPath,magic);
3603   if (*magic == '\0')
3604     (void) CopyMagickString(magic,image_info->magick,MaxTextExtent);
3605   else
3606     {
3607       /*
3608         User specified image format.
3609       */
3610       LocaleUpper(magic);
3611       if (IsMagickConflict(magic) == MagickFalse)
3612         {
3613           (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3614           if (LocaleCompare(magic,"EPHEMERAL") != 0)
3615             image_info->affirm=MagickTrue;
3616           else
3617             image_info->temporary=MagickTrue;
3618         }
3619     }
3620   magick_info=GetMagickInfo(magic,sans_exception);
3621   sans_exception=DestroyExceptionInfo(sans_exception);
3622   if ((magick_info == (const MagickInfo *) NULL) ||
3623       (GetMagickEndianSupport(magick_info) == MagickFalse))
3624     image_info->endian=UndefinedEndian;
3625   GetPathComponent(image_info->filename,CanonicalPath,filename);
3626   (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
3627   if (rectify != MagickFalse)
3628     {
3629       /*
3630         Rectify multi-image file support.
3631       */
3632       (void) InterpretImageFilename(image_info,(Image *) NULL,
3633         image_info->filename,(int) image_info->scene,filename);
3634       if ((LocaleCompare(filename,image_info->filename) != 0) &&
3635           (strchr(filename,'%') == (char *) NULL))
3636         image_info->adjoin=MagickFalse;
3637       magick_info=GetMagickInfo(magic,exception);
3638       if (magick_info != (const MagickInfo *) NULL)
3639         if (GetMagickAdjoin(magick_info) == MagickFalse)
3640           image_info->adjoin=MagickFalse;
3641       return(MagickTrue);
3642     }
3643   if (image_info->affirm != MagickFalse)
3644     return(MagickTrue);
3645   /*
3646     Determine the image format from the first few bytes of the file.
3647   */
3648   image=AcquireImage(image_info);
3649   (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent);
3650   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3651   if (status == MagickFalse)
3652     {
3653       image=DestroyImage(image);
3654       return(MagickFalse);
3655     }
3656   if ((IsBlobSeekable(image) == MagickFalse) ||
3657       (IsBlobExempt(image) != MagickFalse))
3658     {
3659       /*
3660         Copy standard input or pipe to temporary file.
3661       */
3662       *filename='\0';
3663       status=ImageToFile(image,filename,exception);
3664       (void) CloseBlob(image);
3665       if (status == MagickFalse)
3666         {
3667           image=DestroyImage(image);
3668           return(MagickFalse);
3669         }
3670       SetImageInfoFile(image_info,(FILE *) NULL);
3671       (void) CopyMagickString(image->filename,filename,MaxTextExtent);
3672       status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3673       if (status == MagickFalse)
3674         {
3675           image=DestroyImage(image);
3676           return(MagickFalse);
3677         }
3678       (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
3679       image_info->temporary=MagickTrue;
3680     }
3681   (void) ResetMagickMemory(magick,0,sizeof(magick));
3682   count=ReadBlob(image,2*MaxTextExtent,magick);
3683   (void) CloseBlob(image);
3684   image=DestroyImage(image);
3685   /*
3686     Check magic.xml configuration file.
3687   */
3688   sans_exception=AcquireExceptionInfo();
3689   magic_info=GetMagicInfo(magick,(size_t) count,sans_exception);
3690   if ((magic_info != (const MagicInfo *) NULL) &&
3691       (GetMagicName(magic_info) != (char *) NULL))
3692     {
3693       (void) CopyMagickString(image_info->magick,GetMagicName(magic_info),
3694         MaxTextExtent);
3695       magick_info=GetMagickInfo(image_info->magick,sans_exception);
3696       if ((magick_info == (const MagickInfo *) NULL) ||
3697           (GetMagickEndianSupport(magick_info) == MagickFalse))
3698         image_info->endian=UndefinedEndian;
3699       sans_exception=DestroyExceptionInfo(sans_exception);
3700       return(MagickTrue);
3701     }
3702   magick_info=GetMagickInfo(image_info->magick,sans_exception);
3703   if ((magick_info == (const MagickInfo *) NULL) ||
3704       (GetMagickEndianSupport(magick_info) == MagickFalse))
3705     image_info->endian=UndefinedEndian;
3706   sans_exception=DestroyExceptionInfo(sans_exception);
3707   return(MagickTrue);
3708 }
3709 \f
3710 /*
3711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3712 %                                                                             %
3713 %                                                                             %
3714 %                                                                             %
3715 %   S e t I m a g e I n f o B l o b                                           %
3716 %                                                                             %
3717 %                                                                             %
3718 %                                                                             %
3719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3720 %
3721 %  SetImageInfoBlob() sets the image info blob member.
3722 %
3723 %  The format of the SetImageInfoBlob method is:
3724 %
3725 %      void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3726 %        const size_t length)
3727 %
3728 %  A description of each parameter follows:
3729 %
3730 %    o image_info: the image info.
3731 %
3732 %    o blob: the blob.
3733 %
3734 %    o length: the blob length.
3735 %
3736 */
3737 MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3738   const size_t length)
3739 {
3740   assert(image_info != (ImageInfo *) NULL);
3741   assert(image_info->signature == MagickSignature);
3742   if (image_info->debug != MagickFalse)
3743     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3744       image_info->filename);
3745   image_info->blob=(void *) blob;
3746   image_info->length=length;
3747 }
3748 \f
3749 /*
3750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3751 %                                                                             %
3752 %                                                                             %
3753 %                                                                             %
3754 %   S e t I m a g e I n f o F i l e                                           %
3755 %                                                                             %
3756 %                                                                             %
3757 %                                                                             %
3758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3759 %
3760 %  SetImageInfoFile() sets the image info file member.
3761 %
3762 %  The format of the SetImageInfoFile method is:
3763 %
3764 %      void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3765 %
3766 %  A description of each parameter follows:
3767 %
3768 %    o image_info: the image info.
3769 %
3770 %    o file: the file.
3771 %
3772 */
3773 MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3774 {
3775   assert(image_info != (ImageInfo *) NULL);
3776   assert(image_info->signature == MagickSignature);
3777   if (image_info->debug != MagickFalse)
3778     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3779       image_info->filename);
3780   image_info->file=file;
3781 }
3782 \f
3783 /*
3784 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3785 %                                                                             %
3786 %                                                                             %
3787 %                                                                             %
3788 %   S e t I m a g e M a s k                                                   %
3789 %                                                                             %
3790 %                                                                             %
3791 %                                                                             %
3792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3793 %
3794 %  SetImageMask() associates a mask with the image.  The mask must be the same
3795 %  dimensions as the image.
3796 %
3797 %  The format of the SetImageMask method is:
3798 %
3799 %      MagickBooleanType SetImageMask(Image *image,const Image *mask)
3800 %
3801 %  A description of each parameter follows:
3802 %
3803 %    o image: the image.
3804 %
3805 %    o mask: the image mask.
3806 %
3807 */
3808 MagickExport MagickBooleanType SetImageMask(Image *image,
3809   const Image *mask)
3810 {
3811   assert(image != (Image *) NULL);
3812   if (image->debug != MagickFalse)
3813     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3814   assert(image->signature == MagickSignature);
3815   if (mask != (const Image *) NULL)
3816     if ((mask->columns != image->columns) || (mask->rows != image->rows))
3817       ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename);
3818   if (image->mask != (Image *) NULL)
3819     image->mask=DestroyImage(image->mask);
3820   image->mask=NewImageList();
3821   if (mask == (Image *) NULL)
3822     return(MagickTrue);
3823   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
3824     return(MagickFalse);
3825   image->mask=CloneImage(mask,0,0,MagickTrue,&image->exception);
3826   if (image->mask == (Image *) NULL)
3827     return(MagickFalse);
3828   return(MagickTrue);
3829 }
3830 \f
3831 /*
3832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3833 %                                                                             %
3834 %                                                                             %
3835 %                                                                             %
3836 %     S e t I m a g e O p a c i t y                                           %
3837 %                                                                             %
3838 %                                                                             %
3839 %                                                                             %
3840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3841 %
3842 %  SetImageOpacity() sets the opacity levels of the image.
3843 %
3844 %  The format of the SetImageOpacity method is:
3845 %
3846 %      MagickBooleanType SetImageOpacity(Image *image,const Quantum opacity)
3847 %
3848 %  A description of each parameter follows:
3849 %
3850 %    o image: the image.
3851 %
3852 %    o opacity: the level of transparency: 0 is fully opaque and QuantumRange is
3853 %      fully transparent.
3854 %
3855 */
3856 MagickExport MagickBooleanType SetImageOpacity(Image *image,
3857   const Quantum opacity)
3858 {
3859   CacheView
3860     *image_view;
3861
3862   ExceptionInfo
3863     *exception;
3864
3865   long
3866     y;
3867
3868   MagickBooleanType
3869     status;
3870
3871   assert(image != (Image *) NULL);
3872   if (image->debug != MagickFalse)
3873     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3874   assert(image->signature == MagickSignature);
3875   image->matte=opacity != OpaqueOpacity ? MagickTrue : MagickFalse;
3876   status=MagickTrue;
3877   exception=(&image->exception);
3878   image_view=AcquireCacheView(image);
3879 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3880   #pragma omp parallel for schedule(dynamic,4) shared(status)
3881 #endif
3882   for (y=0; y < (long) image->rows; y++)
3883   {
3884     register long
3885       x;
3886
3887     register PixelPacket
3888       *__restrict q;
3889
3890     if (status == MagickFalse)
3891       continue;
3892     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3893     if (q == (PixelPacket *) NULL)
3894       {
3895         status=MagickFalse;
3896         continue;
3897       }
3898     for (x=0; x < (long) image->columns; x++)
3899     {
3900       q->opacity=opacity;
3901       q++;
3902     }
3903     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3904       status=MagickFalse;
3905   }
3906   image_view=DestroyCacheView(image_view);
3907   return(status);
3908 }
3909 \f
3910 /*
3911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3912 %                                                                             %
3913 %                                                                             %
3914 %                                                                             %
3915 %   S e t I m a g e T y p e                                                   %
3916 %                                                                             %
3917 %                                                                             %
3918 %                                                                             %
3919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3920 %
3921 %  SetImageType() sets the type of image.  Choose from these types:
3922 %
3923 %        Bilevel        Grayscale       GrayscaleMatte
3924 %        Palette        PaletteMatte    TrueColor
3925 %        TrueColorMatte ColorSeparation ColorSeparationMatte
3926 %        OptimizeType
3927 %
3928 %  The format of the SetImageType method is:
3929 %
3930 %      MagickBooleanType SetImageType(Image *image,const ImageType type)
3931 %
3932 %  A description of each parameter follows:
3933 %
3934 %    o image: the image.
3935 %
3936 %    o type: Image type.
3937 %
3938 */
3939 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type)
3940 {
3941   const char
3942     *artifact;
3943
3944   ImageInfo
3945     *image_info;
3946
3947   MagickBooleanType
3948     status;
3949
3950   QuantizeInfo
3951     *quantize_info;
3952
3953   assert(image != (Image *) NULL);
3954   if (image->debug != MagickFalse)
3955     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3956   assert(image->signature == MagickSignature);
3957   status=MagickTrue;
3958   image_info=AcquireImageInfo();
3959   image_info->dither=image->dither;
3960   artifact=GetImageArtifact(image,"dither");
3961   if (artifact != (const char *) NULL)
3962     (void) SetImageOption(image_info,"dither",artifact);
3963   switch (type)
3964   {
3965     case BilevelType:
3966     {
3967       if (IsGrayImage(image,&image->exception) == MagickFalse)
3968         status=TransformImageColorspace(image,GRAYColorspace);
3969       if (IsMonochromeImage(image,&image->exception) == MagickFalse)
3970         {
3971           quantize_info=AcquireQuantizeInfo(image_info);
3972           quantize_info->number_colors=2;
3973           quantize_info->colorspace=GRAYColorspace;
3974           status=QuantizeImage(quantize_info,image);
3975           quantize_info=DestroyQuantizeInfo(quantize_info);
3976         }
3977       image->matte=MagickFalse;
3978       break;
3979     }
3980     case GrayscaleType:
3981     {
3982       if (IsGrayImage(image,&image->exception) == MagickFalse)
3983         status=TransformImageColorspace(image,GRAYColorspace);
3984       image->matte=MagickFalse;
3985       break;
3986     }
3987     case GrayscaleMatteType:
3988     {
3989       if (IsGrayImage(image,&image->exception) == MagickFalse)
3990         status=TransformImageColorspace(image,GRAYColorspace);
3991       if (image->matte == MagickFalse)
3992         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3993       break;
3994     }
3995     case PaletteType:
3996     {
3997       if (image->colorspace != RGBColorspace)
3998         status=TransformImageColorspace(image,RGBColorspace);
3999       if ((image->storage_class == DirectClass) || (image->colors > 256))
4000         {
4001           quantize_info=AcquireQuantizeInfo(image_info);
4002           quantize_info->number_colors=256;
4003           status=QuantizeImage(quantize_info,image);
4004           quantize_info=DestroyQuantizeInfo(quantize_info);
4005         }
4006       image->matte=MagickFalse;
4007       break;
4008     }
4009     case PaletteBilevelMatteType:
4010     {
4011       if (image->colorspace != RGBColorspace)
4012         status=TransformImageColorspace(image,RGBColorspace);
4013       if (image->matte == MagickFalse)
4014         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
4015       (void) BilevelImageChannel(image,AlphaChannel,(double) QuantumRange/2.0);
4016       quantize_info=AcquireQuantizeInfo(image_info);
4017       status=QuantizeImage(quantize_info,image);
4018       quantize_info=DestroyQuantizeInfo(quantize_info);
4019       break;
4020     }
4021     case PaletteMatteType:
4022     {
4023       if (image->colorspace != RGBColorspace)
4024         status=TransformImageColorspace(image,RGBColorspace);
4025       if (image->matte == MagickFalse)
4026         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
4027       quantize_info=AcquireQuantizeInfo(image_info);
4028       quantize_info->colorspace=TransparentColorspace;
4029       status=QuantizeImage(quantize_info,image);
4030       quantize_info=DestroyQuantizeInfo(quantize_info);
4031       break;
4032     }
4033     case TrueColorType:
4034     {
4035       if (image->colorspace != RGBColorspace)
4036         status=TransformImageColorspace(image,RGBColorspace);
4037       if (image->storage_class != DirectClass)
4038         status=SetImageStorageClass(image,DirectClass);
4039       image->matte=MagickFalse;
4040       break;
4041     }
4042     case TrueColorMatteType:
4043     {
4044       if (image->colorspace != RGBColorspace)
4045         status=TransformImageColorspace(image,RGBColorspace);
4046       if (image->storage_class != DirectClass)
4047         status=SetImageStorageClass(image,DirectClass);
4048       if (image->matte == MagickFalse)
4049         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
4050       break;
4051     }
4052     case ColorSeparationType:
4053     {
4054       if (image->colorspace != CMYKColorspace)
4055         {
4056           if (image->colorspace != RGBColorspace)
4057             status=TransformImageColorspace(image,RGBColorspace);
4058           status=TransformImageColorspace(image,CMYKColorspace);
4059         }
4060       if (image->storage_class != DirectClass)
4061         status=SetImageStorageClass(image,DirectClass);
4062       image->matte=MagickFalse;
4063       break;
4064     }
4065     case ColorSeparationMatteType:
4066     {
4067       if (image->colorspace != CMYKColorspace)
4068         {
4069           if (image->colorspace != RGBColorspace)
4070             status=TransformImageColorspace(image,RGBColorspace);
4071           status=TransformImageColorspace(image,CMYKColorspace);
4072         }
4073       if (image->storage_class != DirectClass)
4074         status=SetImageStorageClass(image,DirectClass);
4075       if (image->matte == MagickFalse)
4076         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
4077       break;
4078     }
4079     case OptimizeType:
4080     case UndefinedType:
4081       break;
4082   }
4083   image->type=type;
4084   image_info=DestroyImageInfo(image_info);
4085   return(status);
4086 }
4087 \f
4088 /*
4089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4090 %                                                                             %
4091 %                                                                             %
4092 %                                                                             %
4093 %   S e t I m a g e V i r t u a l P i x e l M e t h o d                       %
4094 %                                                                             %
4095 %                                                                             %
4096 %                                                                             %
4097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4098 %
4099 %  SetImageVirtualPixelMethod() sets the "virtual pixels" method for the
4100 %  image and returns the previous setting.  A virtual pixel is any pixel access
4101 %  that is outside the boundaries of the image cache.
4102 %
4103 %  The format of the SetImageVirtualPixelMethod() method is:
4104 %
4105 %      VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
4106 %        const VirtualPixelMethod virtual_pixel_method)
4107 %
4108 %  A description of each parameter follows:
4109 %
4110 %    o image: the image.
4111 %
4112 %    o virtual_pixel_method: choose the type of virtual pixel.
4113 %
4114 */
4115 MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
4116   const VirtualPixelMethod virtual_pixel_method)
4117 {
4118   assert(image != (const Image *) NULL);
4119   assert(image->signature == MagickSignature);
4120   if (image->debug != MagickFalse)
4121     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4122   return(SetPixelCacheVirtualMethod(image,virtual_pixel_method));
4123 }
4124 \f
4125 /*
4126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4127 %                                                                             %
4128 %                                                                             %
4129 %                                                                             %
4130 +   S o r t C o l o r m a p B y I n t e n s i t y                             %
4131 %                                                                             %
4132 %                                                                             %
4133 %                                                                             %
4134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4135 %
4136 %  SortColormapByIntensity() sorts the colormap of a PseudoClass image by
4137 %  decreasing color intensity.
4138 %
4139 %  The format of the SortColormapByIntensity method is:
4140 %
4141 %      MagickBooleanType SortColormapByIntensity(Image *image)
4142 %
4143 %  A description of each parameter follows:
4144 %
4145 %    o image: A pointer to an Image structure.
4146 %
4147 */
4148
4149 #if defined(__cplusplus) || defined(c_plusplus)
4150 extern "C" {
4151 #endif
4152
4153 static int IntensityCompare(const void *x,const void *y)
4154 {
4155   const PixelPacket
4156     *color_1,
4157     *color_2;
4158
4159   int
4160     intensity;
4161
4162   color_1=(const PixelPacket *) x;
4163   color_2=(const PixelPacket *) y;
4164   intensity=(int) PixelIntensityToQuantum(color_2)-
4165     (int) PixelIntensityToQuantum(color_1);
4166   return(intensity);
4167 }
4168
4169 #if defined(__cplusplus) || defined(c_plusplus)
4170 }
4171 #endif
4172
4173 MagickExport MagickBooleanType SortColormapByIntensity(Image *image)
4174 {
4175   CacheView
4176     *image_view;
4177
4178   ExceptionInfo
4179     *exception;
4180
4181   long
4182     y;
4183
4184   MagickBooleanType
4185     status;
4186
4187   register long
4188     i;
4189
4190   unsigned short
4191     *pixels;
4192
4193   assert(image != (Image *) NULL);
4194   if (image->debug != MagickFalse)
4195     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4196   assert(image->signature == MagickSignature);
4197   if (image->storage_class != PseudoClass)
4198     return(MagickTrue);
4199   /*
4200     Allocate memory for pixel indexes.
4201   */
4202   pixels=(unsigned short *) AcquireQuantumMemory((size_t) image->colors,
4203     sizeof(*pixels));
4204   if (pixels == (unsigned short *) NULL)
4205     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
4206       image->filename);
4207   /*
4208     Assign index values to colormap entries.
4209   */
4210 #if defined(MAGICKCORE_OPENMP_SUPPORT)
4211   #pragma omp parallel for schedule(dynamic,4) shared(status)
4212 #endif
4213   for (i=0; i < (long) image->colors; i++)
4214     image->colormap[i].opacity=(IndexPacket) i;
4215   /*
4216     Sort image colormap by decreasing color popularity.
4217   */
4218   qsort((void *) image->colormap,(size_t) image->colors,
4219     sizeof(*image->colormap),IntensityCompare);
4220   /*
4221     Update image colormap indexes to sorted colormap order.
4222   */
4223 #if defined(MAGICKCORE_OPENMP_SUPPORT)
4224   #pragma omp parallel for schedule(dynamic,4) shared(status)
4225 #endif
4226   for (i=0; i < (long) image->colors; i++)
4227     pixels[(long) image->colormap[i].opacity]=(unsigned short) i;
4228   status=MagickTrue;
4229   exception=(&image->exception);
4230   image_view=AcquireCacheView(image);
4231   for (y=0; y < (long) image->rows; y++)
4232   {
4233     IndexPacket
4234       index;
4235
4236     register long
4237       x;
4238
4239     register IndexPacket
4240       *__restrict indexes;
4241
4242     register PixelPacket
4243       *__restrict q;
4244
4245     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
4246     if (q == (PixelPacket *) NULL)
4247       {
4248         status=MagickFalse;
4249         continue;
4250       }
4251     indexes=GetCacheViewAuthenticIndexQueue(image_view);
4252     for (x=0; x < (long) image->columns; x++)
4253     {
4254       index=(IndexPacket) pixels[(long) indexes[x]];
4255       indexes[x]=index;
4256       *q++=image->colormap[(long) index];
4257     }
4258     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
4259       status=MagickFalse;
4260     if (status == MagickFalse)
4261       break;
4262   }
4263   image_view=DestroyCacheView(image_view);
4264   pixels=(unsigned short *) RelinquishMagickMemory(pixels);
4265   return(status);
4266 }
4267
4268 /*
4269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4270 %                                                                             %
4271 %                                                                             %
4272 %                                                                             %
4273 %   S t r i p I m a g e                                                       %
4274 %                                                                             %
4275 %                                                                             %
4276 %                                                                             %
4277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4278 %
4279 %  StripImage() strips an image of all profiles and comments.
4280 %
4281 %  The format of the StripImage method is:
4282 %
4283 %      MagickBooleanType StripImage(Image *image)
4284 %
4285 %  A description of each parameter follows:
4286 %
4287 %    o image: the image.
4288 %
4289 */
4290 MagickExport MagickBooleanType StripImage(Image *image)
4291 {
4292   assert(image != (Image *) NULL);
4293   if (image->debug != MagickFalse)
4294     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4295   DestroyImageProfiles(image);
4296   (void) DeleteImageProperty(image,"comment");
4297   return(MagickTrue);
4298 }
4299 \f
4300 /*
4301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4302 %                                                                             %
4303 %                                                                             %
4304 %                                                                             %
4305 +   S y n c I m a g e                                                         %
4306 %                                                                             %
4307 %                                                                             %
4308 %                                                                             %
4309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4310 %
4311 %  SyncImage() initializes the red, green, and blue intensities of each pixel
4312 %  as defined by the colormap index.
4313 %
4314 %  The format of the SyncImage method is:
4315 %
4316 %      MagickBooleanType SyncImage(Image *image)
4317 %
4318 %  A description of each parameter follows:
4319 %
4320 %    o image: the image.
4321 %
4322 */
4323
4324 static inline IndexPacket PushColormapIndex(Image *image,
4325   const unsigned long index,MagickBooleanType *range_exception)
4326 {
4327   if (index < image->colors)
4328     return((IndexPacket) index);
4329   *range_exception=MagickTrue;
4330   return((IndexPacket) 0);
4331 }
4332
4333 MagickExport MagickBooleanType SyncImage(Image *image)
4334 {
4335   CacheView
4336     *image_view;
4337
4338   ExceptionInfo
4339     *exception;
4340
4341   long
4342     y;
4343
4344   MagickBooleanType
4345     range_exception,
4346     status;
4347
4348   assert(image != (Image *) NULL);
4349   if (image->debug != MagickFalse)
4350     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4351   assert(image->signature == MagickSignature);
4352   if (image->storage_class == DirectClass)
4353     return(MagickFalse);
4354   range_exception=MagickFalse;
4355   status=MagickTrue;
4356   exception=(&image->exception);
4357   image_view=AcquireCacheView(image);
4358   for (y=0; y < (long) image->rows; y++)
4359   {
4360     IndexPacket
4361       index;
4362
4363     PixelPacket
4364       pixel;
4365
4366     register IndexPacket
4367       *__restrict indexes;
4368
4369     register long
4370       x;
4371
4372     register PixelPacket
4373       *__restrict q;
4374
4375     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
4376     if (q == (PixelPacket *) NULL)
4377       {
4378         status=MagickFalse;
4379         continue;
4380       }
4381     indexes=GetCacheViewAuthenticIndexQueue(image_view);
4382     for (x=0; x < (long) image->columns; x++)
4383     {
4384       index=PushColormapIndex(image,(unsigned long) indexes[x],
4385         &range_exception);
4386       pixel=image->colormap[(long) index];
4387       q->red=pixel.red;
4388       q->green=pixel.green;
4389       q->blue=pixel.blue;
4390       q++;
4391     }
4392     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
4393       status=MagickFalse;
4394     if (status == MagickFalse)
4395       break;
4396   }
4397   image_view=DestroyCacheView(image_view);
4398   if (range_exception != MagickFalse)
4399     (void) ThrowMagickException(&image->exception,GetMagickModule(),
4400       CorruptImageError,"InvalidColormapIndex","`%s'",image->filename);
4401   return(status);
4402 }
4403 \f
4404 /*
4405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4406 %                                                                             %
4407 %                                                                             %
4408 %                                                                             %
4409 %     T e x t u r e I m a g e                                                 %
4410 %                                                                             %
4411 %                                                                             %
4412 %                                                                             %
4413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4414 %
4415 %  TextureImage() repeatedly tiles the texture image across and down the image
4416 %  canvas.
4417 %
4418 %  The format of the TextureImage method is:
4419 %
4420 %      MagickBooleanType TextureImage(Image *image,const Image *texture)
4421 %
4422 %  A description of each parameter follows:
4423 %
4424 %    o image: the image.
4425 %
4426 %    o texture: This image is the texture to layer on the background.
4427 %
4428 */
4429 MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
4430 {
4431 #define TextureImageTag  "Texture/Image"
4432
4433   ExceptionInfo
4434     *exception;
4435
4436   long
4437     y;
4438
4439   MagickStatusType
4440     status;
4441
4442   assert(image != (Image *) NULL);
4443   if (image->debug != MagickFalse)
4444     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4445   assert(image->signature == MagickSignature);
4446   if (texture == (const Image *) NULL)
4447     return(MagickFalse);
4448   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
4449     return(MagickFalse);
4450   /*
4451     Tile texture onto the image background.
4452   */
4453   status=MagickTrue;
4454   exception=(&image->exception);
4455   for (y=0; y < (long) image->rows; y+=texture->rows)
4456   {
4457     register long
4458       x;
4459
4460     for (x=0; x < (long) image->columns; x+=texture->columns)
4461       status|=CompositeImage(image,image->compose,texture,x+
4462         texture->tile_offset.x,y+texture->tile_offset.y);
4463     if (image->progress_monitor != (MagickProgressMonitor) NULL)
4464       {
4465         MagickBooleanType
4466           proceed;
4467
4468         proceed=SetImageProgress(image,TextureImageTag,y,image->rows);
4469         if (proceed == MagickFalse)
4470           status=MagickFalse;
4471       }
4472   }
4473   (void) SetImageProgress(image,TextureImageTag,image->rows,image->rows);
4474   return(status != 0 ? MagickTrue : MagickFalse);
4475 }