constitute.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %     CCCC   OOO   N   N  SSSSS  TTTTT  IIIII  TTTTT  U   U  TTTTT  EEEEE     %
00007 %    C      O   O  NN  N  SS       T      I      T    U   U    T    E         %
00008 %    C      O   O  N N N  ESSS     T      I      T    U   U    T    EEE       %
00009 %    C      O   O  N  NN     SS    T      I      T    U   U    T    E         %
00010 %     CCCC   OOO   N   N  SSSSS    T    IIIII    T     UUU     T    EEEEE     %
00011 %                                                                             %
00012 %                                                                             %
00013 %                  MagickCore Methods to Consitute an Image                   %
00014 %                                                                             %
00015 %                             Software Design                                 %
00016 %                               John Cristy                                   %
00017 %                               October 1998                                  %
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   Include declarations.
00041 */
00042 #include "magick/studio.h"
00043 #include "magick/blob.h"
00044 #include "magick/blob-private.h"
00045 #include "magick/exception.h"
00046 #include "magick/exception-private.h"
00047 #include "magick/cache.h"
00048 #include "magick/client.h"
00049 #include "magick/constitute.h"
00050 #include "magick/delegate.h"
00051 #include "magick/geometry.h"
00052 #include "magick/identify.h"
00053 #include "magick/image-private.h"
00054 #include "magick/list.h"
00055 #include "magick/magick.h"
00056 #include "magick/memory_.h"
00057 #include "magick/monitor.h"
00058 #include "magick/option.h"
00059 #include "magick/pixel.h"
00060 #include "magick/policy.h"
00061 #include "magick/profile.h"
00062 #include "magick/property.h"
00063 #include "magick/quantum.h"
00064 #include "magick/resize.h"
00065 #include "magick/resource_.h"
00066 #include "magick/semaphore.h"
00067 #include "magick/statistic.h"
00068 #include "magick/stream.h"
00069 #include "magick/string_.h"
00070 #include "magick/timer.h"
00071 #include "magick/transform.h"
00072 #include "magick/utility.h"
00073 
00074 static SemaphoreInfo
00075   *constitute_semaphore = (SemaphoreInfo *) NULL;
00076 
00077 /*
00078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00079 %                                                                             %
00080 %                                                                             %
00081 %                                                                             %
00082 %   C o n s t i t u t e I m a g e                                             %
00083 %                                                                             %
00084 %                                                                             %
00085 %                                                                             %
00086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00087 %
00088 %  ConstituteImage() returns an image from the pixel data you supply.
00089 %  The pixel data must be in scanline order top-to-bottom.  The data can be
00090 %  char, short int, int, float, or double.  Float and double require the
00091 %  pixels to be normalized [0..1], otherwise [0..QuantumRange].  For example, to
00092 %  create a 640x480 image from unsigned red-green-blue character data, use:
00093 %
00094 %      image = ConstituteImage(640,480,"RGB",CharPixel,pixels,&exception);
00095 %
00096 %  The format of the ConstituteImage method is:
00097 %
00098 %      Image *ConstituteImage(const unsigned long columns,
00099 %        const unsigned long rows,const char *map,const StorageType storage,
00100 %        const void *pixels,ExceptionInfo *exception)
00101 %
00102 %  A description of each parameter follows:
00103 %
00104 %    o columns: width in pixels of the image.
00105 %
00106 %    o rows: height in pixels of the image.
00107 %
00108 %    o map:  This string reflects the expected ordering of the pixel array.
00109 %      It can be any combination or order of R = red, G = green, B = blue,
00110 %      A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
00111 %      Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
00112 %      P = pad.
00113 %
00114 %    o storage: Define the data type of the pixels.  Float and double types are
00115 %      expected to be normalized [0..1] otherwise [0..QuantumRange].  Choose
00116 %      from these types: CharPixel, DoublePixel, FloatPixel, IntegerPixel,
00117 %      LongPixel, QuantumPixel, or ShortPixel.
00118 %
00119 %    o pixels: This array of values contain the pixel components as defined by
00120 %      map and type.  You must preallocate this array where the expected
00121 %      length varies depending on the values of width, height, map, and type.
00122 %
00123 %    o exception: return any errors or warnings in this structure.
00124 %
00125 */
00126 MagickExport Image *ConstituteImage(const unsigned long columns,
00127   const unsigned long rows,const char *map,const StorageType storage,
00128   const void *pixels,ExceptionInfo *exception)
00129 {
00130   Image
00131     *image;
00132 
00133   MagickBooleanType
00134     status;
00135 
00136   /*
00137     Allocate image structure.
00138   */
00139   assert(map != (const char *) NULL);
00140   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",map);
00141   assert(pixels != (void *) NULL);
00142   assert(exception != (ExceptionInfo *) NULL);
00143   assert(exception->signature == MagickSignature);
00144   image=AcquireImage((ImageInfo *) NULL);
00145   if (image == (Image *) NULL)
00146     return((Image *) NULL);
00147   if ((columns == 0) || (rows == 0))
00148     ThrowImageException(OptionError,"NonZeroWidthAndHeightRequired");
00149   image->columns=columns;
00150   image->rows=rows;
00151   (void) SetImageBackgroundColor(image);
00152   status=ImportImagePixels(image,0,0,columns,rows,map,storage,pixels);
00153   if (status == MagickFalse)
00154     {
00155       InheritException(exception,&image->exception);
00156       image=DestroyImage(image);
00157     }
00158   return(image);
00159 }
00160 
00161 /*
00162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00163 %                                                                             %
00164 %                                                                             %
00165 %                                                                             %
00166 +   D e s t r o y C o n s t i t u t e                                         %
00167 %                                                                             %
00168 %                                                                             %
00169 %                                                                             %
00170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00171 %
00172 %  DestroyConstitute() destroys the constitute environment.
00173 %
00174 %  The format of the DestroyConstitute method is:
00175 %
00176 %      DestroyConstitute(void)
00177 %
00178 */
00179 MagickExport void DestroyConstitute(void)
00180 {
00181   if (constitute_semaphore != (SemaphoreInfo *) NULL)
00182     DestroySemaphoreInfo(&constitute_semaphore);
00183 }
00184 
00185 /*
00186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00187 %                                                                             %
00188 %                                                                             %
00189 %                                                                             %
00190 %   P i n g I m a g e                                                         %
00191 %                                                                             %
00192 %                                                                             %
00193 %                                                                             %
00194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00195 %
00196 %  PingImage() returns all the properties of an image or image sequence
00197 %  except for the pixels.  It is much faster and consumes far less memory
00198 %  than ReadImage().  On failure, a NULL image is returned and exception
00199 %  describes the reason for the failure.
00200 %
00201 %  The format of the PingImage method is:
00202 %
00203 %      Image *PingImage(const ImageInfo *image_info,ExceptionInfo *exception)
00204 %
00205 %  A description of each parameter follows:
00206 %
00207 %    o image_info: Ping the image defined by the file or filename members of
00208 %      this structure.
00209 %
00210 %    o exception: return any errors or warnings in this structure.
00211 %
00212 */
00213 
00214 #if defined(__cplusplus) || defined(c_plusplus)
00215 extern "C" {
00216 #endif
00217 
00218 static size_t PingStream(const Image *magick_unused(image),
00219   const void *magick_unused(pixels),const size_t columns)
00220 {
00221   return(columns);
00222 }
00223 
00224 #if defined(__cplusplus) || defined(c_plusplus)
00225 }
00226 #endif
00227 
00228 MagickExport Image *PingImage(const ImageInfo *image_info,
00229   ExceptionInfo *exception)
00230 {
00231   Image
00232     *image;
00233 
00234   ImageInfo
00235     *ping_info;
00236 
00237   assert(image_info != (ImageInfo *) NULL);
00238   assert(image_info->signature == MagickSignature);
00239   if (image_info->debug != MagickFalse)
00240     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
00241       image_info->filename);
00242   assert(exception != (ExceptionInfo *) NULL);
00243   ping_info=CloneImageInfo(image_info);
00244   ping_info->ping=MagickTrue;
00245   image=ReadStream(ping_info,&PingStream,exception);
00246   if (image != (Image *) NULL)
00247     {
00248       ResetTimer(&image->timer);
00249       if (ping_info->verbose != MagickFalse)
00250         (void) IdentifyImage(image,stdout,MagickFalse);
00251     }
00252   ping_info=DestroyImageInfo(ping_info);
00253   return(image);
00254 }
00255 
00256 /*
00257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00258 %                                                                             %
00259 %                                                                             %
00260 %                                                                             %
00261 %   P i n g I m a g e s                                                       %
00262 %                                                                             %
00263 %                                                                             %
00264 %                                                                             %
00265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00266 %
00267 %  PingImages() pings one or more images and returns them as an image list.
00268 %
00269 %  The format of the PingImage method is:
00270 %
00271 %      Image *PingImages(const ImageInfo *image_info,ExceptionInfo *exception)
00272 %
00273 %  A description of each parameter follows:
00274 %
00275 %    o image_info: the image info.
00276 %
00277 %    o exception: return any errors or warnings in this structure.
00278 %
00279 */
00280 MagickExport Image *PingImages(const ImageInfo *image_info,
00281   ExceptionInfo *exception)
00282 {
00283   char
00284     filename[MaxTextExtent];
00285 
00286   Image
00287     *image,
00288     *images;
00289 
00290   ImageInfo
00291     *read_info;
00292 
00293   /*
00294     Ping image list from a file.
00295   */
00296   assert(image_info != (ImageInfo *) NULL);
00297   assert(image_info->signature == MagickSignature);
00298   if (image_info->debug != MagickFalse)
00299     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
00300       image_info->filename);
00301   assert(exception != (ExceptionInfo *) NULL);
00302   (void) InterpretImageFilename(image_info,(Image *) NULL,image_info->filename,
00303     (int) image_info->scene,filename);
00304   if (LocaleCompare(filename,image_info->filename) != 0)
00305     {
00306       ExceptionInfo
00307         *sans;
00308 
00309       long
00310         extent,
00311         scene;
00312 
00313       /*
00314         Images of the form image-%d.png[1-5].
00315       */
00316       read_info=CloneImageInfo(image_info);
00317       sans=AcquireExceptionInfo();
00318       (void) SetImageInfo(read_info,MagickFalse,sans);
00319       sans=DestroyExceptionInfo(sans);
00320       (void) CopyMagickString(filename,read_info->filename,MaxTextExtent);
00321       images=NewImageList();
00322       extent=(long) (read_info->scene+read_info->number_scenes);
00323       for (scene=(long) read_info->scene; scene < (long) extent; scene++)
00324       {
00325         (void) InterpretImageFilename(image_info,(Image *) NULL,filename,(int)
00326           scene,read_info->filename);
00327         image=PingImage(read_info,exception);
00328         if (image == (Image *) NULL)
00329           continue;
00330         AppendImageToList(&images,image);
00331       }
00332       read_info=DestroyImageInfo(read_info);
00333       return(images);
00334     }
00335   return(PingImage(image_info,exception));
00336 }
00337 
00338 /*
00339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00340 %                                                                             %
00341 %                                                                             %
00342 %                                                                             %
00343 %   R e a d I m a g e                                                         %
00344 %                                                                             %
00345 %                                                                             %
00346 %                                                                             %
00347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00348 %
00349 %  ReadImage() reads an image or image sequence from a file or file handle.
00350 %  The method returns a NULL if there is a memory shortage or if the image
00351 %  cannot be read.  On failure, a NULL image is returned and exception
00352 %  describes the reason for the failure.
00353 %
00354 %  The format of the ReadImage method is:
00355 %
00356 %      Image *ReadImage(const ImageInfo *image_info,ExceptionInfo *exception)
00357 %
00358 %  A description of each parameter follows:
00359 %
00360 %    o image_info: Read the image defined by the file or filename members of
00361 %      this structure.
00362 %
00363 %    o exception: return any errors or warnings in this structure.
00364 %
00365 */
00366 MagickExport Image *ReadImage(const ImageInfo *image_info,
00367   ExceptionInfo *exception)
00368 {
00369   char
00370     filename[MaxTextExtent],
00371     magick[MaxTextExtent],
00372     magick_filename[MaxTextExtent];
00373 
00374   const char
00375     *value;
00376 
00377   const DelegateInfo
00378     *delegate_info;
00379 
00380   const MagickInfo
00381     *magick_info;
00382 
00383   ExceptionInfo
00384     *sans_exception;
00385 
00386   GeometryInfo
00387     geometry_info;
00388 
00389   Image
00390     *image,
00391     *next;
00392 
00393   ImageInfo
00394     *read_info;
00395 
00396   MagickStatusType
00397     flags,
00398     thread_support;
00399 
00400   PolicyDomain
00401     domain;
00402 
00403   PolicyRights
00404     rights;
00405 
00406   /*
00407     Determine image type from filename prefix or suffix (e.g. image.jpg).
00408   */
00409   assert(image_info != (ImageInfo *) NULL);
00410   assert(image_info->signature == MagickSignature);
00411   assert(image_info->filename != (char *) NULL);
00412   if (image_info->debug != MagickFalse)
00413     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
00414       image_info->filename);
00415   assert(exception != (ExceptionInfo *) NULL);
00416   read_info=CloneImageInfo(image_info);
00417   (void) CopyMagickString(magick_filename,read_info->filename,MaxTextExtent);
00418   (void) SetImageInfo(read_info,MagickFalse,exception);
00419   (void) CopyMagickString(filename,read_info->filename,MaxTextExtent);
00420   (void) CopyMagickString(magick,read_info->magick,MaxTextExtent);
00421   domain=CoderPolicyDomain;
00422   rights=ReadPolicyRights;
00423   if (IsRightsAuthorized(domain,rights,read_info->magick) == MagickFalse)
00424     {
00425       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
00426         "NotAuthorized","`%s'",read_info->filename);
00427       return((Image *) NULL);
00428     }
00429   /*
00430     Call appropriate image reader based on image type.
00431   */
00432   sans_exception=AcquireExceptionInfo();
00433   magick_info=GetMagickInfo(read_info->magick,sans_exception);
00434   sans_exception=DestroyExceptionInfo(sans_exception);
00435   if (magick_info != (const MagickInfo *) NULL)
00436     {
00437       if (GetMagickEndianSupport(magick_info) == MagickFalse)
00438         read_info->endian=UndefinedEndian;
00439       else
00440         if ((image_info->endian == UndefinedEndian) &&
00441             (GetMagickRawSupport(magick_info) != MagickFalse))
00442           {
00443             unsigned long
00444               lsb_first;
00445 
00446             lsb_first=1;
00447             read_info->endian=(*(char *) &lsb_first) == 1 ? LSBEndian :
00448               MSBEndian;
00449          }
00450     }
00451   if ((magick_info != (const MagickInfo *) NULL) &&
00452       (GetMagickSeekableStream(magick_info) != MagickFalse))
00453     {
00454       MagickBooleanType
00455         status;
00456 
00457       image=AcquireImage(read_info);
00458       (void) CopyMagickString(image->filename,read_info->filename,
00459         MaxTextExtent);
00460       status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
00461       if (status == MagickFalse)
00462         {
00463           read_info=DestroyImageInfo(read_info);
00464           image=DestroyImage(image);
00465           return((Image *) NULL);
00466         }
00467       if (IsBlobSeekable(image) == MagickFalse)
00468         {
00469           /*
00470             Coder requires a seekable stream.
00471           */
00472           *read_info->filename='\0';
00473           status=ImageToFile(image,read_info->filename,exception);
00474           if (status == MagickFalse)
00475             {
00476               (void) CloseBlob(image);
00477               read_info=DestroyImageInfo(read_info);
00478               image=DestroyImage(image);
00479               return((Image *) NULL);
00480             }
00481           read_info->temporary=MagickTrue;
00482         }
00483       (void) CloseBlob(image);
00484       image=DestroyImage(image);
00485     }
00486   image=NewImageList();
00487   if ((magick_info != (const MagickInfo *) NULL) &&
00488       (GetImageDecoder(magick_info) != (DecodeImageHandler *) NULL))
00489     {
00490       thread_support=GetMagickThreadSupport(magick_info);
00491       if ((thread_support & DecoderThreadSupport) == 0)
00492         AcquireSemaphoreInfo(&constitute_semaphore);
00493       image=GetImageDecoder(magick_info)(read_info,exception);
00494       if ((thread_support & DecoderThreadSupport) == 0)
00495         RelinquishSemaphoreInfo(constitute_semaphore);
00496     }
00497   else
00498     {
00499       delegate_info=GetDelegateInfo(read_info->magick,(char *) NULL,exception);
00500       if (delegate_info == (const DelegateInfo *) NULL)
00501         {
00502           if (IsPathAccessible(read_info->filename) != MagickFalse)
00503             (void) ThrowMagickException(exception,GetMagickModule(),
00504               MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
00505               read_info->filename);
00506           if (read_info->temporary != MagickFalse)
00507             (void) RelinquishUniqueFileResource(read_info->filename);
00508           read_info=DestroyImageInfo(read_info);
00509           return((Image *) NULL);
00510         }
00511       /*
00512         Let our decoding delegate process the image.
00513       */
00514       image=AcquireImage(read_info);
00515       if (image == (Image *) NULL)
00516         {
00517           read_info=DestroyImageInfo(read_info);
00518           return((Image *) NULL);
00519         }
00520       (void) CopyMagickString(image->filename,read_info->filename,
00521         MaxTextExtent);
00522       *read_info->filename='\0';
00523       if (GetDelegateThreadSupport(delegate_info) == MagickFalse)
00524         AcquireSemaphoreInfo(&constitute_semaphore);
00525       (void) InvokeDelegate(read_info,image,read_info->magick,(char *) NULL,
00526         exception);
00527       if (GetDelegateThreadSupport(delegate_info) == MagickFalse)
00528         RelinquishSemaphoreInfo(constitute_semaphore);
00529       image=DestroyImageList(image);
00530       read_info->temporary=MagickTrue;
00531       (void) SetImageInfo(read_info,MagickFalse,exception);
00532       magick_info=GetMagickInfo(read_info->magick,exception);
00533       if ((magick_info == (const MagickInfo *) NULL) ||
00534           (GetImageDecoder(magick_info) == (DecodeImageHandler *) NULL))
00535         {
00536           if (IsPathAccessible(read_info->filename) != MagickFalse)
00537             (void) ThrowMagickException(exception,GetMagickModule(),
00538               MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
00539               read_info->filename);
00540           else
00541             ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
00542               read_info->filename);
00543           read_info=DestroyImageInfo(read_info);
00544           return((Image *) NULL);
00545         }
00546       thread_support=GetMagickThreadSupport(magick_info);
00547       if ((thread_support & DecoderThreadSupport) == 0)
00548         AcquireSemaphoreInfo(&constitute_semaphore);
00549       image=(Image *) (GetImageDecoder(magick_info))(read_info,exception);
00550       if ((thread_support & DecoderThreadSupport) == 0)
00551         RelinquishSemaphoreInfo(constitute_semaphore);
00552     }
00553   if (read_info->temporary != MagickFalse)
00554     {
00555       (void) RelinquishUniqueFileResource(read_info->filename);
00556       read_info->temporary=MagickFalse;
00557       if (image != (Image *) NULL)
00558         (void) CopyMagickString(image->filename,filename,MaxTextExtent);
00559     }
00560   if (image == (Image *) NULL)
00561     {
00562       read_info=DestroyImageInfo(read_info);
00563       return(image);
00564     }
00565   if (exception->severity >= ErrorException)
00566     (void) LogMagickEvent(ExceptionEvent,GetMagickModule(),
00567       "Coder (%s) generated an image despite an error (%d), "
00568       "notify the developers",image->magick,exception->severity);
00569   if (IsBlobTemporary(image) != MagickFalse)
00570     (void) RelinquishUniqueFileResource(read_info->filename);
00571   if ((GetNextImageInList(image) != (Image *) NULL) &&
00572       (IsSceneGeometry(read_info->scenes,MagickFalse) != MagickFalse))
00573     {
00574       Image
00575         *clones;
00576 
00577       clones=CloneImages(image,read_info->scenes,exception);
00578       if (clones == (Image *) NULL)
00579         (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
00580           "SubimageSpecificationReturnsNoImages","`%s'",read_info->filename);
00581       else
00582         {
00583           image=DestroyImageList(image);
00584           image=GetFirstImageInList(clones);
00585         }
00586     }
00587   if (GetBlobError(image) != MagickFalse)
00588     {
00589       ThrowFileException(exception,FileOpenError,
00590         "AnErrorHasOccurredReadingFromFile",read_info->filename);
00591       image=DestroyImageList(image);
00592       read_info=DestroyImageInfo(read_info);
00593       return((Image *) NULL);
00594     }
00595   for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
00596   {
00597     char
00598       timestamp[MaxTextExtent];
00599 
00600     const StringInfo
00601       *profile;
00602 
00603     next->taint=MagickFalse;
00604     if (next->magick_columns == 0)
00605       next->magick_columns=next->columns;
00606     if (next->magick_rows == 0)
00607       next->magick_rows=next->rows;
00608     if ((LocaleCompare(magick,"HTTP") != 0) &&
00609         (LocaleCompare(magick,"FTP") != 0))
00610       (void) CopyMagickString(next->magick,magick,MaxTextExtent);
00611     (void) CopyMagickString(next->magick_filename,magick_filename,
00612       MaxTextExtent);
00613     if (IsBlobTemporary(image) != MagickFalse)
00614       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
00615     value=GetImageProperty(next,"tiff:Orientation");
00616     if (value == (char *) NULL)
00617       value=GetImageProperty(next,"exif:Orientation");
00618     if (value != (char *) NULL)
00619       {
00620         next->orientation=(OrientationType) atol(value);
00621         (void) DeleteImageProperty(next,"tiff:Orientation");
00622         (void) DeleteImageProperty(next,"exif:Orientation");
00623       }
00624     value=GetImageProperty(next,"tiff:XResolution");
00625     if (value == (char *) NULL)
00626       value=GetImageProperty(next,"exif:XResolution");
00627     if (value != (char *) NULL)
00628       {
00629         geometry_info.rho=next->x_resolution;
00630         geometry_info.sigma=1.0;
00631         flags=ParseGeometry(value,&geometry_info);
00632         if (geometry_info.sigma != 0)
00633           next->x_resolution=geometry_info.rho/geometry_info.sigma;
00634         (void) DeleteImageProperty(next,"exif:XResolution");
00635         (void) DeleteImageProperty(next,"tiff:XResolution");
00636       }
00637     value=GetImageProperty(next,"tiff:YResolution");
00638     if (value == (char *) NULL)
00639       value=GetImageProperty(next,"exif:YResolution");
00640     if (value != (char *) NULL)
00641       {
00642         geometry_info.rho=next->y_resolution;
00643         geometry_info.sigma=1.0;
00644         flags=ParseGeometry(value,&geometry_info);
00645         if (geometry_info.sigma != 0)
00646           next->y_resolution=geometry_info.rho/geometry_info.sigma;
00647         (void) DeleteImageProperty(next,"exif:YResolution");
00648         (void) DeleteImageProperty(next,"tiff:YResolution");
00649       }
00650     value=GetImageProperty(next,"tiff:ResolutionUnit");
00651     if (value == (char *) NULL)
00652       value=GetImageProperty(next,"exif:ResolutionUnit");
00653     if (value != (char *) NULL)
00654       {
00655         next->units=(ResolutionType) (atoi(value)-1);
00656         (void) DeleteImageProperty(next,"exif:ResolutionUnit");
00657         (void) DeleteImageProperty(next,"tiff:ResolutionUnit");
00658       }
00659     if (next->page.width == 0)
00660       next->page.width=next->columns;
00661     if (next->page.height == 0)
00662       next->page.height=next->rows;
00663     if (*read_info->filename != '\0')
00664       {
00665         char
00666           *property;
00667 
00668         const char
00669           *option;
00670 
00671         option=GetImageOption(read_info,"caption");
00672         if (option != (const char *) NULL)
00673           {
00674             property=InterpretImageProperties(read_info,next,option);
00675             (void) SetImageProperty(next,"caption",property);
00676             property=DestroyString(property);
00677           }
00678         option=GetImageOption(read_info,"comment");
00679         if (option != (const char *) NULL)
00680           {
00681             property=InterpretImageProperties(read_info,next,option);
00682             (void) SetImageProperty(next,"comment",property);
00683             property=DestroyString(property);
00684           }
00685         option=GetImageOption(read_info,"label");
00686         if (option != (const char *) NULL)
00687           {
00688             property=InterpretImageProperties(read_info,next,option);
00689             (void) SetImageProperty(next,"label",property);
00690             property=DestroyString(property);
00691           }
00692       }
00693     if (LocaleCompare(next->magick,"TEXT") == 0)
00694       (void) ParseAbsoluteGeometry("0x0+0+0",&next->page);
00695     if ((read_info->extract != (char *) NULL) &&
00696         (read_info->stream == (StreamHandler) NULL))
00697       {
00698         RectangleInfo
00699           geometry;
00700 
00701         flags=ParseAbsoluteGeometry(read_info->extract,&geometry);
00702         if ((next->columns != geometry.width) ||
00703             (next->rows != geometry.height))
00704           {
00705             if (((flags & XValue) != 0) || ((flags & YValue) != 0))
00706               {
00707                 Image
00708                   *crop_image;
00709 
00710                 crop_image=CropImage(next,&geometry,exception);
00711                 if (crop_image != (Image *) NULL)
00712                   ReplaceImageInList(&next,crop_image);
00713               }
00714             else
00715               if (((flags & WidthValue) != 0) || ((flags & HeightValue) != 0))
00716                 {
00717                   Image
00718                     *size_image;
00719 
00720                   flags=ParseRegionGeometry(next,read_info->extract,&geometry,
00721                     exception);
00722                   size_image=ResizeImage(next,geometry.width,geometry.height,
00723                     next->filter,next->blur,exception);
00724                   if (size_image != (Image *) NULL)
00725                     ReplaceImageInList(&next,size_image);
00726                 }
00727           }
00728       }
00729     profile=GetImageProfile(next,"icc");
00730     if (profile == (const StringInfo *) NULL)
00731       profile=GetImageProfile(next,"icm");
00732     if (profile != (const StringInfo *) NULL)
00733       {
00734         next->color_profile.length=GetStringInfoLength(profile);
00735         next->color_profile.info=GetStringInfoDatum(profile);
00736       }
00737     profile=GetImageProfile(next,"iptc");
00738     if (profile == (const StringInfo *) NULL)
00739       profile=GetImageProfile(next,"8bim");
00740     if (profile != (const StringInfo *) NULL)
00741       {
00742         next->iptc_profile.length=GetStringInfoLength(profile);
00743         next->iptc_profile.info=GetStringInfoDatum(profile);
00744       }
00745     (void) FormatMagickTime(GetBlobProperties(next)->st_mtime,MaxTextExtent,
00746       timestamp);
00747     (void) SetImageProperty(next,"modify-date",timestamp);
00748     (void) FormatMagickTime(GetBlobProperties(next)->st_ctime,MaxTextExtent,
00749       timestamp);
00750     (void) SetImageProperty(next,"create-date",timestamp);
00751     if (read_info->verbose != MagickFalse)
00752       (void) IdentifyImage(next,stdout,MagickFalse);
00753     image=next;
00754   }
00755   read_info=DestroyImageInfo(read_info);
00756   return(GetFirstImageInList(image));
00757 }
00758 
00759 /*
00760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00761 %                                                                             %
00762 %                                                                             %
00763 %                                                                             %
00764 %   R e a d I m a g e s                                                       %
00765 %                                                                             %
00766 %                                                                             %
00767 %                                                                             %
00768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00769 %
00770 %  ReadImages() reads one or more images and returns them as an image list.
00771 %
00772 %  The format of the ReadImage method is:
00773 %
00774 %      Image *ReadImages(const ImageInfo *image_info,ExceptionInfo *exception)
00775 %
00776 %  A description of each parameter follows:
00777 %
00778 %    o image_info: the image info.
00779 %
00780 %    o exception: return any errors or warnings in this structure.
00781 %
00782 */
00783 MagickExport Image *ReadImages(const ImageInfo *image_info,
00784   ExceptionInfo *exception)
00785 {
00786   char
00787     filename[MaxTextExtent];
00788 
00789   Image
00790     *image,
00791     *images;
00792 
00793   ImageInfo
00794     *read_info;
00795 
00796   /*
00797     Read image list from a file.
00798   */
00799   assert(image_info != (ImageInfo *) NULL);
00800   assert(image_info->signature == MagickSignature);
00801   if (image_info->debug != MagickFalse)
00802     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
00803       image_info->filename);
00804   assert(exception != (ExceptionInfo *) NULL);
00805   (void) InterpretImageFilename(image_info,(Image *) NULL,image_info->filename,
00806     (int) image_info->scene,filename);
00807   if (LocaleCompare(filename,image_info->filename) != 0)
00808     {
00809       ExceptionInfo
00810         *sans;
00811 
00812       long
00813         extent,
00814         scene;
00815 
00816       /*
00817         Images of the form image-%d.png[1-5].
00818       */
00819       read_info=CloneImageInfo(image_info);
00820       sans=AcquireExceptionInfo();
00821       (void) SetImageInfo(read_info,MagickFalse,sans);
00822       sans=DestroyExceptionInfo(sans);
00823       (void) CopyMagickString(filename,read_info->filename,MaxTextExtent);
00824       images=NewImageList();
00825       extent=(long) (read_info->scene+read_info->number_scenes);
00826       for (scene=(long) read_info->scene; scene < (long) extent; scene++)
00827       {
00828         (void) InterpretImageFilename(image_info,(Image *) NULL,filename,(int)
00829           scene,read_info->filename);
00830         image=ReadImage(read_info,exception);
00831         if (image == (Image *) NULL)
00832           continue;
00833         AppendImageToList(&images,image);
00834       }
00835       read_info=DestroyImageInfo(read_info);
00836       return(images);
00837     }
00838   return(ReadImage(image_info,exception));
00839 }
00840 
00841 /*
00842 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00843 %                                                                             %
00844 %                                                                             %
00845 %                                                                             %
00846 +   R e a d I n l i n e I m a g e                                             %
00847 %                                                                             %
00848 %                                                                             %
00849 %                                                                             %
00850 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00851 %
00852 %  ReadInlineImage() reads a Base64-encoded inline image or image sequence.
00853 %  The method returns a NULL if there is a memory shortage or if the image
00854 %  cannot be read.  On failure, a NULL image is returned and exception
00855 %  describes the reason for the failure.
00856 %
00857 %  The format of the ReadInlineImage method is:
00858 %
00859 %      Image *ReadInlineImage(const ImageInfo *image_info,const char *content,
00860 %        ExceptionInfo *exception)
00861 %
00862 %  A description of each parameter follows:
00863 %
00864 %    o image_info: the image info.
00865 %
00866 %    o content: the image encoded in Base64.
00867 %
00868 %    o exception: return any errors or warnings in this structure.
00869 %
00870 */
00871 MagickExport Image *ReadInlineImage(const ImageInfo *image_info,
00872   const char *content,ExceptionInfo *exception)
00873 {
00874   Image
00875     *image;
00876 
00877   ImageInfo
00878     *read_info;
00879 
00880   unsigned char
00881     *blob;
00882 
00883   size_t
00884     length;
00885 
00886   register const char
00887     *p;
00888 
00889   image=NewImageList();
00890   for (p=content; (*p != ',') && (*p != '\0'); p++) ;
00891   if (*p == '\0')
00892     ThrowReaderException(CorruptImageError,"CorruptImage");
00893   p++;
00894   length=0;
00895   blob=Base64Decode(p,&length);
00896   if (length == 0)
00897     ThrowReaderException(CorruptImageError,"CorruptImage");
00898   read_info=CloneImageInfo(image_info);
00899   (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
00900     (void *) NULL);
00901   image=BlobToImage(read_info,blob,length,exception);
00902   blob=(unsigned char *) RelinquishMagickMemory(blob);
00903   read_info=DestroyImageInfo(read_info);
00904   return(image);
00905 }
00906 
00907 /*
00908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00909 %                                                                             %
00910 %                                                                             %
00911 %                                                                             %
00912 %   W r i t e I m a g e                                                       %
00913 %                                                                             %
00914 %                                                                             %
00915 %                                                                             %
00916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00917 %
00918 %  WriteImage() writes an image or an image sequence to a file or filehandle.
00919 %  If writing to a file on disk, the name is defined by the filename member of
00920 %  the image structure.  Write() returns MagickFalse is these is a memory
00921 %  shortage or if the image cannot be written.  Check the exception member of
00922 %  image to determine the cause for any failure.
00923 %
00924 %  The format of the WriteImage method is:
00925 %
00926 %      MagickBooleanType WriteImage(const ImageInfo *image_info,Image *image)
00927 %
00928 %  A description of each parameter follows:
00929 %
00930 %    o image_info: the image info.
00931 %
00932 %    o image: the image.
00933 %
00934 */
00935 MagickExport MagickBooleanType WriteImage(const ImageInfo *image_info,
00936   Image *image)
00937 {
00938   char
00939     filename[MaxTextExtent];
00940 
00941   const DelegateInfo
00942     *delegate_info;
00943 
00944   const MagickInfo
00945     *magick_info;
00946 
00947   ExceptionInfo
00948     *sans_exception;
00949 
00950   ImageInfo
00951     *write_info;
00952 
00953   MagickBooleanType
00954     status,
00955     temporary;
00956 
00957   MagickStatusType
00958     thread_support;
00959 
00960   PolicyDomain
00961     domain;
00962 
00963   PolicyRights
00964     rights;
00965 
00966   /*
00967     Determine image type from filename prefix or suffix (e.g. image.jpg).
00968   */
00969   assert(image_info != (ImageInfo *) NULL);
00970   assert(image_info->signature == MagickSignature);
00971   if (image->debug != MagickFalse)
00972     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
00973       image_info->filename);
00974   assert(image != (Image *) NULL);
00975   assert(image->signature == MagickSignature);
00976   sans_exception=AcquireExceptionInfo();
00977   write_info=CloneImageInfo(image_info);
00978   (void) CopyMagickString(write_info->filename,image->filename,MaxTextExtent);
00979   if (*write_info->magick == '\0')
00980     (void) CopyMagickString(write_info->magick,image->magick,MaxTextExtent);
00981   (void) SetImageInfo(write_info,MagickTrue,sans_exception);
00982   if (LocaleCompare(write_info->magick,"clipmask") == 0)
00983     {
00984       if (image->clip_mask == (Image *) NULL)
00985         {
00986           (void) ThrowMagickException(&image->exception,GetMagickModule(),
00987             OptionError,"NoClipPathDefined","`%s'",image->filename);
00988           return(MagickFalse);
00989         }
00990       image=image->clip_mask;
00991       (void) SetImageInfo(write_info,MagickTrue,sans_exception);
00992     }
00993   (void) CopyMagickString(filename,image->filename,MaxTextExtent);
00994   (void) CopyMagickString(image->filename,write_info->filename,MaxTextExtent);
00995   domain=CoderPolicyDomain;
00996   rights=WritePolicyRights;
00997   if (IsRightsAuthorized(domain,rights,write_info->magick) == MagickFalse)
00998     {
00999       sans_exception=DestroyExceptionInfo(sans_exception);
01000       ThrowBinaryException(PolicyError,"NotAuthorized",filename);
01001     }
01002   magick_info=GetMagickInfo(write_info->magick,sans_exception);
01003   sans_exception=DestroyExceptionInfo(sans_exception);
01004   if (magick_info != (const MagickInfo *) NULL)
01005     {
01006       if (GetMagickEndianSupport(magick_info) == MagickFalse)
01007         image->endian=UndefinedEndian;
01008       else
01009         if ((image_info->endian == UndefinedEndian) &&
01010             (GetMagickRawSupport(magick_info) != MagickFalse))
01011           {
01012             unsigned long
01013               lsb_first;
01014 
01015             lsb_first=1;
01016             image->endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
01017          }
01018     }
01019   (void) SyncImageProfiles(image);
01020   if ((write_info->page == (char *) NULL) &&
01021       (GetPreviousImageInList(image) == (Image *) NULL) &&
01022       (GetNextImageInList(image) == (Image *) NULL) &&
01023       (IsTaintImage(image) == MagickFalse))
01024     {
01025       delegate_info=GetDelegateInfo(image->magick,write_info->magick,
01026         &image->exception);
01027       if ((delegate_info != (const DelegateInfo *) NULL) &&
01028           (GetDelegateMode(delegate_info) == 0) &&
01029           (IsPathAccessible(image->magick_filename) != MagickFalse))
01030         {
01031           /*
01032             Process image with bi-modal delegate.
01033           */
01034           (void) CopyMagickString(image->filename,image->magick_filename,
01035             MaxTextExtent);
01036           status=InvokeDelegate(write_info,image,image->magick,
01037             write_info->magick,&image->exception);
01038           write_info=DestroyImageInfo(write_info);
01039           (void) CopyMagickString(image->filename,filename,MaxTextExtent);
01040           return(status);
01041         }
01042     }
01043   status=MagickFalse;
01044   temporary=MagickFalse;
01045   if ((magick_info != (const MagickInfo *) NULL) &&
01046       (GetMagickSeekableStream(magick_info) != MagickFalse))
01047     {
01048       char
01049         filename[MaxTextExtent];
01050 
01051       (void) CopyMagickString(filename,image->filename,MaxTextExtent);
01052       status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
01053       (void) CopyMagickString(image->filename,filename,MaxTextExtent);
01054       if (status != MagickFalse)
01055         {
01056           if (IsBlobSeekable(image) == MagickFalse)
01057             {
01058               /*
01059                 A seekable stream is required by the encoder.
01060               */
01061               (void) CopyMagickString(write_info->filename,image->filename,
01062                 MaxTextExtent);
01063               (void) AcquireUniqueFilename(image->filename);
01064               temporary=MagickTrue;
01065             }
01066           (void) CloseBlob(image);
01067         }
01068     }
01069   if ((magick_info != (const MagickInfo *) NULL) &&
01070       (GetImageEncoder(magick_info) != (EncodeImageHandler *) NULL))
01071     {
01072       /*
01073         Call appropriate image writer based on image type.
01074       */
01075       thread_support=GetMagickThreadSupport(magick_info);
01076       if ((thread_support & EncoderThreadSupport) == 0)
01077         AcquireSemaphoreInfo(&constitute_semaphore);
01078       status=GetImageEncoder(magick_info)(write_info,image);
01079       if ((thread_support & EncoderThreadSupport) == 0)
01080         RelinquishSemaphoreInfo(constitute_semaphore);
01081     }
01082   else
01083     {
01084       delegate_info=GetDelegateInfo((char *) NULL,write_info->magick,
01085         &image->exception);
01086       if (delegate_info != (DelegateInfo *) NULL)
01087         {
01088           /*
01089             Process the image with delegate.
01090           */
01091           *write_info->filename='\0';
01092           if (GetDelegateThreadSupport(delegate_info) == MagickFalse)
01093             AcquireSemaphoreInfo(&constitute_semaphore);
01094           status=InvokeDelegate(write_info,image,(char *) NULL,
01095             write_info->magick,&image->exception);
01096           if (GetDelegateThreadSupport(delegate_info) == MagickFalse)
01097             RelinquishSemaphoreInfo(constitute_semaphore);
01098           (void) CopyMagickString(image->filename,filename,MaxTextExtent);
01099         }
01100       else
01101         {
01102           sans_exception=AcquireExceptionInfo();
01103           magick_info=GetMagickInfo(write_info->magick,sans_exception);
01104           sans_exception=DestroyExceptionInfo(sans_exception);
01105           if ((write_info->affirm == MagickFalse) &&
01106               (magick_info == (const MagickInfo *) NULL))
01107             {
01108               (void) CopyMagickString(write_info->magick,image->magick,
01109                 MaxTextExtent);
01110               magick_info=GetMagickInfo(write_info->magick,&image->exception);
01111             }
01112           if ((magick_info == (const MagickInfo *) NULL) ||
01113               (GetImageEncoder(magick_info) == (EncodeImageHandler *) NULL))
01114             (void) ThrowMagickException(&image->exception,GetMagickModule(),
01115               MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
01116               image->filename);
01117           else
01118             {
01119               /*
01120                 Call appropriate image writer based on image type.
01121               */
01122               thread_support=GetMagickThreadSupport(magick_info);
01123               if ((thread_support & EncoderThreadSupport) == 0)
01124                 AcquireSemaphoreInfo(&constitute_semaphore);
01125               status=GetImageEncoder(magick_info)(write_info,image);
01126               if ((thread_support & EncoderThreadSupport) == 0)
01127                 RelinquishSemaphoreInfo(constitute_semaphore);
01128             }
01129         }
01130     }
01131   if (GetBlobError(image) != MagickFalse)
01132     ThrowFileException(&image->exception,FileOpenError,
01133       "AnErrorHasOccurredWritingToFile",image->filename);
01134   if (temporary == MagickTrue)
01135     {
01136       /*
01137         Copy temporary image file to permanent.
01138       */
01139       status=OpenBlob(write_info,image,ReadBinaryBlobMode,&image->exception);
01140       if (status != MagickFalse)
01141         status=ImageToFile(image,write_info->filename,&image->exception);
01142       (void) RelinquishUniqueFileResource(image->filename);
01143       (void) CopyMagickString(image->filename,write_info->filename,
01144         MaxTextExtent);
01145       (void) CloseBlob(image);
01146     }
01147   if ((LocaleCompare(write_info->magick,"info") != 0) &&
01148       (write_info->verbose != MagickFalse))
01149     (void) IdentifyImage(image,stdout,MagickFalse);
01150   write_info=DestroyImageInfo(write_info);
01151   return(status);
01152 }
01153 
01154 /*
01155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01156 %                                                                             %
01157 %                                                                             %
01158 %                                                                             %
01159 %   W r i t e I m a g e s                                                     %
01160 %                                                                             %
01161 %                                                                             %
01162 %                                                                             %
01163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01164 %
01165 %  WriteImages() writes an image sequence.
01166 %
01167 %  The format of the WriteImages method is:
01168 %
01169 %      MagickBooleanType WriteImages(const ImageInfo *image_info,Image *images,
01170 %        const char *filename,ExceptionInfo *exception)
01171 %
01172 %  A description of each parameter follows:
01173 %
01174 %    o image_info: the image info.
01175 %
01176 %    o images: the image list.
01177 %
01178 %    o filename: the image filename.
01179 %
01180 %    o exception: return any errors or warnings in this structure.
01181 %
01182 */
01183 MagickExport MagickBooleanType WriteImages(const ImageInfo *image_info,
01184   Image *images,const char *filename,ExceptionInfo *exception)
01185 {
01186   BlobInfo
01187     *blob;
01188 
01189   ExceptionInfo
01190     *sans_exception;
01191 
01192   ImageInfo
01193     *write_info;
01194 
01195   MagickStatusType
01196     status;
01197 
01198   register Image
01199     *p;
01200 
01201   assert(image_info != (const ImageInfo *) NULL);
01202   assert(image_info->signature == MagickSignature);
01203   assert(images != (Image *) NULL);
01204   assert(images->signature == MagickSignature);
01205   if (images->debug != MagickFalse)
01206     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
01207   assert(exception != (ExceptionInfo *) NULL);
01208   write_info=CloneImageInfo(image_info);
01209   images=GetFirstImageInList(images);
01210   blob=CloneBlobInfo(images->blob);  /* thread specific I/O handler */
01211   DestroyBlob(images);
01212   images->blob=blob;
01213   if (filename != (const char *) NULL)
01214     for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
01215       (void) CopyMagickString(p->filename,filename,MaxTextExtent);
01216   (void) CopyMagickString(write_info->filename,images->filename,MaxTextExtent);
01217   if (*write_info->magick == '\0')
01218     (void) CopyMagickString(write_info->magick,images->magick,MaxTextExtent);
01219   sans_exception=AcquireExceptionInfo();
01220   (void) SetImageInfo(write_info,MagickTrue,sans_exception);
01221   sans_exception=DestroyExceptionInfo(sans_exception);
01222   p=images;
01223   for ( ; GetNextImageInList(p) != (Image *) NULL; p=GetNextImageInList(p))
01224     if (p->scene >= GetNextImageInList(p)->scene)
01225       {
01226         register long
01227           i;
01228 
01229         /*
01230           Generate consistent scene numbers.
01231         */
01232         i=(long) images->scene;
01233         for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
01234           p->scene=(unsigned long) i++;
01235         break;
01236       }
01237   /*
01238     Write images.
01239   */
01240   status=MagickTrue;
01241   for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
01242   {
01243     status&=WriteImage(write_info,p);
01244     GetImageException(p,exception);
01245     if (write_info->adjoin != MagickFalse)
01246       break;
01247   }
01248   write_info=DestroyImageInfo(write_info);
01249   return(status != 0 ? MagickTrue : MagickFalse);
01250 }

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