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

Generated on 19 Nov 2009 for MagickCore by  doxygen 1.6.1