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