image.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                     IIIII  M   M   AAA    GGGG  EEEEE                       %
00007 %                       I    MM MM  A   A  G      E                           %
00008 %                       I    M M M  AAAAA  G  GG  EEE                         %
00009 %                       I    M   M  A   A  G   G  E                           %
00010 %                     IIIII  M   M  A   A   GGGG  EEEEE                       %
00011 %                                                                             %
00012 %                                                                             %
00013 %                           MagickCore Image Methods                          %
00014 %                                                                             %
00015 %                              Software Design                                %
00016 %                                John Cristy                                  %
00017 %                                 July 1992                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 %
00038 */
00039 
00040 /*
00041   Include declarations.
00042 */
00043 #include "magick/studio.h"
00044 #include "magick/animate.h"
00045 #include "magick/artifact.h"
00046 #include "magick/blob.h"
00047 #include "magick/blob-private.h"
00048 #include "magick/cache.h"
00049 #include "magick/cache-private.h"
00050 #include "magick/cache-view.h"
00051 #include "magick/client.h"
00052 #include "magick/color.h"
00053 #include "magick/color-private.h"
00054 #include "magick/colormap.h"
00055 #include "magick/colorspace.h"
00056 #include "magick/colorspace-private.h"
00057 #include "magick/composite.h"
00058 #include "magick/composite-private.h"
00059 #include "magick/compress.h"
00060 #include "magick/constitute.h"
00061 #include "magick/deprecate.h"
00062 #include "magick/display.h"
00063 #include "magick/draw.h"
00064 #include "magick/enhance.h"
00065 #include "magick/exception.h"
00066 #include "magick/exception-private.h"
00067 #include "magick/gem.h"
00068 #include "magick/geometry.h"
00069 #include "magick/histogram.h"
00070 #include "magick/image-private.h"
00071 #include "magick/list.h"
00072 #include "magick/magic.h"
00073 #include "magick/magick.h"
00074 #include "magick/memory_.h"
00075 #include "magick/module.h"
00076 #include "magick/monitor.h"
00077 #include "magick/monitor-private.h"
00078 #include "magick/option.h"
00079 #include "magick/paint.h"
00080 #include "magick/pixel-private.h"
00081 #include "magick/profile.h"
00082 #include "magick/property.h"
00083 #include "magick/quantize.h"
00084 #include "magick/random_.h"
00085 #include "magick/segment.h"
00086 #include "magick/semaphore.h"
00087 #include "magick/signature-private.h"
00088 #include "magick/statistic.h"
00089 #include "magick/string_.h"
00090 #include "magick/thread-private.h"
00091 #include "magick/threshold.h"
00092 #include "magick/timer.h"
00093 #include "magick/utility.h"
00094 #include "magick/version.h"
00095 #include "magick/xwindow-private.h"
00096 
00097 /*
00098   Constant declaration.
00099 */
00100 const char
00101   BackgroundColor[] = "#ffffff",  /* white */
00102   BorderColor[] = "#dfdfdf",  /* gray */
00103   DefaultTileFrame[] = "15x15+3+3",
00104   DefaultTileGeometry[] = "120x120+4+3>",
00105   DefaultTileLabel[] = "%f\n%G\n%b",
00106   ForegroundColor[] = "#000",  /* black */
00107   LoadImageTag[] = "Load/Image",
00108   LoadImagesTag[] = "Load/Images",
00109   MatteColor[] = "#bdbdbd",  /* gray */
00110   PSDensityGeometry[] = "72.0x72.0",
00111   PSPageGeometry[] = "612x792",
00112   SaveImageTag[] = "Save/Image",
00113   SaveImagesTag[] = "Save/Images",
00114   TransparentColor[] = "#00000000";  /* transparent black */
00115 
00116 const double
00117   DefaultResolution = 72.0;
00118 
00119 /*
00120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00121 %                                                                             %
00122 %                                                                             %
00123 %                                                                             %
00124 %   A c q u i r e I m a g e                                                   %
00125 %                                                                             %
00126 %                                                                             %
00127 %                                                                             %
00128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00129 %
00130 %  AcquireImage() returns a pointer to an image structure initialized to
00131 %  default values.
00132 %
00133 %  The format of the AcquireImage method is:
00134 %
00135 %      Image *AcquireImage(const ImageInfo *image_info)
00136 %
00137 %  A description of each parameter follows:
00138 %
00139 %    o image_info: Many of the image default values are set from this
00140 %      structure.  For example, filename, compression, depth, background color,
00141 %      and others.
00142 %
00143 */
00144 MagickExport Image *AcquireImage(const ImageInfo *image_info)
00145 {
00146   Image
00147     *image;
00148 
00149   MagickStatusType
00150     flags;
00151 
00152   /*
00153     Allocate image structure.
00154   */
00155   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00156   image=(Image *) AcquireMagickMemory(sizeof(*image));
00157   if (image == (Image *) NULL)
00158     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00159   (void) ResetMagickMemory(image,0,sizeof(*image));
00160   /*
00161     Initialize Image structure.
00162   */
00163   (void) CopyMagickString(image->magick,"MIFF",MaxTextExtent);
00164   image->storage_class=DirectClass;
00165   image->depth=MAGICKCORE_QUANTUM_DEPTH;
00166   image->colorspace=RGBColorspace;
00167   image->interlace=NoInterlace;
00168   image->ticks_per_second=UndefinedTicksPerSecond;
00169   image->compose=OverCompositeOp;
00170   image->blur=1.0;
00171   GetExceptionInfo(&image->exception);
00172   (void) QueryColorDatabase(BackgroundColor,&image->background_color,
00173     &image->exception);
00174   (void) QueryColorDatabase(BorderColor,&image->border_color,&image->exception);
00175   (void) QueryColorDatabase(MatteColor,&image->matte_color,&image->exception);
00176   (void) QueryColorDatabase(TransparentColor,&image->transparent_color,
00177     &image->exception);
00178   image->x_resolution=DefaultResolution;
00179   image->y_resolution=DefaultResolution;
00180   image->units=PixelsPerInchResolution;
00181   GetTimerInfo(&image->timer);
00182   image->cache=AcquirePixelCache(0);
00183   image->blob=CloneBlobInfo((BlobInfo *) NULL);
00184   image->debug=IsEventLogging();
00185   image->reference_count=1;
00186   image->semaphore=AllocateSemaphoreInfo();
00187   image->signature=MagickSignature;
00188   if (image_info == (ImageInfo *) NULL)
00189     return(image);
00190   /*
00191     Transfer image info.
00192   */
00193   SetBlobExempt(image,image_info->file != (FILE *) NULL ? MagickTrue :
00194     MagickFalse);
00195   (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent);
00196   (void) CopyMagickString(image->magick_filename,image_info->filename,
00197     MaxTextExtent);
00198   (void) CopyMagickString(image->magick,image_info->magick,MaxTextExtent);
00199   if (image_info->size != (char *) NULL)
00200     {
00201       (void) ParseAbsoluteGeometry(image_info->size,&image->extract_info);
00202       image->columns=image->extract_info.width;
00203       image->rows=image->extract_info.height;
00204       image->offset=image->extract_info.x;
00205       image->extract_info.x=0;
00206       image->extract_info.y=0;
00207     }
00208   if (image_info->extract != (char *) NULL)
00209     {
00210       RectangleInfo
00211         geometry;
00212 
00213       flags=ParseAbsoluteGeometry(image_info->extract,&geometry);
00214       if (((flags & XValue) != 0) || ((flags & YValue) != 0))
00215         {
00216           image->extract_info=geometry;
00217           Swap(image->columns,image->extract_info.width);
00218           Swap(image->rows,image->extract_info.height);
00219         }
00220     }
00221   image->compression=image_info->compression;
00222   image->quality=image_info->quality;
00223   image->endian=image_info->endian;
00224   image->interlace=image_info->interlace;
00225   image->units=image_info->units;
00226   if (image_info->density != (char *) NULL)
00227     {
00228       GeometryInfo
00229         geometry_info;
00230 
00231       flags=ParseGeometry(image_info->density,&geometry_info);
00232       image->x_resolution=geometry_info.rho;
00233       image->y_resolution=geometry_info.sigma;
00234       if ((flags & SigmaValue) == 0)
00235         image->y_resolution=image->x_resolution;
00236     }
00237   if (image_info->page != (char *) NULL)
00238     {
00239       char
00240         *geometry;
00241 
00242       image->page=image->extract_info;
00243       geometry=GetPageGeometry(image_info->page);
00244       (void) ParseAbsoluteGeometry(geometry,&image->page);
00245       geometry=DestroyString(geometry);
00246     }
00247   if (image_info->depth != 0)
00248     image->depth=image_info->depth;
00249   image->dither=image_info->dither;
00250   image->background_color=image_info->background_color;
00251   image->border_color=image_info->border_color;
00252   image->matte_color=image_info->matte_color;
00253   image->transparent_color=image_info->transparent_color;
00254   image->progress_monitor=image_info->progress_monitor;
00255   image->client_data=image_info->client_data;
00256   if (image_info->cache != (void *) NULL)
00257     ClonePixelCacheMethods(image->cache,image_info->cache);
00258   (void) SetImageVirtualPixelMethod(image,image_info->virtual_pixel_method);
00259   SyncImageSettings(image_info,image);
00260   return(image);
00261 }
00262 
00263 /*
00264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00265 %                                                                             %
00266 %                                                                             %
00267 %                                                                             %
00268 %   A c q u i r e I m a g e C o l o r m a p                                   %
00269 %                                                                             %
00270 %                                                                             %
00271 %                                                                             %
00272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00273 %
00274 %  AcquireImageColormap() allocates an image colormap and initializes
00275 %  it to a linear gray colorspace.  If the image already has a colormap,
00276 %  it is replaced.  AcquireImageColormap() returns MagickTrue if successful,
00277 %  otherwise MagickFalse if there is not enough memory.
00278 %
00279 %  The format of the AcquireImageColormap method is:
00280 %
00281 %      MagickBooleanType AcquireImageColormap(Image *image,
00282 %        const unsigned long colors)
00283 %
00284 %  A description of each parameter follows:
00285 %
00286 %    o image: the image.
00287 %
00288 %    o colors: the number of colors in the image colormap.
00289 %
00290 */
00291 
00292 static inline unsigned long MagickMax(const unsigned long x,
00293   const unsigned long y)
00294 {
00295   if (x > y)
00296     return(x);
00297   return(y);
00298 }
00299 
00300 static inline unsigned long MagickMin(const unsigned long x,
00301   const unsigned long y)
00302 {
00303   if (x < y)
00304     return(x);
00305   return(y);
00306 }
00307 
00308 MagickExport MagickBooleanType AcquireImageColormap(Image *image,
00309   const unsigned long colors)
00310 {
00311   register long
00312     i;
00313 
00314   size_t
00315     length;
00316 
00317   /*
00318     Allocate image colormap.
00319   */
00320   assert(image != (Image *) NULL);
00321   assert(image->signature == MagickSignature);
00322   if (image->debug != MagickFalse)
00323     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00324   image->colors=MagickMin(colors,MaxColormapSize);
00325   length=(size_t) colors;
00326   if (image->colormap == (PixelPacket *) NULL)
00327     image->colormap=(PixelPacket *) AcquireQuantumMemory(length,
00328       sizeof(*image->colormap));
00329   else
00330     image->colormap=(PixelPacket *) ResizeQuantumMemory(image->colormap,length,
00331       sizeof(*image->colormap));
00332   if (image->colormap == (PixelPacket *) NULL)
00333     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00334       image->filename);
00335   for (i=0; i < (long) image->colors; i++)
00336   {
00337     unsigned long
00338       pixel;
00339 
00340     pixel=(unsigned long) (i*(QuantumRange/MagickMax(colors-1,1)));
00341     image->colormap[i].red=(Quantum) pixel;
00342     image->colormap[i].green=(Quantum) pixel;
00343     image->colormap[i].blue=(Quantum) pixel;
00344     image->colormap[i].opacity=OpaqueOpacity;
00345   }
00346   return(SetImageStorageClass(image,PseudoClass));
00347 }
00348 
00349 /*
00350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00351 %                                                                             %
00352 %                                                                             %
00353 %                                                                             %
00354 %   A c q u i r e I m a g e I n f o                                           %
00355 %                                                                             %
00356 %                                                                             %
00357 %                                                                             %
00358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00359 %
00360 %  AcquireImageInfo() allocates the ImageInfo structure.
00361 %
00362 %  The format of the AcquireImageInfo method is:
00363 %
00364 %      ImageInfo *AcquireImageInfo(void)
00365 %
00366 */
00367 MagickExport ImageInfo *AcquireImageInfo(void)
00368 {
00369   ImageInfo
00370     *image_info;
00371 
00372   image_info=(ImageInfo *) AcquireMagickMemory(sizeof(*image_info));
00373   if (image_info == (ImageInfo *) NULL)
00374     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00375   GetImageInfo(image_info);
00376   return(image_info);
00377 }
00378 
00379 /*
00380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00381 %                                                                             %
00382 %                                                                             %
00383 %                                                                             %
00384 %   A c q u i r e N e x t I m a g e                                           %
00385 %                                                                             %
00386 %                                                                             %
00387 %                                                                             %
00388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00389 %
00390 %  AcquireNextImage() initializes the next image in a sequence to
00391 %  default values.  The next member of image points to the newly allocated
00392 %  image.  If there is a memory shortage, next is assigned NULL.
00393 %
00394 %  The format of the AcquireNextImage method is:
00395 %
00396 %      void AcquireNextImage(const ImageInfo *image_info,Image *image)
00397 %
00398 %  A description of each parameter follows:
00399 %
00400 %    o image_info: Many of the image default values are set from this
00401 %      structure.  For example, filename, compression, depth, background color,
00402 %      and others.
00403 %
00404 %    o image: the image.
00405 %
00406 */
00407 MagickExport void AcquireNextImage(const ImageInfo *image_info,Image *image)
00408 {
00409   /*
00410     Allocate image structure.
00411   */
00412   assert(image != (Image *) NULL);
00413   assert(image->signature == MagickSignature);
00414   if (image->debug != MagickFalse)
00415     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00416   image->next=AcquireImage(image_info);
00417   if (GetNextImageInList(image) == (Image *) NULL)
00418     return;
00419   (void) CopyMagickString(GetNextImageInList(image)->filename,image->filename,
00420     MaxTextExtent);
00421   if (image_info != (ImageInfo *) NULL)
00422     (void) CopyMagickString(GetNextImageInList(image)->filename,
00423       image_info->filename,MaxTextExtent);
00424   DestroyBlob(GetNextImageInList(image));
00425   image->next->blob=ReferenceBlob(image->blob);
00426   image->next->endian=image->endian;
00427   image->next->scene=image->scene+1;
00428   image->next->previous=image;
00429 }
00430 
00431 /*
00432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00433 %                                                                             %
00434 %                                                                             %
00435 %                                                                             %
00436 %     A p p e n d I m a g e s                                                 %
00437 %                                                                             %
00438 %                                                                             %
00439 %                                                                             %
00440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00441 %
00442 %  AppendImages() takes all images from the current image pointer to the end
00443 %  of the image list and appends them to each other top-to-bottom if the
00444 %  stack parameter is true, otherwise left-to-right.
00445 %
00446 %  The current gravity setting now effects how the image is justified in the
00447 %  final image.
00448 %
00449 %  The format of the AppendImages method is:
00450 %
00451 %      Image *AppendImages(const Image *image,const MagickBooleanType stack,
00452 %        ExceptionInfo *exception)
00453 %
00454 %  A description of each parameter follows:
00455 %
00456 %    o image: the image sequence.
00457 %
00458 %    o stack: A value other than 0 stacks the images top-to-bottom.
00459 %
00460 %    o exception: return any errors or warnings in this structure.
00461 %
00462 */
00463 MagickExport Image *AppendImages(const Image *image,
00464   const MagickBooleanType stack,ExceptionInfo *exception)
00465 {
00466 #define AppendImageTag  "Append/Image"
00467 
00468   CacheView
00469     *append_view,
00470     *image_view;
00471 
00472   Image
00473     *append_image;
00474 
00475   long
00476     n,
00477     x_offset,
00478     y,
00479     y_offset;
00480 
00481   MagickBooleanType
00482     matte,
00483     proceed,
00484     status;
00485 
00486   RectangleInfo
00487     geometry;
00488 
00489   register const Image
00490     *next;
00491 
00492   unsigned long
00493     height,
00494     number_images,
00495     width;
00496 
00497   /*
00498     Ensure the image have the same column width.
00499   */
00500   assert(image != (Image *) NULL);
00501   assert(image->signature == MagickSignature);
00502   if (image->debug != MagickFalse)
00503     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00504   assert(exception != (ExceptionInfo *) NULL);
00505   assert(exception->signature == MagickSignature);
00506   matte=image->matte;
00507   number_images=1;
00508   width=image->columns;
00509   height=image->rows;
00510   next=GetNextImageInList(image);
00511   for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
00512   {
00513     if (next->matte != MagickFalse)
00514       matte=MagickTrue;
00515     number_images++;
00516     if (stack != MagickFalse)
00517       {
00518         if (next->columns > width)
00519           width=next->columns;
00520         height+=next->rows;
00521         continue;
00522       }
00523     width+=next->columns;
00524     if (next->rows > height)
00525       height=next->rows;
00526   }
00527   /*
00528     Initialize append next attributes.
00529   */
00530   append_image=CloneImage(image,width,height,MagickTrue,exception);
00531   if (append_image == (Image *) NULL)
00532     return((Image *) NULL);
00533   if (SetImageStorageClass(append_image,DirectClass) == MagickFalse)
00534     {
00535       InheritException(exception,&append_image->exception);
00536       append_image=DestroyImage(append_image);
00537       return((Image *) NULL);
00538     }
00539   append_image->matte=matte;
00540   (void) SetImageBackgroundColor(append_image);
00541   status=MagickTrue;
00542   x_offset=0;
00543   y_offset=0;
00544   append_view=AcquireCacheView(append_image);
00545   for (n=0; n < (long) number_images; n++)
00546   {
00547     SetGeometry(append_image,&geometry);
00548     GravityAdjustGeometry(image->columns,image->rows,image->gravity,&geometry);
00549     if (stack != MagickFalse)
00550       x_offset-=geometry.x;
00551     else
00552       y_offset-=geometry.y;
00553     image_view=AcquireCacheView(image);
00554 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00555     #pragma omp parallel for schedule(dynamic,4) shared(status)
00556 #endif
00557     for (y=0; y < (long) image->rows; y++)
00558     {
00559       MagickBooleanType
00560         sync;
00561 
00562       register const IndexPacket
00563         *__restrict indexes;
00564 
00565       register const PixelPacket
00566         *__restrict p;
00567 
00568       register IndexPacket
00569         *__restrict append_indexes;
00570 
00571       register long
00572         x;
00573 
00574       register PixelPacket
00575         *__restrict q;
00576 
00577       if (status == MagickFalse)
00578         continue;
00579       p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
00580       q=QueueCacheViewAuthenticPixels(append_view,x_offset,y+y_offset,
00581         image->columns,1,exception);
00582       if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
00583         {
00584           status=MagickFalse;
00585           continue;
00586         }
00587       indexes=GetCacheViewVirtualIndexQueue(image_view);
00588       append_indexes=GetCacheViewAuthenticIndexQueue(append_view);
00589       for (x=0; x < (long) image->columns; x++)
00590       {
00591         q->red=p->red;
00592         q->green=p->green;
00593         q->blue=p->blue;
00594         q->opacity=OpaqueOpacity;
00595         if (image->matte != MagickFalse)
00596           q->opacity=p->opacity;
00597         if (image->colorspace == CMYKColorspace)
00598           append_indexes[x]=indexes[x];
00599         p++;
00600         q++;
00601       }
00602       sync=SyncCacheViewAuthenticPixels(append_view,exception);
00603       if (sync == MagickFalse)
00604         continue;
00605     }
00606     image_view=DestroyCacheView(image_view);
00607     proceed=SetImageProgress(image,AppendImageTag,n,number_images);
00608     if (proceed == MagickFalse)
00609       break;
00610     if (stack == MagickFalse)
00611       {
00612         x_offset+=image->columns;
00613         y_offset=0;
00614       }
00615     else
00616       {
00617         x_offset=0;
00618         y_offset+=image->rows;
00619       }
00620     image=GetNextImageInList(image);
00621   }
00622   append_view=DestroyCacheView(append_view);
00623   if (status == MagickFalse)
00624     append_image=DestroyImage(append_image);
00625   return(append_image);
00626 }
00627 
00628 /*
00629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00630 %                                                                             %
00631 %                                                                             %
00632 %                                                                             %
00633 %   C a t c h I m a g e E x c e p t i o n                                     %
00634 %                                                                             %
00635 %                                                                             %
00636 %                                                                             %
00637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00638 %
00639 %  CatchImageException() returns if no exceptions are found in the image
00640 %  sequence, otherwise it determines the most severe exception and reports
00641 %  it as a warning or error depending on the severity.
00642 %
00643 %  The format of the CatchImageException method is:
00644 %
00645 %      ExceptionType CatchImageException(Image *image)
00646 %
00647 %  A description of each parameter follows:
00648 %
00649 %    o image: An image sequence.
00650 %
00651 */
00652 MagickExport ExceptionType CatchImageException(Image *image)
00653 {
00654   ExceptionInfo
00655     *exception;
00656 
00657   ExceptionType
00658     severity;
00659 
00660   assert(image != (const Image *) NULL);
00661   assert(image->signature == MagickSignature);
00662   if (image->debug != MagickFalse)
00663     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00664   exception=AcquireExceptionInfo();
00665   GetImageException(image,exception);
00666   CatchException(exception);
00667   severity=exception->severity;
00668   exception=DestroyExceptionInfo(exception);
00669   return(severity);
00670 }
00671 
00672 /*
00673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00674 %                                                                             %
00675 %                                                                             %
00676 %                                                                             %
00677 %   C l i p I m a g e P a t h                                                 %
00678 %                                                                             %
00679 %                                                                             %
00680 %                                                                             %
00681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00682 %
00683 %  ClipImagePath() sets the image clip mask based any clipping path information
00684 %  if it exists.
00685 %
00686 %  The format of the ClipImagePath method is:
00687 %
00688 %      MagickBooleanType ClipImagePath(Image *image,const char *pathname,
00689 %        const MagickBooleanType inside)
00690 %
00691 %  A description of each parameter follows:
00692 %
00693 %    o image: the image.
00694 %
00695 %    o pathname: name of clipping path resource. If name is preceded by #, use
00696 %      clipping path numbered by name.
00697 %
00698 %    o inside: if non-zero, later operations take effect inside clipping path.
00699 %      Otherwise later operations take effect outside clipping path.
00700 %
00701 */
00702 
00703 MagickExport MagickBooleanType ClipImage(Image *image)
00704 {
00705   return(ClipImagePath(image,"#1",MagickTrue));
00706 }
00707 
00708 MagickExport MagickBooleanType ClipImagePath(Image *image,const char *pathname,
00709   const MagickBooleanType inside)
00710 {
00711 #define ClipImagePathTag  "ClipPath/Image"
00712 
00713   char
00714     *property;
00715 
00716   const char
00717     *value;
00718 
00719   Image
00720     *clip_mask;
00721 
00722   ImageInfo
00723     *image_info;
00724 
00725   assert(image != (const Image *) NULL);
00726   assert(image->signature == MagickSignature);
00727   if (image->debug != MagickFalse)
00728     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00729   assert(pathname != NULL);
00730   property=AcquireString(pathname);
00731   (void) FormatMagickString(property,MaxTextExtent,"8BIM:1999,2998:%s",
00732     pathname);
00733   value=GetImageProperty(image,property);
00734   property=DestroyString(property);
00735   if (value == (const char *) NULL)
00736     {
00737       ThrowFileException(&image->exception,OptionError,"NoClipPathDefined",
00738         image->filename);
00739       return(MagickFalse);
00740     }
00741   image_info=AcquireImageInfo();
00742   (void) CopyMagickString(image_info->filename,image->filename,MaxTextExtent);
00743   (void) ConcatenateMagickString(image_info->filename,pathname,MaxTextExtent);
00744   clip_mask=BlobToImage(image_info,value,strlen(value),&image->exception);
00745   image_info=DestroyImageInfo(image_info);
00746   if (clip_mask == (Image *) NULL)
00747     return(MagickFalse);
00748   if (clip_mask->storage_class == PseudoClass)
00749     {
00750       (void) SyncImage(clip_mask);
00751       if (SetImageStorageClass(clip_mask,DirectClass) == MagickFalse)
00752         return(MagickFalse);
00753     }
00754   if (inside == MagickFalse)
00755     (void) NegateImage(clip_mask,MagickFalse);
00756   (void) FormatMagickString(clip_mask->magick_filename,MaxTextExtent,
00757     "8BIM:1999,2998:%s\nPS",pathname);
00758   (void) SetImageClipMask(image,clip_mask);
00759   clip_mask=DestroyImage(clip_mask);
00760   return(MagickTrue);
00761 }
00762 
00763 /*
00764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00765 %                                                                             %
00766 %                                                                             %
00767 %                                                                             %
00768 %   C l o n e I m a g e                                                       %
00769 %                                                                             %
00770 %                                                                             %
00771 %                                                                             %
00772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00773 %
00774 %  CloneImage() copies an image and returns the copy as a new image object.
00775 %  If the specified columns and rows is 0, an exact copy of the image is
00776 %  returned, otherwise the pixel data is undefined and must be initialized
00777 %  with the QueueAuthenticPixels() and SyncAuthenticPixels() methods.  On
00778 %  failure, a NULL image is returned and exception describes the reason for the
00779 %  failure.
00780 %
00781 %  The format of the CloneImage method is:
00782 %
00783 %      Image *CloneImage(const Image *image,const unsigned long columns,
00784 %        const unsigned long rows,const MagickBooleanType orphan,
00785 %        ExceptionInfo *exception)
00786 %
00787 %  A description of each parameter follows:
00788 %
00789 %    o image: the image.
00790 %
00791 %    o columns: the number of columns in the cloned image.
00792 %
00793 %    o rows: the number of rows in the cloned image.
00794 %
00795 %    o detach:  With a value other than 0, the cloned image is detached from
00796 %      its parent I/O stream.
00797 %
00798 %    o exception: return any errors or warnings in this structure.
00799 %
00800 */
00801 MagickExport Image *CloneImage(const Image *image,const unsigned long columns,
00802   const unsigned long rows,const MagickBooleanType detach,
00803   ExceptionInfo *exception)
00804 {
00805   Image
00806     *clone_image;
00807 
00808   MagickRealType
00809     scale;
00810 
00811   size_t
00812     length;
00813 
00814   /*
00815     Clone the image.
00816   */
00817   assert(image != (const Image *) NULL);
00818   assert(image->signature == MagickSignature);
00819   if (image->debug != MagickFalse)
00820     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00821   assert(exception != (ExceptionInfo *) NULL);
00822   assert(exception->signature == MagickSignature);
00823   clone_image=(Image *) AcquireMagickMemory(sizeof(*clone_image));
00824   if (clone_image == (Image *) NULL)
00825     ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
00826   (void) ResetMagickMemory(clone_image,0,sizeof(*clone_image));
00827   clone_image->signature=MagickSignature;
00828   clone_image->storage_class=image->storage_class;
00829   clone_image->colorspace=image->colorspace;
00830   clone_image->matte=image->matte;
00831   clone_image->columns=image->columns;
00832   clone_image->rows=image->rows;
00833   clone_image->dither=image->dither;
00834   if (image->colormap != (PixelPacket *) NULL)
00835     {
00836       /*
00837         Allocate and copy the image colormap.
00838       */
00839       clone_image->colors=image->colors;
00840       length=(size_t) image->colors;
00841       clone_image->colormap=(PixelPacket *) AcquireQuantumMemory(length,
00842         sizeof(*clone_image->colormap));
00843       if (clone_image->colormap == (PixelPacket *) NULL)
00844         ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
00845       (void) CopyMagickMemory(clone_image->colormap,image->colormap,length*
00846         sizeof(*clone_image->colormap));
00847     }
00848   (void) CloneImageProfiles(clone_image,image);
00849   (void) CloneImageProperties(clone_image,image);
00850   (void) CloneImageArtifacts(clone_image,image);
00851   GetTimerInfo(&clone_image->timer);
00852   GetExceptionInfo(&clone_image->exception);
00853   InheritException(&clone_image->exception,&image->exception);
00854   if (image->ascii85 != (void *) NULL)
00855     Ascii85Initialize(clone_image);
00856   clone_image->magick_columns=image->magick_columns;
00857   clone_image->magick_rows=image->magick_rows;
00858   clone_image->type=image->type;
00859   (void) CopyMagickString(clone_image->magick_filename,image->magick_filename,
00860     MaxTextExtent);
00861   (void) CopyMagickString(clone_image->magick,image->magick,MaxTextExtent);
00862   (void) CopyMagickString(clone_image->filename,image->filename,MaxTextExtent);
00863   clone_image->progress_monitor=image->progress_monitor;
00864   clone_image->client_data=image->client_data;
00865   clone_image->reference_count=1;
00866   clone_image->next=NewImageList();
00867   clone_image->previous=NewImageList();
00868   clone_image->list=NewImageList();
00869   clone_image->clip_mask=NewImageList();
00870   clone_image->mask=NewImageList();
00871   if (detach == MagickFalse)
00872     clone_image->blob=ReferenceBlob(image->blob);
00873   else
00874     clone_image->blob=CloneBlobInfo((BlobInfo *) NULL);
00875   clone_image->debug=IsEventLogging();
00876   clone_image->semaphore=AllocateSemaphoreInfo();
00877   if ((columns == 0) && (rows == 0))
00878     {
00879       if (image->montage != (char *) NULL)
00880         (void) CloneString(&clone_image->montage,image->montage);
00881       if (image->directory != (char *) NULL)
00882         (void) CloneString(&clone_image->directory,image->directory);
00883       if (image->clip_mask != (Image *) NULL)
00884         clone_image->clip_mask=CloneImage(image->clip_mask,0,0,MagickTrue,
00885           exception);
00886       if (image->mask != (Image *) NULL)
00887         clone_image->mask=CloneImage(image->mask,0,0,MagickTrue,exception);
00888       clone_image->cache=ReferencePixelCache(image->cache);
00889       return(clone_image);
00890     }
00891   scale=(MagickRealType) columns/(MagickRealType) image->columns;
00892   clone_image->page.width=(unsigned long) (scale*image->page.width+0.5);
00893   clone_image->page.x=(long) (scale*image->page.x+0.5);
00894   clone_image->tile_offset.x=(long) (scale*image->tile_offset.x+0.5);
00895   scale=(MagickRealType) rows/(MagickRealType) image->rows;
00896   clone_image->page.height=(unsigned long) (scale*image->page.height+0.5);
00897   clone_image->page.y=(long) (image->page.y*scale+0.5);
00898   clone_image->tile_offset.y=(long) (scale*image->tile_offset.y+0.5);
00899   clone_image->columns=columns;
00900   clone_image->rows=rows;
00901   clone_image->cache=ClonePixelCache(image->cache);
00902   return(clone_image);
00903 }
00904 
00905 /*
00906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00907 %                                                                             %
00908 %                                                                             %
00909 %                                                                             %
00910 %   C l o n e I m a g e I n f o                                               %
00911 %                                                                             %
00912 %                                                                             %
00913 %                                                                             %
00914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00915 %
00916 %  CloneImageInfo() makes a copy of the given image info structure.  If
00917 %  NULL is specified, a new image info structure is created initialized to
00918 %  default values.
00919 %
00920 %  The format of the CloneImageInfo method is:
00921 %
00922 %      ImageInfo *CloneImageInfo(const ImageInfo *image_info)
00923 %
00924 %  A description of each parameter follows:
00925 %
00926 %    o image_info: the image info.
00927 %
00928 */
00929 MagickExport ImageInfo *CloneImageInfo(const ImageInfo *image_info)
00930 {
00931   ImageInfo
00932     *clone_info;
00933 
00934   clone_info=AcquireImageInfo();
00935   if (image_info == (ImageInfo *) NULL)
00936     return(clone_info);
00937   clone_info->compression=image_info->compression;
00938   clone_info->temporary=image_info->temporary;
00939   clone_info->adjoin=image_info->adjoin;
00940   clone_info->antialias=image_info->antialias;
00941   clone_info->scene=image_info->scene;
00942   clone_info->number_scenes=image_info->number_scenes;
00943   clone_info->depth=image_info->depth;
00944   if (image_info->size != (char *) NULL)
00945     (void) CloneString(&clone_info->size,image_info->size);
00946   if (image_info->extract != (char *) NULL)
00947     (void) CloneString(&clone_info->extract,image_info->extract);
00948   if (image_info->scenes != (char *) NULL)
00949     (void) CloneString(&clone_info->scenes,image_info->scenes);
00950   if (image_info->page != (char *) NULL)
00951     (void) CloneString(&clone_info->page,image_info->page);
00952   clone_info->interlace=image_info->interlace;
00953   clone_info->endian=image_info->endian;
00954   clone_info->units=image_info->units;
00955   clone_info->quality=image_info->quality;
00956   if (image_info->sampling_factor != (char *) NULL)
00957     (void) CloneString(&clone_info->sampling_factor,
00958       image_info->sampling_factor);
00959   if (image_info->server_name != (char *) NULL)
00960     (void) CloneString(&clone_info->server_name,image_info->server_name);
00961   if (image_info->font != (char *) NULL)
00962     (void) CloneString(&clone_info->font,image_info->font);
00963   if (image_info->texture != (char *) NULL)
00964     (void) CloneString(&clone_info->texture,image_info->texture);
00965   if (image_info->density != (char *) NULL)
00966     (void) CloneString(&clone_info->density,image_info->density);
00967   clone_info->pointsize=image_info->pointsize;
00968   clone_info->fuzz=image_info->fuzz;
00969   clone_info->pen=image_info->pen;
00970   clone_info->background_color=image_info->background_color;
00971   clone_info->border_color=image_info->border_color;
00972   clone_info->matte_color=image_info->matte_color;
00973   clone_info->transparent_color=image_info->transparent_color;
00974   clone_info->dither=image_info->dither;
00975   clone_info->monochrome=image_info->monochrome;
00976   clone_info->colors=image_info->colors;
00977   clone_info->colorspace=image_info->colorspace;
00978   clone_info->type=image_info->type;
00979   clone_info->orientation=image_info->orientation;
00980   clone_info->preview_type=image_info->preview_type;
00981   clone_info->group=image_info->group;
00982   clone_info->ping=image_info->ping;
00983   clone_info->verbose=image_info->verbose;
00984   if (image_info->view != (char *) NULL)
00985     (void) CloneString(&clone_info->view,image_info->view);
00986   if (image_info->authenticate != (char *) NULL)
00987     (void) CloneString(&clone_info->authenticate,image_info->authenticate);
00988   (void) CloneImageOptions(clone_info,image_info);
00989   clone_info->progress_monitor=image_info->progress_monitor;
00990   clone_info->client_data=image_info->client_data;
00991   clone_info->cache=image_info->cache;
00992   if (image_info->cache != (void *) NULL)
00993     clone_info->cache=ReferencePixelCache(image_info->cache);
00994   if (image_info->profile != (void *) NULL)
00995     clone_info->profile=(void *) CloneStringInfo((StringInfo *)
00996       image_info->profile);
00997   SetImageInfoFile(clone_info,image_info->file);
00998   SetImageInfoBlob(clone_info,image_info->blob,image_info->length);
00999   clone_info->stream=image_info->stream;
01000   clone_info->virtual_pixel_method=image_info->virtual_pixel_method;
01001   (void) CopyMagickString(clone_info->magick,image_info->magick,MaxTextExtent);
01002   (void) CopyMagickString(clone_info->unique,image_info->unique,MaxTextExtent);
01003   (void) CopyMagickString(clone_info->zero,image_info->zero,MaxTextExtent);
01004   (void) CopyMagickString(clone_info->filename,image_info->filename,
01005     MaxTextExtent);
01006   clone_info->subimage=image_info->scene;  /* deprecated */
01007   clone_info->subrange=image_info->number_scenes;  /* deprecated */
01008   clone_info->channel=image_info->channel;
01009   clone_info->debug=IsEventLogging();
01010   clone_info->signature=image_info->signature;
01011   return(clone_info);
01012 }
01013 
01014 /*
01015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01016 %                                                                             %
01017 %                                                                             %
01018 %                                                                             %
01019 %     C o m b i n e I m a g e s                                               %
01020 %                                                                             %
01021 %                                                                             %
01022 %                                                                             %
01023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01024 %
01025 %  CombineImages() combines one or more images into a single image.  The
01026 %  grayscale value of the pixels of each image in the sequence is assigned in
01027 %  order to the specified channels of the combined image.   The typical
01028 %  ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
01029 %
01030 %  The format of the CombineImages method is:
01031 %
01032 %      Image *CombineImages(const Image *image,const ChannelType channel,
01033 %        ExceptionInfo *exception)
01034 %
01035 %  A description of each parameter follows:
01036 %
01037 %    o image: the image.
01038 %
01039 %    o exception: return any errors or warnings in this structure.
01040 %
01041 */
01042 MagickExport Image *CombineImages(const Image *image,const ChannelType channel,
01043   ExceptionInfo *exception)
01044 {
01045 #define CombineImageTag  "Combine/Image"
01046 
01047   CacheView
01048     *combine_view;
01049 
01050   const Image
01051     *next;
01052 
01053   Image
01054     *combine_image;
01055 
01056   long
01057     progress,
01058     y;
01059 
01060   MagickBooleanType
01061     status;
01062 
01063   /*
01064     Ensure the image are the same size.
01065   */
01066   assert(image != (const Image *) NULL);
01067   assert(image->signature == MagickSignature);
01068   if (image->debug != MagickFalse)
01069     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01070   assert(exception != (ExceptionInfo *) NULL);
01071   assert(exception->signature == MagickSignature);
01072   for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
01073   {
01074     if ((next->columns != image->columns) || (next->rows != image->rows))
01075       ThrowImageException(OptionError,"ImagesAreNotTheSameSize");
01076   }
01077   combine_image=CloneImage(image,0,0,MagickTrue,exception);
01078   if (combine_image == (Image *) NULL)
01079     return((Image *) NULL);
01080   if (SetImageStorageClass(combine_image,DirectClass) == MagickFalse)
01081     {
01082       InheritException(exception,&combine_image->exception);
01083       combine_image=DestroyImage(combine_image);
01084       return((Image *) NULL);
01085     }
01086   if ((channel & OpacityChannel) != 0)
01087     combine_image->matte=MagickTrue;
01088   (void) SetImageBackgroundColor(combine_image);
01089   /*
01090     Combine images.
01091   */
01092   status=MagickTrue;
01093   progress=0;
01094   combine_view=AcquireCacheView(combine_image);
01095 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01096   #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
01097 #endif
01098   for (y=0; y < (long) combine_image->rows; y++)
01099   {
01100     CacheView
01101       *image_view;
01102 
01103     const Image
01104       *next;
01105 
01106     PixelPacket
01107       *pixels;
01108 
01109     register const PixelPacket
01110       *__restrict p;
01111 
01112     register long
01113       x;
01114 
01115     register PixelPacket
01116       *__restrict q;
01117 
01118     if (status == MagickFalse)
01119       continue;
01120     pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns,
01121       1,exception);
01122     if (pixels == (PixelPacket *) NULL)
01123       {
01124         status=MagickFalse;
01125         continue;
01126       }
01127     next=image;
01128     if (((channel & RedChannel) != 0) && (next != (Image *) NULL))
01129       {
01130         image_view=AcquireCacheView(next);
01131         p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
01132         if (p == (const PixelPacket *) NULL)
01133           continue;
01134         q=pixels;
01135         for (x=0; x < (long) combine_image->columns; x++)
01136         {
01137           q->red=PixelIntensityToQuantum(p);
01138           p++;
01139           q++;
01140         }
01141         image_view=DestroyCacheView(image_view);
01142         next=GetNextImageInList(next);
01143       }
01144     if (((channel & GreenChannel) != 0) && (next != (Image *) NULL))
01145       {
01146         image_view=AcquireCacheView(next);
01147         p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
01148         if (p == (const PixelPacket *) NULL)
01149           continue;
01150         q=pixels;
01151         for (x=0; x < (long) combine_image->columns; x++)
01152         {
01153           q->green=PixelIntensityToQuantum(p);
01154           p++;
01155           q++;
01156         }
01157         image_view=DestroyCacheView(image_view);
01158         next=GetNextImageInList(next);
01159       }
01160     if (((channel & BlueChannel) != 0) && (next != (Image *) NULL))
01161       {
01162         image_view=AcquireCacheView(next);
01163         p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
01164         if (p == (const PixelPacket *) NULL)
01165           continue;
01166         q=pixels;
01167         for (x=0; x < (long) combine_image->columns; x++)
01168         {
01169           q->blue=PixelIntensityToQuantum(p);
01170           p++;
01171           q++;
01172         }
01173         image_view=DestroyCacheView(image_view);
01174         next=GetNextImageInList(next);
01175       }
01176     if (((channel & OpacityChannel) != 0) && (next != (Image *) NULL))
01177       {
01178         image_view=AcquireCacheView(next);
01179         p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
01180         if (p == (const PixelPacket *) NULL)
01181           continue;
01182         q=pixels;
01183         for (x=0; x < (long) combine_image->columns; x++)
01184         {
01185           q->opacity=PixelIntensityToQuantum(p);
01186           p++;
01187           q++;
01188         }
01189         image_view=DestroyCacheView(image_view);
01190         next=GetNextImageInList(next);
01191       }
01192     if (((channel & IndexChannel) != 0) &&
01193         (image->colorspace == CMYKColorspace) && (next != (Image *) NULL))
01194       {
01195         IndexPacket
01196           *indexes;
01197 
01198         image_view=AcquireCacheView(next);
01199         p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
01200         if (p == (const PixelPacket *) NULL)
01201           continue;
01202         indexes=GetCacheViewAuthenticIndexQueue(combine_view);
01203         for (x=0; x < (long) combine_image->columns; x++)
01204         {
01205           indexes[x]=PixelIntensityToQuantum(p);
01206           p++;
01207         }
01208         image_view=DestroyCacheView(image_view);
01209         next=GetNextImageInList(next);
01210       }
01211     if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse)
01212       status=MagickFalse;
01213     if (image->progress_monitor != (MagickProgressMonitor) NULL)
01214       {
01215         MagickBooleanType
01216           proceed;
01217 
01218 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01219         #pragma omp critical (MagickCore_CombineImages)
01220 #endif
01221         proceed=SetImageProgress(image,CombineImageTag,progress++,
01222           combine_image->rows);
01223         if (proceed == MagickFalse)
01224           status=MagickFalse;
01225       }
01226   }
01227   combine_view=DestroyCacheView(combine_view);
01228   if (status == MagickFalse)
01229     combine_image=DestroyImage(combine_image);
01230   return(combine_image);
01231 }
01232 
01233 /*
01234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01235 %                                                                             %
01236 %                                                                             %
01237 %                                                                             %
01238 %   D e s t r o y I m a g e                                                   %
01239 %                                                                             %
01240 %                                                                             %
01241 %                                                                             %
01242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01243 %
01244 %  DestroyImage() dereferences an image, deallocating memory associated with
01245 %  the image if the reference count becomes zero.
01246 %
01247 %  The format of the DestroyImage method is:
01248 %
01249 %      Image *DestroyImage(Image *image)
01250 %
01251 %  A description of each parameter follows:
01252 %
01253 %    o image: the image.
01254 %
01255 */
01256 MagickExport Image *DestroyImage(Image *image)
01257 {
01258   MagickBooleanType
01259     destroy;
01260 
01261   /*
01262     Dereference image.
01263   */
01264   assert(image != (Image *) NULL);
01265   assert(image->signature == MagickSignature);
01266   if (image->debug != MagickFalse)
01267     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01268   destroy=MagickFalse;
01269   (void) LockSemaphoreInfo(image->semaphore);
01270   image->reference_count--;
01271   if (image->reference_count == 0)
01272     destroy=MagickTrue;
01273   (void) UnlockSemaphoreInfo(image->semaphore);
01274   if (destroy == MagickFalse)
01275     return((Image *) NULL);
01276   /*
01277     Destroy image.
01278   */
01279   DestroyImagePixels(image);
01280   if (image->clip_mask != (Image *) NULL)
01281     image->clip_mask=DestroyImage(image->clip_mask);
01282   if (image->mask != (Image *) NULL)
01283     image->mask=DestroyImage(image->mask);
01284   if (image->montage != (char *) NULL)
01285     image->montage=DestroyString(image->montage);
01286   if (image->directory != (char *) NULL)
01287     image->directory=DestroyString(image->directory);
01288   if (image->colormap != (PixelPacket *) NULL)
01289     image->colormap=(PixelPacket *) RelinquishMagickMemory(image->colormap);
01290   if (image->geometry != (char *) NULL)
01291     image->geometry=DestroyString(image->geometry);
01292   DestroyImageProfiles(image);
01293   DestroyImageProperties(image);
01294   DestroyImageArtifacts(image);
01295   if (image->ascii85 != (Ascii85Info*) NULL)
01296     image->ascii85=(Ascii85Info *) RelinquishMagickMemory(image->ascii85);
01297   DestroyBlob(image);
01298   (void) DestroyExceptionInfo(&image->exception);
01299   if (image->semaphore != (SemaphoreInfo *) NULL)
01300     DestroySemaphoreInfo(&image->semaphore);
01301   image->signature=(~MagickSignature);
01302   image=(Image *) RelinquishMagickMemory(image);
01303   return(image);
01304 }
01305 
01306 /*
01307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01308 %                                                                             %
01309 %                                                                             %
01310 %                                                                             %
01311 %   D e s t r o y I m a g e I n f o                                           %
01312 %                                                                             %
01313 %                                                                             %
01314 %                                                                             %
01315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01316 %
01317 %  DestroyImageInfo() deallocates memory associated with an ImageInfo
01318 %  structure.
01319 %
01320 %  The format of the DestroyImageInfo method is:
01321 %
01322 %      ImageInfo *DestroyImageInfo(ImageInfo *image_info)
01323 %
01324 %  A description of each parameter follows:
01325 %
01326 %    o image_info: the image info.
01327 %
01328 */
01329 MagickExport ImageInfo *DestroyImageInfo(ImageInfo *image_info)
01330 {
01331   assert(image_info != (ImageInfo *) NULL);
01332   assert(image_info->signature == MagickSignature);
01333   if (image_info->debug != MagickFalse)
01334     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
01335       image_info->filename);
01336   if (image_info->size != (char *) NULL)
01337     image_info->size=DestroyString(image_info->size);
01338   if (image_info->extract != (char *) NULL)
01339     image_info->extract=DestroyString(image_info->extract);
01340   if (image_info->scenes != (char *) NULL)
01341     image_info->scenes=DestroyString(image_info->scenes);
01342   if (image_info->page != (char *) NULL)
01343     image_info->page=DestroyString(image_info->page);
01344   if (image_info->sampling_factor != (char *) NULL)
01345     image_info->sampling_factor=DestroyString(
01346       image_info->sampling_factor);
01347   if (image_info->server_name != (char *) NULL)
01348     image_info->server_name=DestroyString(
01349       image_info->server_name);
01350   if (image_info->font != (char *) NULL)
01351     image_info->font=DestroyString(image_info->font);
01352   if (image_info->texture != (char *) NULL)
01353     image_info->texture=DestroyString(image_info->texture);
01354   if (image_info->density != (char *) NULL)
01355     image_info->density=DestroyString(image_info->density);
01356   if (image_info->view != (char *) NULL)
01357     image_info->view=DestroyString(image_info->view);
01358   if (image_info->authenticate != (char *) NULL)
01359     image_info->authenticate=DestroyString(
01360       image_info->authenticate);
01361   DestroyImageOptions(image_info);
01362   if (image_info->cache != (void *) NULL)
01363     image_info->cache=DestroyPixelCache(image_info->cache);
01364   if (image_info->profile != (StringInfo *) NULL)
01365     image_info->profile=(void *) DestroyStringInfo((StringInfo *)
01366       image_info->profile);
01367   image_info->signature=(~MagickSignature);
01368   image_info=(ImageInfo *) RelinquishMagickMemory(image_info);
01369   return(image_info);
01370 }
01371 
01372 /*
01373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01374 %                                                                             %
01375 %                                                                             %
01376 %                                                                             %
01377 +   D i s a s s o c i a t e I m a g e S t r e a m                             %
01378 %                                                                             %
01379 %                                                                             %
01380 %                                                                             %
01381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01382 %
01383 %  DisassociateImageStream() disassociates the image stream.
01384 %
01385 %  The format of the DisassociateImageStream method is:
01386 %
01387 %      MagickBooleanType DisassociateImageStream(const Image *image)
01388 %
01389 %  A description of each parameter follows:
01390 %
01391 %    o image: the image.
01392 %
01393 */
01394 MagickExport void DisassociateImageStream(Image *image)
01395 {
01396   assert(image != (const Image *) NULL);
01397   assert(image->signature == MagickSignature);
01398   if (image->debug != MagickFalse)
01399     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01400   (void) DetachBlob(image->blob);
01401 }
01402 
01403 /*
01404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01405 %                                                                             %
01406 %                                                                             %
01407 %                                                                             %
01408 %   G e t I m a g e A l p h a C h a n n e l                                   %
01409 %                                                                             %
01410 %                                                                             %
01411 %                                                                             %
01412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01413 %
01414 %  GetImageAlphaChannel() returns MagickFalse if the image alpha channel is
01415 %  not activated.  That is, the image is RGB rather than RGBA or CMYK rather
01416 %  than CMYKA.
01417 %
01418 %  The format of the GetImageAlphaChannel method is:
01419 %
01420 %      MagickBooleanType GetImageAlphaChannel(const Image *image)
01421 %
01422 %  A description of each parameter follows:
01423 %
01424 %    o image: the image.
01425 %
01426 */
01427 MagickExport MagickBooleanType GetImageAlphaChannel(const Image *image)
01428 {
01429   assert(image != (const Image *) NULL);
01430   if (image->debug != MagickFalse)
01431     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01432   assert(image->signature == MagickSignature);
01433   return(image->matte);
01434 }
01435 
01436 /*
01437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01438 %                                                                             %
01439 %                                                                             %
01440 %                                                                             %
01441 %   G e t I m a g e C l i p M a s k                                           %
01442 %                                                                             %
01443 %                                                                             %
01444 %                                                                             %
01445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01446 %
01447 %  GetImageClipMask() returns the clip path associated with the image.
01448 %
01449 %  The format of the GetImageClipMask method is:
01450 %
01451 %      Image *GetImageClipMask(const Image *image,ExceptionInfo *exception)
01452 %
01453 %  A description of each parameter follows:
01454 %
01455 %    o image: the image.
01456 %
01457 */
01458 MagickExport Image *GetImageClipMask(const Image *image,
01459   ExceptionInfo *exception)
01460 {
01461   assert(image != (const Image *) NULL);
01462   if (image->debug != MagickFalse)
01463     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01464   assert(image->signature == MagickSignature);
01465   if (image->clip_mask == (Image *) NULL)
01466     return((Image *) NULL);
01467   return(CloneImage(image->clip_mask,0,0,MagickTrue,exception));
01468 }
01469 
01470 /*
01471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01472 %                                                                             %
01473 %                                                                             %
01474 %                                                                             %
01475 %   G e t I m a g e E x c e p t i o n                                         %
01476 %                                                                             %
01477 %                                                                             %
01478 %                                                                             %
01479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01480 %
01481 %  GetImageException() traverses an image sequence and returns any
01482 %  error more severe than noted by the exception parameter.
01483 %
01484 %  The format of the GetImageException method is:
01485 %
01486 %      void GetImageException(Image *image,ExceptionInfo *exception)
01487 %
01488 %  A description of each parameter follows:
01489 %
01490 %    o image: Specifies a pointer to a list of one or more images.
01491 %
01492 %    o exception: return the highest severity exception.
01493 %
01494 */
01495 MagickExport void GetImageException(Image *image,ExceptionInfo *exception)
01496 {
01497   register Image
01498     *next;
01499 
01500   assert(image != (Image *) NULL);
01501   assert(image->signature == MagickSignature);
01502   if (image->debug != MagickFalse)
01503     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01504   assert(exception != (ExceptionInfo *) NULL);
01505   assert(exception->signature == MagickSignature);
01506   for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
01507   {
01508     if (next->exception.severity == UndefinedException)
01509       continue;
01510     if (next->exception.severity > exception->severity)
01511       InheritException(exception,&next->exception);
01512     next->exception.severity=UndefinedException;
01513   }
01514 }
01515 
01516 /*
01517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01518 %                                                                             %
01519 %                                                                             %
01520 %                                                                             %
01521 %   G e t I m a g e I n f o                                                   %
01522 %                                                                             %
01523 %                                                                             %
01524 %                                                                             %
01525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01526 %
01527 %  GetImageInfo() initializes image_info to default values.
01528 %
01529 %  The format of the GetImageInfo method is:
01530 %
01531 %      void GetImageInfo(ImageInfo *image_info)
01532 %
01533 %  A description of each parameter follows:
01534 %
01535 %    o image_info: the image info.
01536 %
01537 */
01538 MagickExport void GetImageInfo(ImageInfo *image_info)
01539 {
01540   ExceptionInfo
01541     *exception;
01542 
01543   /*
01544     File and image dimension members.
01545   */
01546   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01547   assert(image_info != (ImageInfo *) NULL);
01548   (void) ResetMagickMemory(image_info,0,sizeof(*image_info));
01549   image_info->adjoin=MagickTrue;
01550   image_info->interlace=NoInterlace;
01551   image_info->channel=DefaultChannels;
01552   image_info->quality=UndefinedCompressionQuality;
01553   image_info->antialias=MagickTrue;
01554   image_info->dither=MagickTrue;
01555   exception=AcquireExceptionInfo();
01556   (void) QueryColorDatabase(BackgroundColor,&image_info->background_color,
01557     exception);
01558   (void) QueryColorDatabase(BorderColor,&image_info->border_color,exception);
01559   (void) QueryColorDatabase(MatteColor,&image_info->matte_color,exception);
01560   (void) QueryColorDatabase(TransparentColor,&image_info->transparent_color,
01561     exception);
01562   exception=DestroyExceptionInfo(exception);
01563   image_info->debug=IsEventLogging();
01564   image_info->signature=MagickSignature;
01565 }
01566 
01567 /*
01568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01569 %                                                                             %
01570 %                                                                             %
01571 %                                                                             %
01572 %   G e t I m a g e M a s k                                                   %
01573 %                                                                             %
01574 %                                                                             %
01575 %                                                                             %
01576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01577 %
01578 %  GetImageMask() returns the mask associated with the image.
01579 %
01580 %  The format of the GetImageMask method is:
01581 %
01582 %      Image *GetImageMask(const Image *image,ExceptionInfo *exception)
01583 %
01584 %  A description of each parameter follows:
01585 %
01586 %    o image: the image.
01587 %
01588 */
01589 MagickExport Image *GetImageMask(const Image *image,ExceptionInfo *exception)
01590 {
01591   assert(image != (const Image *) NULL);
01592   if (image->debug != MagickFalse)
01593     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01594   assert(image->signature == MagickSignature);
01595   if (image->mask == (Image *) NULL)
01596     return((Image *) NULL);
01597   return(CloneImage(image->mask,0,0,MagickTrue,exception));
01598 }
01599 
01600 /*
01601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01602 %                                                                             %
01603 %                                                                             %
01604 %                                                                             %
01605 +   G e t I m a g e R e f e r e n c e C o u n t                               %
01606 %                                                                             %
01607 %                                                                             %
01608 %                                                                             %
01609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01610 %
01611 %  GetImageReferenceCount() returns the image reference count.
01612 %
01613 %  The format of the GetReferenceCount method is:
01614 %
01615 %      long GetImageReferenceCount(Image *image)
01616 %
01617 %  A description of each parameter follows:
01618 %
01619 %    o image: the image.
01620 %
01621 */
01622 MagickExport long GetImageReferenceCount(Image *image)
01623 {
01624   long
01625     reference_count;
01626 
01627   assert(image != (Image *) NULL);
01628   assert(image->signature == MagickSignature);
01629   if (image->debug != MagickFalse)
01630     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01631   (void) LockSemaphoreInfo(image->semaphore);
01632   reference_count=image->reference_count;
01633   (void) UnlockSemaphoreInfo(image->semaphore);
01634   return(reference_count);
01635 }
01636 
01637 /*
01638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01639 %                                                                             %
01640 %                                                                             %
01641 %                                                                             %
01642 %   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                       %
01643 %                                                                             %
01644 %                                                                             %
01645 %                                                                             %
01646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01647 %
01648 %  GetImageVirtualPixelMethod() gets the "virtual pixels" method for the
01649 %  image.  A virtual pixel is any pixel access that is outside the boundaries
01650 %  of the image cache.
01651 %
01652 %  The format of the GetImageVirtualPixelMethod() method is:
01653 %
01654 %      VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
01655 %
01656 %  A description of each parameter follows:
01657 %
01658 %    o image: the image.
01659 %
01660 */
01661 MagickExport VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
01662 {
01663   assert(image != (Image *) NULL);
01664   assert(image->signature == MagickSignature);
01665   if (image->debug != MagickFalse)
01666     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01667   return(GetPixelCacheVirtualMethod(image));
01668 }
01669 
01670 /*
01671 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01672 %                                                                             %
01673 %                                                                             %
01674 %                                                                             %
01675 %  I n t e r p r e t I m a g e F i l e n a m e                                %
01676 %                                                                             %
01677 %                                                                             %
01678 %                                                                             %
01679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01680 %
01681 %  InterpretImageFilename() interprets embedded characters in an image filename.
01682 %  The filename length is returned.
01683 %
01684 %  The format of the InterpretImageFilename method is:
01685 %
01686 %      size_t InterpretImageFilename(const ImageInfo *image_info,
01687 %        Image *image,const char *format,int value,char *filename)
01688 %
01689 %  A description of each parameter follows.
01690 %
01691 %    o image_info: the image info..
01692 %
01693 %    o image: the image.
01694 %
01695 %    o format:  A filename describing the format to use to write the numeric
01696 %      argument. Only the first numeric format identifier is replaced.
01697 %
01698 %    o value:  Numeric value to substitute into format filename.
01699 %
01700 %    o filename:  return the formatted filename in this character buffer.
01701 %
01702 */
01703 MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
01704   Image *image,const char *format,int value,char *filename)
01705 {
01706   char
01707     *q;
01708 
01709   int
01710     c;
01711 
01712   MagickBooleanType
01713     canonical;
01714 
01715   register const char
01716     *p;
01717 
01718   canonical=MagickFalse;
01719   (void) CopyMagickString(filename,format,MaxTextExtent);
01720   for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
01721   {
01722     q=(char *) p+1;
01723     if (*q == '%')
01724       {
01725         p=q+1;
01726         continue;
01727       }
01728     if (*q == '0')
01729       {
01730         long
01731           value;
01732 
01733         value=strtol(q,&q,10);
01734       }
01735     switch (*q)
01736     {
01737       case 'd':
01738       case 'o':
01739       case 'x':
01740       {
01741         q++;
01742         c=(*q);
01743         *q='\0';
01744         (void) FormatMagickString(filename+(p-format),(size_t) (MaxTextExtent-
01745           (p-format)),p,value);
01746         *q=c;
01747         (void) ConcatenateMagickString(filename,q,MaxTextExtent);
01748         canonical=MagickTrue;
01749         if (*(q-1) != '%')
01750           break;
01751         p++;
01752         break;
01753       }
01754       case '[':
01755       {
01756         char
01757           pattern[MaxTextExtent];
01758 
01759         const char
01760           *value;
01761 
01762         long
01763           depth;
01764 
01765         register char
01766           *r;
01767 
01768         register long
01769           i;
01770 
01771         /*
01772           Image option.
01773         */
01774         if (strchr(p,']') == (char *) NULL)
01775           break;
01776         depth=1;
01777         r=q+1;
01778         for (i=0; (i < (MaxTextExtent-1L)) && (*r != '\0'); i++)
01779         {
01780           if (*r == '[')
01781             depth++;
01782           if (*r == ']')
01783             depth--;
01784           if (depth <= 0)
01785             break;
01786           pattern[i]=(*r++);
01787         }
01788         pattern[i]='\0';
01789         if (LocaleNCompare(pattern,"filename:",9) != 0)
01790           break;
01791         value=(const char *) NULL;
01792         if ((image_info != (const ImageInfo *) NULL) &&
01793             (image != (const Image *) NULL))
01794           value=GetMagickProperty(image_info,image,pattern);
01795         else
01796           if (image != (Image *) NULL)
01797             value=GetImageProperty(image,pattern);
01798           else
01799             if (image_info != (ImageInfo *) NULL)
01800               value=GetImageOption(image_info,pattern);
01801         if (value == (const char *) NULL)
01802           break;
01803         q--;
01804         c=(*q);
01805         *q='\0';
01806         (void) CopyMagickString(filename+(p-format),value,(size_t)
01807           (MaxTextExtent-(p-format)));
01808         *q=c;
01809         (void) ConcatenateMagickString(filename,r+1,MaxTextExtent);
01810         canonical=MagickTrue;
01811         if (*(q-1) != '%')
01812           break;
01813         p++;
01814         break;
01815       }
01816       default:
01817         break;
01818     }
01819   }
01820   for (q=filename; *q != '\0'; q++)
01821     if ((*q == '%') && (*(q+1) == '%'))
01822       (void) CopyMagickString(q,q+1,(size_t) (MaxTextExtent-(q-filename)));
01823   if (canonical == MagickFalse)
01824     (void) CopyMagickString(filename,format,MaxTextExtent);
01825   return(strlen(filename));
01826 }
01827 
01828 /*
01829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01830 %                                                                             %
01831 %                                                                             %
01832 %                                                                             %
01833 %   I s H i g h D y n a m i c R a n g e I m a g e                             %
01834 %                                                                             %
01835 %                                                                             %
01836 %                                                                             %
01837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01838 %
01839 %  IsHighDynamicRangeImage() returns MagickTrue if any pixel component is
01840 %  non-integer or exceeds the bounds of the quantum depth (e.g. for Q16
01841 %  0..65535.
01842 %
01843 %  The format of the IsHighDynamicRangeImage method is:
01844 %
01845 %      MagickBooleanType IsHighDynamicRangeImage(const Image *image,
01846 %        ExceptionInfo *exception)
01847 %
01848 %  A description of each parameter follows:
01849 %
01850 %    o image: the image.
01851 %
01852 %    o exception: return any errors or warnings in this structure.
01853 %
01854 */
01855 MagickExport MagickBooleanType IsHighDynamicRangeImage(const Image *image,
01856   ExceptionInfo *exception)
01857 {
01858 #if !defined(MAGICKCORE_HDRI_SUPPORT)
01859   (void) image;
01860   (void) exception;
01861   return(MagickFalse);
01862 #else
01863   CacheView
01864     *image_view;
01865 
01866   long
01867     y;
01868 
01869   MagickBooleanType
01870     status;
01871 
01872   MagickPixelPacket
01873     zero;
01874 
01875   assert(image != (Image *) NULL);
01876   assert(image->signature == MagickSignature);
01877   if (image->debug != MagickFalse)
01878     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01879   status=MagickTrue;
01880   GetMagickPixelPacket(image,&zero);
01881   image_view=AcquireCacheView(image);
01882 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01883   #pragma omp parallel for schedule(dynamic,4) shared(status)
01884 #endif
01885   for (y=0; y < (long) image->rows; y++)
01886   {
01887     MagickPixelPacket
01888       pixel;
01889 
01890     register const IndexPacket
01891       *indexes;
01892 
01893     register const PixelPacket
01894       *p;
01895 
01896     register long
01897       x;
01898 
01899     if (status == MagickFalse)
01900       continue;
01901     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
01902     if (p == (const PixelPacket *) NULL)
01903       {
01904         status=MagickFalse;
01905         continue;
01906       }
01907     indexes=GetCacheViewVirtualIndexQueue(image_view);
01908     pixel=zero;
01909     for (x=0; x < (long) image->columns; x++)
01910     {
01911       SetMagickPixelPacket(image,p,indexes+x,&pixel);
01912       if ((pixel.red < 0.0) || (pixel.red > QuantumRange) ||
01913           (pixel.red != (QuantumAny) pixel.red))
01914         break;
01915       if ((pixel.green < 0.0) || (pixel.green > QuantumRange) ||
01916           (pixel.green != (QuantumAny) pixel.green))
01917         break;
01918       if ((pixel.blue < 0.0) || (pixel.blue > QuantumRange) ||
01919           (pixel.blue != (QuantumAny) pixel.blue))
01920         break;
01921       if (pixel.matte != MagickFalse)
01922         {
01923           if ((pixel.opacity < 0.0) || (pixel.opacity > QuantumRange) ||
01924               (pixel.opacity != (QuantumAny) pixel.opacity))
01925             break;
01926         }
01927       if (pixel.colorspace == CMYKColorspace)
01928         {
01929           if ((pixel.index < 0.0) || (pixel.index > QuantumRange) ||
01930               (pixel.index != (QuantumAny) pixel.index))
01931             break;
01932         }
01933       p++;
01934     }
01935     if (x < (long) image->columns)
01936       status=MagickFalse;
01937   }
01938   image_view=DestroyCacheView(image_view);
01939   return(status != MagickFalse ? MagickFalse : MagickTrue);
01940 #endif
01941 }
01942 
01943 /*
01944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01945 %                                                                             %
01946 %                                                                             %
01947 %                                                                             %
01948 %     I s I m a g e O b j e c t                                               %
01949 %                                                                             %
01950 %                                                                             %
01951 %                                                                             %
01952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01953 %
01954 %  IsImageObject() returns MagickTrue if the image sequence contains a valid
01955 %  set of image objects.
01956 %
01957 %  The format of the IsImageObject method is:
01958 %
01959 %      MagickBooleanType IsImageObject(const Image *image)
01960 %
01961 %  A description of each parameter follows:
01962 %
01963 %    o image: the image.
01964 %
01965 */
01966 MagickExport MagickBooleanType IsImageObject(const Image *image)
01967 {
01968   register const Image
01969     *p;
01970 
01971   assert(image != (Image *) NULL);
01972   if (image->debug != MagickFalse)
01973     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01974   for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
01975     if (p->signature != MagickSignature)
01976       return(MagickFalse);
01977   return(MagickTrue);
01978 }
01979 
01980 /*
01981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01982 %                                                                             %
01983 %                                                                             %
01984 %                                                                             %
01985 %     I s T a i n t I m a g e                                                 %
01986 %                                                                             %
01987 %                                                                             %
01988 %                                                                             %
01989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01990 %
01991 %  IsTaintImage() returns MagickTrue any pixel in the image has been altered
01992 %  since it was first constituted.
01993 %
01994 %  The format of the IsTaintImage method is:
01995 %
01996 %      MagickBooleanType IsTaintImage(const Image *image)
01997 %
01998 %  A description of each parameter follows:
01999 %
02000 %    o image: the image.
02001 %
02002 */
02003 MagickExport MagickBooleanType IsTaintImage(const Image *image)
02004 {
02005   char
02006     magick[MaxTextExtent],
02007     filename[MaxTextExtent];
02008 
02009   register const Image
02010     *p;
02011 
02012   assert(image != (Image *) NULL);
02013   if (image->debug != MagickFalse)
02014     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02015   assert(image->signature == MagickSignature);
02016   (void) CopyMagickString(magick,image->magick,MaxTextExtent);
02017   (void) CopyMagickString(filename,image->filename,MaxTextExtent);
02018   for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
02019   {
02020     if (p->taint != MagickFalse)
02021       return(MagickTrue);
02022     if (LocaleCompare(p->magick,magick) != 0)
02023       return(MagickTrue);
02024     if (LocaleCompare(p->filename,filename) != 0)
02025       return(MagickTrue);
02026   }
02027   return(MagickFalse);
02028 }
02029 
02030 /*
02031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02032 %                                                                             %
02033 %                                                                             %
02034 %                                                                             %
02035 %   M o d i f y I m a g e                                                     %
02036 %                                                                             %
02037 %                                                                             %
02038 %                                                                             %
02039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02040 %
02041 %  ModifyImage() ensures that there is only a single reference to the image
02042 %  to be modified, updating the provided image pointer to point to a clone of
02043 %  the original image if necessary.
02044 %
02045 %  The format of the ModifyImage method is:
02046 %
02047 %      MagickBooleanType ModifyImage(Image *image,ExceptionInfo *exception)
02048 %
02049 %  A description of each parameter follows:
02050 %
02051 %    o image: the image.
02052 %
02053 %    o exception: return any errors or warnings in this structure.
02054 %
02055 */
02056 MagickExport MagickBooleanType ModifyImage(Image **image,
02057   ExceptionInfo *exception)
02058 {
02059   Image
02060     *clone_image;
02061 
02062   assert(image != (Image **) NULL);
02063   assert(*image != (Image *) NULL);
02064   assert((*image)->signature == MagickSignature);
02065   if ((*image)->debug != MagickFalse)
02066     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
02067   if (GetImageReferenceCount(*image) <= 1)
02068     return(MagickTrue);
02069   clone_image=CloneImage(*image,0,0,MagickTrue,exception);
02070   (void) LockSemaphoreInfo((*image)->semaphore);
02071   (*image)->reference_count--;
02072   (void) UnlockSemaphoreInfo((*image)->semaphore);
02073   *image=clone_image;
02074   return(MagickTrue);
02075 }
02076 
02077 /*
02078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02079 %                                                                             %
02080 %                                                                             %
02081 %                                                                             %
02082 %   N e w M a g i c k I m a g e                                               %
02083 %                                                                             %
02084 %                                                                             %
02085 %                                                                             %
02086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02087 %
02088 %  NewMagickImage() creates a blank image canvas of the specified size and
02089 %  background color.
02090 %
02091 %  The format of the NewMagickImage method is:
02092 %
02093 %      Image *NewMagickImage(const ImageInfo *image_info,
02094 %        const unsigned long width,const unsigned long height,
02095 %        const MagickPixelPacket *background)
02096 %
02097 %  A description of each parameter follows:
02098 %
02099 %    o image: the image.
02100 %
02101 %    o width: the image width.
02102 %
02103 %    o height: the image height.
02104 %
02105 %    o background: the image color.
02106 %
02107 */
02108 MagickExport Image *NewMagickImage(const ImageInfo *image_info,
02109   const unsigned long width,const unsigned long height,
02110   const MagickPixelPacket *background)
02111 {
02112   CacheView
02113     *image_view;
02114 
02115   ExceptionInfo
02116     *exception;
02117 
02118   Image
02119     *image;
02120 
02121   long
02122     y;
02123 
02124   MagickBooleanType
02125     status;
02126 
02127   assert(image_info != (const ImageInfo *) NULL);
02128   if (image_info->debug != MagickFalse)
02129     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02130   assert(image_info->signature == MagickSignature);
02131   assert(background != (const MagickPixelPacket *) NULL);
02132   image=AcquireImage(image_info);
02133   image->columns=width;
02134   image->rows=height;
02135   image->colorspace=background->colorspace;
02136   image->matte=background->matte;
02137   image->fuzz=background->fuzz;
02138   image->depth=background->depth;
02139   status=MagickTrue;
02140   exception=(&image->exception);
02141   image_view=AcquireCacheView(image);
02142   for (y=0; y < (long) image->rows; y++)
02143   {
02144     register IndexPacket
02145       *__restrict indexes;
02146 
02147     register long
02148       x;
02149 
02150     register PixelPacket
02151       *__restrict q;
02152 
02153     q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
02154     if (q == (PixelPacket *) NULL)
02155       {
02156         status=MagickFalse;
02157         continue;
02158       }
02159     indexes=GetCacheViewAuthenticIndexQueue(image_view);
02160     for (x=0; x < (long) image->columns; x++)
02161     {
02162       SetPixelPacket(image,background,q,indexes+x);
02163       q++;
02164     }
02165     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
02166       status=MagickFalse;
02167     if (status == MagickFalse)
02168       break;
02169   }
02170   image_view=DestroyCacheView(image_view);
02171   if (status == MagickFalse)
02172     image=DestroyImage(image);
02173   return(image);
02174 }
02175 
02176 /*
02177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02178 %                                                                             %
02179 %                                                                             %
02180 %                                                                             %
02181 %   R e f e r e n c e I m a g e                                               %
02182 %                                                                             %
02183 %                                                                             %
02184 %                                                                             %
02185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02186 %
02187 %  ReferenceImage() increments the reference count associated with an image
02188 %  returning a pointer to the image.
02189 %
02190 %  The format of the ReferenceImage method is:
02191 %
02192 %      Image *ReferenceImage(Image *image)
02193 %
02194 %  A description of each parameter follows:
02195 %
02196 %    o image: the image.
02197 %
02198 */
02199 MagickExport Image *ReferenceImage(Image *image)
02200 {
02201   assert(image != (Image *) NULL);
02202   if (image->debug != MagickFalse)
02203     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02204   assert(image->signature == MagickSignature);
02205   (void) LockSemaphoreInfo(image->semaphore);
02206   image->reference_count++;
02207   (void) UnlockSemaphoreInfo(image->semaphore);
02208   return(image);
02209 }
02210 
02211 /*
02212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02213 %                                                                             %
02214 %                                                                             %
02215 %                                                                             %
02216 %   R e s e t I m a g e P a g e                                               %
02217 %                                                                             %
02218 %                                                                             %
02219 %                                                                             %
02220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02221 %
02222 %  ResetImagePage() resets the image page canvas and position.
02223 %
02224 %  The format of the ResetImagePage method is:
02225 %
02226 %      MagickBooleanType ResetImagePage(Image *image,const char *page)
02227 %
02228 %  A description of each parameter follows:
02229 %
02230 %    o image: the image.
02231 %
02232 %    o page: the relative page specification.
02233 %
02234 */
02235 MagickExport MagickBooleanType ResetImagePage(Image *image,const char *page)
02236 {
02237   MagickStatusType
02238     flags;
02239 
02240   RectangleInfo
02241     geometry;
02242 
02243   assert(image != (Image *) NULL);
02244   assert(image->signature == MagickSignature);
02245   if (image->debug != MagickFalse)
02246     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02247   flags=ParseAbsoluteGeometry(page,&geometry);
02248   if ((flags & WidthValue) != 0)
02249     {
02250       if ((flags & HeightValue) == 0)
02251         geometry.height=geometry.width;
02252       image->page.width=geometry.width;
02253       image->page.height=geometry.height;
02254     }
02255   if ((flags & AspectValue) != 0)
02256     {
02257       if ((flags & XValue) != 0)
02258         image->page.x+=geometry.x;
02259       if ((flags & YValue) != 0)
02260         image->page.y+=geometry.y;
02261     }
02262   else
02263     {
02264       if ((flags & XValue) != 0)
02265         {
02266           image->page.x=geometry.x;
02267           if ((image->page.width == 0) && (geometry.x > 0))
02268             image->page.width=image->columns+geometry.x;
02269         }
02270       if ((flags & YValue) != 0)
02271         {
02272           image->page.y=geometry.y;
02273           if ((image->page.height == 0) && (geometry.y > 0))
02274             image->page.height=image->rows+geometry.y;
02275         }
02276     }
02277   return(MagickTrue);
02278 }
02279 
02280 /*
02281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02282 %                                                                             %
02283 %                                                                             %
02284 %                                                                             %
02285 %     S e p a r a t e I m a g e C h a n n e l                                 %
02286 %                                                                             %
02287 %                                                                             %
02288 %                                                                             %
02289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02290 %
02291 %  SeparateImageChannel() separates a channel from the image and returns it as
02292 %  a grayscale image.  A channel is a particular color component of each pixel
02293 %  in the image.
02294 %
02295 %  The format of the SeparateImageChannel method is:
02296 %
02297 %      MagickBooleanType SeparateImageChannel(Image *image,
02298 %        const ChannelType channel)
02299 %
02300 %  A description of each parameter follows:
02301 %
02302 %    o image: the image.
02303 %
02304 %    o channel: Identify which channel to extract: RedChannel, GreenChannel,
02305 %      BlueChannel, OpacityChannel, CyanChannel, MagentaChannel,
02306 %      YellowChannel, or BlackChannel.
02307 %
02308 */
02309 MagickExport MagickBooleanType SeparateImageChannel(Image *image,
02310   const ChannelType channel)
02311 {
02312 #define SeparateImageTag  "Separate/Image"
02313 
02314   CacheView
02315     *image_view;
02316 
02317   ExceptionInfo
02318     *exception;
02319 
02320   long
02321     progress,
02322     y;
02323 
02324   MagickBooleanType
02325     status;
02326 
02327   assert(image != (Image *) NULL);
02328   assert(image->signature == MagickSignature);
02329   if (image->debug != MagickFalse)
02330     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02331   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
02332     return(MagickFalse);
02333   /*
02334     Separate image channels.
02335   */
02336   status=MagickTrue;
02337   if ( channel == GrayChannels )
02338     image->matte=MagickTrue;
02339   progress=0;
02340   exception=(&image->exception);
02341   image_view=AcquireCacheView(image);
02342 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02343   #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
02344 #endif
02345   for (y=0; y < (long) image->rows; y++)
02346   {
02347     register IndexPacket
02348       *__restrict indexes;
02349 
02350     register long
02351       x;
02352 
02353     register PixelPacket
02354       *__restrict q;
02355 
02356     if (status == MagickFalse)
02357       continue;
02358     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
02359     if (q == (PixelPacket *) NULL)
02360       {
02361         status=MagickFalse;
02362         continue;
02363       }
02364     indexes=GetCacheViewAuthenticIndexQueue(image_view);
02365     switch (channel)
02366     {
02367       case RedChannel:
02368       {
02369         for (x=0; x < (long) image->columns; x++)
02370         {
02371           q->green=q->red;
02372           q->blue=q->red;
02373           q++;
02374         }
02375         break;
02376       }
02377       case GreenChannel:
02378       {
02379         for (x=0; x < (long) image->columns; x++)
02380         {
02381           q->red=q->green;
02382           q->blue=q->green;
02383           q++;
02384         }
02385         break;
02386       }
02387       case BlueChannel:
02388       {
02389         for (x=0; x < (long) image->columns; x++)
02390         {
02391           q->red=q->blue;
02392           q->green=q->blue;
02393           q++;
02394         }
02395         break;
02396       }
02397       case OpacityChannel:
02398       {
02399         for (x=0; x < (long) image->columns; x++)
02400         {
02401           q->red=q->opacity;
02402           q->green=q->opacity;
02403           q->blue=q->opacity;
02404           q++;
02405         }
02406         break;
02407       }
02408       case BlackChannel:
02409       {
02410         if ((image->storage_class != PseudoClass) &&
02411             (image->colorspace != CMYKColorspace))
02412           break;
02413         for (x=0; x < (long) image->columns; x++)
02414         {
02415           q->red=indexes[x];
02416           q->green=indexes[x];
02417           q->blue=indexes[x];
02418           q++;
02419         }
02420         break;
02421       }
02422       case TrueAlphaChannel:
02423       {
02424         for (x=0; x < (long) image->columns; x++)
02425         {
02426           q->red=(Quantum) (QuantumRange-q->opacity);
02427           q->green=(Quantum) (QuantumRange-q->opacity);
02428           q->blue=(Quantum) (QuantumRange-q->opacity);
02429           q++;
02430         }
02431         break;
02432       }
02433       case GrayChannels:
02434       {
02435         for (x=0; x < (long) image->columns; x++)
02436         {
02437           q->opacity=(Quantum) (QuantumRange-PixelIntensityToQuantum(q));
02438           q++;
02439         }
02440         break;
02441       }
02442       default:
02443         break;
02444     }
02445     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
02446       status=MagickFalse;
02447     if (image->progress_monitor != (MagickProgressMonitor) NULL)
02448       {
02449         MagickBooleanType
02450           proceed;
02451 
02452 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02453         #pragma omp critical (MagickCore_SeparateImageChannel)
02454 #endif
02455         proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows);
02456         if (proceed == MagickFalse)
02457           status=MagickFalse;
02458       }
02459   }
02460   image_view=DestroyCacheView(image_view);
02461   if ( channel != GrayChannels )
02462     image->matte=MagickFalse;
02463   (void) SetImageColorspace(image,RGBColorspace);
02464   return(status);
02465 }
02466 
02467 /*
02468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02469 %                                                                             %
02470 %                                                                             %
02471 %                                                                             %
02472 %     S e p a r a t e I m a g e s                                             %
02473 %                                                                             %
02474 %                                                                             %
02475 %                                                                             %
02476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02477 %
02478 %  SeparateImages() returns a separate grayscale image for each channel
02479 %  specified.
02480 %
02481 %  The format of the SeparateImages method is:
02482 %
02483 %      MagickBooleanType SeparateImages(const Image *image,
02484 %        const ChannelType channel,ExceptionInfo *exception)
02485 %
02486 %  A description of each parameter follows:
02487 %
02488 %    o image: the image.
02489 %
02490 %    o channel: Identify which channels to extract: RedChannel, GreenChannel,
02491 %      BlueChannel, OpacityChannel, CyanChannel, MagentaChannel,
02492 %      YellowChannel, or BlackChannel.
02493 %
02494 %    o exception: return any errors or warnings in this structure.
02495 %
02496 */
02497 MagickExport Image *SeparateImages(const Image *image,const ChannelType channel,
02498   ExceptionInfo *exception)
02499 {
02500   Image
02501     *images,
02502     *separate_image;
02503 
02504   assert(image != (Image *) NULL);
02505   assert(image->signature == MagickSignature);
02506   if (image->debug != MagickFalse)
02507     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02508   images=NewImageList();
02509   if ((channel & RedChannel) != 0)
02510     {
02511       separate_image=CloneImage(image,0,0,MagickTrue,exception);
02512       (void) SeparateImageChannel(separate_image,RedChannel);
02513       AppendImageToList(&images,separate_image);
02514     }
02515   if ((channel & GreenChannel) != 0)
02516     {
02517       separate_image=CloneImage(image,0,0,MagickTrue,exception);
02518       (void) SeparateImageChannel(separate_image,GreenChannel);
02519       AppendImageToList(&images,separate_image);
02520     }
02521   if ((channel & BlueChannel) != 0)
02522     {
02523       separate_image=CloneImage(image,0,0,MagickTrue,exception);
02524       (void) SeparateImageChannel(separate_image,BlueChannel);
02525       AppendImageToList(&images,separate_image);
02526     }
02527   if (((channel & BlackChannel) != 0) && (image->colorspace == CMYKColorspace))
02528     {
02529       separate_image=CloneImage(image,0,0,MagickTrue,exception);
02530       (void) SeparateImageChannel(separate_image,BlackChannel);
02531       AppendImageToList(&images,separate_image);
02532     }
02533   if ((channel & OpacityChannel) != 0)
02534     {
02535       separate_image=CloneImage(image,0,0,MagickTrue,exception);
02536       (void) SeparateImageChannel(separate_image,OpacityChannel);
02537       AppendImageToList(&images,separate_image);
02538     }
02539   return(images);
02540 }
02541 
02542 /*
02543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02544 %                                                                             %
02545 %                                                                             %
02546 %                                                                             %
02547 %   S e t I m a g e A l p h a C h a n n e l                                   %
02548 %                                                                             %
02549 %                                                                             %
02550 %                                                                             %
02551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02552 %
02553 %  SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha
02554 %  channel.
02555 %
02556 %  The format of the SetImageAlphaChannel method is:
02557 %
02558 %      MagickBooleanType SetImageAlphaChannel(Image *image,
02559 %        const AlphaChannelType alpha_type)
02560 %
02561 %  A description of each parameter follows:
02562 %
02563 %    o image: the image.
02564 %
02565 %    o alpha_type:  The alpha channel type: ActivateAlphaChannel,
02566 %      CopyAlphaChannel, DeactivateAlphaChannel, ExtractAlphaChannel,
02567 %      OpaqueAlphaChannel, ResetAlphaChannel, SetAlphaChannel,
02568 %      ShapeAlphaChannel, and TransparentAlphaChannel.
02569 %
02570 */
02571 MagickExport MagickBooleanType SetImageAlphaChannel(Image *image,
02572   const AlphaChannelType alpha_type)
02573 {
02574   MagickBooleanType
02575     status;
02576 
02577   assert(image != (Image *) NULL);
02578   if (image->debug != MagickFalse)
02579     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02580   assert(image->signature == MagickSignature);
02581   status=MagickFalse;
02582   switch (alpha_type)
02583   {
02584     case ActivateAlphaChannel:
02585     {
02586       image->matte=MagickTrue;
02587       break;
02588     }
02589     case BackgroundAlphaChannel:
02590     {
02591       CacheView
02592         *image_view;
02593 
02594       ExceptionInfo
02595         *exception;
02596 
02597       IndexPacket
02598         index;
02599 
02600       long
02601         y;
02602 
02603       MagickBooleanType
02604         status;
02605 
02606       MagickPixelPacket
02607         background;
02608 
02609       PixelPacket
02610         pixel;
02611 
02612       /*
02613         Set transparent pixels to background color.
02614       */
02615       if (image->matte == MagickFalse)
02616         break;
02617       if (SetImageStorageClass(image,DirectClass) == MagickFalse)
02618         break;
02619       GetMagickPixelPacket(image,&background);
02620       SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *)
02621         NULL,&background);
02622       if (image->colorspace == CMYKColorspace)
02623         ConvertRGBToCMYK(&background);
02624       index=0;
02625       SetPixelPacket(image,&background,&pixel,&index);
02626       status=MagickTrue;
02627       exception=(&image->exception);
02628       image_view=AcquireCacheView(image);
02629       #if defined(MAGICKCORE_OPENMP_SUPPORT)
02630         #pragma omp parallel for schedule(dynamic,4) shared(status)
02631       #endif
02632       for (y=0; y < (long) image->rows; y++)
02633       {
02634         register IndexPacket
02635           *__restrict indexes;
02636 
02637         register long
02638           x;
02639 
02640         register PixelPacket
02641           *__restrict q;
02642 
02643         if (status == MagickFalse)
02644           continue;
02645         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
02646           exception);
02647         if (q == (PixelPacket *) NULL)
02648           {
02649             status=MagickFalse;
02650             continue;
02651           }
02652         for (x=0; x < (long) image->columns; x++)
02653         {
02654           if (q->opacity == TransparentOpacity)
02655             {
02656               q->red=pixel.red;
02657               q->green=pixel.green;
02658               q->blue=pixel.blue;
02659             }
02660           q++;
02661         }
02662         if (image->colorspace == CMYKColorspace)
02663           {
02664             indexes=GetCacheViewAuthenticIndexQueue(image_view);
02665             for (x=0; x < (long) image->columns; x++)
02666               indexes[x]=index;
02667           }
02668         if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
02669           status=MagickFalse;
02670       }
02671       image_view=DestroyCacheView(image_view);
02672       return(status);
02673     }
02674     case DeactivateAlphaChannel:
02675     {
02676       image->matte=MagickFalse;
02677       break;
02678     }
02679     case ShapeAlphaChannel:
02680     case CopyAlphaChannel:
02681     {
02682       /*
02683         Special usage case for SeparateImageChannel(): copy grayscale color to
02684         the alpha channel.
02685       */
02686       status=SeparateImageChannel(image,GrayChannels);
02687       image->matte=MagickTrue; /* make sure transparency is now on! */
02688       if (alpha_type == ShapeAlphaChannel)
02689         {
02690           MagickPixelPacket
02691             background;
02692 
02693           /*
02694             Reset all color channels to background color.
02695           */
02696           GetMagickPixelPacket(image,&background);
02697           SetMagickPixelPacket(image,&(image->background_color),(IndexPacket *)
02698             NULL,&background);
02699           (void) LevelColorsImage(image,&background,&background,MagickTrue);
02700         }
02701       break;
02702     }
02703     case ExtractAlphaChannel:
02704     {
02705       status=SeparateImageChannel(image,TrueAlphaChannel);
02706       image->matte=MagickFalse;
02707       break;
02708     }
02709     case ResetAlphaChannel:
02710     case OpaqueAlphaChannel:
02711     {
02712       status=SetImageOpacity(image,OpaqueOpacity);
02713       image->matte=MagickTrue;
02714       break;
02715     }
02716     case TransparentAlphaChannel:
02717     {
02718       status=SetImageOpacity(image,TransparentOpacity);
02719       image->matte=MagickTrue;
02720       break;
02721     }
02722     case SetAlphaChannel:
02723     {
02724       if (image->matte == MagickFalse)
02725         {
02726           status=SetImageOpacity(image,OpaqueOpacity);
02727           image->matte=MagickTrue;
02728         }
02729       break;
02730     }
02731     case UndefinedAlphaChannel:
02732       break;
02733   }
02734   return(status);
02735 }
02736 
02737 /*
02738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02739 %                                                                             %
02740 %                                                                             %
02741 %                                                                             %
02742 %   S e t I m a g e B a c k g r o u n d C o l o r                             %
02743 %                                                                             %
02744 %                                                                             %
02745 %                                                                             %
02746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02747 %
02748 %  SetImageBackgroundColor() initializes the image pixels to the image
02749 %  background color.  The background color is defined by the background_color
02750 %  member of the image structure.
02751 %
02752 %  The format of the SetImage method is:
02753 %
02754 %      MagickBooleanType SetImageBackgroundColor(Image *image)
02755 %
02756 %  A description of each parameter follows:
02757 %
02758 %    o image: the image.
02759 %
02760 */
02761 MagickExport MagickBooleanType SetImageBackgroundColor(Image *image)
02762 {
02763   CacheView
02764     *image_view;
02765 
02766   ExceptionInfo
02767     *exception;
02768 
02769   IndexPacket
02770     index;
02771 
02772   long
02773     y;
02774 
02775   MagickBooleanType
02776     status;
02777 
02778   MagickPixelPacket
02779     background;
02780 
02781   PixelPacket
02782     pixel;
02783 
02784   assert(image != (Image *) NULL);
02785   if (image->debug != MagickFalse)
02786     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02787   assert(image->signature == MagickSignature);
02788   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
02789     return(MagickFalse);
02790   if (image->background_color.opacity != OpaqueOpacity)
02791     image->matte=MagickTrue;
02792   GetMagickPixelPacket(image,&background);
02793   SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *)
02794     NULL,&background);
02795   if (image->colorspace == CMYKColorspace)
02796     ConvertRGBToCMYK(&background);
02797   index=0;
02798   SetPixelPacket(image,&background,&pixel,&index);
02799   /*
02800     Set image background color.
02801   */
02802   status=MagickTrue;
02803   exception=(&image->exception);
02804   image_view=AcquireCacheView(image);
02805 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02806   #pragma omp parallel for schedule(dynamic,4) shared(status)
02807 #endif
02808   for (y=0; y < (long) image->rows; y++)
02809   {
02810     register IndexPacket
02811       *__restrict indexes;
02812 
02813     register long
02814       x;
02815 
02816     register PixelPacket
02817       *__restrict q;
02818 
02819     if (status == MagickFalse)
02820       continue;
02821     q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
02822     if (q == (PixelPacket *) NULL)
02823       {
02824         status=MagickFalse;
02825         continue;
02826       }
02827     for (x=0; x < (long) image->columns; x++)
02828       *q++=pixel;
02829     if (image->colorspace == CMYKColorspace)
02830       {
02831         indexes=GetCacheViewAuthenticIndexQueue(image_view);
02832         for (x=0; x < (long) image->columns; x++)
02833           indexes[x]=index;
02834       }
02835     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
02836       status=MagickFalse;
02837   }
02838   image_view=DestroyCacheView(image_view);
02839   return(status);
02840 }
02841 
02842 /*
02843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02844 %                                                                             %
02845 %                                                                             %
02846 %                                                                             %
02847 %   S e t I m a g e S t o r a g e C l a s s                                   %
02848 %                                                                             %
02849 %                                                                             %
02850 %                                                                             %
02851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02852 %
02853 %  SetImageStorageClass() sets the image class: DirectClass for true color
02854 %  images or PseudoClass for colormapped images.
02855 %
02856 %  The format of the SetImageStorageClass method is:
02857 %
02858 %      MagickBooleanType SetImageStorageClass(Image *image,
02859 %        const ClassType storage_class)
02860 %
02861 %  A description of each parameter follows:
02862 %
02863 %    o image: the image.
02864 %
02865 %    o storage_class:  The image class.
02866 %
02867 */
02868 MagickExport MagickBooleanType SetImageStorageClass(Image *image,
02869   const ClassType storage_class)
02870 {
02871   Cache
02872     cache;
02873 
02874   if (image->storage_class == storage_class)
02875     return(MagickTrue);
02876   image->storage_class=storage_class;
02877   cache=GetImagePixelCache(image,MagickTrue,&image->exception);
02878   return(cache == (Cache) NULL ? MagickFalse : MagickTrue);
02879 }
02880 
02881 /*
02882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02883 %                                                                             %
02884 %                                                                             %
02885 %                                                                             %
02886 %   S e t I m a g e C l i p M a s k                                           %
02887 %                                                                             %
02888 %                                                                             %
02889 %                                                                             %
02890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02891 %
02892 %  SetImageClipMask() associates a clip path with the image.  The clip path
02893 %  must be the same dimensions as the image.  Set any pixel component of
02894 %  the clip path to TransparentOpacity to prevent that corresponding image
02895 %  pixel component from being updated when SyncAuthenticPixels() is applied.
02896 %
02897 %  The format of the SetImageClipMask method is:
02898 %
02899 %      MagickBooleanType SetImageClipMask(Image *image,const Image *clip_mask)
02900 %
02901 %  A description of each parameter follows:
02902 %
02903 %    o image: the image.
02904 %
02905 %    o clip_mask: the image clip path.
02906 %
02907 */
02908 MagickExport MagickBooleanType SetImageClipMask(Image *image,
02909   const Image *clip_mask)
02910 {
02911   assert(image != (Image *) NULL);
02912   if (image->debug != MagickFalse)
02913     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02914   assert(image->signature == MagickSignature);
02915   if (clip_mask != (const Image *) NULL)
02916     if ((clip_mask->columns != image->columns) ||
02917         (clip_mask->rows != image->rows))
02918       ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename);
02919   if (image->clip_mask != (Image *) NULL)
02920     image->clip_mask=DestroyImage(image->clip_mask);
02921   image->clip_mask=NewImageList();
02922   if (clip_mask == (Image *) NULL)
02923     return(MagickTrue);
02924   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
02925     return(MagickFalse);
02926   image->clip_mask=CloneImage(clip_mask,0,0,MagickTrue,&image->exception);
02927   if (image->clip_mask == (Image *) NULL)
02928     return(MagickFalse);
02929   return(MagickTrue);
02930 }
02931 
02932 /*
02933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02934 %                                                                             %
02935 %                                                                             %
02936 %                                                                             %
02937 %   S e t I m a g e E x t e n t                                               %
02938 %                                                                             %
02939 %                                                                             %
02940 %                                                                             %
02941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02942 %
02943 %  SetImageExtent() sets the image size (i.e. columns & rows).
02944 %
02945 %  The format of the SetImageExtent method is:
02946 %
02947 %      MagickBooleanType SetImageExtent(Image *image,
02948 %        const unsigned long columns,const unsigned long rows)
02949 %
02950 %  A description of each parameter follows:
02951 %
02952 %    o image: the image.
02953 %
02954 %    o columns:  The image width in pixels.
02955 %
02956 %    o rows:  The image height in pixels.
02957 %
02958 */
02959 MagickExport MagickBooleanType SetImageExtent(Image *image,
02960   const unsigned long columns,const unsigned long rows)
02961 {
02962   Cache
02963     cache;
02964 
02965   if ((columns != 0) && (rows != 0))
02966     {
02967       image->columns=columns;
02968       image->rows=rows;
02969     }
02970   cache=GetImagePixelCache(image,MagickTrue,&image->exception);
02971   return(cache == (Cache) NULL ? MagickFalse : MagickTrue);
02972 }
02973 
02974 /*
02975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02976 %                                                                             %
02977 %                                                                             %
02978 %                                                                             %
02979 +   S e t I m a g e I n f o                                                   %
02980 %                                                                             %
02981 %                                                                             %
02982 %                                                                             %
02983 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02984 %
02985 %  SetImageInfo() initializes the `magick' field of the ImageInfo structure.
02986 %  It is set to a type of image format based on the prefix or suffix of the
02987 %  filename.  For example, `ps:image' returns PS indicating a Postscript image.
02988 %  JPEG is returned for this filename: `image.jpg'.  The filename prefix has
02989 %  precendence over the suffix.  Use an optional index enclosed in brackets
02990 %  after a file name to specify a desired scene of a multi-resolution image
02991 %  format like Photo CD (e.g. img0001.pcd[4]).  A True (non-zero) return value
02992 %  indicates success.
02993 %
02994 %  The format of the SetImageInfo method is:
02995 %
02996 %      MagickBooleanType SetImageInfo(ImageInfo *image_info,
02997 %        const MagickBooleanType rectify,ExceptionInfo *exception)
02998 %
02999 %  A description of each parameter follows:
03000 %
03001 %    o image_info: the image info..
03002 %
03003 %    o rectify: an unsigned value other than zero rectifies the attribute for
03004 %      multi-frame support (user may want multi-frame but image format may not
03005 %      support it).
03006 %
03007 %    o exception: return any errors or warnings in this structure.
03008 %
03009 */
03010 MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info,
03011   const MagickBooleanType rectify,ExceptionInfo *exception)
03012 {
03013   char
03014     extension[MaxTextExtent],
03015     filename[MaxTextExtent],
03016     magic[MaxTextExtent],
03017     *q,
03018     subimage[MaxTextExtent];
03019 
03020   const MagicInfo
03021     *magic_info;
03022 
03023   const MagickInfo
03024     *magick_info;
03025 
03026   ExceptionInfo
03027     *sans_exception;
03028 
03029   Image
03030     *image;
03031 
03032   MagickBooleanType
03033     status;
03034 
03035   register const char
03036     *p;
03037 
03038   ssize_t
03039     count;
03040 
03041   unsigned char
03042     magick[2*MaxTextExtent];
03043 
03044   /*
03045     Look for 'image.format' in filename.
03046   */
03047   assert(image_info != (ImageInfo *) NULL);
03048   assert(image_info->signature == MagickSignature);
03049   if (image_info->debug != MagickFalse)
03050     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
03051       image_info->filename);
03052   *subimage='\0';
03053   GetPathComponent(image_info->filename,SubimagePath,subimage);
03054   if (*subimage != '\0')
03055     {
03056       /*
03057         Look for scene specification (e.g. img0001.pcd[4]).
03058       */
03059       if (IsSceneGeometry(subimage,MagickFalse) == MagickFalse)
03060         {
03061           if (IsGeometry(subimage) != MagickFalse)
03062             (void) CloneString(&image_info->extract,subimage);
03063         }
03064       else
03065         {
03066           unsigned long
03067             first,
03068             last;
03069 
03070           (void) CloneString(&image_info->scenes,subimage);
03071           image_info->scene=(unsigned long) atol(image_info->scenes);
03072           image_info->number_scenes=image_info->scene;
03073           p=image_info->scenes;
03074           for (q=(char *) image_info->scenes; *q != '\0'; p++)
03075           {
03076             while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
03077               p++;
03078             first=(unsigned long) strtol(p,&q,10);
03079             last=first;
03080             while (isspace((int) ((unsigned char) *q)) != 0)
03081               q++;
03082             if (*q == '-')
03083               last=(unsigned long) strtol(q+1,&q,10);
03084             if (first > last)
03085               Swap(first,last);
03086             if (first < image_info->scene)
03087               image_info->scene=first;
03088             if (last > image_info->number_scenes)
03089               image_info->number_scenes=last;
03090             p=q;
03091           }
03092           image_info->number_scenes-=image_info->scene-1;
03093           image_info->subimage=image_info->scene;
03094           image_info->subrange=image_info->number_scenes;
03095         }
03096     }
03097   *extension='\0';
03098   GetPathComponent(image_info->filename,ExtensionPath,extension);
03099 #if defined(MAGICKCORE_ZLIB_DELEGATE)
03100   if (*extension != '\0')
03101     if ((LocaleCompare(extension,"gz") == 0) ||
03102         (LocaleCompare(extension,"Z") == 0) ||
03103         (LocaleCompare(extension,"wmz") == 0))
03104       {
03105         char
03106           path[MaxTextExtent];
03107 
03108         (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
03109         path[strlen(path)-strlen(extension)-1]='\0';
03110         GetPathComponent(path,ExtensionPath,extension);
03111       }
03112 #endif
03113 #if defined(MAGICKCORE_BZLIB_DELEGATE)
03114   if (*extension != '\0')
03115     if (LocaleCompare(extension,"bz2") == 0)
03116       {
03117         char
03118           path[MaxTextExtent];
03119 
03120         (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
03121         path[strlen(path)-strlen(extension)-1]='\0';
03122         GetPathComponent(path,ExtensionPath,extension);
03123       }
03124 #endif
03125   image_info->affirm=MagickFalse;
03126   sans_exception=AcquireExceptionInfo();
03127   if (*extension != '\0')
03128     {
03129       MagickFormatType
03130         format_type;
03131 
03132       register long
03133         i;
03134 
03135       static const char
03136         *format_type_formats[] =
03137         {
03138           "AUTOTRACE",
03139           "BROWSE",
03140           "DCRAW",
03141           "EDIT",
03142           "EPHEMERAL",
03143           "LAUNCH",
03144           "MPEG:DECODE",
03145           "MPEG:ENCODE",
03146           "PRINT",
03147           "PS:ALPHA",
03148           "PS:CMYK",
03149           "PS:COLOR",
03150           "PS:GRAY",
03151           "PS:MONO",
03152           "SCAN",
03153           "SHOW",
03154           "WIN",
03155           (char *) NULL
03156         };
03157 
03158       /*
03159         User specified image format.
03160       */
03161       (void) CopyMagickString(magic,extension,MaxTextExtent);
03162       LocaleUpper(magic);
03163       /*
03164         Look for explicit image formats.
03165       */
03166       format_type=UndefinedFormatType;
03167       i=0;
03168       while ((format_type != UndefinedFormatType) &&
03169              (format_type_formats[i] != (char *) NULL))
03170       {
03171         if ((*magic == *format_type_formats[i]) &&
03172             (LocaleCompare(magic,format_type_formats[i]) == 0))
03173           format_type=ExplicitFormatType;
03174         i++;
03175       }
03176       magick_info=GetMagickInfo(magic,sans_exception);
03177       if ((magick_info != (const MagickInfo *) NULL) &&
03178           (magick_info->format_type != UndefinedFormatType))
03179         format_type=magick_info->format_type;
03180       if (format_type == UndefinedFormatType)
03181         (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
03182       else
03183         if (format_type == ExplicitFormatType)
03184           {
03185             image_info->affirm=MagickTrue;
03186             (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
03187           }
03188       if (LocaleCompare(magic,"RGB") == 0)
03189         image_info->affirm=MagickFalse;  /* maybe SGI disguised as RGB */
03190     }
03191   /*
03192     Look for explicit 'format:image' in filename.
03193   */
03194   *magic='\0';
03195   GetPathComponent(image_info->filename,MagickPath,magic);
03196   if (*magic == '\0')
03197     (void) CopyMagickString(magic,image_info->magick,MaxTextExtent);
03198   else
03199     {
03200       /*
03201         User specified image format.
03202       */
03203       LocaleUpper(magic);
03204       if (IsMagickConflict(magic) == MagickFalse)
03205         {
03206           (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
03207           if (LocaleCompare(magic,"EPHEMERAL") != 0)
03208             image_info->affirm=MagickTrue;
03209           else
03210             image_info->temporary=MagickTrue;
03211         }
03212     }
03213   magick_info=GetMagickInfo(magic,sans_exception);
03214   sans_exception=DestroyExceptionInfo(sans_exception);
03215   if ((magick_info == (const MagickInfo *) NULL) ||
03216       (GetMagickEndianSupport(magick_info) == MagickFalse))
03217     image_info->endian=UndefinedEndian;
03218   GetPathComponent(image_info->filename,CanonicalPath,filename);
03219   (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
03220   if (rectify != MagickFalse)
03221     {
03222       /*
03223         Rectify multi-image file support.
03224       */
03225       (void) InterpretImageFilename(image_info,(Image *) NULL,
03226         image_info->filename,(int) image_info->scene,filename);
03227       if ((LocaleCompare(filename,image_info->filename) != 0) &&
03228           (strchr(filename,'%') == (char *) NULL))
03229         image_info->adjoin=MagickFalse;
03230       magick_info=GetMagickInfo(magic,exception);
03231       if (magick_info != (const MagickInfo *) NULL)
03232         if (GetMagickAdjoin(magick_info) == MagickFalse)
03233           image_info->adjoin=MagickFalse;
03234       return(MagickTrue);
03235     }
03236   if (image_info->affirm != MagickFalse)
03237     return(MagickTrue);
03238   /*
03239     Determine the image format from the first few bytes of the file.
03240   */
03241   image=AcquireImage(image_info);
03242   (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent);
03243   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
03244   if (status == MagickFalse)
03245     {
03246       image=DestroyImage(image);
03247       return(MagickFalse);
03248     }
03249   if ((IsBlobSeekable(image) == MagickFalse) ||
03250       (IsBlobExempt(image) != MagickFalse))
03251     {
03252       /*
03253         Copy standard input or pipe to temporary file.
03254       */
03255       *filename='\0';
03256       status=ImageToFile(image,filename,exception);
03257       (void) CloseBlob(image);
03258       if (status == MagickFalse)
03259         {
03260           image=DestroyImage(image);
03261           return(MagickFalse);
03262         }
03263       SetImageInfoFile(image_info,(FILE *) NULL);
03264       (void) CopyMagickString(image->filename,filename,MaxTextExtent);
03265       status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
03266       if (status == MagickFalse)
03267         {
03268           image=DestroyImage(image);
03269           return(MagickFalse);
03270         }
03271       (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
03272       image_info->temporary=MagickTrue;
03273     }
03274   (void) ResetMagickMemory(magick,0,sizeof(magick));
03275   count=ReadBlob(image,2*MaxTextExtent,magick);
03276   (void) CloseBlob(image);
03277   image=DestroyImage(image);
03278   /*
03279     Check magic.xml configuration file.
03280   */
03281   sans_exception=AcquireExceptionInfo();
03282   magic_info=GetMagicInfo(magick,(size_t) count,sans_exception);
03283   if ((magic_info != (const MagicInfo *) NULL) &&
03284       (GetMagicName(magic_info) != (char *) NULL))
03285     {
03286       (void) CopyMagickString(image_info->magick,GetMagicName(magic_info),
03287         MaxTextExtent);
03288       magick_info=GetMagickInfo(image_info->magick,sans_exception);
03289       if ((magick_info == (const MagickInfo *) NULL) ||
03290           (GetMagickEndianSupport(magick_info) == MagickFalse))
03291         image_info->endian=UndefinedEndian;
03292       sans_exception=DestroyExceptionInfo(sans_exception);
03293       return(MagickTrue);
03294     }
03295   magick_info=GetMagickInfo(image_info->magick,sans_exception);
03296   if ((magick_info == (const MagickInfo *) NULL) ||
03297       (GetMagickEndianSupport(magick_info) == MagickFalse))
03298     image_info->endian=UndefinedEndian;
03299   sans_exception=DestroyExceptionInfo(sans_exception);
03300   return(MagickTrue);
03301 }
03302 
03303 /*
03304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03305 %                                                                             %
03306 %                                                                             %
03307 %                                                                             %
03308 %   S e t I m a g e I n f o B l o b                                           %
03309 %                                                                             %
03310 %                                                                             %
03311 %                                                                             %
03312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03313 %
03314 %  SetImageInfoBlob() sets the image info blob member.
03315 %
03316 %  The format of the SetImageInfoBlob method is:
03317 %
03318 %      void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
03319 %        const size_t length)
03320 %
03321 %  A description of each parameter follows:
03322 %
03323 %    o image_info: the image info.
03324 %
03325 %    o blob: the blob.
03326 %
03327 %    o length: the blob length.
03328 %
03329 */
03330 MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
03331   const size_t length)
03332 {
03333   assert(image_info != (ImageInfo *) NULL);
03334   assert(image_info->signature == MagickSignature);
03335   if (image_info->debug != MagickFalse)
03336     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
03337       image_info->filename);
03338   image_info->blob=(void *) blob;
03339   image_info->length=length;
03340 }
03341 
03342 /*
03343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03344 %                                                                             %
03345 %                                                                             %
03346 %                                                                             %
03347 %   S e t I m a g e I n f o F i l e                                           %
03348 %                                                                             %
03349 %                                                                             %
03350 %                                                                             %
03351 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03352 %
03353 %  SetImageInfoFile() sets the image info file member.
03354 %
03355 %  The format of the SetImageInfoFile method is:
03356 %
03357 %      void SetImageInfoFile(ImageInfo *image_info,FILE *file)
03358 %
03359 %  A description of each parameter follows:
03360 %
03361 %    o image_info: the image info.
03362 %
03363 %    o file: the file.
03364 %
03365 */
03366 MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file)
03367 {
03368   assert(image_info != (ImageInfo *) NULL);
03369   assert(image_info->signature == MagickSignature);
03370   if (image_info->debug != MagickFalse)
03371     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
03372       image_info->filename);
03373   image_info->file=file;
03374 }
03375 
03376 /*
03377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03378 %                                                                             %
03379 %                                                                             %
03380 %                                                                             %
03381 %   S e t I m a g e M a s k                                                   %
03382 %                                                                             %
03383 %                                                                             %
03384 %                                                                             %
03385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03386 %
03387 %  SetImageMask() associates a mask with the image.  The mask must be the same
03388 %  dimensions as the image.
03389 %
03390 %  The format of the SetImageMask method is:
03391 %
03392 %      MagickBooleanType SetImageMask(Image *image,const Image *mask)
03393 %
03394 %  A description of each parameter follows:
03395 %
03396 %    o image: the image.
03397 %
03398 %    o mask: the image mask.
03399 %
03400 */
03401 MagickExport MagickBooleanType SetImageMask(Image *image,
03402   const Image *mask)
03403 {
03404   assert(image != (Image *) NULL);
03405   if (image->debug != MagickFalse)
03406     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03407   assert(image->signature == MagickSignature);
03408   if (mask != (const Image *) NULL)
03409     if ((mask->columns != image->columns) || (mask->rows != image->rows))
03410       ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename);
03411   if (image->mask != (Image *) NULL)
03412     image->mask=DestroyImage(image->mask);
03413   image->mask=NewImageList();
03414   if (mask == (Image *) NULL)
03415     return(MagickTrue);
03416   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
03417     return(MagickFalse);
03418   image->mask=CloneImage(mask,0,0,MagickTrue,&image->exception);
03419   if (image->mask == (Image *) NULL)
03420     return(MagickFalse);
03421   return(MagickTrue);
03422 }
03423 
03424 /*
03425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03426 %                                                                             %
03427 %                                                                             %
03428 %                                                                             %
03429 %     S e t I m a g e O p a c i t y                                           %
03430 %                                                                             %
03431 %                                                                             %
03432 %                                                                             %
03433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03434 %
03435 %  SetImageOpacity() sets the opacity levels of the image.
03436 %
03437 %  The format of the SetImageOpacity method is:
03438 %
03439 %      MagickBooleanType SetImageOpacity(Image *image,const Quantum opacity)
03440 %
03441 %  A description of each parameter follows:
03442 %
03443 %    o image: the image.
03444 %
03445 %    o opacity: the level of transparency: 0 is fully opaque and QuantumRange is
03446 %      fully transparent.
03447 %
03448 */
03449 MagickExport MagickBooleanType SetImageOpacity(Image *image,
03450   const Quantum opacity)
03451 {
03452   CacheView
03453     *image_view;
03454 
03455   ExceptionInfo
03456     *exception;
03457 
03458   long
03459     y;
03460 
03461   MagickBooleanType
03462     status;
03463 
03464   assert(image != (Image *) NULL);
03465   if (image->debug != MagickFalse)
03466     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03467   assert(image->signature == MagickSignature);
03468   image->matte=opacity != OpaqueOpacity ? MagickTrue : MagickFalse;
03469   status=MagickTrue;
03470   exception=(&image->exception);
03471   image_view=AcquireCacheView(image);
03472 #if defined(MAGICKCORE_OPENMP_SUPPORT)
03473   #pragma omp parallel for schedule(dynamic,4) shared(status)
03474 #endif
03475   for (y=0; y < (long) image->rows; y++)
03476   {
03477     register long
03478       x;
03479 
03480     register PixelPacket
03481       *__restrict q;
03482 
03483     if (status == MagickFalse)
03484       continue;
03485     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
03486     if (q == (PixelPacket *) NULL)
03487       {
03488         status=MagickFalse;
03489         continue;
03490       }
03491     for (x=0; x < (long) image->columns; x++)
03492     {
03493       q->opacity=opacity;
03494       q++;
03495     }
03496     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
03497       status=MagickFalse;
03498   }
03499   image_view=DestroyCacheView(image_view);
03500   return(status);
03501 }
03502 
03503 /*
03504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03505 %                                                                             %
03506 %                                                                             %
03507 %                                                                             %
03508 %   S e t I m a g e T y p e                                                   %
03509 %                                                                             %
03510 %                                                                             %
03511 %                                                                             %
03512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03513 %
03514 %  SetImageType() sets the type of image.  Choose from these types:
03515 %
03516 %        Bilevel        Grayscale       GrayscaleMatte
03517 %        Palette        PaletteMatte    TrueColor
03518 %        TrueColorMatte ColorSeparation ColorSeparationMatte
03519 %        OptimizeType
03520 %
03521 %  The format of the SetImageType method is:
03522 %
03523 %      MagickBooleanType SetImageType(Image *image,const ImageType type)
03524 %
03525 %  A description of each parameter follows:
03526 %
03527 %    o image: the image.
03528 %
03529 %    o type: Image type.
03530 %
03531 */
03532 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type)
03533 {
03534   const char
03535     *artifact;
03536 
03537   ImageInfo
03538     *image_info;
03539 
03540   MagickBooleanType
03541     status;
03542 
03543   QuantizeInfo
03544     *quantize_info;
03545 
03546   assert(image != (Image *) NULL);
03547   if (image->debug != MagickFalse)
03548     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03549   assert(image->signature == MagickSignature);
03550   status=MagickTrue;
03551   image_info=AcquireImageInfo();
03552   image_info->dither=image->dither;
03553   artifact=GetImageArtifact(image,"dither");
03554   if (artifact != (const char *) NULL)
03555     (void) SetImageOption(image_info,"dither",artifact);
03556   switch (type)
03557   {
03558     case BilevelType:
03559     {
03560       if (IsGrayImage(image,&image->exception) == MagickFalse)
03561         status=TransformImageColorspace(image,GRAYColorspace);
03562       if (IsMonochromeImage(image,&image->exception) == MagickFalse)
03563         {
03564           quantize_info=AcquireQuantizeInfo(image_info);
03565           quantize_info->number_colors=2;
03566           quantize_info->colorspace=GRAYColorspace;
03567           status=QuantizeImage(quantize_info,image);
03568           quantize_info=DestroyQuantizeInfo(quantize_info);
03569         }
03570       image->matte=MagickFalse;
03571       break;
03572     }
03573     case GrayscaleType:
03574     {
03575       if (IsGrayImage(image,&image->exception) == MagickFalse)
03576         status=TransformImageColorspace(image,GRAYColorspace);
03577       image->matte=MagickFalse;
03578       break;
03579     }
03580     case GrayscaleMatteType:
03581     {
03582       if (IsGrayImage(image,&image->exception) == MagickFalse)
03583         status=TransformImageColorspace(image,GRAYColorspace);
03584       if (image->matte == MagickFalse)
03585         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
03586       break;
03587     }
03588     case PaletteType:
03589     {
03590       if (image->colorspace != RGBColorspace)
03591         status=TransformImageColorspace(image,RGBColorspace);
03592       if ((image->storage_class == DirectClass) || (image->colors > 256))
03593         {
03594           quantize_info=AcquireQuantizeInfo(image_info);
03595           quantize_info->number_colors=256;
03596           status=QuantizeImage(quantize_info,image);
03597           quantize_info=DestroyQuantizeInfo(quantize_info);
03598         }
03599       image->matte=MagickFalse;
03600       break;
03601     }
03602     case PaletteBilevelMatteType:
03603     {
03604       if (image->colorspace != RGBColorspace)
03605         status=TransformImageColorspace(image,RGBColorspace);
03606       if (image->matte == MagickFalse)
03607         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
03608       (void) BilevelImageChannel(image,AlphaChannel,(double) QuantumRange/2.0);
03609       quantize_info=AcquireQuantizeInfo(image_info);
03610       status=QuantizeImage(quantize_info,image);
03611       quantize_info=DestroyQuantizeInfo(quantize_info);
03612       break;
03613     }
03614     case PaletteMatteType:
03615     {
03616       if (image->colorspace != RGBColorspace)
03617         status=TransformImageColorspace(image,RGBColorspace);
03618       if (image->matte == MagickFalse)
03619         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
03620       quantize_info=AcquireQuantizeInfo(image_info);
03621       quantize_info->colorspace=TransparentColorspace;
03622       status=QuantizeImage(quantize_info,image);
03623       quantize_info=DestroyQuantizeInfo(quantize_info);
03624       break;
03625     }
03626     case TrueColorType:
03627     {
03628       if (image->colorspace != RGBColorspace)
03629         status=TransformImageColorspace(image,RGBColorspace);
03630       if (image->storage_class != DirectClass)
03631         status=SetImageStorageClass(image,DirectClass);
03632       image->matte=MagickFalse;
03633       break;
03634     }
03635     case TrueColorMatteType:
03636     {
03637       if (image->colorspace != RGBColorspace)
03638         status=TransformImageColorspace(image,RGBColorspace);
03639       if (image->storage_class != DirectClass)
03640         status=SetImageStorageClass(image,DirectClass);
03641       if (image->matte == MagickFalse)
03642         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
03643       break;
03644     }
03645     case ColorSeparationType:
03646     {
03647       if (image->colorspace != CMYKColorspace)
03648         {
03649           if (image->colorspace != RGBColorspace)
03650             status=TransformImageColorspace(image,RGBColorspace);
03651           status=TransformImageColorspace(image,CMYKColorspace);
03652         }
03653       if (image->storage_class != DirectClass)
03654         status=SetImageStorageClass(image,DirectClass);
03655       image->matte=MagickFalse;
03656       break;
03657     }
03658     case ColorSeparationMatteType:
03659     {
03660       if (image->colorspace != CMYKColorspace)
03661         {
03662           if (image->colorspace != RGBColorspace)
03663             status=TransformImageColorspace(image,RGBColorspace);
03664           status=TransformImageColorspace(image,CMYKColorspace);
03665         }
03666       if (image->storage_class != DirectClass)
03667         status=SetImageStorageClass(image,DirectClass);
03668       if (image->matte == MagickFalse)
03669         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
03670       break;
03671     }
03672     case OptimizeType:
03673     case UndefinedType:
03674       break;
03675   }
03676   image->type=type;
03677   image_info=DestroyImageInfo(image_info);
03678   return(status);
03679 }
03680 
03681 /*
03682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03683 %                                                                             %
03684 %                                                                             %
03685 %                                                                             %
03686 %   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                       %
03687 %                                                                             %
03688 %                                                                             %
03689 %                                                                             %
03690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03691 %
03692 %  SetImageVirtualPixelMethod() sets the "virtual pixels" method for the
03693 %  image and returns the previous setting.  A virtual pixel is any pixel access
03694 %  that is outside the boundaries of the image cache.
03695 %
03696 %  The format of the SetImageVirtualPixelMethod() method is:
03697 %
03698 %      VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
03699 %        const VirtualPixelMethod virtual_pixel_method)
03700 %
03701 %  A description of each parameter follows:
03702 %
03703 %    o image: the image.
03704 %
03705 %    o virtual_pixel_method: choose the type of virtual pixel.
03706 %
03707 */
03708 MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
03709   const VirtualPixelMethod virtual_pixel_method)
03710 {
03711   assert(image != (const Image *) NULL);
03712   assert(image->signature == MagickSignature);
03713   if (image->debug != MagickFalse)
03714     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03715   return(SetPixelCacheVirtualMethod(image,virtual_pixel_method));
03716 }
03717 
03718 /*
03719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03720 %                                                                             %
03721 %                                                                             %
03722 %                                                                             %
03723 %   S t r i p I m a g e                                                       %
03724 %                                                                             %
03725 %                                                                             %
03726 %                                                                             %
03727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03728 %
03729 %  StripImage() strips an image of all profiles and comments.
03730 %
03731 %  The format of the StripImage method is:
03732 %
03733 %      MagickBooleanType StripImage(Image *image)
03734 %
03735 %  A description of each parameter follows:
03736 %
03737 %    o image: the image.
03738 %
03739 */
03740 MagickExport MagickBooleanType StripImage(Image *image)
03741 {
03742   assert(image != (Image *) NULL);
03743   if (image->debug != MagickFalse)
03744     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03745   DestroyImageProfiles(image);
03746   (void) DeleteImageProperty(image,"comment");
03747   return(MagickTrue);
03748 }
03749 
03750 /*
03751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03752 %                                                                             %
03753 %                                                                             %
03754 %                                                                             %
03755 +   S y n c I m a g e                                                         %
03756 %                                                                             %
03757 %                                                                             %
03758 %                                                                             %
03759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03760 %
03761 %  SyncImage() initializes the red, green, and blue intensities of each pixel
03762 %  as defined by the colormap index.
03763 %
03764 %  The format of the SyncImage method is:
03765 %
03766 %      MagickBooleanType SyncImage(Image *image)
03767 %
03768 %  A description of each parameter follows:
03769 %
03770 %    o image: the image.
03771 %
03772 */
03773 
03774 static inline IndexPacket PushColormapIndex(Image *image,
03775   const unsigned long index,MagickBooleanType *range_exception)
03776 {
03777   if (index < image->colors)
03778     return((IndexPacket) index);
03779   *range_exception=MagickTrue;
03780   return((IndexPacket) 0);
03781 }
03782 
03783 MagickExport MagickBooleanType SyncImage(Image *image)
03784 {
03785   CacheView
03786     *image_view;
03787 
03788   ExceptionInfo
03789     *exception;
03790 
03791   long
03792     y;
03793 
03794   MagickBooleanType
03795     range_exception,
03796     status;
03797 
03798   assert(image != (Image *) NULL);
03799   if (image->debug != MagickFalse)
03800     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03801   assert(image->signature == MagickSignature);
03802   if (image->storage_class == DirectClass)
03803     return(MagickFalse);
03804   range_exception=MagickFalse;
03805   status=MagickTrue;
03806   exception=(&image->exception);
03807   image_view=AcquireCacheView(image);
03808   for (y=0; y < (long) image->rows; y++)
03809   {
03810     IndexPacket
03811       index;
03812 
03813     PixelPacket
03814       pixel;
03815 
03816     register IndexPacket
03817       *__restrict indexes;
03818 
03819     register long
03820       x;
03821 
03822     register PixelPacket
03823       *__restrict q;
03824 
03825     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
03826     if (q == (PixelPacket *) NULL)
03827       {
03828         status=MagickFalse;
03829         continue;
03830       }
03831     indexes=GetCacheViewAuthenticIndexQueue(image_view);
03832     for (x=0; x < (lon