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