MagickCore  7.1.0
Convert, Edit, Or Compose Bitmap Images
constitute.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % CCCC OOO N N SSSSS TTTTT IIIII TTTTT U U TTTTT EEEEE %
7 % C O O NN N SS T I T U U T E %
8 % C O O N N N ESSS T I T U U T EEE %
9 % C O O N NN SS T I T U U T E %
10 % CCCC OOO N N SSSSS T IIIII T UUU T EEEEE %
11 % %
12 % %
13 % MagickCore Methods to Consitute an Image %
14 % %
15 % Software Design %
16 % Cristy %
17 % October 1998 %
18 % %
19 % %
20 % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40  Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/attribute.h"
44 #include "MagickCore/blob.h"
46 #include "MagickCore/exception.h"
48 #include "MagickCore/cache.h"
49 #include "MagickCore/client.h"
52 #include "MagickCore/constitute.h"
54 #include "MagickCore/delegate.h"
55 #include "MagickCore/geometry.h"
56 #include "MagickCore/identify.h"
58 #include "MagickCore/list.h"
59 #include "MagickCore/magick.h"
60 #include "MagickCore/memory_.h"
61 #include "MagickCore/monitor.h"
63 #include "MagickCore/option.h"
64 #include "MagickCore/pixel.h"
66 #include "MagickCore/policy.h"
67 #include "MagickCore/profile.h"
69 #include "MagickCore/property.h"
70 #include "MagickCore/quantum.h"
71 #include "MagickCore/resize.h"
72 #include "MagickCore/resource_.h"
73 #include "MagickCore/semaphore.h"
74 #include "MagickCore/statistic.h"
75 #include "MagickCore/stream.h"
76 #include "MagickCore/string_.h"
78 #include "MagickCore/timer.h"
79 #include "MagickCore/token.h"
80 #include "MagickCore/transform.h"
81 #include "MagickCore/utility.h"
83 
84 /*
85  Typedef declaractions.
86 */
87 typedef struct _ConstituteInfo
88 {
89  const char
91  *comment,
92  *dispose,
93  *label;
94 
98 
101 
102  size_t
104 
105  ssize_t
108 
109 /*
110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
111 % %
112 % %
113 % %
114 % C o n s t i t u t e I m a g e %
115 % %
116 % %
117 % %
118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119 %
120 % ConstituteImage() returns an image from the pixel data you supply.
121 % The pixel data must be in scanline order top-to-bottom. The data can be
122 % char, short int, int, float, or double. Float and double require the
123 % pixels to be normalized [0..1], otherwise [0..QuantumRange]. For example, to
124 % create a 640x480 image from unsigned red-green-blue character data, use:
125 %
126 % image = ConstituteImage(640,480,"RGB",CharPixel,pixels,&exception);
127 %
128 % The format of the ConstituteImage method is:
129 %
130 % Image *ConstituteImage(const size_t columns,const size_t rows,
131 % const char *map,const StorageType storage,const void *pixels,
132 % ExceptionInfo *exception)
133 %
134 % A description of each parameter follows:
135 %
136 % o columns: width in pixels of the image.
137 %
138 % o rows: height in pixels of the image.
139 %
140 % o map: This string reflects the expected ordering of the pixel array.
141 % It can be any combination or order of R = red, G = green, B = blue,
142 % A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
143 % Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
144 % P = pad.
145 %
146 % o storage: Define the data type of the pixels. Float and double types are
147 % expected to be normalized [0..1] otherwise [0..QuantumRange]. Choose
148 % from these types: CharPixel, DoublePixel, FloatPixel, IntegerPixel,
149 % LongPixel, QuantumPixel, or ShortPixel.
150 %
151 % o pixels: This array of values contain the pixel components as defined by
152 % map and type. You must preallocate this array where the expected
153 % length varies depending on the values of width, height, map, and type.
154 %
155 % o exception: return any errors or warnings in this structure.
156 %
157 */
158 MagickExport Image *ConstituteImage(const size_t columns,const size_t rows,
159  const char *map,const StorageType storage,const void *pixels,
160  ExceptionInfo *exception)
161 {
162  Image
163  *image;
164 
166  status;
167 
168  ssize_t
169  i;
170 
171  size_t
172  length;
173 
174  /*
175  Allocate image structure.
176  */
177  assert(map != (const char *) NULL);
178  assert(pixels != (void *) NULL);
179  assert(exception != (ExceptionInfo *) NULL);
180  assert(exception->signature == MagickCoreSignature);
181  if (IsEventLogging() != MagickFalse)
182  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",map);
183  image=AcquireImage((ImageInfo *) NULL,exception);
184  if (image == (Image *) NULL)
185  return((Image *) NULL);
186  switch (storage)
187  {
188  case CharPixel: image->depth=8*sizeof(unsigned char); break;
189  case DoublePixel: image->depth=8*sizeof(double); break;
190  case FloatPixel: image->depth=8*sizeof(float); break;
191  case LongPixel: image->depth=8*sizeof(unsigned long); break;
192  case LongLongPixel: image->depth=8*sizeof(MagickSizeType); break;
193  case ShortPixel: image->depth=8*sizeof(unsigned short); break;
194  default: break;
195  }
196  length=strlen(map);
197  for (i=0; i < (ssize_t) length; i++)
198  {
199  switch (map[i])
200  {
201  case 'a':
202  case 'A':
203  case 'O':
204  case 'o':
205  {
207  break;
208  }
209  case 'C':
210  case 'c':
211  case 'm':
212  case 'M':
213  case 'Y':
214  case 'y':
215  case 'K':
216  case 'k':
217  {
218  image->colorspace=CMYKColorspace;
219  break;
220  }
221  case 'I':
222  case 'i':
223  {
224  image->colorspace=GRAYColorspace;
225  break;
226  }
227  default:
228  {
229  if (length == 1)
230  image->colorspace=GRAYColorspace;
231  break;
232  }
233  }
234  }
235  status=SetImageExtent(image,columns,rows,exception);
236  if (status == MagickFalse)
237  return(DestroyImageList(image));
238  status=ResetImagePixels(image,exception);
239  if (status == MagickFalse)
240  return(DestroyImageList(image));
241  status=ImportImagePixels(image,0,0,columns,rows,map,storage,pixels,exception);
242  if (status == MagickFalse)
243  image=DestroyImage(image);
244  return(image);
245 }
246 
247 /*
248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249 % %
250 % %
251 % %
252 % P i n g I m a g e %
253 % %
254 % %
255 % %
256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257 %
258 % PingImage() returns all the properties of an image or image sequence
259 % except for the pixels. It is much faster and consumes far less memory
260 % than ReadImage(). On failure, a NULL image is returned and exception
261 % describes the reason for the failure.
262 %
263 % The format of the PingImage method is:
264 %
265 % Image *PingImage(const ImageInfo *image_info,ExceptionInfo *exception)
266 %
267 % A description of each parameter follows:
268 %
269 % o image_info: Ping the image defined by the file or filename members of
270 % this structure.
271 %
272 % o exception: return any errors or warnings in this structure.
273 %
274 */
275 
276 #if defined(__cplusplus) || defined(c_plusplus)
277 extern "C" {
278 #endif
279 
280 static size_t PingStream(const Image *magick_unused(image),
281  const void *magick_unused(pixels),const size_t columns)
282 {
283  magick_unreferenced(image);
284  magick_unreferenced(pixels);
285  return(columns);
286 }
287 
288 #if defined(__cplusplus) || defined(c_plusplus)
289 }
290 #endif
291 
293  ExceptionInfo *exception)
294 {
295  Image
296  *image;
297 
298  ImageInfo
299  *ping_info;
300 
301  assert(image_info != (ImageInfo *) NULL);
302  assert(image_info->signature == MagickCoreSignature);
303  assert(exception != (ExceptionInfo *) NULL);
304  if (IsEventLogging() != MagickFalse)
306  image_info->filename);
307  ping_info=CloneImageInfo(image_info);
308  ping_info->ping=MagickTrue;
309  image=ReadStream(ping_info,&PingStream,exception);
310  if (image != (Image *) NULL)
311  {
312  ResetTimer(&image->timer);
313  if (ping_info->verbose != MagickFalse)
314  (void) IdentifyImage(image,stdout,MagickFalse,exception);
315  }
316  ping_info=DestroyImageInfo(ping_info);
317  return(image);
318 }
319 
320 /*
321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322 % %
323 % %
324 % %
325 % P i n g I m a g e s %
326 % %
327 % %
328 % %
329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330 %
331 % PingImages() pings one or more images and returns them as an image list.
332 %
333 % The format of the PingImage method is:
334 %
335 % Image *PingImages(ImageInfo *image_info,const char *filename,
336 % ExceptionInfo *exception)
337 %
338 % A description of each parameter follows:
339 %
340 % o image_info: the image info.
341 %
342 % o filename: the image filename.
343 %
344 % o exception: return any errors or warnings in this structure.
345 %
346 */
347 MagickExport Image *PingImages(ImageInfo *image_info,const char *filename,
348  ExceptionInfo *exception)
349 {
350  char
351  ping_filename[MagickPathExtent];
352 
353  Image
354  *image,
355  *images;
356 
357  ImageInfo
358  *read_info;
359 
360  /*
361  Ping image list from a file.
362  */
363  assert(image_info != (ImageInfo *) NULL);
364  assert(image_info->signature == MagickCoreSignature);
365  assert(exception != (ExceptionInfo *) NULL);
366  if (IsEventLogging() != MagickFalse)
368  image_info->filename);
369  (void) SetImageOption(image_info,"filename",filename);
370  (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
371  (void) InterpretImageFilename(image_info,(Image *) NULL,image_info->filename,
372  (int) image_info->scene,ping_filename,exception);
373  if (LocaleCompare(ping_filename,image_info->filename) != 0)
374  {
376  *sans;
377 
378  ssize_t
379  extent,
380  scene;
381 
382  /*
383  Images of the form image-%d.png[1-5].
384  */
385  read_info=CloneImageInfo(image_info);
386  sans=AcquireExceptionInfo();
387  (void) SetImageInfo(read_info,0,sans);
388  sans=DestroyExceptionInfo(sans);
389  if (read_info->number_scenes == 0)
390  {
391  read_info=DestroyImageInfo(read_info);
392  return(PingImage(image_info,exception));
393  }
394  (void) CopyMagickString(ping_filename,read_info->filename,
396  images=NewImageList();
397  extent=(ssize_t) (read_info->scene+read_info->number_scenes);
398  for (scene=(ssize_t) read_info->scene; scene < (ssize_t) extent; scene++)
399  {
400  (void) InterpretImageFilename(image_info,(Image *) NULL,ping_filename,
401  (int) scene,read_info->filename,exception);
402  image=PingImage(read_info,exception);
403  if (image == (Image *) NULL)
404  continue;
405  AppendImageToList(&images,image);
406  }
407  read_info=DestroyImageInfo(read_info);
408  return(images);
409  }
410  return(PingImage(image_info,exception));
411 }
412 
413 /*
414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
415 % %
416 % %
417 % %
418 % R e a d I m a g e %
419 % %
420 % %
421 % %
422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423 %
424 % ReadImage() reads an image or image sequence from a file or file handle.
425 % The method returns a NULL if there is a memory shortage or if the image
426 % cannot be read. On failure, a NULL image is returned and exception
427 % describes the reason for the failure.
428 %
429 % The format of the ReadImage method is:
430 %
431 % Image *ReadImage(const ImageInfo *image_info,ExceptionInfo *exception)
432 %
433 % A description of each parameter follows:
434 %
435 % o image_info: Read the image defined by the file or filename members of
436 % this structure.
437 %
438 % o exception: return any errors or warnings in this structure.
439 %
440 */
441 
442 static MagickBooleanType IsCoderAuthorized(const char *coder,
443  const PolicyRights rights,ExceptionInfo *exception)
444 {
445  if (IsRightsAuthorized(CoderPolicyDomain,rights,coder) == MagickFalse)
446  {
447  errno=EPERM;
449  "NotAuthorized","`%s'",coder);
450  return(MagickFalse);
451  }
452  return(MagickTrue);
453 }
454 
455 static void InitializeConstituteInfo(const ImageInfo *image_info,
456  ConstituteInfo *constitute_info)
457 {
458  const char
459  *option;
460 
461  memset(constitute_info,0,sizeof(*constitute_info));
462  constitute_info->sync_from_exif=MagickTrue;
463  constitute_info->sync_from_tiff=MagickTrue;
464  option=GetImageOption(image_info,"exif:sync-image");
465  if (IsStringFalse(option) != MagickFalse)
466  constitute_info->sync_from_exif=MagickFalse;
467  option=GetImageOption(image_info,"tiff:sync-image");
468  if (IsStringFalse(option) != MagickFalse)
469  constitute_info->sync_from_tiff=MagickFalse;
470  constitute_info->caption=GetImageOption(image_info,"caption");
471  constitute_info->comment=GetImageOption(image_info,"comment");
472  constitute_info->label=GetImageOption(image_info,"label");
473  option=GetImageOption(image_info,"delay");
474  if (option != (const char *) NULL)
475  {
477  geometry_info;
478 
479  constitute_info->delay_flags=ParseGeometry(option,&geometry_info);
480  if (constitute_info->delay_flags != NoValue)
481  {
482  constitute_info->delay=floor(geometry_info.rho+0.5);
483  if ((constitute_info->delay_flags & SigmaValue) != 0)
484  constitute_info->ticks_per_second=CastDoubleToLong(floor(
485  geometry_info.sigma+0.5));
486  }
487  }
488 }
489 
491  ConstituteInfo *constitute_info,ExceptionInfo *exception)
492 {
493  const char
494  *orientation;
495 
496  orientation=(const char *) NULL;
497  if (constitute_info->sync_from_exif != MagickFalse)
498  {
499  orientation=GetImageProperty(image,"exif:Orientation",exception);
500  if (orientation != (const char *) NULL)
501  {
502  image->orientation=(OrientationType) StringToLong(orientation);
503  (void) DeleteImageProperty(image,"exif:Orientation");
504  }
505  }
506  if ((orientation == (const char *) NULL) &&
507  (constitute_info->sync_from_tiff != MagickFalse))
508  {
509  orientation=GetImageProperty(image,"tiff:Orientation",exception);
510  if (orientation != (const char *) NULL)
511  {
512  image->orientation=(OrientationType) StringToLong(orientation);
513  (void) DeleteImageProperty(image,"tiff:Orientation");
514  }
515  }
516 }
517 
519  ConstituteInfo *constitute_info, ExceptionInfo *exception)
520 {
521  const char
522  *resolution_x,
523  *resolution_y,
524  *resolution_units;
525 
527  used_tiff;
528 
529  resolution_x=(const char *) NULL;
530  resolution_y=(const char *) NULL;
531  resolution_units=(const char *) NULL;
532  used_tiff=MagickFalse;
533  if (constitute_info->sync_from_exif != MagickFalse)
534  {
535  resolution_x=GetImageProperty(image,"exif:XResolution",exception);
536  resolution_y=GetImageProperty(image,"exif:YResolution",exception);
537  if ((resolution_x != (const char *) NULL) &&
538  (resolution_y != (const char *) NULL))
539  resolution_units=GetImageProperty(image,"exif:ResolutionUnit",
540  exception);
541  }
542  if ((resolution_x == (const char *) NULL) &&
543  (resolution_y == (const char *) NULL) &&
544  (constitute_info->sync_from_tiff != MagickFalse))
545  {
546  resolution_x=GetImageProperty(image,"tiff:XResolution",exception);
547  resolution_y=GetImageProperty(image,"tiff:YResolution",exception);
548  if ((resolution_x != (const char *) NULL) &&
549  (resolution_y != (const char *) NULL))
550  {
551  used_tiff=MagickTrue;
552  resolution_units=GetImageProperty(image,"tiff:ResolutionUnit",
553  exception);
554  }
555  }
556  if ((resolution_x != (const char *) NULL) &&
557  (resolution_y != (const char *) NULL))
558  {
560  geometry_info;
561 
562  ssize_t
563  option_type;
564 
565  geometry_info.rho=image->resolution.x;
566  geometry_info.sigma=1.0;
567  (void) ParseGeometry(resolution_x,&geometry_info);
568  if (geometry_info.sigma != 0)
569  image->resolution.x=geometry_info.rho/geometry_info.sigma;
570  if (strchr(resolution_x,',') != (char *) NULL)
571  image->resolution.x=geometry_info.rho+geometry_info.sigma/1000.0;
572  geometry_info.rho=image->resolution.y;
573  geometry_info.sigma=1.0;
574  (void) ParseGeometry(resolution_y,&geometry_info);
575  if (geometry_info.sigma != 0)
576  image->resolution.y=geometry_info.rho/geometry_info.sigma;
577  if (strchr(resolution_y,',') != (char *) NULL)
578  image->resolution.y=geometry_info.rho+geometry_info.sigma/1000.0;
579  if (resolution_units != (char *) NULL)
580  {
582  resolution_units);
583  if (option_type >= 0)
584  image->units=(ResolutionType) option_type;
585  }
586  if (used_tiff == MagickFalse)
587  {
588  (void) DeleteImageProperty(image,"exif:XResolution");
589  (void) DeleteImageProperty(image,"exif:YResolution");
590  (void) DeleteImageProperty(image,"exif:ResolutionUnit");
591  }
592  else
593  {
594  (void) DeleteImageProperty(image,"tiff:XResolution");
595  (void) DeleteImageProperty(image,"tiff:YResolution");
596  (void) DeleteImageProperty(image,"tiff:ResolutionUnit");
597  }
598  }
599 }
600 
602  ExceptionInfo *exception)
603 {
604  char
605  filename[MagickPathExtent],
606  magick[MagickPathExtent],
607  magick_filename[MagickPathExtent];
608 
610  constitute_info;
611 
612  const DelegateInfo
613  *delegate_info;
614 
615  const MagickInfo
616  *magick_info;
617 
619  *decoder;
620 
622  *sans_exception;
623 
624  Image
625  *image,
626  *next;
627 
628  ImageInfo
629  *read_info;
630 
632  status;
633 
634  /*
635  Determine image type from filename prefix or suffix (e.g. image.jpg).
636  */
637  assert(image_info != (ImageInfo *) NULL);
638  assert(image_info->signature == MagickCoreSignature);
639  assert(image_info->filename != (char *) NULL);
640  if (IsEventLogging() != MagickFalse)
642  image_info->filename);
643  assert(exception != (ExceptionInfo *) NULL);
644  read_info=CloneImageInfo(image_info);
645  (void) CopyMagickString(magick_filename,read_info->filename,MagickPathExtent);
646  (void) SetImageInfo(read_info,0,exception);
647  (void) CopyMagickString(filename,read_info->filename,MagickPathExtent);
648  (void) CopyMagickString(magick,read_info->magick,MagickPathExtent);
649  /*
650  Call appropriate image reader based on image type.
651  */
652  sans_exception=AcquireExceptionInfo();
653  magick_info=GetMagickInfo(read_info->magick,sans_exception);
654  if (sans_exception->severity == PolicyError)
655  InheritException(exception,sans_exception);
656  sans_exception=DestroyExceptionInfo(sans_exception);
657  if (magick_info != (const MagickInfo *) NULL)
658  {
659  if (GetMagickEndianSupport(magick_info) == MagickFalse)
660  read_info->endian=UndefinedEndian;
661  else
662  if ((image_info->endian == UndefinedEndian) &&
663  (GetMagickRawSupport(magick_info) != MagickFalse))
664  {
665  unsigned long
666  lsb_first;
667 
668  lsb_first=1;
669  read_info->endian=(*(char *) &lsb_first) == 1 ? LSBEndian :
670  MSBEndian;
671  }
672  }
673  if ((magick_info != (const MagickInfo *) NULL) &&
675  {
676  image=AcquireImage(read_info,exception);
677  (void) CopyMagickString(image->filename,read_info->filename,
679  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
680  if (status == MagickFalse)
681  {
682  read_info=DestroyImageInfo(read_info);
683  image=DestroyImage(image);
684  return((Image *) NULL);
685  }
686  if (IsBlobSeekable(image) == MagickFalse)
687  {
688  /*
689  Coder requires a seekable stream.
690  */
691  *read_info->filename='\0';
692  status=ImageToFile(image,read_info->filename,exception);
693  if (status == MagickFalse)
694  {
695  (void) CloseBlob(image);
696  read_info=DestroyImageInfo(read_info);
697  image=DestroyImage(image);
698  return((Image *) NULL);
699  }
700  read_info->temporary=MagickTrue;
701  }
702  (void) CloseBlob(image);
703  image=DestroyImage(image);
704  }
705  image=NewImageList();
706  decoder=GetImageDecoder(magick_info);
707  if (decoder == (DecodeImageHandler *) NULL)
708  {
709  delegate_info=GetDelegateInfo(read_info->magick,(char *) NULL,exception);
710  if (delegate_info == (const DelegateInfo *) NULL)
711  {
712  (void) SetImageInfo(read_info,0,exception);
713  (void) CopyMagickString(read_info->filename,filename,
715  magick_info=GetMagickInfo(read_info->magick,exception);
716  decoder=GetImageDecoder(magick_info);
717  }
718  }
719  if (decoder != (DecodeImageHandler *) NULL)
720  {
721  /*
722  Call appropriate image reader based on image type.
723  */
724  if (GetMagickDecoderThreadSupport(magick_info) == MagickFalse)
725  LockSemaphoreInfo(magick_info->semaphore);
726  status=IsCoderAuthorized(read_info->magick,ReadPolicyRights,exception);
727  image=(Image *) NULL;
728  if (status != MagickFalse)
729  image=decoder(read_info,exception);
730  if (GetMagickDecoderThreadSupport(magick_info) == MagickFalse)
731  UnlockSemaphoreInfo(magick_info->semaphore);
732  }
733  else
734  {
735  delegate_info=GetDelegateInfo(read_info->magick,(char *) NULL,exception);
736  if (delegate_info == (const DelegateInfo *) NULL)
737  {
738  (void) ThrowMagickException(exception,GetMagickModule(),
739  MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
740  read_info->magick);
741  if (read_info->temporary != MagickFalse)
742  (void) RelinquishUniqueFileResource(read_info->filename);
743  read_info=DestroyImageInfo(read_info);
744  return((Image *) NULL);
745  }
746  /*
747  Let our decoding delegate process the image.
748  */
749  image=AcquireImage(read_info,exception);
750  if (image == (Image *) NULL)
751  {
752  read_info=DestroyImageInfo(read_info);
753  return((Image *) NULL);
754  }
755  (void) CopyMagickString(image->filename,read_info->filename,
757  *read_info->filename='\0';
758  if (GetDelegateThreadSupport(delegate_info) == MagickFalse)
759  LockSemaphoreInfo(delegate_info->semaphore);
760  status=InvokeDelegate(read_info,image,read_info->magick,(char *) NULL,
761  exception);
762  if (GetDelegateThreadSupport(delegate_info) == MagickFalse)
763  UnlockSemaphoreInfo(delegate_info->semaphore);
764  image=DestroyImageList(image);
765  read_info->temporary=MagickTrue;
766  if (status != MagickFalse)
767  (void) SetImageInfo(read_info,0,exception);
768  magick_info=GetMagickInfo(read_info->magick,exception);
769  decoder=GetImageDecoder(magick_info);
770  if (decoder == (DecodeImageHandler *) NULL)
771  {
772  if (IsPathAccessible(read_info->filename) != MagickFalse)
773  (void) ThrowMagickException(exception,GetMagickModule(),
774  MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
775  read_info->magick);
776  else
777  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
778  read_info->filename);
779  read_info=DestroyImageInfo(read_info);
780  return((Image *) NULL);
781  }
782  /*
783  Call appropriate image reader based on image type.
784  */
785  if (GetMagickDecoderThreadSupport(magick_info) == MagickFalse)
786  LockSemaphoreInfo(magick_info->semaphore);
787  status=IsCoderAuthorized(read_info->magick,ReadPolicyRights,exception);
788  image=(Image *) NULL;
789  if (status != MagickFalse)
790  image=(decoder)(read_info,exception);
791  if (GetMagickDecoderThreadSupport(magick_info) == MagickFalse)
792  UnlockSemaphoreInfo(magick_info->semaphore);
793  }
794  if (read_info->temporary != MagickFalse)
795  {
796  (void) RelinquishUniqueFileResource(read_info->filename);
797  read_info->temporary=MagickFalse;
798  if (image != (Image *) NULL)
799  (void) CopyMagickString(image->filename,filename,MagickPathExtent);
800  }
801  if (image == (Image *) NULL)
802  {
803  read_info=DestroyImageInfo(read_info);
804  return(image);
805  }
806  if (exception->severity >= ErrorException)
808  "Coder (%s) generated an image despite an error (%d), "
809  "notify the developers",image->magick,exception->severity);
810  if (IsBlobTemporary(image) != MagickFalse)
811  (void) RelinquishUniqueFileResource(read_info->filename);
812  if ((IsSceneGeometry(read_info->scenes,MagickFalse) != MagickFalse) &&
813  (GetImageListLength(image) != 1))
814  {
815  Image
816  *clones;
817 
818  clones=CloneImages(image,read_info->scenes,exception);
819  if (clones != (Image *) NULL)
820  {
821  image=DestroyImageList(image);
822  image=GetFirstImageInList(clones);
823  }
824  }
825  InitializeConstituteInfo(read_info,&constitute_info);
826  for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
827  {
828  char
829  magick_path[MagickPathExtent],
830  *property;
831 
832  const StringInfo
833  *profile;
834 
835  static const char
836  *source_date_epoch = (const char *) NULL;
837 
838  static MagickBooleanType
839  epoch_initalized = MagickFalse;
840 
841  next->taint=MagickFalse;
842  GetPathComponent(magick_filename,MagickPath,magick_path);
843  if ((*magick_path == '\0') && (*next->magick == '\0'))
844  (void) CopyMagickString(next->magick,magick,MagickPathExtent);
845  (void) CopyMagickString(next->magick_filename,magick_filename,
847  if (IsBlobTemporary(image) != MagickFalse)
848  (void) CopyMagickString(next->filename,filename,MagickPathExtent);
849  if (next->magick_columns == 0)
850  next->magick_columns=next->columns;
851  if (next->magick_rows == 0)
852  next->magick_rows=next->rows;
853  (void) GetImageProperty(next,"exif:*",exception);
854  (void) GetImageProperty(next,"icc:*",exception);
855  (void) GetImageProperty(next,"iptc:*",exception);
856  (void) GetImageProperty(next,"xmp:*",exception);
857  SyncOrientationFromProperties(next,&constitute_info,exception);
858  SyncResolutionFromProperties(next,&constitute_info,exception);
859  if (next->page.width == 0)
860  next->page.width=next->columns;
861  if (next->page.height == 0)
862  next->page.height=next->rows;
863  if (constitute_info.caption != (const char *) NULL)
864  {
865  property=InterpretImageProperties(read_info,next,
866  constitute_info.caption,exception);
867  (void) SetImageProperty(next,"caption",property,exception);
868  property=DestroyString(property);
869  }
870  if (constitute_info.comment != (const char *) NULL)
871  {
872  property=InterpretImageProperties(read_info,next,
873  constitute_info.comment,exception);
874  (void) SetImageProperty(next,"comment",property,exception);
875  property=DestroyString(property);
876  }
877  if (constitute_info.label != (const char *) NULL)
878  {
879  property=InterpretImageProperties(read_info,next,
880  constitute_info.label,exception);
881  (void) SetImageProperty(next,"label",property,exception);
882  property=DestroyString(property);
883  }
884  if (LocaleCompare(next->magick,"TEXT") == 0)
885  (void) ParseAbsoluteGeometry("0x0+0+0",&next->page);
886  if ((read_info->extract != (char *) NULL) &&
887  (read_info->stream == (StreamHandler) NULL))
888  {
890  geometry;
891 
893  flags;
894 
895  SetGeometry(next,&geometry);
896  flags=ParseAbsoluteGeometry(read_info->extract,&geometry);
897  if ((next->columns != geometry.width) ||
898  (next->rows != geometry.height))
899  {
900  if (((flags & XValue) != 0) || ((flags & YValue) != 0))
901  {
902  Image
903  *crop_image;
904 
905  crop_image=CropImage(next,&geometry,exception);
906  if (crop_image != (Image *) NULL)
907  ReplaceImageInList(&next,crop_image);
908  }
909  else
910  if (((flags & WidthValue) != 0) || ((flags & HeightValue) != 0))
911  {
912  Image
913  *size_image;
914 
915  flags=ParseRegionGeometry(next,read_info->extract,&geometry,
916  exception);
917  size_image=ResizeImage(next,geometry.width,geometry.height,
918  next->filter,exception);
919  if (size_image != (Image *) NULL)
920  ReplaceImageInList(&next,size_image);
921  }
922  }
923  }
924  profile=GetImageProfile(next,"icc");
925  if (profile == (const StringInfo *) NULL)
926  profile=GetImageProfile(next,"icm");
927  profile=GetImageProfile(next,"iptc");
928  if (profile == (const StringInfo *) NULL)
929  profile=GetImageProfile(next,"8bim");
930  if (epoch_initalized == MagickFalse)
931  {
932  source_date_epoch=getenv("SOURCE_DATE_EPOCH");
933  epoch_initalized=MagickTrue;
934  }
935  if (source_date_epoch == (const char *) NULL)
936  {
937  char
938  timestamp[MagickTimeExtent];
939 
940  (void) FormatMagickTime((time_t) GetBlobProperties(next)->st_mtime,
941  sizeof(timestamp),timestamp);
942  (void) SetImageProperty(next,"date:modify",timestamp,exception);
943  (void) FormatMagickTime((time_t) GetBlobProperties(next)->st_ctime,
944  sizeof(timestamp),timestamp);
945  (void) SetImageProperty(next,"date:create",timestamp,exception);
946  }
947  if (constitute_info.delay_flags != NoValue)
948  {
949  if ((constitute_info.delay_flags & GreaterValue) != 0)
950  {
951  if (next->delay > constitute_info.delay)
952  next->delay=constitute_info.delay;
953  }
954  else
955  if ((constitute_info.delay_flags & LessValue) != 0)
956  {
957  if (next->delay < constitute_info.delay)
958  next->delay=constitute_info.delay;
959  }
960  else
961  next->delay=constitute_info.delay;
962  if ((constitute_info.delay_flags & SigmaValue) != 0)
963  next->ticks_per_second=constitute_info.ticks_per_second;
964  }
965  if (constitute_info.dispose != (const char *) NULL)
966  {
967  ssize_t
968  option_type;
969 
971  constitute_info.dispose);
972  if (option_type >= 0)
973  next->dispose=(DisposeType) option_type;
974  }
975  if (read_info->verbose != MagickFalse)
976  (void) IdentifyImage(next,stderr,MagickFalse,exception);
977  image=next;
978  }
979  read_info=DestroyImageInfo(read_info);
980  if (GetBlobError(image) != MagickFalse)
981  ThrowReaderException(CorruptImageError,"UnableToReadImageData");
982  return(GetFirstImageInList(image));
983 }
984 
985 /*
986 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
987 % %
988 % %
989 % %
990 % R e a d I m a g e s %
991 % %
992 % %
993 % %
994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
995 %
996 % ReadImages() reads one or more images and returns them as an image list.
997 %
998 % The format of the ReadImage method is:
999 %
1000 % Image *ReadImages(ImageInfo *image_info,const char *filename,
1001 % ExceptionInfo *exception)
1002 %
1003 % A description of each parameter follows:
1004 %
1005 % o image_info: the image info.
1006 %
1007 % o filename: the image filename.
1008 %
1009 % o exception: return any errors or warnings in this structure.
1010 %
1011 */
1012 MagickExport Image *ReadImages(ImageInfo *image_info,const char *filename,
1013  ExceptionInfo *exception)
1014 {
1015  char
1016  read_filename[MagickPathExtent];
1017 
1018  Image
1019  *image,
1020  *images;
1021 
1022  ImageInfo
1023  *read_info;
1024 
1025  /*
1026  Read image list from a file.
1027  */
1028  assert(image_info != (ImageInfo *) NULL);
1029  assert(image_info->signature == MagickCoreSignature);
1030  assert(exception != (ExceptionInfo *) NULL);
1031  if (IsEventLogging() != MagickFalse)
1033  image_info->filename);
1034  read_info=CloneImageInfo(image_info);
1035  *read_info->magick='\0';
1036  (void) SetImageOption(read_info,"filename",filename);
1037  (void) CopyMagickString(read_info->filename,filename,MagickPathExtent);
1038  (void) InterpretImageFilename(read_info,(Image *) NULL,filename,
1039  (int) read_info->scene,read_filename,exception);
1040  if (LocaleCompare(read_filename,read_info->filename) != 0)
1041  {
1043  *sans;
1044 
1045  ssize_t
1046  extent,
1047  scene;
1048 
1049  /*
1050  Images of the form image-%d.png[1-5].
1051  */
1052  sans=AcquireExceptionInfo();
1053  (void) SetImageInfo(read_info,0,sans);
1054  sans=DestroyExceptionInfo(sans);
1055  if (read_info->number_scenes != 0)
1056  {
1057  (void) CopyMagickString(read_filename,read_info->filename,
1059  images=NewImageList();
1060  extent=(ssize_t) (read_info->scene+read_info->number_scenes);
1061  scene=(ssize_t) read_info->scene;
1062  for ( ; scene < (ssize_t) extent; scene++)
1063  {
1064  (void) InterpretImageFilename(image_info,(Image *) NULL,
1065  read_filename,(int) scene,read_info->filename,exception);
1066  image=ReadImage(read_info,exception);
1067  if (image == (Image *) NULL)
1068  continue;
1069  AppendImageToList(&images,image);
1070  }
1071  read_info=DestroyImageInfo(read_info);
1072  return(images);
1073  }
1074  }
1075  (void) CopyMagickString(read_info->filename,filename,MagickPathExtent);
1076  image=ReadImage(read_info,exception);
1077  read_info=DestroyImageInfo(read_info);
1078  return(image);
1079 }
1080 
1081 /*
1082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1083 % %
1084 % %
1085 % %
1086 + R e a d I n l i n e I m a g e %
1087 % %
1088 % %
1089 % %
1090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1091 %
1092 % ReadInlineImage() reads a Base64-encoded inline image or image sequence.
1093 % The method returns a NULL if there is a memory shortage or if the image
1094 % cannot be read. On failure, a NULL image is returned and exception
1095 % describes the reason for the failure.
1096 %
1097 % The format of the ReadInlineImage method is:
1098 %
1099 % Image *ReadInlineImage(const ImageInfo *image_info,const char *content,
1100 % ExceptionInfo *exception)
1101 %
1102 % A description of each parameter follows:
1103 %
1104 % o image_info: the image info.
1105 %
1106 % o content: the image encoded in Base64.
1107 %
1108 % o exception: return any errors or warnings in this structure.
1109 %
1110 */
1112  const char *content,ExceptionInfo *exception)
1113 {
1114  Image
1115  *image;
1116 
1117  ImageInfo
1118  *read_info;
1119 
1120  unsigned char
1121  *blob;
1122 
1123  size_t
1124  length;
1125 
1126  const char
1127  *p;
1128 
1129  /*
1130  Skip over header (e.g. data:image/gif;base64,).
1131  */
1132  image=NewImageList();
1133  for (p=content; (*p != ',') && (*p != '\0'); p++) ;
1134  if (*p == '\0')
1135  ThrowReaderException(CorruptImageError,"CorruptImage");
1136  blob=Base64Decode(++p,&length);
1137  if (length == 0)
1138  {
1139  blob=(unsigned char *) RelinquishMagickMemory(blob);
1140  ThrowReaderException(CorruptImageError,"CorruptImage");
1141  }
1142  read_info=CloneImageInfo(image_info);
1143  (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
1144  (void *) NULL);
1145  *read_info->filename='\0';
1146  *read_info->magick='\0';
1147  for (p=content; (*p != '/') && (*p != '\0'); p++) ;
1148  if (*p != '\0')
1149  {
1150  char
1151  *q;
1152 
1153  ssize_t
1154  i;
1155 
1156  /*
1157  Extract media type.
1158  */
1159  if (LocaleNCompare(++p,"x-",2) == 0)
1160  p+=2;
1161  (void) strcpy(read_info->filename,"data.");
1162  q=read_info->filename+5;
1163  for (i=0; (*p != ';') && (*p != '\0') && (i < (MagickPathExtent-6)); i++)
1164  *q++=(*p++);
1165  *q++='\0';
1166  }
1167  image=BlobToImage(read_info,blob,length,exception);
1168  blob=(unsigned char *) RelinquishMagickMemory(blob);
1169  read_info=DestroyImageInfo(read_info);
1170  return(image);
1171 }
1172 
1173 /*
1174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1175 % %
1176 % %
1177 % %
1178 % W r i t e I m a g e %
1179 % %
1180 % %
1181 % %
1182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1183 %
1184 % WriteImage() writes an image or an image sequence to a file or file handle.
1185 % If writing to a file is on disk, the name is defined by the filename member
1186 % of the image structure. WriteImage() returns MagickFalse is there is a
1187 % memory shortage or if the image cannot be written. Check the exception
1188 % member of image to determine the cause for any failure.
1189 %
1190 % The format of the WriteImage method is:
1191 %
1192 % MagickBooleanType WriteImage(const ImageInfo *image_info,Image *image,
1193 % ExceptionInfo *exception)
1194 %
1195 % A description of each parameter follows:
1196 %
1197 % o image_info: the image info.
1198 %
1199 % o image: the image.
1200 %
1201 % o exception: return any errors or warnings in this structure.
1202 %
1203 */
1205  Image *image,ExceptionInfo *exception)
1206 {
1207  char
1208  filename[MagickPathExtent];
1209 
1210  const char
1211  *option;
1212 
1213  const DelegateInfo
1214  *delegate_info;
1215 
1216  const MagickInfo
1217  *magick_info;
1218 
1220  *encoder;
1221 
1223  *sans_exception;
1224 
1225  ImageInfo
1226  *write_info;
1227 
1229  status,
1230  temporary;
1231 
1232  /*
1233  Determine image type from filename prefix or suffix (e.g. image.jpg).
1234  */
1235  assert(image_info != (ImageInfo *) NULL);
1236  assert(image_info->signature == MagickCoreSignature);
1237  assert(image != (Image *) NULL);
1238  if (IsEventLogging() != MagickFalse)
1240  image_info->filename);
1241  assert(image->signature == MagickCoreSignature);
1242  assert(exception != (ExceptionInfo *) NULL);
1243  sans_exception=AcquireExceptionInfo();
1244  write_info=CloneImageInfo(image_info);
1245  (void) CopyMagickString(write_info->filename,image->filename,
1247  (void) SetImageInfo(write_info,1,sans_exception);
1248  if (*write_info->magick == '\0')
1249  (void) CopyMagickString(write_info->magick,image->magick,MagickPathExtent);
1250  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
1251  (void) CopyMagickString(image->filename,write_info->filename,
1253  /*
1254  Call appropriate image writer based on image type.
1255  */
1256  magick_info=GetMagickInfo(write_info->magick,sans_exception);
1257  if (sans_exception->severity == PolicyError)
1258  magick_info=GetMagickInfo(write_info->magick,exception);
1259  sans_exception=DestroyExceptionInfo(sans_exception);
1260  if (magick_info != (const MagickInfo *) NULL)
1261  {
1262  if (GetMagickEndianSupport(magick_info) == MagickFalse)
1263  image->endian=UndefinedEndian;
1264  else
1265  if ((image_info->endian == UndefinedEndian) &&
1266  (GetMagickRawSupport(magick_info) != MagickFalse))
1267  {
1268  unsigned long
1269  lsb_first;
1270 
1271  lsb_first=1;
1272  image->endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
1273  }
1274  }
1275  (void) SyncImageProfiles(image);
1276  DisassociateImageStream(image);
1277  option=GetImageOption(image_info,"delegate:bimodal");
1278  if ((IsStringTrue(option) != MagickFalse) &&
1279  (write_info->page == (char *) NULL) &&
1280  (GetPreviousImageInList(image) == (Image *) NULL) &&
1281  (GetNextImageInList(image) == (Image *) NULL) &&
1282  (IsTaintImage(image) == MagickFalse) )
1283  {
1284  delegate_info=GetDelegateInfo(image->magick,write_info->magick,exception);
1285  if ((delegate_info != (const DelegateInfo *) NULL) &&
1286  (GetDelegateMode(delegate_info) == 0) &&
1288  {
1289  /*
1290  Process image with bi-modal delegate.
1291  */
1292  (void) CopyMagickString(image->filename,image->magick_filename,
1294  status=InvokeDelegate(write_info,image,image->magick,
1295  write_info->magick,exception);
1296  write_info=DestroyImageInfo(write_info);
1297  (void) CopyMagickString(image->filename,filename,MagickPathExtent);
1298  return(status);
1299  }
1300  }
1301  status=MagickFalse;
1302  temporary=MagickFalse;
1303  if ((magick_info != (const MagickInfo *) NULL) &&
1304  (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
1305  {
1306  char
1307  image_filename[MagickPathExtent];
1308 
1309  (void) CopyMagickString(image_filename,image->filename,MagickPathExtent);
1310  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1311  (void) CopyMagickString(image->filename, image_filename,MagickPathExtent);
1312  if (status != MagickFalse)
1313  {
1314  if (IsBlobSeekable(image) == MagickFalse)
1315  {
1316  /*
1317  A seekable stream is required by the encoder.
1318  */
1319  write_info->adjoin=MagickTrue;
1320  (void) CopyMagickString(write_info->filename,image->filename,
1322  (void) AcquireUniqueFilename(image->filename);
1323  temporary=MagickTrue;
1324  }
1325  (void) CloseBlob(image);
1326  }
1327  }
1328  encoder=GetImageEncoder(magick_info);
1329  if (encoder != (EncodeImageHandler *) NULL)
1330  {
1331  /*
1332  Call appropriate image writer based on image type.
1333  */
1334  if (GetMagickEncoderThreadSupport(magick_info) == MagickFalse)
1335  LockSemaphoreInfo(magick_info->semaphore);
1336  status=IsCoderAuthorized(write_info->magick,WritePolicyRights,exception);
1337  if (status != MagickFalse)
1338  status=encoder(write_info,image,exception);
1339  if (GetMagickEncoderThreadSupport(magick_info) == MagickFalse)
1340  UnlockSemaphoreInfo(magick_info->semaphore);
1341  }
1342  else
1343  {
1344  delegate_info=GetDelegateInfo((char *) NULL,write_info->magick,exception);
1345  if (delegate_info != (DelegateInfo *) NULL)
1346  {
1347  /*
1348  Process the image with delegate.
1349  */
1350  *write_info->filename='\0';
1351  if (GetDelegateThreadSupport(delegate_info) == MagickFalse)
1352  LockSemaphoreInfo(delegate_info->semaphore);
1353  status=InvokeDelegate(write_info,image,(char *) NULL,
1354  write_info->magick,exception);
1355  if (GetDelegateThreadSupport(delegate_info) == MagickFalse)
1356  UnlockSemaphoreInfo(delegate_info->semaphore);
1357  (void) CopyMagickString(image->filename,filename,MagickPathExtent);
1358  }
1359  else
1360  {
1361  sans_exception=AcquireExceptionInfo();
1362  magick_info=GetMagickInfo(write_info->magick,sans_exception);
1363  if (sans_exception->severity == PolicyError)
1364  magick_info=GetMagickInfo(write_info->magick,exception);
1365  sans_exception=DestroyExceptionInfo(sans_exception);
1366  if ((write_info->affirm == MagickFalse) &&
1367  (magick_info == (const MagickInfo *) NULL))
1368  {
1369  (void) CopyMagickString(write_info->magick,image->magick,
1371  magick_info=GetMagickInfo(write_info->magick,exception);
1372  }
1373  encoder=GetImageEncoder(magick_info);
1374  if (encoder == (EncodeImageHandler *) NULL)
1375  {
1376  char
1377  extension[MagickPathExtent];
1378 
1379  GetPathComponent(image->filename,ExtensionPath,extension);
1380  if (*extension != '\0')
1381  magick_info=GetMagickInfo(extension,exception);
1382  else
1383  magick_info=GetMagickInfo(image->magick,exception);
1384  (void) CopyMagickString(image->filename,filename,
1386  encoder=GetImageEncoder(magick_info);
1387  }
1388  if (encoder == (EncodeImageHandler *) NULL)
1389  {
1390  magick_info=GetMagickInfo(image->magick,exception);
1391  encoder=GetImageEncoder(magick_info);
1392  if (encoder == (EncodeImageHandler *) NULL)
1393  (void) ThrowMagickException(exception,GetMagickModule(),
1394  MissingDelegateError,"NoEncodeDelegateForThisImageFormat",
1395  "`%s'",write_info->magick);
1396  }
1397  if (encoder != (EncodeImageHandler *) NULL)
1398  {
1399  /*
1400  Call appropriate image writer based on image type.
1401  */
1402  if (GetMagickEncoderThreadSupport(magick_info) == MagickFalse)
1403  LockSemaphoreInfo(magick_info->semaphore);
1404  status=IsCoderAuthorized(write_info->magick,WritePolicyRights,
1405  exception);
1406  if (status != MagickFalse)
1407  status=encoder(write_info,image,exception);
1408  if (GetMagickEncoderThreadSupport(magick_info) == MagickFalse)
1409  UnlockSemaphoreInfo(magick_info->semaphore);
1410  }
1411  }
1412  }
1413  if (temporary != MagickFalse)
1414  {
1415  /*
1416  Copy temporary image file to permanent.
1417  */
1418  status=OpenBlob(write_info,image,ReadBinaryBlobMode,exception);
1419  if (status != MagickFalse)
1420  {
1421  (void) RelinquishUniqueFileResource(write_info->filename);
1422  status=ImageToFile(image,write_info->filename,exception);
1423  }
1424  (void) CloseBlob(image);
1425  (void) RelinquishUniqueFileResource(image->filename);
1426  (void) CopyMagickString(image->filename,write_info->filename,
1428  }
1429  if ((LocaleCompare(write_info->magick,"info") != 0) &&
1430  (write_info->verbose != MagickFalse))
1431  (void) IdentifyImage(image,stdout,MagickFalse,exception);
1432  write_info=DestroyImageInfo(write_info);
1433  if (GetBlobError(image) != MagickFalse)
1434  ThrowWriterException(FileOpenError,"UnableToWriteFile");
1435  return(status);
1436 }
1437 
1438 /*
1439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1440 % %
1441 % %
1442 % %
1443 % W r i t e I m a g e s %
1444 % %
1445 % %
1446 % %
1447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1448 %
1449 % WriteImages() writes an image sequence into one or more files. While
1450 % WriteImage() can write an image sequence, it is limited to writing
1451 % the sequence into a single file using a format which supports multiple
1452 % frames. WriteImages(), however, does not have this limitation, instead it
1453 % generates multiple output files if necessary (or when requested). When
1454 % ImageInfo's adjoin flag is set to MagickFalse, the file name is expected
1455 % to include a printf-style formatting string for the frame number (e.g.
1456 % "image%02d.png").
1457 %
1458 % The format of the WriteImages method is:
1459 %
1460 % MagickBooleanType WriteImages(const ImageInfo *image_info,Image *images,
1461 % const char *filename,ExceptionInfo *exception)
1462 %
1463 % A description of each parameter follows:
1464 %
1465 % o image_info: the image info.
1466 %
1467 % o images: the image list.
1468 %
1469 % o filename: the image filename.
1470 %
1471 % o exception: return any errors or warnings in this structure.
1472 %
1473 */
1475  Image *images,const char *filename,ExceptionInfo *exception)
1476 {
1477 #define WriteImageTag "Write/Image"
1478 
1480  *sans_exception;
1481 
1482  ImageInfo
1483  *write_info;
1484 
1486  proceed;
1487 
1489  progress;
1490 
1492  progress_monitor;
1493 
1495  number_images;
1496 
1498  status;
1499 
1500  Image
1501  *p;
1502 
1503  assert(image_info != (const ImageInfo *) NULL);
1504  assert(image_info->signature == MagickCoreSignature);
1505  assert(images != (Image *) NULL);
1506  assert(images->signature == MagickCoreSignature);
1507  if (IsEventLogging() != MagickFalse)
1508  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1509  assert(exception != (ExceptionInfo *) NULL);
1510  write_info=CloneImageInfo(image_info);
1511  *write_info->magick='\0';
1512  images=GetFirstImageInList(images);
1513  if (filename != (const char *) NULL)
1514  for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1515  (void) CopyMagickString(p->filename,filename,MagickPathExtent);
1516  (void) CopyMagickString(write_info->filename,images->filename,
1518  sans_exception=AcquireExceptionInfo();
1519  (void) SetImageInfo(write_info,(unsigned int) GetImageListLength(images),
1520  sans_exception);
1521  sans_exception=DestroyExceptionInfo(sans_exception);
1522  if (*write_info->magick == '\0')
1523  (void) CopyMagickString(write_info->magick,images->magick,MagickPathExtent);
1524  p=images;
1525  for ( ; GetNextImageInList(p) != (Image *) NULL; p=GetNextImageInList(p))
1526  {
1527  Image
1528  *next;
1529 
1530  next=GetNextImageInList(p);
1531  if (next == (Image *) NULL)
1532  break;
1533  if (p->scene >= next->scene)
1534  {
1535  ssize_t
1536  i;
1537 
1538  /*
1539  Generate consistent scene numbers.
1540  */
1541  i=(ssize_t) images->scene;
1542  for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1543  p->scene=(size_t) i++;
1544  break;
1545  }
1546  }
1547  /*
1548  Write images.
1549  */
1550  status=MagickTrue;
1551  progress_monitor=(MagickProgressMonitor) NULL;
1552  progress=0;
1553  number_images=GetImageListLength(images);
1554  for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1555  {
1556  if (number_images != 1)
1557  progress_monitor=SetImageProgressMonitor(p,(MagickProgressMonitor) NULL,
1558  p->client_data);
1559  status&=WriteImage(write_info,p,exception);
1560  if (number_images != 1)
1561  (void) SetImageProgressMonitor(p,progress_monitor,p->client_data);
1562  if (write_info->adjoin != MagickFalse)
1563  break;
1564  if (number_images != 1)
1565  {
1566 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1567  #pragma omp atomic
1568 #endif
1569  progress++;
1570  proceed=SetImageProgress(p,WriteImageTag,progress,number_images);
1571  if (proceed == MagickFalse)
1572  break;
1573  }
1574  }
1575  write_info=DestroyImageInfo(write_info);
1576  return(status != 0 ? MagickTrue : MagickFalse);
1577 }
size_t rows
Definition: image.h:172
MagickExport Image * ResizeImage(const Image *image, const size_t columns, const size_t rows, const FilterType filter, ExceptionInfo *exception)
Definition: resize.c:3717
MagickExport Image * CloneImages(const Image *images, const char *scenes, ExceptionInfo *exception)
Definition: list.c:206
MagickExport MagickBooleanType IsStringFalse(const char *value)
Definition: string.c:1429
EndianType endian
Definition: image.h:404
size_t signature
Definition: image.h:488
DisposeType dispose
Definition: image.h:237
char magick[MagickPathExtent]
Definition: image.h:480
MagickExport MagickBooleanType GetDelegateThreadSupport(const DelegateInfo *delegate_info)
Definition: delegate.c:1538
char * scenes
Definition: image.h:390
MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain, const PolicyRights rights, const char *pattern)
Definition: policy.c:623
ssize_t ticks_per_second
Definition: image.h:245
FilterType filter
Definition: image.h:219
MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:449
MagickExport ssize_t ParseCommandOption(const CommandOption option, const MagickBooleanType list, const char *options)
Definition: option.c:3077
OrientationType
Definition: image.h:76
MagickExport MagickBooleanType GetBlobError(const Image *image)
Definition: blob.c:1718
char * extract
Definition: image.h:390
PolicyRights
Definition: policy.h:41
size_t signature
Definition: exception.h:123
size_t number_scenes
Definition: image.h:396
MagickExport Image * PingImage(const ImageInfo *image_info, ExceptionInfo *exception)
Definition: constitute.c:292
double rho
Definition: geometry.h:108
MagickExport MagickStatusType ParseAbsoluteGeometry(const char *geometry, RectangleInfo *region_info)
Definition: geometry.c:717
EndianType endian
Definition: image.h:228
MagickBooleanType taint
Definition: image.h:169
StorageType
Definition: pixel.h:146
MagickExport MagickBooleanType IdentifyImage(Image *image, FILE *file, const MagickBooleanType verbose, ExceptionInfo *exception)
Definition: identify.c:472
MagickExport MagickBooleanType GetMagickEncoderThreadSupport(const MagickInfo *magick_info)
Definition: magick.c:545
const char * dispose
Definition: constitute.c:90
MagickExport const DelegateInfo * GetDelegateInfo(const char *decode, const char *encode, ExceptionInfo *exception)
Definition: delegate.c:1223
MagickExport Image * ReadInlineImage(const ImageInfo *image_info, const char *content, ExceptionInfo *exception)
Definition: constitute.c:1111
MagickExport ExceptionInfo * AcquireExceptionInfo(void)
Definition: exception.c:115
static MagickBooleanType IsCoderAuthorized(const char *coder, const PolicyRights rights, ExceptionInfo *exception)
Definition: constitute.c:442
MagickExport ssize_t GetDelegateMode(const DelegateInfo *delegate_info)
Definition: delegate.c:1505
MagickExport size_t CopyMagickString(char *magick_restrict destination, const char *magick_restrict source, const size_t length)
Definition: string.c:731
MagickBooleanType EncodeImageHandler(const ImageInfo *, Image *, ExceptionInfo *)
Definition: magick.h:62
ResolutionType units
Definition: image.h:198
size_t delay
Definition: image.h:240
#define WriteImageTag
char magick[MagickPathExtent]
Definition: image.h:319
size_t magick_rows
Definition: image.h:324
MagickExport MagickBooleanType ImageToFile(Image *image, char *filename, ExceptionInfo *exception)
Definition: blob.c:2303
MagickBooleanType verbose
Definition: image.h:445
static long StringToLong(const char *magick_restrict value)
MagickExport const char * GetImageOption(const ImageInfo *image_info, const char *option)
Definition: option.c:2389
#define MagickTimeExtent
double sigma
Definition: geometry.h:108
size_t width
Definition: geometry.h:132
MagickExport MagickBooleanType AcquireUniqueFilename(char *path)
Definition: utility.c:111
Definition: log.h:52
ssize_t MagickOffsetType
Definition: magick-type.h:133
MagickExport MagickBooleanType SetImageOption(ImageInfo *image_info, const char *option, const char *value)
Definition: option.c:3347
Definition: image.h:151
MagickExport Image * GetPreviousImageInList(const Image *images)
Definition: list.c:818
SemaphoreInfo * semaphore
Definition: delegate.h:45
StreamHandler stream
Definition: image.h:468
MagickExport MagickBooleanType GetMagickRawSupport(const MagickInfo *magick_info)
Definition: magick.c:975
MagickExport Image * CropImage(const Image *image, const RectangleInfo *geometry, ExceptionInfo *exception)
Definition: transform.c:538
MagickExport const struct stat * GetBlobProperties(const Image *)
Definition: blob.c:1816
double x
Definition: geometry.h:125
MagickExport Image * PingImages(ImageInfo *image_info, const char *filename, ExceptionInfo *exception)
Definition: constitute.c:347
#define MagickCoreSignature
MagickExport MagickBooleanType ImportImagePixels(Image *image, const ssize_t x, const ssize_t y, const size_t width, const size_t height, const char *map, const StorageType type, const void *pixels, ExceptionInfo *exception)
Definition: pixel.c:4138
MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:293
MagickExport MagickBooleanType GetMagickDecoderSeekableStream(const MagickInfo *magick_info)
Definition: magick.c:415
MagickExport Image * GetFirstImageInList(const Image *images)
Definition: list.c:576
SemaphoreInfo * semaphore
Definition: magick.h:96
MagickExport Image * BlobToImage(const ImageInfo *image_info, const void *blob, const size_t length, ExceptionInfo *exception)
Definition: blob.c:423
MagickExport void GetPathComponent(const char *path, PathType type, char *component)
Definition: utility.c:1225
MagickBooleanType
Definition: magick-type.h:161
MagickExport Image * NewImageList(void)
Definition: list.c:953
size_t scene
Definition: image.h:240
unsigned int MagickStatusType
Definition: magick-type.h:125
MagickExport MagickBooleanType WriteImage(const ImageInfo *image_info, Image *image, ExceptionInfo *exception)
Definition: constitute.c:1204
static ssize_t CastDoubleToLong(const double x)
Definition: image-private.h:55
const char * label
Definition: constitute.c:90
MagickExport unsigned char * Base64Decode(const char *source, size_t *length)
Definition: utility.c:347
char filename[MagickPathExtent]
Definition: image.h:480
MagickExport int LocaleNCompare(const char *p, const char *q, const size_t length)
Definition: locale.c:1524
double y
Definition: geometry.h:125
MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
Definition: resource.c:1100
MagickExport MagickBooleanType CloseBlob(Image *)
MagickExport MagickBooleanType SetImageProperty(Image *image, const char *property, const char *value, ExceptionInfo *exception)
Definition: property.c:4360
MagickExport const StringInfo * GetImageProfile(const Image *image, const char *name)
Definition: profile.c:259
size_t scene
Definition: image.h:396
#define magick_unused(x)
RectangleInfo page
Definition: image.h:212
size_t magick_columns
Definition: image.h:324
size_t MagickSizeType
Definition: magick-type.h:134
#define MagickPathExtent
static void InitializeConstituteInfo(const ImageInfo *image_info, ConstituteInfo *constitute_info)
Definition: constitute.c:455
MagickExport MagickBooleanType IsStringTrue(const char *value)
Definition: string.c:1388
MagickExport MagickBooleanType IsEventLogging(void)
Definition: log.c:763
MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
Definition: blob.c:2966
#define ThrowFileException(exception, severity, tag, context)
PixelTrait alpha_trait
Definition: image.h:280
static size_t PingStream(const Image *magick_unused(image), const void *magick_unused(pixels), const size_t columns)
Definition: constitute.c:280
MagickExport Image * ReadImage(const ImageInfo *image_info, ExceptionInfo *exception)
Definition: constitute.c:601
MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info, const unsigned int frames, ExceptionInfo *exception)
Definition: image.c:2788
#define ThrowReaderException(severity, tag)
char magick_filename[MagickPathExtent]
Definition: image.h:319
MagickExport DecodeImageHandler * GetImageDecoder(const MagickInfo *magick_info)
Definition: magick.c:224
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
Definition: exception.c:1145
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1699
MagickExport MagickBooleanType IsPathAccessible(const char *path)
Definition: utility.c:1497
size_t signature
Definition: image.h:354
size_t columns
Definition: image.h:172
MagickExport const MagickInfo * GetMagickInfo(const char *name, ExceptionInfo *exception)
Definition: magick.c:612
MagickExport Image * AcquireImage(const ImageInfo *image_info, ExceptionInfo *exception)
Definition: image.c:134
MagickExport MagickBooleanType OpenBlob(const ImageInfo *, Image *, const BlobMode, ExceptionInfo *)
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
Definition: monitor.h:26
size_t height
Definition: geometry.h:132
MagickExport void ResetTimer(TimerInfo *time_info)
Definition: timer.c:442
MagickExport EncodeImageHandler * GetImageEncoder(const MagickInfo *magick_info)
Definition: magick.c:254
MagickExport Image * ReadStream(const ImageInfo *image_info, StreamHandler stream, ExceptionInfo *exception)
Definition: stream.c:1043
MagickExport MagickProgressMonitor SetImageProgressMonitor(Image *image, const MagickProgressMonitor progress_monitor, void *client_data)
Definition: monitor.c:194
MagickExport Image * DestroyImageList(Image *images)
Definition: list.c:477
MagickExport MagickBooleanType GetMagickEndianSupport(const MagickInfo *magick_info)
Definition: magick.c:577
static void SyncResolutionFromProperties(Image *image, ConstituteInfo *constitute_info, ExceptionInfo *exception)
Definition: constitute.c:518
MagickExport size_t InterpretImageFilename(const ImageInfo *image_info, Image *image, const char *format, int value, char *filename, ExceptionInfo *exception)
Definition: image.c:1651
MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
Definition: blob.c:2887
MagickExport MagickBooleanType SetImageExtent(Image *image, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: image.c:2662
MagickExport Image * ReadImages(ImageInfo *image_info, const char *filename, ExceptionInfo *exception)
Definition: constitute.c:1012
TimerInfo timer
Definition: image.h:300
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1406
MagickExport MagickBooleanType GetMagickDecoderThreadSupport(const MagickInfo *magick_info)
Definition: magick.c:449
DisposeType
Definition: layer.h:27
char filename[MagickPathExtent]
Definition: image.h:319
#define GetMagickModule()
Definition: log.h:28
MagickStatusType delay_flags
Definition: constitute.c:100
MagickBooleanType affirm
Definition: image.h:384
MagickExport Image * ConstituteImage(const size_t columns, const size_t rows, const char *map, const StorageType storage, const void *pixels, ExceptionInfo *exception)
Definition: constitute.c:158
MagickExport MagickBooleanType GetMagickEncoderSeekableStream(const MagickInfo *magick_info)
Definition: magick.c:511
MagickExport char * InterpretImageProperties(ImageInfo *image_info, Image *image, const char *embed_text, ExceptionInfo *exception)
Definition: property.c:3630
MagickExport MagickBooleanType ResetImagePixels(Image *image, ExceptionInfo *exception)
Definition: image.c:2245
MagickExport ImageInfo * DestroyImageInfo(ImageInfo *image_info)
Definition: image.c:1252
MagickExport MagickBooleanType IsTaintImage(const Image *image)
Definition: image.c:1944
MagickExport void ReplaceImageInList(Image **images, Image *replace)
Definition: list.c:1181
MagickExport Image * GetNextImageInList(const Image *images)
Definition: list.c:786
MagickExport char * DestroyString(char *string)
Definition: string.c:788
MagickExport MagickBooleanType DeleteImageProperty(Image *image, const char *property)
Definition: property.c:280
MagickExport const char * GetImageProperty(const Image *image, const char *property, ExceptionInfo *exception)
Definition: property.c:2245
static void SyncOrientationFromProperties(Image *image, ConstituteInfo *constitute_info, ExceptionInfo *exception)
Definition: constitute.c:490
MagickExport ImageInfo * CloneImageInfo(const ImageInfo *image_info)
Definition: image.c:940
MagickExport MagickStatusType ParseGeometry(const char *geometry, GeometryInfo *geometry_info)
Definition: geometry.c:867
MagickExport void AppendImageToList(Image **images, const Image *append)
Definition: list.c:80
MagickBooleanType sync_from_tiff
Definition: constitute.c:96
MagickExport void SetGeometry(const Image *image, RectangleInfo *geometry)
Definition: geometry.c:1734
MagickPrivate MagickBooleanType SyncImageProfiles(Image *)
Definition: profile.c:2448
struct _ConstituteInfo ConstituteInfo
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1162
PointInfo resolution
Definition: image.h:209
#define magick_unreferenced(x)
MagickExport MagickProgressMonitor SetImageInfoProgressMonitor(ImageInfo *image_info, const MagickProgressMonitor progress_monitor, void *client_data)
Definition: monitor.c:243
MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info, Image *image, const char *decode, const char *encode, ExceptionInfo *exception)
Definition: delegate.c:1688
ResolutionType
Definition: image.h:89
#define MagickExport
OrientationType orientation
Definition: image.h:166
const char * caption
Definition: constitute.c:90
MagickBooleanType adjoin
Definition: image.h:384
char * page
Definition: image.h:390
MagickExport ssize_t FormatMagickTime(const time_t time, const size_t length, char *timestamp)
Definition: timer.c:255
MagickBooleanType ping
Definition: image.h:445
MagickExport MagickBooleanType IsSceneGeometry(const char *geometry, const MagickBooleanType pedantic)
Definition: geometry.c:660
const char * comment
Definition: constitute.c:90
MagickExport size_t GetImageListLength(const Image *images)
Definition: list.c:711
#define ThrowWriterException(severity, tag)
MagickBooleanType sync_from_exif
Definition: constitute.c:96
void * client_data
Definition: image.h:306
MagickExport Image * DestroyImage(Image *image)
Definition: image.c:1181
ColorspaceType colorspace
Definition: image.h:157
ssize_t ticks_per_second
Definition: constitute.c:106
MagickExport MagickStatusType ParseRegionGeometry(const Image *image, const char *geometry, RectangleInfo *region_info, ExceptionInfo *exception)
Definition: geometry.c:1695
MagickExport void DisassociateImageStream(Image *image)
Definition: image.c:1314
size_t(* StreamHandler)(const Image *, const void *, const size_t)
Definition: stream.h:31
MagickExport MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
Definition: monitor.c:136
MagickBooleanType temporary
Definition: image.h:384
MagickExport ExceptionInfo * DestroyExceptionInfo(ExceptionInfo *exception)
Definition: exception.c:418
MagickExport MagickBooleanType WriteImages(const ImageInfo *image_info, Image *images, const char *filename, ExceptionInfo *exception)
Definition: constitute.c:1474
MagickExport void InheritException(ExceptionInfo *exception, const ExceptionInfo *relative)
Definition: exception.c:687
size_t depth
Definition: image.h:172
ExceptionType severity
Definition: exception.h:104
Image * DecodeImageHandler(const ImageInfo *, ExceptionInfo *)
Definition: magick.h:59