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

Generated on Thu Jul 2 12:03:20 2009 for MagickCore by  doxygen 1.5.8