MagickCore  7.1.2-29
Convert, Edit, Or Compose Bitmap Images
blob.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % BBBB L OOO BBBB %
7 % B B L O O B B %
8 % BBBB L O O BBBB %
9 % B B L O O B B %
10 % BBBB LLLLL OOO BBBB %
11 % %
12 % %
13 % MagickCore Binary Large OBjectS Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1999 %
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/license/ %
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 /*
41  Include declarations.
42 */
43 #ifdef __VMS
44 #include <types.h>
45 #include <mman.h>
46 #endif
47 #include "MagickCore/studio.h"
48 #include "MagickCore/blob.h"
49 #include "MagickCore/blob-private.h"
50 #include "MagickCore/cache.h"
51 #include "MagickCore/client.h"
52 #include "MagickCore/constitute.h"
53 #include "MagickCore/delegate.h"
54 #include "MagickCore/exception.h"
55 #include "MagickCore/exception-private.h"
56 #include "MagickCore/geometry.h"
57 #include "MagickCore/image-private.h"
58 #include "MagickCore/list.h"
59 #include "MagickCore/locale_.h"
60 #include "MagickCore/log.h"
61 #include "MagickCore/magick.h"
62 #include "MagickCore/memory_.h"
63 #include "MagickCore/memory-private.h"
64 #include "MagickCore/nt-base-private.h"
65 #include "MagickCore/option.h"
66 #include "MagickCore/policy.h"
67 #include "MagickCore/policy-private.h"
68 #include "MagickCore/resource_.h"
69 #include "MagickCore/semaphore.h"
70 #include "MagickCore/string_.h"
71 #include "MagickCore/string-private.h"
72 #include "MagickCore/timer-private.h"
73 #include "MagickCore/token.h"
74 #include "MagickCore/utility.h"
75 #include "MagickCore/utility-private.h"
76 #if defined(MAGICKCORE_ZLIB_DELEGATE)
77 #include "zlib.h"
78 #endif
79 #if defined(MAGICKCORE_BZLIB_DELEGATE)
80 #include "bzlib.h"
81 #endif
82 ␌
83 /*
84  Define declarations.
85 */
86 #define MagickMaxBlobExtent (8*8192)
87 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
88 # define MAP_ANONYMOUS MAP_ANON
89 #endif
90 #if !defined(MAP_FAILED)
91 #define MAP_FAILED ((void *) -1)
92 #endif
93 #if defined(__OS2__)
94 #include <io.h>
95 #define _O_BINARY O_BINARY
96 #endif
97 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
98 # if !defined(fsync)
99 # define fsync _commit
100 # endif
101 # if !defined(mmap)
102 # define MAGICKCORE_HAVE_MMAP 1
103 # define mmap(address,length,protection,access,file,offset) \
104  NTMapMemory(address,length,protection,access,file,offset)
105 # endif
106 # if !defined(munmap)
107 # define munmap(address,length) NTUnmapMemory(address,length)
108 # endif
109 # if !defined(pclose)
110 # define pclose _pclose
111 # endif
112 # if !defined(popen)
113 # define popen _popen
114 # endif
115 #endif
116 ␌
117 /*
118  Typedef declarations.
119 */
120 typedef union FileInfo
121 {
122  FILE
123  *file;
124 
125 #if defined(MAGICKCORE_ZLIB_DELEGATE)
126  gzFile
127  gzfile;
128 #endif
129 
130 #if defined(MAGICKCORE_BZLIB_DELEGATE)
131  BZFILE
132  *bzfile;
133 #endif
134 } FileInfo;
135 
136 struct _BlobInfo
137 {
138  size_t
139  length,
140  extent,
141  quantum;
142 
143  BlobMode
144  mode;
145 
146  MagickBooleanType
147  mapped,
148  eof;
149 
150  int
151  error,
152  error_number;
153 
154  MagickOffsetType
155  offset;
156 
157  MagickSizeType
158  size;
159 
160  MagickBooleanType
161  exempt,
162  synchronize,
163  temporary;
164 
165  int
166  status;
167 
168  StreamType
169  type;
170 
171  FileInfo
172  file_info;
173 
174  struct stat
175  properties;
176 
177  StreamHandler
178  stream;
179 
181  *custom_stream;
182 
183  unsigned char
184  *data;
185 
186  MagickBooleanType
187  debug;
188 
190  *semaphore;
191 
192  ssize_t
193  reference_count;
194 
195  size_t
196  signature;
197 };
198 
200 {
201  CustomStreamHandler
202  reader,
203  writer;
204 
205  CustomStreamSeeker
206  seeker;
207 
208  CustomStreamTeller
209  teller;
210 
211  void
212  *data;
213 
214  size_t
215  signature;
216 };
217 ␌
218 /*
219  Forward declarations.
220 */
221 static int
222  SyncBlob(const Image *);
223 ␌
224 /*
225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226 % %
227 % %
228 % %
229 + A c q u i r e C u s t o m S t r e a m I n f o %
230 % %
231 % %
232 % %
233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234 %
235 % AcquireCustomStreamInfo() allocates the CustomStreamInfo structure.
236 %
237 % The format of the AcquireCustomStreamInfo method is:
238 %
239 % CustomStreamInfo *AcquireCustomStreamInfo(ExceptionInfo *exception)
240 %
241 % A description of each parameter follows:
242 %
243 % o exception: return any errors or warnings in this structure.
244 %
245 */
246 MagickExport CustomStreamInfo *AcquireCustomStreamInfo(
247  ExceptionInfo *magick_unused(exception))
248 {
250  *custom_stream;
251 
252  magick_unreferenced(exception);
253  custom_stream=(CustomStreamInfo *) AcquireCriticalMemory(
254  sizeof(*custom_stream));
255  (void) memset(custom_stream,0,sizeof(*custom_stream));
256  custom_stream->signature=MagickCoreSignature;
257  return(custom_stream);
258 }
259 ␌
260 /*
261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262 % %
263 % %
264 % %
265 + A t t a c h B l o b %
266 % %
267 % %
268 % %
269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270 %
271 % AttachBlob() attaches a blob to the BlobInfo structure.
272 %
273 % The format of the AttachBlob method is:
274 %
275 % void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
276 %
277 % A description of each parameter follows:
278 %
279 % o blob_info: Specifies a pointer to a BlobInfo structure.
280 %
281 % o blob: the address of a character stream in one of the image formats
282 % understood by ImageMagick.
283 %
284 % o length: This size_t integer reflects the length in bytes of the blob.
285 %
286 */
287 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
288  const size_t length)
289 {
290  assert(blob_info != (BlobInfo *) NULL);
291  if (IsEventLogging() != MagickFalse)
292  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
293  blob_info->length=length;
294  blob_info->extent=length;
295  blob_info->quantum=(size_t) MagickMaxBlobExtent;
296  blob_info->offset=0;
297  blob_info->type=BlobStream;
298  blob_info->file_info.file=(FILE *) NULL;
299  blob_info->data=(unsigned char *) blob;
300  blob_info->mapped=MagickFalse;
301 }
302 ␌
303 /*
304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305 % %
306 % %
307 % %
308 + A t t a c h C u s t o m S t r e a m %
309 % %
310 % %
311 % %
312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313 %
314 % AttachCustomStream() attaches a CustomStreamInfo to the BlobInfo structure.
315 %
316 % The format of the AttachCustomStream method is:
317 %
318 % void AttachCustomStream(BlobInfo *blob_info,
319 % CustomStreamInfo *custom_stream)
320 %
321 % A description of each parameter follows:
322 %
323 % o blob_info: specifies a pointer to a BlobInfo structure.
324 %
325 % o custom_stream: the custom stream info.
326 %
327 */
328 MagickExport void AttachCustomStream(BlobInfo *blob_info,
329  CustomStreamInfo *custom_stream)
330 {
331  assert(blob_info != (BlobInfo *) NULL);
332  assert(custom_stream != (CustomStreamInfo *) NULL);
333  assert(custom_stream->signature == MagickCoreSignature);
334  if (IsEventLogging() != MagickFalse)
335  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
336  blob_info->type=CustomStream;
337  blob_info->custom_stream=custom_stream;
338 }
339 ␌
340 /*
341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342 % %
343 % %
344 % %
345 + B l o b T o F i l e %
346 % %
347 % %
348 % %
349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350 %
351 % BlobToFile() writes a blob to a file. It returns MagickFalse if an error
352 % occurs otherwise MagickTrue.
353 %
354 % The format of the BlobToFile method is:
355 %
356 % MagickBooleanType BlobToFile(char *filename,const void *blob,
357 % const size_t length,ExceptionInfo *exception)
358 %
359 % A description of each parameter follows:
360 %
361 % o filename: Write the blob to this file. The filename buffer length must
362 % be a minimum of MagickPathExtent characters.
363 %
364 % o blob: the address of a blob.
365 %
366 % o length: This length in bytes of the blob.
367 %
368 % o exception: return any errors or warnings in this structure.
369 %
370 */
371 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
372  const size_t length,ExceptionInfo *exception)
373 {
374  int
375  file;
376 
377  size_t
378  i;
379 
380  ssize_t
381  count;
382 
383  assert(filename != (const char *) NULL);
384  assert(blob != (const void *) NULL);
385  if (IsEventLogging() != MagickFalse)
386  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
387  if (*filename == '\0')
388  file=AcquireUniqueFileResource(filename);
389  else
390  file=open_utf8(filename,O_WRONLY | O_CREAT | O_EXCL | O_BINARY,P_MODE);
391  if (file == -1)
392  {
393  ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
394  return(MagickFalse);
395  }
396  for (i=0; i < length; i+=(size_t) count)
397  {
398  count=MagickWrite(file,(const char *) blob+i,MagickMin(length-i,(size_t)
399  MagickMaxBufferExtent));
400  if (count <= 0)
401  break;
402  }
403  file=close_utf8(file);
404  if ((file == -1) || (i < length))
405  {
406  ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
407  return(MagickFalse);
408  }
409  return(MagickTrue);
410 }
411 ␌
412 /*
413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414 % %
415 % %
416 % %
417 % B l o b T o I m a g e %
418 % %
419 % %
420 % %
421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
422 %
423 % BlobToImage() implements direct to memory image formats. It returns the
424 % blob as an image.
425 %
426 % The format of the BlobToImage method is:
427 %
428 % Image *BlobToImage(const ImageInfo *image_info,const void *blob,
429 % const size_t length,ExceptionInfo *exception)
430 %
431 % A description of each parameter follows:
432 %
433 % o image_info: the image info.
434 %
435 % o blob: the address of a character stream in one of the image formats
436 % understood by ImageMagick.
437 %
438 % o length: This size_t integer reflects the length in bytes of the blob.
439 %
440 % o exception: return any errors or warnings in this structure.
441 %
442 */
443 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
444  const size_t length,ExceptionInfo *exception)
445 {
446  const MagickInfo
447  *magick_info;
448 
449  Image
450  *image;
451 
452  ImageInfo
453  *blob_info,
454  *clone_info;
455 
456  MagickBooleanType
457  status;
458 
459  assert(image_info != (ImageInfo *) NULL);
460  assert(image_info->signature == MagickCoreSignature);
461  assert(exception != (ExceptionInfo *) NULL);
462  if (IsEventLogging() != MagickFalse)
463  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
464  image_info->filename);
465  if ((blob == (const void *) NULL) || (length == 0))
466  {
467  (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
468  "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
469  return((Image *) NULL);
470  }
471  blob_info=CloneImageInfo(image_info);
472  blob_info->blob=(void *) blob;
473  blob_info->length=length;
474  if (*blob_info->magick == '\0')
475  (void) SetImageInfo(blob_info,0,exception);
476  magick_info=GetMagickInfo(blob_info->magick,exception);
477  if (magick_info == (const MagickInfo *) NULL)
478  {
479  (void) ThrowMagickException(exception,GetMagickModule(),
480  MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
481  blob_info->magick);
482  blob_info=DestroyImageInfo(blob_info);
483  return((Image *) NULL);
484  }
485  if (GetMagickBlobSupport(magick_info) != MagickFalse)
486  {
487  char
488  filename[MagickPathExtent];
489 
490  /*
491  Native blob support for this image format.
492  */
493  (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
494  (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
495  blob_info->magick,filename);
496  image=ReadImage(blob_info,exception);
497  if (image != (Image *) NULL)
498  (void) DetachBlob(image->blob);
499  blob_info=DestroyImageInfo(blob_info);
500  return(image);
501  }
502  /*
503  Write blob to a temporary file on disk.
504  */
505  blob_info->blob=(void *) NULL;
506  blob_info->length=0;
507  *blob_info->filename='\0';
508  status=BlobToFile(blob_info->filename,blob,length,exception);
509  if (status == MagickFalse)
510  {
511  (void) RelinquishUniqueFileResource(blob_info->filename);
512  blob_info=DestroyImageInfo(blob_info);
513  return((Image *) NULL);
514  }
515  clone_info=CloneImageInfo(blob_info);
516  (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
517  blob_info->magick,blob_info->filename);
518  image=ReadImage(clone_info,exception);
519  if (image != (Image *) NULL)
520  {
521  Image
522  *images;
523 
524  /*
525  Restore original filenames and image format.
526  */
527  for (images=GetFirstImageInList(image); images != (Image *) NULL; )
528  {
529  (void) CopyMagickString(images->filename,image_info->filename,
530  MagickPathExtent);
531  (void) CopyMagickString(images->magick_filename,image_info->filename,
532  MagickPathExtent);
533  (void) CopyMagickString(images->magick,magick_info->name,
534  MagickPathExtent);
535  images=GetNextImageInList(images);
536  }
537  }
538  clone_info=DestroyImageInfo(clone_info);
539  (void) RelinquishUniqueFileResource(blob_info->filename);
540  blob_info=DestroyImageInfo(blob_info);
541  return(image);
542 }
543 ␌
544 /*
545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546 % %
547 % %
548 % %
549 + C l o n e B l o b I n f o %
550 % %
551 % %
552 % %
553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554 %
555 % CloneBlobInfo() makes a duplicate of the given blob info structure, or if
556 % blob info is NULL, a new one.
557 %
558 % The format of the CloneBlobInfo method is:
559 %
560 % BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
561 %
562 % A description of each parameter follows:
563 %
564 % o blob_info: the blob info.
565 %
566 */
567 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
568 {
569  BlobInfo
570  *clone_info;
571 
573  *semaphore;
574 
575  clone_info=(BlobInfo *) AcquireCriticalMemory(sizeof(*clone_info));
576  GetBlobInfo(clone_info);
577  if (blob_info == (BlobInfo *) NULL)
578  return(clone_info);
579  semaphore=clone_info->semaphore;
580  (void) memcpy(clone_info,blob_info,sizeof(*clone_info));
581  if (blob_info->mapped != MagickFalse)
582  (void) AcquireMagickResource(MapResource,blob_info->length);
583  clone_info->semaphore=semaphore;
584  LockSemaphoreInfo(clone_info->semaphore);
585  clone_info->reference_count=1;
586  UnlockSemaphoreInfo(clone_info->semaphore);
587  return(clone_info);
588 }
589 ␌
590 /*
591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592 % %
593 % %
594 % %
595 + C l o s e B l o b %
596 % %
597 % %
598 % %
599 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
600 %
601 % CloseBlob() closes a stream associated with the image.
602 %
603 % The format of the CloseBlob method is:
604 %
605 % MagickBooleanType CloseBlob(Image *image)
606 %
607 % A description of each parameter follows:
608 %
609 % o image: the image.
610 %
611 */
612 
613 static inline void ThrowBlobException(BlobInfo *blob_info)
614 {
615  if ((blob_info->status == 0) && (errno != 0))
616  blob_info->error_number=errno;
617  blob_info->status=(-1);
618 }
619 
620 MagickExport MagickBooleanType CloseBlob(Image *image)
621 {
622  BlobInfo
623  *magick_restrict blob_info;
624 
625  int
626  status;
627 
628  /*
629  Close image file.
630  */
631  assert(image != (Image *) NULL);
632  assert(image->signature == MagickCoreSignature);
633  if (IsEventLogging() != MagickFalse)
634  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
635  blob_info=image->blob;
636  if ((blob_info == (BlobInfo *) NULL) || (blob_info->type == UndefinedStream))
637  return(MagickTrue);
638  (void) SyncBlob(image);
639  status=blob_info->status;
640  switch (blob_info->type)
641  {
642  case UndefinedStream:
643  break;
644  case StandardStream:
645  case FileStream:
646  case PipeStream:
647  {
648  if (blob_info->synchronize != MagickFalse)
649  {
650  status=fflush(blob_info->file_info.file);
651  if (status != 0)
652  ThrowBlobException(blob_info);
653  status=fsync(fileno(blob_info->file_info.file));
654  if (status != 0)
655  ThrowBlobException(blob_info);
656  }
657  if ((status != 0) && (ferror(blob_info->file_info.file) != 0))
658  ThrowBlobException(blob_info);
659  break;
660  }
661  case ZipStream:
662  {
663 #if defined(MAGICKCORE_ZLIB_DELEGATE)
664  status=Z_OK;
665  (void) gzerror(blob_info->file_info.gzfile,&status);
666  if (status != Z_OK)
667  ThrowBlobException(blob_info);
668 #endif
669  break;
670  }
671  case BZipStream:
672  {
673 #if defined(MAGICKCORE_BZLIB_DELEGATE)
674  status=BZ_OK;
675  (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
676  if (status != BZ_OK)
677  ThrowBlobException(blob_info);
678 #endif
679  break;
680  }
681  case FifoStream:
682  break;
683  case BlobStream:
684  {
685  if (blob_info->file_info.file != (FILE *) NULL)
686  {
687  if (blob_info->synchronize != MagickFalse)
688  {
689  status=fflush(blob_info->file_info.file);
690  if (status != 0)
691  ThrowBlobException(blob_info);
692  status=fsync(fileno(blob_info->file_info.file));
693  if (status != 0)
694  ThrowBlobException(blob_info);
695  }
696  if ((status != 0) && (ferror(blob_info->file_info.file) != 0))
697  ThrowBlobException(blob_info);
698  }
699  break;
700  }
701  case CustomStream:
702  break;
703  }
704  blob_info->size=GetBlobSize(image);
705  image->extent=blob_info->size;
706  blob_info->eof=MagickFalse;
707  blob_info->error=0;
708  blob_info->mode=UndefinedBlobMode;
709  if (blob_info->exempt != MagickFalse)
710  {
711  blob_info->type=UndefinedStream;
712  return(blob_info->status != 0 ? MagickFalse : MagickTrue);
713  }
714  switch (blob_info->type)
715  {
716  case UndefinedStream:
717  case StandardStream:
718  break;
719  case FileStream:
720  {
721  if (blob_info->file_info.file != (FILE *) NULL)
722  {
723  status=fclose(blob_info->file_info.file);
724  if (status != 0)
725  ThrowBlobException(blob_info);
726  }
727  break;
728  }
729  case PipeStream:
730  {
731 #if defined(MAGICKCORE_HAVE_PCLOSE)
732  status=pclose(blob_info->file_info.file);
733  if (status != 0)
734  ThrowBlobException(blob_info);
735 #endif
736  break;
737  }
738  case ZipStream:
739  {
740 #if defined(MAGICKCORE_ZLIB_DELEGATE)
741  status=gzclose(blob_info->file_info.gzfile);
742  if (status != Z_OK)
743  ThrowBlobException(blob_info);
744 #endif
745  break;
746  }
747  case BZipStream:
748  {
749 #if defined(MAGICKCORE_BZLIB_DELEGATE)
750  BZ2_bzclose(blob_info->file_info.bzfile);
751 #endif
752  break;
753  }
754  case FifoStream:
755  break;
756  case BlobStream:
757  {
758  if (blob_info->file_info.file != (FILE *) NULL)
759  {
760  status=fclose(blob_info->file_info.file);
761  if (status != 0)
762  ThrowBlobException(blob_info);
763  }
764  break;
765  }
766  case CustomStream:
767  break;
768  }
769  (void) DetachBlob(blob_info);
770  return(blob_info->status != 0 ? MagickFalse : MagickTrue);
771 }
772 ␌
773 /*
774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
775 % %
776 % %
777 % %
778 % C u s t o m S t r e a m T o I m a g e %
779 % %
780 % %
781 % %
782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
783 %
784 % CustomStreamToImage() is the equivalent of ReadImage(), but reads the
785 % formatted "file" from the supplied method rather than to an actual file.
786 %
787 % The format of the CustomStreamToImage method is:
788 %
789 % Image *CustomStreamToImage(const ImageInfo *image_info,
790 % ExceptionInfo *exception)
791 %
792 % A description of each parameter follows:
793 %
794 % o image_info: the image info.
795 %
796 % o exception: return any errors or warnings in this structure.
797 %
798 */
799 MagickExport Image *CustomStreamToImage(const ImageInfo *image_info,
800  ExceptionInfo *exception)
801 {
802  const MagickInfo
803  *magick_info;
804 
805  Image
806  *image;
807 
808  ImageInfo
809  *blob_info;
810 
811  assert(image_info != (ImageInfo *) NULL);
812  assert(image_info->signature == MagickCoreSignature);
813  assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
814  assert(image_info->custom_stream->signature == MagickCoreSignature);
815  assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
816  assert(exception != (ExceptionInfo *) NULL);
817  if (IsEventLogging() != MagickFalse)
818  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
819  image_info->filename);
820  blob_info=CloneImageInfo(image_info);
821  if (*blob_info->magick == '\0')
822  (void) SetImageInfo(blob_info,0,exception);
823  magick_info=GetMagickInfo(blob_info->magick,exception);
824  if (magick_info == (const MagickInfo *) NULL)
825  {
826  (void) ThrowMagickException(exception,GetMagickModule(),
827  MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
828  blob_info->magick);
829  blob_info=DestroyImageInfo(blob_info);
830  return((Image *) NULL);
831  }
832  image=(Image *) NULL;
833  if ((GetMagickBlobSupport(magick_info) != MagickFalse) ||
834  (*blob_info->filename != '\0'))
835  {
836  char
837  filename[MagickPathExtent];
838 
839  /*
840  Native blob support for this image format or SetImageInfo changed the
841  blob to a file.
842  */
843  (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
844  (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
845  blob_info->magick,filename);
846  image=ReadImage(blob_info,exception);
847  }
848  else
849  {
850  char
851  unique[MagickPathExtent];
852 
853  int
854  file;
855 
856  ImageInfo
857  *clone_info;
858 
859  unsigned char
860  *blob;
861 
862  /*
863  Write data to file on disk.
864  */
865  blob_info->custom_stream=(CustomStreamInfo *) NULL;
866  blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
867  sizeof(*blob));
868  if (blob == (unsigned char *) NULL)
869  {
870  ThrowFileException(exception,BlobError,"UnableToReadBlob",
871  image_info->filename);
872  blob_info=DestroyImageInfo(blob_info);
873  return((Image *) NULL);
874  }
875  file=AcquireUniqueFileResource(unique);
876  if (file == -1)
877  {
878  ThrowFileException(exception,BlobError,"UnableToReadBlob",
879  image_info->filename);
880  blob=(unsigned char *) RelinquishMagickMemory(blob);
881  blob_info=DestroyImageInfo(blob_info);
882  return((Image *) NULL);
883  }
884  clone_info=CloneImageInfo(blob_info);
885  blob_info->file=fdopen(file,"wb+");
886  if (blob_info->file != (FILE *) NULL)
887  {
888  ssize_t
889  count;
890 
891  count=(ssize_t) MagickMaxBufferExtent;
892  while (count == (ssize_t) MagickMaxBufferExtent)
893  {
894  count=image_info->custom_stream->reader(blob,MagickMaxBufferExtent,
895  image_info->custom_stream->data);
896  count=(ssize_t) write(file,(const char *) blob,(size_t) count);
897  }
898  (void) fclose(blob_info->file);
899  (void) FormatLocaleString(clone_info->filename,MagickPathExtent,
900  "%s:%s",blob_info->magick,unique);
901  image=ReadImage(clone_info,exception);
902  if (image != (Image *) NULL)
903  {
904  Image
905  *images;
906 
907  /*
908  Restore original filenames and image format.
909  */
910  for (images=GetFirstImageInList(image); images != (Image *) NULL; )
911  {
912  (void) CopyMagickString(images->filename,image_info->filename,
913  MagickPathExtent);
914  (void) CopyMagickString(images->magick_filename,
915  image_info->filename,MagickPathExtent);
916  (void) CopyMagickString(images->magick,magick_info->name,
917  MagickPathExtent);
918  images=GetNextImageInList(images);
919  }
920  }
921  }
922  clone_info=DestroyImageInfo(clone_info);
923  blob=(unsigned char *) RelinquishMagickMemory(blob);
924  (void) RelinquishUniqueFileResource(unique);
925  }
926  blob_info=DestroyImageInfo(blob_info);
927  if (image != (Image *) NULL)
928  if (CloseBlob(image) == MagickFalse)
929  image=DestroyImageList(image);
930  return(image);
931 }
932 ␌
933 /*
934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
935 % %
936 % %
937 % %
938 + D e s t r o y B l o b %
939 % %
940 % %
941 % %
942 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
943 %
944 % DestroyBlob() deallocates memory associated with a blob.
945 %
946 % The format of the DestroyBlob method is:
947 %
948 % void DestroyBlob(Image *image)
949 %
950 % A description of each parameter follows:
951 %
952 % o image: the image.
953 %
954 */
955 MagickExport void DestroyBlob(Image *image)
956 {
957  BlobInfo
958  *magick_restrict blob_info;
959 
960  MagickBooleanType
961  destroy;
962 
963  assert(image != (Image *) NULL);
964  assert(image->signature == MagickCoreSignature);
965  assert(image->blob != (BlobInfo *) NULL);
966  assert(image->blob->signature == MagickCoreSignature);
967  if (IsEventLogging() != MagickFalse)
968  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
969  blob_info=image->blob;
970  destroy=MagickFalse;
971  LockSemaphoreInfo(blob_info->semaphore);
972  blob_info->reference_count--;
973  assert(blob_info->reference_count >= 0);
974  if (blob_info->reference_count == 0)
975  destroy=MagickTrue;
976  UnlockSemaphoreInfo(blob_info->semaphore);
977  if (destroy == MagickFalse)
978  {
979  image->blob=(BlobInfo *) NULL;
980  return;
981  }
982  (void) CloseBlob(image);
983  if (blob_info->mapped != MagickFalse)
984  {
985  (void) UnmapBlob(blob_info->data,blob_info->length);
986  RelinquishMagickResource(MapResource,blob_info->length);
987  }
988  if (blob_info->semaphore != (SemaphoreInfo *) NULL)
989  RelinquishSemaphoreInfo(&blob_info->semaphore);
990  blob_info->signature=(~MagickCoreSignature);
991  image->blob=(BlobInfo *) RelinquishMagickMemory(blob_info);
992 }
993 ␌
994 /*
995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
996 % %
997 % %
998 % %
999 + D e s t r o y C u s t o m S t r e a m I n f o %
1000 % %
1001 % %
1002 % %
1003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 %
1005 % DestroyCustomStreamInfo() destroys memory associated with the
1006 % CustomStreamInfo structure.
1007 %
1008 % The format of the DestroyCustomStreamInfo method is:
1009 %
1010 % CustomStreamInfo *DestroyCustomStreamInfo(CustomStreamInfo *stream_info)
1011 %
1012 % A description of each parameter follows:
1013 %
1014 % o custom_stream: the custom stream info.
1015 %
1016 */
1017 MagickExport CustomStreamInfo *DestroyCustomStreamInfo(
1018  CustomStreamInfo *custom_stream)
1019 {
1020  assert(custom_stream != (CustomStreamInfo *) NULL);
1021  assert(custom_stream->signature == MagickCoreSignature);
1022  if (IsEventLogging() != MagickFalse)
1023  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1024  custom_stream->signature=(~MagickCoreSignature);
1025  custom_stream=(CustomStreamInfo *) RelinquishMagickMemory(custom_stream);
1026  return(custom_stream);
1027 }
1028 ␌
1029 /*
1030 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1031 % %
1032 % %
1033 % %
1034 + D e t a c h B l o b %
1035 % %
1036 % %
1037 % %
1038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1039 %
1040 % DetachBlob() detaches a blob from the BlobInfo structure.
1041 %
1042 % The format of the DetachBlob method is:
1043 %
1044 % void *DetachBlob(BlobInfo *blob_info)
1045 %
1046 % A description of each parameter follows:
1047 %
1048 % o blob_info: Specifies a pointer to a BlobInfo structure.
1049 %
1050 */
1051 MagickExport void *DetachBlob(BlobInfo *blob_info)
1052 {
1053  void
1054  *data;
1055 
1056  assert(blob_info != (BlobInfo *) NULL);
1057  if (IsEventLogging() != MagickFalse)
1058  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1059  if (blob_info->mapped != MagickFalse)
1060  {
1061  (void) UnmapBlob(blob_info->data,blob_info->length);
1062  blob_info->data=NULL;
1063  RelinquishMagickResource(MapResource,blob_info->length);
1064  }
1065  blob_info->mapped=MagickFalse;
1066  blob_info->length=0;
1067  /*
1068  We should not reset blob_info->extent because we use it to check if the
1069  blob was opened inside ImagesToBlob and ImagesToBlob.
1070  */
1071  blob_info->offset=0;
1072  blob_info->mode=UndefinedBlobMode;
1073  blob_info->eof=MagickFalse;
1074  blob_info->error=0;
1075  blob_info->exempt=MagickFalse;
1076  blob_info->type=UndefinedStream;
1077  blob_info->file_info.file=(FILE *) NULL;
1078  data=blob_info->data;
1079  blob_info->data=(unsigned char *) NULL;
1080  blob_info->stream=(StreamHandler) NULL;
1081  blob_info->custom_stream=(CustomStreamInfo *) NULL;
1082  return(data);
1083 }
1084 ␌
1085 /*
1086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1087 % %
1088 % %
1089 % %
1090 + D i s a s s o c i a t e B l o b %
1091 % %
1092 % %
1093 % %
1094 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1095 %
1096 % DisassociateBlob() disassociates the image stream. It checks if the
1097 % blob of the specified image is referenced by other images. If the reference
1098 % count is higher then 1 a new blob is assigned to the specified image.
1099 %
1100 % The format of the DisassociateBlob method is:
1101 %
1102 % void DisassociateBlob(const Image *image)
1103 %
1104 % A description of each parameter follows:
1105 %
1106 % o image: the image.
1107 %
1108 */
1109 MagickExport void DisassociateBlob(Image *image)
1110 {
1111  BlobInfo
1112  *magick_restrict blob_info,
1113  *clone_info;
1114 
1115  MagickBooleanType
1116  clone;
1117 
1118  assert(image != (Image *) NULL);
1119  assert(image->signature == MagickCoreSignature);
1120  assert(image->blob != (BlobInfo *) NULL);
1121  assert(image->blob->signature == MagickCoreSignature);
1122  if (IsEventLogging() != MagickFalse)
1123  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1124  blob_info=image->blob;
1125  clone=MagickFalse;
1126  LockSemaphoreInfo(blob_info->semaphore);
1127  assert(blob_info->reference_count >= 0);
1128  if (blob_info->reference_count > 1)
1129  clone=MagickTrue;
1130  UnlockSemaphoreInfo(blob_info->semaphore);
1131  if (clone == MagickFalse)
1132  return;
1133  clone_info=CloneBlobInfo(blob_info);
1134  DestroyBlob(image);
1135  image->blob=clone_info;
1136 }
1137 ␌
1138 /*
1139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1140 % %
1141 % %
1142 % %
1143 + D i s c a r d B l o b B y t e s %
1144 % %
1145 % %
1146 % %
1147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1148 %
1149 % DiscardBlobBytes() discards bytes in a blob.
1150 %
1151 % The format of the DiscardBlobBytes method is:
1152 %
1153 % MagickBooleanType DiscardBlobBytes(Image *image,
1154 % const MagickSizeType length)
1155 %
1156 % A description of each parameter follows.
1157 %
1158 % o image: the image.
1159 %
1160 % o length: the number of bytes to skip.
1161 %
1162 */
1163 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
1164  const MagickSizeType length)
1165 {
1166  MagickSizeType
1167  i;
1168 
1169  size_t
1170  quantum;
1171 
1172  ssize_t
1173  count;
1174 
1175  unsigned char
1176  buffer[MagickMinBufferExtent >> 1];
1177 
1178  assert(image != (Image *) NULL);
1179  assert(image->signature == MagickCoreSignature);
1180  if (length != (MagickSizeType) ((MagickOffsetType) length))
1181  return(MagickFalse);
1182  count=0;
1183  for (i=0; i < length; i+=(MagickSizeType) count)
1184  {
1185  quantum=(size_t) MagickMin(length-i,sizeof(buffer));
1186  (void) ReadBlobStream(image,quantum,buffer,&count);
1187  if (count <= 0)
1188  {
1189  count=0;
1190  if (errno != EINTR)
1191  break;
1192  }
1193  }
1194  return(i < (MagickSizeType) length ? MagickFalse : MagickTrue);
1195 }
1196 ␌
1197 /*
1198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1199 % %
1200 % %
1201 % %
1202 + D u p l i c a t e s B l o b %
1203 % %
1204 % %
1205 % %
1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1207 %
1208 % DuplicateBlob() duplicates a blob descriptor.
1209 %
1210 % The format of the DuplicateBlob method is:
1211 %
1212 % void DuplicateBlob(Image *image,const Image *duplicate)
1213 %
1214 % A description of each parameter follows:
1215 %
1216 % o image: the image.
1217 %
1218 % o duplicate: the duplicate image.
1219 %
1220 */
1221 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
1222 {
1223  assert(image != (Image *) NULL);
1224  assert(image->signature == MagickCoreSignature);
1225  assert(duplicate != (Image *) NULL);
1226  assert(duplicate->signature == MagickCoreSignature);
1227  if (IsEventLogging() != MagickFalse)
1228  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1229  DestroyBlob(image);
1230  image->blob=ReferenceBlob(duplicate->blob);
1231 }
1232 ␌
1233 /*
1234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1235 % %
1236 % %
1237 % %
1238 + E O F B l o b %
1239 % %
1240 % %
1241 % %
1242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1243 %
1244 % EOFBlob() returns a non-zero value when EOF has been detected reading from
1245 % a blob or file.
1246 %
1247 % The format of the EOFBlob method is:
1248 %
1249 % int EOFBlob(const Image *image)
1250 %
1251 % A description of each parameter follows:
1252 %
1253 % o image: the image.
1254 %
1255 */
1256 MagickExport int EOFBlob(const Image *image)
1257 {
1258  BlobInfo
1259  *magick_restrict blob_info;
1260 
1261  assert(image != (Image *) NULL);
1262  assert(image->signature == MagickCoreSignature);
1263  assert(image->blob != (BlobInfo *) NULL);
1264  assert(image->blob->type != UndefinedStream);
1265  if (IsEventLogging() != MagickFalse)
1266  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1267  blob_info=image->blob;
1268  switch (blob_info->type)
1269  {
1270  case UndefinedStream:
1271  case StandardStream:
1272  break;
1273  case FileStream:
1274  case PipeStream:
1275  {
1276  blob_info->eof=feof(blob_info->file_info.file) != 0 ? MagickTrue :
1277  MagickFalse;
1278  break;
1279  }
1280  case ZipStream:
1281  {
1282 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1283  blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
1284  MagickFalse;
1285 #endif
1286  break;
1287  }
1288  case BZipStream:
1289  {
1290 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1291  int
1292  status;
1293 
1294  status=0;
1295  (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
1296  blob_info->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
1297 #endif
1298  break;
1299  }
1300  case FifoStream:
1301  {
1302  blob_info->eof=MagickFalse;
1303  break;
1304  }
1305  case BlobStream:
1306  break;
1307  case CustomStream:
1308  break;
1309  }
1310  return((int) blob_info->eof);
1311 }
1312 ␌
1313 /*
1314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1315 % %
1316 % %
1317 % %
1318 + E r r o r B l o b %
1319 % %
1320 % %
1321 % %
1322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1323 %
1324 % ErrorBlob() returns a non-zero value when an error has been detected reading
1325 % from a blob or file.
1326 %
1327 % The format of the ErrorBlob method is:
1328 %
1329 % int ErrorBlob(const Image *image)
1330 %
1331 % A description of each parameter follows:
1332 %
1333 % o image: the image.
1334 %
1335 */
1336 MagickExport int ErrorBlob(const Image *image)
1337 {
1338  BlobInfo
1339  *magick_restrict blob_info;
1340 
1341  assert(image != (Image *) NULL);
1342  assert(image->signature == MagickCoreSignature);
1343  assert(image->blob != (BlobInfo *) NULL);
1344  assert(image->blob->type != UndefinedStream);
1345  if (IsEventLogging() != MagickFalse)
1346  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1347  blob_info=image->blob;
1348  switch (blob_info->type)
1349  {
1350  case UndefinedStream:
1351  case StandardStream:
1352  break;
1353  case FileStream:
1354  case PipeStream:
1355  {
1356  blob_info->error=ferror(blob_info->file_info.file);
1357  break;
1358  }
1359  case ZipStream:
1360  {
1361 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1362  (void) gzerror(blob_info->file_info.gzfile,&blob_info->error);
1363 #endif
1364  break;
1365  }
1366  case BZipStream:
1367  {
1368 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1369  (void) BZ2_bzerror(blob_info->file_info.bzfile,&blob_info->error);
1370 #endif
1371  break;
1372  }
1373  case FifoStream:
1374  {
1375  blob_info->error=0;
1376  break;
1377  }
1378  case BlobStream:
1379  break;
1380  case CustomStream:
1381  break;
1382  }
1383  return(blob_info->error);
1384 }
1385 ␌
1386 /*
1387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1388 % %
1389 % %
1390 % %
1391 % F i l e T o B l o b %
1392 % %
1393 % %
1394 % %
1395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1396 %
1397 % FileToBlob() returns the contents of a file as a buffer terminated with
1398 % the '\0' character. The length of the buffer (not including the extra
1399 % terminating '\0' character) is returned via the 'length' parameter. Free
1400 % the buffer with RelinquishMagickMemory().
1401 %
1402 % The format of the FileToBlob method is:
1403 %
1404 % void *FileToBlob(const char *filename,const size_t extent,
1405 % size_t *length,ExceptionInfo *exception)
1406 %
1407 % A description of each parameter follows:
1408 %
1409 % o blob: FileToBlob() returns the contents of a file as a blob. If
1410 % an error occurs NULL is returned.
1411 %
1412 % o filename: the filename.
1413 %
1414 % o extent: The maximum length of the blob.
1415 %
1416 % o length: On return, this reflects the actual length of the blob.
1417 %
1418 % o exception: return any errors or warnings in this structure.
1419 %
1420 */
1421 MagickExport void *FileToBlob(const char *filename,const size_t extent,
1422  size_t *length,ExceptionInfo *exception)
1423 {
1424  int
1425  file;
1426 
1427  MagickBooleanType
1428  status;
1429 
1430  MagickOffsetType
1431  offset;
1432 
1433  size_t
1434  i;
1435 
1436  ssize_t
1437  count;
1438 
1439  struct stat
1440  attributes;
1441 
1442  unsigned char
1443  *blob;
1444 
1445  void
1446  *map;
1447 
1448  assert(filename != (const char *) NULL);
1449  assert(exception != (ExceptionInfo *) NULL);
1450  assert(exception->signature == MagickCoreSignature);
1451  if (IsEventLogging() != MagickFalse)
1452  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1453  *length=0;
1454  if (IsPathAuthorized(ReadPolicyRights,filename) == MagickFalse)
1455  ThrowPolicyException(filename,NULL);
1456  file=fileno(stdin);
1457  if (LocaleCompare(filename,"-") != 0)
1458  {
1459  int
1460  flags = O_RDONLY | O_BINARY;
1461 
1462  status=GetPathAttributes(filename,&attributes);
1463  if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
1464  {
1465  ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1466  return(NULL);
1467  }
1468  file=open_utf8(filename,flags,0);
1469  }
1470  if (file == -1)
1471  {
1472  ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1473  return(NULL);
1474  }
1475  if (IsPathAuthorized(ReadPolicyRights,filename) == MagickFalse)
1476  {
1477  file=close_utf8(file)-1;
1478  ThrowPolicyException(filename,NULL);
1479  }
1480  offset=(MagickOffsetType) lseek(file,0,SEEK_END);
1481  count=0;
1482  if ((file == fileno(stdin)) || (offset < 0) ||
1483  (offset != (MagickOffsetType) ((ssize_t) offset)))
1484  {
1485  size_t
1486  quantum;
1487 
1488  struct stat
1489  file_stats;
1490 
1491  /*
1492  Stream is not seekable.
1493  */
1494  offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1495  quantum=(size_t) MagickMaxBufferExtent;
1496  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1497  quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1498  blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1499  for (i=0; blob != (unsigned char *) NULL; i+=(size_t) count)
1500  {
1501  count=MagickRead(file,blob+i,quantum);
1502  if (count <= 0)
1503  break;
1504  if (~i < ((size_t) count+quantum+1))
1505  {
1506  blob=(unsigned char *) RelinquishMagickMemory(blob);
1507  break;
1508  }
1509  blob=(unsigned char *) ResizeQuantumMemory(blob,i+(size_t) count+
1510  quantum+1,sizeof(*blob));
1511  if ((i+(size_t) count) >= extent)
1512  break;
1513  }
1514  if (LocaleCompare(filename,"-") != 0)
1515  file=close_utf8(file);
1516  if (blob == (unsigned char *) NULL)
1517  {
1518  (void) ThrowMagickException(exception,GetMagickModule(),
1519  ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1520  return(NULL);
1521  }
1522  if (file == -1)
1523  {
1524  blob=(unsigned char *) RelinquishMagickMemory(blob);
1525  ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1526  return(NULL);
1527  }
1528  *length=(size_t) MagickMin(i+(size_t) count,extent);
1529  blob[*length]='\0';
1530  return(blob);
1531  }
1532  *length=(size_t) MagickMin(offset,(MagickOffsetType)
1533  MagickMin(extent,(size_t) MAGICK_SSIZE_MAX));
1534  blob=(unsigned char *) NULL;
1535  if (~(*length) >= (MagickPathExtent-1))
1536  blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
1537  sizeof(*blob));
1538  if (blob == (unsigned char *) NULL)
1539  {
1540  file=close_utf8(file);
1541  (void) ThrowMagickException(exception,GetMagickModule(),
1542  ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1543  return(NULL);
1544  }
1545  map=MapBlob(file,ReadMode,0,*length);
1546  if (map != (unsigned char *) NULL)
1547  {
1548  (void) memcpy(blob,map,*length);
1549  (void) UnmapBlob(map,*length);
1550  }
1551  else
1552  {
1553  (void) lseek(file,0,SEEK_SET);
1554  for (i=0; i < *length; i+=(size_t) count)
1555  {
1556  count=MagickRead(file,blob+i,(size_t) MagickMin(*length-i,(size_t)
1557  MagickMaxBufferExtent));
1558  if (count <= 0)
1559  break;
1560  }
1561  if (i < *length)
1562  {
1563  file=close_utf8(file)-1;
1564  blob=(unsigned char *) RelinquishMagickMemory(blob);
1565  ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1566  return(NULL);
1567  }
1568  }
1569  blob[*length]='\0';
1570  if (LocaleCompare(filename,"-") != 0)
1571  file=close_utf8(file);
1572  if (file == -1)
1573  {
1574  blob=(unsigned char *) RelinquishMagickMemory(blob);
1575  ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1576  }
1577  return(blob);
1578 }
1579 ␌
1580 /*
1581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1582 % %
1583 % %
1584 % %
1585 % F i l e T o I m a g e %
1586 % %
1587 % %
1588 % %
1589 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1590 %
1591 % FileToImage() write the contents of a file to an image.
1592 %
1593 % The format of the FileToImage method is:
1594 %
1595 % MagickBooleanType FileToImage(Image *,const char *filename)
1596 %
1597 % A description of each parameter follows:
1598 %
1599 % o image: the image.
1600 %
1601 % o filename: the filename.
1602 %
1603 */
1604 
1605 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1606  const void *magick_restrict data)
1607 {
1608  BlobInfo
1609  *magick_restrict blob_info;
1610 
1611  MagickSizeType
1612  extent;
1613 
1614  unsigned char
1615  *magick_restrict q;
1616 
1617  assert(image->blob != (BlobInfo *) NULL);
1618  assert(image->blob->type != UndefinedStream);
1619  assert(data != NULL);
1620  blob_info=image->blob;
1621  if (blob_info->type != BlobStream)
1622  return(WriteBlob(image,length,(const unsigned char *) data));
1623  if (blob_info->offset > (MagickOffsetType) (MAGICK_SSIZE_MAX-length))
1624  {
1625  errno=EOVERFLOW;
1626  return(0);
1627  }
1628  extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
1629  if (extent >= blob_info->extent)
1630  {
1631  extent+=blob_info->quantum+length;
1632  blob_info->quantum<<=1;
1633  if (SetBlobExtent(image,extent) == MagickFalse)
1634  return(0);
1635  }
1636  q=blob_info->data+blob_info->offset;
1637  (void) memcpy(q,data,length);
1638  blob_info->offset+=(MagickOffsetType) length;
1639  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
1640  blob_info->length=(size_t) blob_info->offset;
1641  return((ssize_t) length);
1642 }
1643 
1644 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1645  ExceptionInfo *exception)
1646 {
1647  int
1648  file;
1649 
1650  size_t
1651  length,
1652  quantum;
1653 
1654  ssize_t
1655  count;
1656 
1657  struct stat
1658  file_stats;
1659 
1660  unsigned char
1661  *blob;
1662 
1663  assert(image != (const Image *) NULL);
1664  assert(image->signature == MagickCoreSignature);
1665  assert(filename != (const char *) NULL);
1666  if (IsEventLogging() != MagickFalse)
1667  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1668  if (IsPathAuthorized(ReadPolicyRights,filename) == MagickFalse)
1669  ThrowPolicyException(filename,MagickFalse);
1670  file=fileno(stdin);
1671  if (LocaleCompare(filename,"-") != 0)
1672  {
1673  int
1674  flags = O_RDONLY | O_BINARY;
1675 
1676  file=open_utf8(filename,flags,0);
1677  }
1678  if (file == -1)
1679  {
1680  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1681  return(MagickFalse);
1682  }
1683  if (IsPathAuthorized(ReadPolicyRights,filename) == MagickFalse)
1684  ThrowPolicyException(filename,MagickFalse);
1685  quantum=(size_t) MagickMaxBufferExtent;
1686  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1687  quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1688  blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1689  if (blob == (unsigned char *) NULL)
1690  {
1691  file=close_utf8(file);
1692  ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1693  filename);
1694  return(MagickFalse);
1695  }
1696  for ( ; ; )
1697  {
1698  count=MagickRead(file,blob,quantum);
1699  if (count <= 0)
1700  break;
1701  length=(size_t) count;
1702  count=WriteBlobStream(image,length,blob);
1703  if (count != (ssize_t) length)
1704  {
1705  ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1706  break;
1707  }
1708  }
1709  file=close_utf8(file);
1710  if (file == -1)
1711  ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1712  blob=(unsigned char *) RelinquishMagickMemory(blob);
1713  return(MagickTrue);
1714 }
1715 ␌
1716 /*
1717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1718 % %
1719 % %
1720 % %
1721 + G e t B l o b E r r o r %
1722 % %
1723 % %
1724 % %
1725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1726 %
1727 % GetBlobError() returns MagickTrue if the blob associated with the specified
1728 % image encountered an error.
1729 %
1730 % The format of the GetBlobError method is:
1731 %
1732 % MagickBooleanType GetBlobError(const Image *image)
1733 %
1734 % A description of each parameter follows:
1735 %
1736 % o image: the image.
1737 %
1738 */
1739 MagickExport MagickBooleanType GetBlobError(const Image *image)
1740 {
1741  assert(image != (const Image *) NULL);
1742  assert(image->signature == MagickCoreSignature);
1743  if (IsEventLogging() != MagickFalse)
1744  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1745  if ((image->blob->status != 0) && (image->blob->error_number != 0))
1746  errno=image->blob->error_number;
1747  return(image->blob->status == 0 ? MagickFalse : MagickTrue);
1748 }
1749 ␌
1750 /*
1751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1752 % %
1753 % %
1754 % %
1755 + G e t B l o b F i l e H a n d l e %
1756 % %
1757 % %
1758 % %
1759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1760 %
1761 % GetBlobFileHandle() returns the file handle associated with the image blob.
1762 %
1763 % The format of the GetBlobFile method is:
1764 %
1765 % FILE *GetBlobFileHandle(const Image *image)
1766 %
1767 % A description of each parameter follows:
1768 %
1769 % o image: the image.
1770 %
1771 */
1772 MagickExport FILE *GetBlobFileHandle(const Image *image)
1773 {
1774  assert(image != (const Image *) NULL);
1775  assert(image->signature == MagickCoreSignature);
1776  return(image->blob->file_info.file);
1777 }
1778 ␌
1779 /*
1780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781 % %
1782 % %
1783 % %
1784 + G e t B l o b I n f o %
1785 % %
1786 % %
1787 % %
1788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1789 %
1790 % GetBlobInfo() initializes the BlobInfo structure.
1791 %
1792 % The format of the GetBlobInfo method is:
1793 %
1794 % void GetBlobInfo(BlobInfo *blob_info)
1795 %
1796 % A description of each parameter follows:
1797 %
1798 % o blob_info: Specifies a pointer to a BlobInfo structure.
1799 %
1800 */
1801 MagickExport void GetBlobInfo(BlobInfo *blob_info)
1802 {
1803  assert(blob_info != (BlobInfo *) NULL);
1804  (void) memset(blob_info,0,sizeof(*blob_info));
1805  blob_info->type=UndefinedStream;
1806  blob_info->quantum=(size_t) MagickMaxBlobExtent;
1807  blob_info->properties.st_mtime=GetMagickTime();
1808  blob_info->properties.st_ctime=blob_info->properties.st_mtime;
1809  blob_info->debug=GetLogEventMask() & BlobEvent ? MagickTrue : MagickFalse;
1810  blob_info->reference_count=1;
1811  blob_info->semaphore=AcquireSemaphoreInfo();
1812  blob_info->signature=MagickCoreSignature;
1813 }
1814 ␌
1815 /*
1816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1817 % %
1818 % %
1819 % %
1820 % G e t B l o b P r o p e r t i e s %
1821 % %
1822 % %
1823 % %
1824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1825 %
1826 % GetBlobProperties() returns information about an image blob.
1827 %
1828 % The format of the GetBlobProperties method is:
1829 %
1830 % const struct stat *GetBlobProperties(const Image *image)
1831 %
1832 % A description of each parameter follows:
1833 %
1834 % o image: the image.
1835 %
1836 */
1837 MagickExport const struct stat *GetBlobProperties(const Image *image)
1838 {
1839  assert(image != (Image *) NULL);
1840  assert(image->signature == MagickCoreSignature);
1841  if (IsEventLogging() != MagickFalse)
1842  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1843  return(&image->blob->properties);
1844 }
1845 ␌
1846 /*
1847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1848 % %
1849 % %
1850 % %
1851 + G e t B l o b S i z e %
1852 % %
1853 % %
1854 % %
1855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1856 %
1857 % GetBlobSize() returns the current length of the image file or blob; zero is
1858 % returned if the size cannot be determined.
1859 %
1860 % The format of the GetBlobSize method is:
1861 %
1862 % MagickSizeType GetBlobSize(const Image *image)
1863 %
1864 % A description of each parameter follows:
1865 %
1866 % o image: the image.
1867 %
1868 */
1869 MagickExport MagickSizeType GetBlobSize(const Image *image)
1870 {
1871  BlobInfo
1872  *magick_restrict blob_info;
1873 
1874  MagickSizeType
1875  extent;
1876 
1877  assert(image != (Image *) NULL);
1878  assert(image->signature == MagickCoreSignature);
1879  assert(image->blob != (BlobInfo *) NULL);
1880  if (IsEventLogging() != MagickFalse)
1881  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1882  blob_info=image->blob;
1883  extent=0;
1884  switch (blob_info->type)
1885  {
1886  case UndefinedStream:
1887  case StandardStream:
1888  {
1889  extent=blob_info->size;
1890  break;
1891  }
1892  case FileStream:
1893  {
1894  int
1895  file_descriptor;
1896 
1897  extent=(MagickSizeType) blob_info->properties.st_size;
1898  if (extent == 0)
1899  extent=blob_info->size;
1900  file_descriptor=fileno(blob_info->file_info.file);
1901  if (file_descriptor == -1)
1902  break;
1903  if (fstat(file_descriptor,&blob_info->properties) == 0)
1904  extent=(MagickSizeType) blob_info->properties.st_size;
1905  break;
1906  }
1907  case PipeStream:
1908  {
1909  extent=blob_info->size;
1910  break;
1911  }
1912  case ZipStream:
1913  case BZipStream:
1914  {
1915  MagickBooleanType
1916  status;
1917 
1918  status=GetPathAttributes(image->filename,&blob_info->properties);
1919  if (status != MagickFalse)
1920  extent=(MagickSizeType) blob_info->properties.st_size;
1921  break;
1922  }
1923  case FifoStream:
1924  break;
1925  case BlobStream:
1926  {
1927  extent=(MagickSizeType) blob_info->length;
1928  break;
1929  }
1930  case CustomStream:
1931  {
1932  if ((blob_info->custom_stream->teller != (CustomStreamTeller) NULL) &&
1933  (blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL))
1934  {
1935  MagickOffsetType
1936  offset;
1937 
1938  offset=blob_info->custom_stream->teller(
1939  blob_info->custom_stream->data);
1940  extent=(MagickSizeType) blob_info->custom_stream->seeker(0,SEEK_END,
1941  blob_info->custom_stream->data);
1942  (void) blob_info->custom_stream->seeker(offset,SEEK_SET,
1943  blob_info->custom_stream->data);
1944  }
1945  break;
1946  }
1947  }
1948  return(extent);
1949 }
1950 ␌
1951 /*
1952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1953 % %
1954 % %
1955 % %
1956 + G e t B l o b S t r e a m D a t a %
1957 % %
1958 % %
1959 % %
1960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1961 %
1962 % GetBlobStreamData() returns the stream data for the image.
1963 %
1964 % The format of the GetBlobStreamData method is:
1965 %
1966 % void *GetBlobStreamData(const Image *image)
1967 %
1968 % A description of each parameter follows:
1969 %
1970 % o image: the image.
1971 %
1972 */
1973 MagickExport void *GetBlobStreamData(const Image *image)
1974 {
1975  assert(image != (const Image *) NULL);
1976  assert(image->signature == MagickCoreSignature);
1977  return(image->blob->data);
1978 }
1979 ␌
1980 /*
1981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1982 % %
1983 % %
1984 % %
1985 + G e t B l o b S t r e a m H a n d l e r %
1986 % %
1987 % %
1988 % %
1989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1990 %
1991 % GetBlobStreamHandler() returns the stream handler for the image.
1992 %
1993 % The format of the GetBlobStreamHandler method is:
1994 %
1995 % StreamHandler GetBlobStreamHandler(const Image *image)
1996 %
1997 % A description of each parameter follows:
1998 %
1999 % o image: the image.
2000 %
2001 */
2002 MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
2003 {
2004  assert(image != (const Image *) NULL);
2005  assert(image->signature == MagickCoreSignature);
2006  if (IsEventLogging() != MagickFalse)
2007  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2008  return(image->blob->stream);
2009 }
2010 ␌
2011 /*
2012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2013 % %
2014 % %
2015 % %
2016 % I m a g e T o B l o b %
2017 % %
2018 % %
2019 % %
2020 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2021 %
2022 % ImageToBlob() implements direct to memory image formats. It returns the
2023 % image as a formatted blob and its length. The magick member of the Image
2024 % structure determines the format of the returned blob (GIF, JPEG, PNG,
2025 % etc.). This method is the equivalent of WriteImage(), but writes the
2026 % formatted "file" to a memory buffer rather than to an actual file.
2027 %
2028 % The format of the ImageToBlob method is:
2029 %
2030 % void *ImageToBlob(const ImageInfo *image_info,Image *image,
2031 % size_t *length,ExceptionInfo *exception)
2032 %
2033 % A description of each parameter follows:
2034 %
2035 % o image_info: the image info.
2036 %
2037 % o image: the image.
2038 %
2039 % o length: return the actual length of the blob.
2040 %
2041 % o exception: return any errors or warnings in this structure.
2042 %
2043 */
2044 MagickExport void *ImageToBlob(const ImageInfo *image_info,
2045  Image *image,size_t *length,ExceptionInfo *exception)
2046 {
2047  const MagickInfo
2048  *magick_info;
2049 
2050  ImageInfo
2051  *blob_info;
2052 
2053  MagickBooleanType
2054  status;
2055 
2056  void
2057  *blob;
2058 
2059  assert(image_info != (const ImageInfo *) NULL);
2060  assert(image_info->signature == MagickCoreSignature);
2061  assert(image != (Image *) NULL);
2062  assert(image->signature == MagickCoreSignature);
2063  assert(exception != (ExceptionInfo *) NULL);
2064  assert(exception->signature == MagickCoreSignature);
2065  if (IsEventLogging() != MagickFalse)
2066  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2067  image_info->filename);
2068  *length=0;
2069  blob=(unsigned char *) NULL;
2070  blob_info=CloneImageInfo(image_info);
2071  blob_info->adjoin=MagickFalse;
2072  (void) SetImageInfo(blob_info,1,exception);
2073  if (*blob_info->magick != '\0')
2074  (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
2075  magick_info=GetMagickInfo(image->magick,exception);
2076  if (magick_info == (const MagickInfo *) NULL)
2077  {
2078  (void) ThrowMagickException(exception,GetMagickModule(),
2079  MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2080  image->magick);
2081  blob_info=DestroyImageInfo(blob_info);
2082  return(blob);
2083  }
2084  (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
2085  if (GetMagickBlobSupport(magick_info) != MagickFalse)
2086  {
2087  /*
2088  Native blob support for this image format.
2089  */
2090  blob_info->length=0;
2091  blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
2092  sizeof(unsigned char));
2093  if (blob_info->blob == NULL)
2094  (void) ThrowMagickException(exception,GetMagickModule(),
2095  ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
2096  else
2097  {
2098  (void) CloseBlob(image);
2099  image->blob->exempt=MagickTrue;
2100  image->blob->extent=0;
2101  *image->filename='\0';
2102  status=WriteImage(blob_info,image,exception);
2103  *length=image->blob->length;
2104  blob=DetachBlob(image->blob);
2105  if (blob != (void *) NULL)
2106  {
2107  if (status == MagickFalse)
2108  blob=RelinquishMagickMemory(blob);
2109  else
2110  blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2111  }
2112  else if ((status == MagickFalse) && (image->blob->extent == 0))
2113  blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2114  }
2115  }
2116  else
2117  {
2118  char
2119  unique[MagickPathExtent];
2120 
2121  int
2122  file;
2123 
2124  /*
2125  Write file to disk in blob image format.
2126  */
2127  file=AcquireUniqueFileResource(unique);
2128  if (file == -1)
2129  {
2130  ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2131  image_info->filename);
2132  }
2133  else
2134  {
2135  blob_info->file=fdopen(file,"wb");
2136  if (blob_info->file != (FILE *) NULL)
2137  {
2138  (void) FormatLocaleString(image->filename,MagickPathExtent,
2139  "%s:%s",image->magick,unique);
2140  status=WriteImage(blob_info,image,exception);
2141  (void) fclose(blob_info->file);
2142  if (status != MagickFalse)
2143  blob=FileToBlob(unique,SIZE_MAX,length,exception);
2144  }
2145  (void) RelinquishUniqueFileResource(unique);
2146  }
2147  }
2148  blob_info=DestroyImageInfo(blob_info);
2149  return(blob);
2150 }
2151 ␌
2152 /*
2153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2154 % %
2155 % %
2156 % %
2157 + I m a g e T o C u s t o m S t r e a m %
2158 % %
2159 % %
2160 % %
2161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2162 %
2163 % ImageToCustomStream() is the equivalent of WriteImage(), but writes the
2164 % formatted "file" to the custom stream rather than to an actual file.
2165 %
2166 % The format of the ImageToCustomStream method is:
2167 %
2168 % void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2169 % ExceptionInfo *exception)
2170 %
2171 % A description of each parameter follows:
2172 %
2173 % o image_info: the image info.
2174 %
2175 % o image: the image.
2176 %
2177 % o exception: return any errors or warnings in this structure.
2178 %
2179 */
2180 MagickExport void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2181  ExceptionInfo *exception)
2182 {
2183  const MagickInfo
2184  *magick_info;
2185 
2186  ImageInfo
2187  *clone_info;
2188 
2189  MagickBooleanType
2190  blob_support,
2191  status;
2192 
2193  assert(image_info != (const ImageInfo *) NULL);
2194  assert(image_info->signature == MagickCoreSignature);
2195  assert(image != (Image *) NULL);
2196  assert(image->signature == MagickCoreSignature);
2197  assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2198  assert(image_info->custom_stream->signature == MagickCoreSignature);
2199  assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2200  assert(exception != (ExceptionInfo *) NULL);
2201  if (IsEventLogging() != MagickFalse)
2202  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2203  image_info->filename);
2204  clone_info=CloneImageInfo(image_info);
2205  clone_info->adjoin=MagickFalse;
2206  (void) SetImageInfo(clone_info,1,exception);
2207  if (*clone_info->magick != '\0')
2208  (void) CopyMagickString(image->magick,clone_info->magick,MagickPathExtent);
2209  magick_info=GetMagickInfo(image->magick,exception);
2210  if (magick_info == (const MagickInfo *) NULL)
2211  {
2212  (void) ThrowMagickException(exception,GetMagickModule(),
2213  MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2214  image->magick);
2215  clone_info=DestroyImageInfo(clone_info);
2216  return;
2217  }
2218  (void) CopyMagickString(clone_info->magick,image->magick,MagickPathExtent);
2219  blob_support=GetMagickBlobSupport(magick_info);
2220  if ((blob_support != MagickFalse) &&
2221  (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2222  {
2223  if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2224  (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2225  blob_support=MagickFalse;
2226  }
2227  if (blob_support != MagickFalse)
2228  {
2229  /*
2230  Native blob support for this image format.
2231  */
2232  (void) CloseBlob(image);
2233  *image->filename='\0';
2234  (void) WriteImage(clone_info,image,exception);
2235  }
2236  else
2237  {
2238  char
2239  unique[MagickPathExtent];
2240 
2241  int
2242  file;
2243 
2244  unsigned char
2245  *blob;
2246 
2247  /*
2248  Write file to disk in blob image format.
2249  */
2250  clone_info->custom_stream=(CustomStreamInfo *) NULL;
2251  blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2252  sizeof(*blob));
2253  if (blob == (unsigned char *) NULL)
2254  {
2255  ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2256  image_info->filename);
2257  clone_info=DestroyImageInfo(clone_info);
2258  return;
2259  }
2260  file=AcquireUniqueFileResource(unique);
2261  if (file == -1)
2262  {
2263  ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2264  image_info->filename);
2265  blob=(unsigned char *) RelinquishMagickMemory(blob);
2266  clone_info=DestroyImageInfo(clone_info);
2267  return;
2268  }
2269  clone_info->file=fdopen(file,"wb+");
2270  if (clone_info->file != (FILE *) NULL)
2271  {
2272  ssize_t
2273  count;
2274 
2275  (void) FormatLocaleString(image->filename,MagickPathExtent,"%s:%s",
2276  image->magick,unique);
2277  status=WriteImage(clone_info,image,exception);
2278  if (status != MagickFalse)
2279  {
2280  (void) fseek(clone_info->file,0,SEEK_SET);
2281  count=(ssize_t) MagickMaxBufferExtent;
2282  while (count == (ssize_t) MagickMaxBufferExtent)
2283  {
2284  count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2285  clone_info->file);
2286  (void) image_info->custom_stream->writer(blob,(size_t) count,
2287  image_info->custom_stream->data);
2288  }
2289  }
2290  (void) fclose(clone_info->file);
2291  }
2292  blob=(unsigned char *) RelinquishMagickMemory(blob);
2293  (void) RelinquishUniqueFileResource(unique);
2294  }
2295  clone_info=DestroyImageInfo(clone_info);
2296 }
2297 ␌
2298 /*
2299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2300 % %
2301 % %
2302 % %
2303 % I m a g e T o F i l e %
2304 % %
2305 % %
2306 % %
2307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2308 %
2309 % ImageToFile() writes an image to a file. It returns MagickFalse if an error
2310 % occurs otherwise MagickTrue.
2311 %
2312 % The format of the ImageToFile method is:
2313 %
2314 % MagickBooleanType ImageToFile(Image *image,char *filename,
2315 % ExceptionInfo *exception)
2316 %
2317 % A description of each parameter follows:
2318 %
2319 % o image: the image.
2320 %
2321 % o filename: Write the image to this file.
2322 %
2323 % o exception: return any errors or warnings in this structure.
2324 %
2325 */
2326 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
2327  ExceptionInfo *exception)
2328 {
2329  int
2330  file;
2331 
2332  const unsigned char
2333  *p;
2334 
2335  size_t
2336  i;
2337 
2338  size_t
2339  length,
2340  quantum;
2341 
2342  ssize_t
2343  count;
2344 
2345  struct stat
2346  file_stats;
2347 
2348  unsigned char
2349  *buffer;
2350 
2351  assert(image != (Image *) NULL);
2352  assert(image->signature == MagickCoreSignature);
2353  assert(image->blob != (BlobInfo *) NULL);
2354  assert(image->blob->type != UndefinedStream);
2355  assert(filename != (const char *) NULL);
2356  if (IsEventLogging() != MagickFalse)
2357  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
2358  if (*filename == '\0')
2359  file=AcquireUniqueFileResource(filename);
2360  else
2361  if (LocaleCompare(filename,"-") == 0)
2362  file=fileno(stdout);
2363  else
2364  file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,P_MODE);
2365  if (file == -1)
2366  {
2367  ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2368  return(MagickFalse);
2369  }
2370  quantum=(size_t) MagickMaxBufferExtent;
2371  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2372  quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2373  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2374  if (buffer == (unsigned char *) NULL)
2375  {
2376  file=close_utf8(file)-1;
2377  (void) ThrowMagickException(exception,GetMagickModule(),
2378  ResourceLimitError,"MemoryAllocationError","`%s'",filename);
2379  return(MagickFalse);
2380  }
2381  length=0;
2382  p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2383  for (i=0; count > 0; )
2384  {
2385  length=(size_t) count;
2386  for (i=0; i < length; i+=(size_t) count)
2387  {
2388  count=MagickWrite(file,p+i,(size_t) (length-i));
2389  if (count <= 0)
2390  break;
2391  }
2392  if (i < length)
2393  break;
2394  p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2395  }
2396  if (LocaleCompare(filename,"-") != 0)
2397  file=close_utf8(file);
2398  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2399  if ((file == -1) || (i < length))
2400  {
2401  if (file != -1)
2402  file=close_utf8(file);
2403  ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2404  return(MagickFalse);
2405  }
2406  return(MagickTrue);
2407 }
2408 ␌
2409 /*
2410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2411 % %
2412 % %
2413 % %
2414 % I m a g e s T o B l o b %
2415 % %
2416 % %
2417 % %
2418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2419 %
2420 % ImagesToBlob() implements direct to memory image formats. It returns the
2421 % image sequence as a blob and its length. The magick member of the ImageInfo
2422 % structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
2423 %
2424 % Note, some image formats do not permit multiple images to the same image
2425 % stream (e.g. JPEG). in this instance, just the first image of the
2426 % sequence is returned as a blob.
2427 %
2428 % The format of the ImagesToBlob method is:
2429 %
2430 % void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2431 % size_t *length,ExceptionInfo *exception)
2432 %
2433 % A description of each parameter follows:
2434 %
2435 % o image_info: the image info.
2436 %
2437 % o images: the image list.
2438 %
2439 % o length: return the actual length of the blob.
2440 %
2441 % o exception: return any errors or warnings in this structure.
2442 %
2443 */
2444 MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2445  size_t *length,ExceptionInfo *exception)
2446 {
2447  const MagickInfo
2448  *magick_info;
2449 
2450  ImageInfo
2451  *blob_info;
2452 
2453  MagickBooleanType
2454  status;
2455 
2456  void
2457  *blob;
2458 
2459  assert(image_info != (const ImageInfo *) NULL);
2460  assert(image_info->signature == MagickCoreSignature);
2461  assert(images != (Image *) NULL);
2462  assert(images->signature == MagickCoreSignature);
2463  assert(exception != (ExceptionInfo *) NULL);
2464  if (IsEventLogging() != MagickFalse)
2465  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2466  image_info->filename);
2467  *length=0;
2468  blob=(unsigned char *) NULL;
2469  blob_info=CloneImageInfo(image_info);
2470  (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
2471  exception);
2472  if (*blob_info->magick != '\0')
2473  (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
2474  magick_info=GetMagickInfo(images->magick,exception);
2475  if (magick_info == (const MagickInfo *) NULL)
2476  {
2477  (void) ThrowMagickException(exception,GetMagickModule(),
2478  MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2479  images->magick);
2480  blob_info=DestroyImageInfo(blob_info);
2481  return(blob);
2482  }
2483  if (GetMagickAdjoin(magick_info) == MagickFalse)
2484  {
2485  blob_info=DestroyImageInfo(blob_info);
2486  return(ImageToBlob(image_info,images,length,exception));
2487  }
2488  (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
2489  if (GetMagickBlobSupport(magick_info) != MagickFalse)
2490  {
2491  /*
2492  Native blob support for this images format.
2493  */
2494  blob_info->length=0;
2495  blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
2496  sizeof(unsigned char));
2497  if (blob_info->blob == (void *) NULL)
2498  (void) ThrowMagickException(exception,GetMagickModule(),
2499  ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2500  else
2501  {
2502  (void) CloseBlob(images);
2503  images->blob->exempt=MagickTrue;
2504  images->blob->extent=0;
2505  *images->filename='\0';
2506  status=WriteImages(blob_info,images,images->filename,exception);
2507  *length=images->blob->length;
2508  blob=DetachBlob(images->blob);
2509  if (blob != (void *) NULL)
2510  {
2511  if (status == MagickFalse)
2512  blob=RelinquishMagickMemory(blob);
2513  else
2514  blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2515  }
2516  else if ((status == MagickFalse) && (images->blob->extent == 0))
2517  blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2518  }
2519  }
2520  else
2521  {
2522  char
2523  filename[MagickPathExtent],
2524  unique[MagickPathExtent];
2525 
2526  int
2527  file;
2528 
2529  /*
2530  Write file to disk in blob images format.
2531  */
2532  file=AcquireUniqueFileResource(unique);
2533  if (file == -1)
2534  {
2535  ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2536  image_info->filename);
2537  }
2538  else
2539  {
2540  blob_info->file=fdopen(file,"wb");
2541  if (blob_info->file != (FILE *) NULL)
2542  {
2543  (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2544  images->magick,unique);
2545  status=WriteImages(blob_info,images,filename,exception);
2546  (void) fclose(blob_info->file);
2547  if (status != MagickFalse)
2548  blob=FileToBlob(unique,SIZE_MAX,length,exception);
2549  }
2550  (void) RelinquishUniqueFileResource(unique);
2551  }
2552  }
2553  blob_info=DestroyImageInfo(blob_info);
2554  return(blob);
2555 }
2556 ␌
2557 /*
2558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2559 % %
2560 % %
2561 % %
2562 + I m a g e s T o C u s t o m B l o b %
2563 % %
2564 % %
2565 % %
2566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2567 %
2568 % ImagesToCustomStream() is the equivalent of WriteImages(), but writes the
2569 % formatted "file" to the custom stream rather than to an actual file.
2570 %
2571 % The format of the ImageToCustomStream method is:
2572 %
2573 % void ImagesToCustomStream(const ImageInfo *image_info,Image *images,
2574 % ExceptionInfo *exception)
2575 %
2576 % A description of each parameter follows:
2577 %
2578 % o image_info: the image info.
2579 %
2580 % o images: the image list.
2581 %
2582 % o exception: return any errors or warnings in this structure.
2583 %
2584 */
2585 MagickExport void ImagesToCustomStream(const ImageInfo *image_info,
2586  Image *images,ExceptionInfo *exception)
2587 {
2588  const MagickInfo
2589  *magick_info;
2590 
2591  ImageInfo
2592  *clone_info;
2593 
2594  MagickBooleanType
2595  blob_support,
2596  status;
2597 
2598  assert(image_info != (const ImageInfo *) NULL);
2599  assert(image_info->signature == MagickCoreSignature);
2600  assert(images != (Image *) NULL);
2601  assert(images->signature == MagickCoreSignature);
2602  assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2603  assert(image_info->custom_stream->signature == MagickCoreSignature);
2604  assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2605  assert(exception != (ExceptionInfo *) NULL);
2606  if (IsEventLogging() != MagickFalse)
2607  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2608  image_info->filename);
2609  clone_info=CloneImageInfo(image_info);
2610  (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
2611  exception);
2612  if (*clone_info->magick != '\0')
2613  (void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
2614  magick_info=GetMagickInfo(images->magick,exception);
2615  if (magick_info == (const MagickInfo *) NULL)
2616  {
2617  (void) ThrowMagickException(exception,GetMagickModule(),
2618  MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2619  images->magick);
2620  clone_info=DestroyImageInfo(clone_info);
2621  return;
2622  }
2623  (void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
2624  blob_support=GetMagickBlobSupport(magick_info);
2625  if ((blob_support != MagickFalse) &&
2626  (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2627  {
2628  if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2629  (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2630  blob_support=MagickFalse;
2631  }
2632  if (blob_support != MagickFalse)
2633  {
2634  /*
2635  Native blob support for this image format.
2636  */
2637  (void) CloseBlob(images);
2638  *images->filename='\0';
2639  (void) WriteImages(clone_info,images,images->filename,exception);
2640  }
2641  else
2642  {
2643  char
2644  filename[MagickPathExtent],
2645  unique[MagickPathExtent];
2646 
2647  int
2648  file;
2649 
2650  unsigned char
2651  *blob;
2652 
2653  /*
2654  Write file to disk in blob image format.
2655  */
2656  clone_info->custom_stream=(CustomStreamInfo *) NULL;
2657  blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2658  sizeof(*blob));
2659  if (blob == (unsigned char *) NULL)
2660  {
2661  ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2662  image_info->filename);
2663  clone_info=DestroyImageInfo(clone_info);
2664  return;
2665  }
2666  file=AcquireUniqueFileResource(unique);
2667  if (file == -1)
2668  {
2669  ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2670  image_info->filename);
2671  blob=(unsigned char *) RelinquishMagickMemory(blob);
2672  clone_info=DestroyImageInfo(clone_info);
2673  return;
2674  }
2675  clone_info->file=fdopen(file,"wb+");
2676  if (clone_info->file != (FILE *) NULL)
2677  {
2678  ssize_t
2679  count;
2680 
2681  (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2682  images->magick,unique);
2683  status=WriteImages(clone_info,images,filename,exception);
2684  if (status != MagickFalse)
2685  {
2686  (void) fseek(clone_info->file,0,SEEK_SET);
2687  count=(ssize_t) MagickMaxBufferExtent;
2688  while (count == (ssize_t) MagickMaxBufferExtent)
2689  {
2690  count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2691  clone_info->file);
2692  (void) image_info->custom_stream->writer(blob,(size_t) count,
2693  image_info->custom_stream->data);
2694  }
2695  }
2696  (void) fclose(clone_info->file);
2697  }
2698  blob=(unsigned char *) RelinquishMagickMemory(blob);
2699  (void) RelinquishUniqueFileResource(unique);
2700  }
2701  clone_info=DestroyImageInfo(clone_info);
2702 }
2703 ␌
2704 /*
2705 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2706 % %
2707 % %
2708 % %
2709 % I n j e c t I m a g e B l o b %
2710 % %
2711 % %
2712 % %
2713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2714 %
2715 % InjectImageBlob() injects the image with a copy of itself in the specified
2716 % format (e.g. inject JPEG into a PDF image).
2717 %
2718 % The format of the InjectImageBlob method is:
2719 %
2720 % MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2721 % Image *image,Image *inject_image,const char *format,
2722 % ExceptionInfo *exception)
2723 %
2724 % A description of each parameter follows:
2725 %
2726 % o image_info: the image info..
2727 %
2728 % o image: the image.
2729 %
2730 % o inject_image: inject into the image stream.
2731 %
2732 % o format: the image format.
2733 %
2734 % o exception: return any errors or warnings in this structure.
2735 %
2736 */
2737 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2738  Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2739 {
2740  char
2741  filename[MagickPathExtent];
2742 
2743  FILE
2744  *unique_file;
2745 
2746  Image
2747  *byte_image;
2748 
2749  ImageInfo
2750  *write_info;
2751 
2752  int
2753  file;
2754 
2755  MagickBooleanType
2756  status;
2757 
2758  size_t
2759  quantum;
2760 
2761  struct stat
2762  file_stats;
2763 
2764  unsigned char
2765  *buffer;
2766 
2767  /*
2768  Write inject image to a temporary file.
2769  */
2770  assert(image_info != (ImageInfo *) NULL);
2771  assert(image_info->signature == MagickCoreSignature);
2772  assert(image != (Image *) NULL);
2773  assert(image->signature == MagickCoreSignature);
2774  assert(inject_image != (Image *) NULL);
2775  assert(inject_image->signature == MagickCoreSignature);
2776  assert(exception != (ExceptionInfo *) NULL);
2777  if (IsEventLogging() != MagickFalse)
2778  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2779  unique_file=(FILE *) NULL;
2780  file=AcquireUniqueFileResource(filename);
2781  if (file != -1)
2782  unique_file=fdopen(file,"wb");
2783  if ((file == -1) || (unique_file == (FILE *) NULL))
2784  {
2785  (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2786  ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2787  image->filename);
2788  return(MagickFalse);
2789  }
2790  byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2791  if (byte_image == (Image *) NULL)
2792  {
2793  (void) fclose(unique_file);
2794  (void) RelinquishUniqueFileResource(filename);
2795  return(MagickFalse);
2796  }
2797  (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
2798  format,filename);
2799  DestroyBlob(byte_image);
2800  byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2801  write_info=CloneImageInfo(image_info);
2802  SetImageInfoFile(write_info,unique_file);
2803  status=WriteImage(write_info,byte_image,exception);
2804  write_info=DestroyImageInfo(write_info);
2805  byte_image=DestroyImage(byte_image);
2806  (void) fclose(unique_file);
2807  if (status == MagickFalse)
2808  {
2809  (void) RelinquishUniqueFileResource(filename);
2810  return(MagickFalse);
2811  }
2812  /*
2813  Inject into image stream.
2814  */
2815  file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2816  if (file == -1)
2817  {
2818  (void) RelinquishUniqueFileResource(filename);
2819  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2820  image_info->filename);
2821  return(MagickFalse);
2822  }
2823  quantum=(size_t) MagickMaxBufferExtent;
2824  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2825  quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2826  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2827  if (buffer == (unsigned char *) NULL)
2828  {
2829  (void) RelinquishUniqueFileResource(filename);
2830  file=close_utf8(file);
2831  ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2832  image->filename);
2833  }
2834  for ( ; ; )
2835  {
2836  ssize_t count = read(file,buffer,quantum);
2837  if (count <= 0)
2838  {
2839  count=0;
2840  if (errno != EINTR)
2841  break;
2842  }
2843  status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2844  MagickFalse;
2845  }
2846  file=close_utf8(file);
2847  if (file == -1)
2848  ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2849  (void) RelinquishUniqueFileResource(filename);
2850  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2851  return(status);
2852 }
2853 ␌
2854 /*
2855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2856 % %
2857 % %
2858 % %
2859 % I s B l o b E x e m p t %
2860 % %
2861 % %
2862 % %
2863 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2864 %
2865 % IsBlobExempt() returns true if the blob is exempt.
2866 %
2867 % The format of the IsBlobExempt method is:
2868 %
2869 % MagickBooleanType IsBlobExempt(const Image *image)
2870 %
2871 % A description of each parameter follows:
2872 %
2873 % o image: the image.
2874 %
2875 */
2876 MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2877 {
2878  assert(image != (const Image *) NULL);
2879  assert(image->signature == MagickCoreSignature);
2880  if (IsEventLogging() != MagickFalse)
2881  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2882  return(image->blob->exempt);
2883 }
2884 ␌
2885 /*
2886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2887 % %
2888 % %
2889 % %
2890 % I s B l o b S e e k a b l e %
2891 % %
2892 % %
2893 % %
2894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2895 %
2896 % IsBlobSeekable() returns true if the blob is seekable.
2897 %
2898 % The format of the IsBlobSeekable method is:
2899 %
2900 % MagickBooleanType IsBlobSeekable(const Image *image)
2901 %
2902 % A description of each parameter follows:
2903 %
2904 % o image: the image.
2905 %
2906 */
2907 MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2908 {
2909  BlobInfo
2910  *magick_restrict blob_info;
2911 
2912  assert(image != (const Image *) NULL);
2913  assert(image->signature == MagickCoreSignature);
2914  if (IsEventLogging() != MagickFalse)
2915  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2916  blob_info=image->blob;
2917  switch (blob_info->type)
2918  {
2919  case BlobStream:
2920  return(MagickTrue);
2921  case FileStream:
2922  {
2923  int
2924  status;
2925 
2926  if (blob_info->file_info.file == (FILE *) NULL)
2927  return(MagickFalse);
2928  status=fseek(blob_info->file_info.file,0,SEEK_CUR);
2929  return(status == -1 ? MagickFalse : MagickTrue);
2930  }
2931  case ZipStream:
2932  {
2933 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2934  MagickOffsetType
2935  offset;
2936 
2937  if (blob_info->file_info.gzfile == (gzFile) NULL)
2938  return(MagickFalse);
2939  offset=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
2940  return(offset < 0 ? MagickFalse : MagickTrue);
2941 #else
2942  break;
2943 #endif
2944  }
2945  case UndefinedStream:
2946  case BZipStream:
2947  case FifoStream:
2948  case PipeStream:
2949  case StandardStream:
2950  break;
2951  case CustomStream:
2952  {
2953  if ((blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL) &&
2954  (blob_info->custom_stream->teller != (CustomStreamTeller) NULL))
2955  return(MagickTrue);
2956  break;
2957  }
2958  default:
2959  break;
2960  }
2961  return(MagickFalse);
2962 }
2963 ␌
2964 /*
2965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2966 % %
2967 % %
2968 % %
2969 % I s B l o b T e m p o r a r y %
2970 % %
2971 % %
2972 % %
2973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2974 %
2975 % IsBlobTemporary() returns true if the blob is temporary.
2976 %
2977 % The format of the IsBlobTemporary method is:
2978 %
2979 % MagickBooleanType IsBlobTemporary(const Image *image)
2980 %
2981 % A description of each parameter follows:
2982 %
2983 % o image: the image.
2984 %
2985 */
2986 MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2987 {
2988  assert(image != (const Image *) NULL);
2989  assert(image->signature == MagickCoreSignature);
2990  if (IsEventLogging() != MagickFalse)
2991  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2992  return(image->blob->temporary);
2993 }
2994 ␌
2995 /*
2996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2997 % %
2998 % %
2999 % %
3000 + M a p B l o b %
3001 % %
3002 % %
3003 % %
3004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3005 %
3006 % MapBlob() creates a mapping from a file to a binary large object.
3007 %
3008 % The format of the MapBlob method is:
3009 %
3010 % void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
3011 % const size_t length)
3012 %
3013 % A description of each parameter follows:
3014 %
3015 % o file: map this file descriptor.
3016 %
3017 % o mode: ReadMode, WriteMode, or IOMode.
3018 %
3019 % o offset: starting at this offset within the file.
3020 %
3021 % o length: the length of the mapping is returned in this pointer.
3022 %
3023 */
3024 MagickExport void *MapBlob(int file,const MapMode mode,
3025  const MagickOffsetType offset,const size_t length)
3026 {
3027 #if defined(MAGICKCORE_HAVE_MMAP)
3028  int
3029  flags,
3030  protection;
3031 
3032  void
3033  *map;
3034 
3035  /*
3036  Map file.
3037  */
3038  flags=0;
3039  if (file == -1)
3040 #if defined(MAP_ANONYMOUS)
3041  flags|=MAP_ANONYMOUS;
3042 #else
3043  return(NULL);
3044 #endif
3045  switch (mode)
3046  {
3047  case ReadMode:
3048  default:
3049  {
3050  protection=PROT_READ;
3051  flags|=MAP_PRIVATE;
3052  break;
3053  }
3054  case WriteMode:
3055  {
3056  protection=PROT_WRITE;
3057  flags|=MAP_SHARED;
3058  break;
3059  }
3060  case IOMode:
3061  {
3062  protection=PROT_READ | PROT_WRITE;
3063  flags|=MAP_SHARED;
3064  break;
3065  }
3066  }
3067 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
3068  map=mmap((char *) NULL,length,protection,flags,file,offset);
3069 #else
3070  map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,offset);
3071  if (map == MAP_FAILED)
3072  map=mmap((char *) NULL,length,protection,flags,file,offset);
3073 #endif
3074  if (map == MAP_FAILED)
3075  return(NULL);
3076  return(map);
3077 #else
3078  (void) file;
3079  (void) mode;
3080  (void) offset;
3081  (void) length;
3082  return(NULL);
3083 #endif
3084 }
3085 ␌
3086 /*
3087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3088 % %
3089 % %
3090 % %
3091 + M S B O r d e r L o n g %
3092 % %
3093 % %
3094 % %
3095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3096 %
3097 % MSBOrderLong() converts a least-significant byte first buffer of integers to
3098 % most-significant byte first.
3099 %
3100 % The format of the MSBOrderLong method is:
3101 %
3102 % void MSBOrderLong(unsigned char *buffer,const size_t length)
3103 %
3104 % A description of each parameter follows.
3105 %
3106 % o buffer: Specifies a pointer to a buffer of integers.
3107 %
3108 % o length: Specifies the length of the buffer.
3109 %
3110 */
3111 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
3112 {
3113  int
3114  c;
3115 
3116  unsigned char
3117  *p,
3118  *q;
3119 
3120  assert(buffer != (unsigned char *) NULL);
3121  q=buffer+length;
3122  while (buffer < q)
3123  {
3124  p=buffer+3;
3125  c=(int) (*p);
3126  *p=(*buffer);
3127  *buffer++=(unsigned char) c;
3128  p=buffer+1;
3129  c=(int) (*p);
3130  *p=(*buffer);
3131  *buffer++=(unsigned char) c;
3132  buffer+=2;
3133  }
3134 }
3135 ␌
3136 /*
3137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3138 % %
3139 % %
3140 % %
3141 + M S B O r d e r S h o r t %
3142 % %
3143 % %
3144 % %
3145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3146 %
3147 % MSBOrderShort() converts a least-significant byte first buffer of integers
3148 % to most-significant byte first.
3149 %
3150 % The format of the MSBOrderShort method is:
3151 %
3152 % void MSBOrderShort(unsigned char *p,const size_t length)
3153 %
3154 % A description of each parameter follows.
3155 %
3156 % o p: Specifies a pointer to a buffer of integers.
3157 %
3158 % o length: Specifies the length of the buffer.
3159 %
3160 */
3161 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
3162 {
3163  int
3164  c;
3165 
3166  unsigned char
3167  *q;
3168 
3169  assert(p != (unsigned char *) NULL);
3170  q=p+length;
3171  while (p < q)
3172  {
3173  c=(int) (*p);
3174  *p=(*(p+1));
3175  p++;
3176  *p++=(unsigned char) c;
3177  }
3178 }
3179 ␌
3180 /*
3181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3182 % %
3183 % %
3184 % %
3185 + O p e n B l o b %
3186 % %
3187 % %
3188 % %
3189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3190 %
3191 % OpenBlob() opens a file associated with the image. A file name of '-' sets
3192 % the file to stdin for type 'r' and stdout for type 'w'. If the filename
3193 % suffix is '.gz', the image is decompressed for type 'r' and compressed for
3194 % type 'w'. If the filename prefix is '|', it is piped to or from a system
3195 % command.
3196 %
3197 % The format of the OpenBlob method is:
3198 %
3199 % MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
3200 % const BlobMode mode,ExceptionInfo *exception)
3201 %
3202 % A description of each parameter follows:
3203 %
3204 % o image_info: the image info.
3205 %
3206 % o image: the image.
3207 %
3208 % o mode: the mode for opening the file.
3209 %
3210 */
3211 
3212 static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
3213  const BlobInfo *blob_info)
3214 {
3215  const char
3216  *option;
3217 
3218  int
3219  status;
3220 
3221  size_t
3222  size;
3223 
3224  size=MagickMinBufferExtent;
3225  option=GetImageOption(image_info,"stream:buffer-size");
3226  if (option != (const char *) NULL)
3227  size=StringToUnsignedLong(option);
3228  status=setvbuf(blob_info->file_info.file,(char *) NULL,size == 0 ?
3229  _IONBF : _IOFBF,size);
3230  return(status == 0 ? MagickTrue : MagickFalse);
3231 }
3232 
3233 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3234 static inline gzFile gzopen_utf8(const char *path,const char *mode)
3235 {
3236 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
3237  return(gzopen(path,mode));
3238 #else
3239  gzFile
3240  file;
3241 
3242  wchar_t
3243  *path_wide;
3244 
3245  path_wide=NTCreateWidePath(path);
3246  if (path_wide == (wchar_t *) NULL)
3247  return((gzFile) NULL);
3248  file=gzopen_w(path_wide,mode);
3249  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
3250  return(file);
3251 #endif
3252 }
3253 #endif
3254 
3255 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
3256  Image *image,const BlobMode mode,ExceptionInfo *exception)
3257 {
3258  BlobInfo
3259  *magick_restrict blob_info;
3260 
3261  char
3262  extension[MagickPathExtent],
3263  filename[MagickPathExtent];
3264 
3265  const char
3266  *type;
3267 
3268  int
3269  flags = O_RDONLY;
3270 
3271  MagickBooleanType
3272  status;
3273 
3274  PolicyRights
3275  rights;
3276 
3277  assert(image_info != (ImageInfo *) NULL);
3278  assert(image_info->signature == MagickCoreSignature);
3279  assert(image != (Image *) NULL);
3280  assert(image->signature == MagickCoreSignature);
3281  if (IsEventLogging() != MagickFalse)
3282  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3283  image_info->filename);
3284  blob_info=image->blob;
3285  if (image_info->blob != (void *) NULL)
3286  {
3287  if (image_info->stream != (StreamHandler) NULL)
3288  blob_info->stream=(StreamHandler) image_info->stream;
3289  AttachBlob(blob_info,image_info->blob,image_info->length);
3290  return(MagickTrue);
3291  }
3292  if ((image_info->custom_stream != (CustomStreamInfo *) NULL) &&
3293  (*image->filename == '\0'))
3294  {
3295  blob_info->type=CustomStream;
3296  blob_info->custom_stream=image_info->custom_stream;
3297  if (blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL)
3298  blob_info->custom_stream->seeker(0,SEEK_SET,
3299  blob_info->custom_stream->data);
3300  return(MagickTrue);
3301  }
3302  (void) DetachBlob(blob_info);
3303  blob_info->mode=mode;
3304  switch (mode)
3305  {
3306  case ReadBlobMode:
3307  {
3308  flags=O_RDONLY;
3309  type="r";
3310  break;
3311  }
3312  case ReadBinaryBlobMode:
3313  {
3314  flags=O_RDONLY | O_BINARY;
3315  type="rb";
3316  break;
3317  }
3318  case WriteBlobMode:
3319  {
3320  flags=O_WRONLY | O_CREAT | O_TRUNC;
3321  type="w";
3322  break;
3323  }
3324  case WriteBinaryBlobMode:
3325  {
3326  flags=O_RDWR | O_CREAT | O_TRUNC | O_BINARY;
3327  type="w+b";
3328  break;
3329  }
3330  case AppendBlobMode:
3331  {
3332  flags=O_WRONLY | O_CREAT | O_APPEND;
3333  type="a";
3334  break;
3335  }
3336  case AppendBinaryBlobMode:
3337  {
3338  flags=O_RDWR | O_CREAT | O_APPEND | O_BINARY;
3339  type="a+b";
3340  break;
3341  }
3342  default:
3343  {
3344  flags=O_RDONLY;
3345  type="r";
3346  break;
3347  }
3348  }
3349  if (*type != 'r')
3350  blob_info->synchronize=image_info->synchronize;
3351  if (image_info->stream != (StreamHandler) NULL)
3352  {
3353  blob_info->stream=image_info->stream;
3354  if (*type == 'w')
3355  {
3356  blob_info->type=FifoStream;
3357  return(MagickTrue);
3358  }
3359  }
3360  /*
3361  Open image file.
3362  */
3363  *filename='\0';
3364  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3365  rights=ReadPolicyRights;
3366  if (*type == 'w')
3367  rights=WritePolicyRights;
3368  if (IsPathAuthorized(rights,filename) == MagickFalse)
3369  ThrowPolicyException(filename,MagickFalse);
3370  if ((LocaleCompare(filename,"-") == 0) ||
3371  ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
3372  {
3373  blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
3374 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3375  if (strchr(type,'b') != (char *) NULL)
3376  (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
3377 #endif
3378  blob_info->type=StandardStream;
3379  blob_info->exempt=MagickTrue;
3380  return(SetStreamBuffering(image_info,blob_info));
3381  }
3382  if ((LocaleNCompare(filename,"fd:",3) == 0) &&
3383  (IsGeometry(filename+3) != MagickFalse))
3384  {
3385  char
3386  fileMode[2];
3387 
3388  *fileMode=(*type);
3389  fileMode[1]='\0';
3390  blob_info->file_info.file=fdopen(StringToLong(filename+3),fileMode);
3391  if (blob_info->file_info.file == (FILE *) NULL)
3392  {
3393  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3394  return(MagickFalse);
3395  }
3396 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3397  if (strchr(type,'b') != (char *) NULL)
3398  (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
3399 #endif
3400  blob_info->type=FileStream;
3401  blob_info->exempt=MagickTrue;
3402  return(SetStreamBuffering(image_info,blob_info));
3403  }
3404 #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
3405  if (*filename == '|')
3406  {
3407  char
3408  fileMode[MagickPathExtent],
3409  *sanitize_command;
3410 
3411  /*
3412  Pipe image to or from a system command.
3413  */
3414 #if defined(SIGPIPE)
3415  if (*type == 'w')
3416  (void) signal(SIGPIPE,SIG_IGN);
3417 #endif
3418  *fileMode=(*type);
3419  fileMode[1]='\0';
3420  sanitize_command=SanitizeString(filename+1);
3421  blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,fileMode);
3422  sanitize_command=DestroyString(sanitize_command);
3423  if (blob_info->file_info.file == (FILE *) NULL)
3424  {
3425  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3426  return(MagickFalse);
3427  }
3428  blob_info->type=PipeStream;
3429  blob_info->exempt=MagickTrue;
3430  return(SetStreamBuffering(image_info,blob_info));
3431  }
3432 #endif
3433  status=GetPathAttributes(filename,&blob_info->properties);
3434 #if defined(S_ISFIFO)
3435  if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
3436  {
3437  blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3438  if (blob_info->file_info.file == (FILE *) NULL)
3439  {
3440  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3441  return(MagickFalse);
3442  }
3443  blob_info->type=FileStream;
3444  blob_info->exempt=MagickTrue;
3445  return(SetStreamBuffering(image_info,blob_info));
3446  }
3447 #endif
3448  GetPathComponent(image->filename,ExtensionPath,extension);
3449  if (*type == 'w')
3450  {
3451  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3452  if ((image_info->adjoin == MagickFalse) ||
3453  (strchr(filename,'%') != (char *) NULL))
3454  {
3455  /*
3456  Form filename for multi-part images.
3457  */
3458  (void) InterpretImageFilename(image_info,image,image->filename,(int)
3459  image->scene,filename,exception);
3460  if ((LocaleCompare(filename,image->filename) == 0) &&
3461  ((GetPreviousImageInList(image) != (Image *) NULL) ||
3462  (GetNextImageInList(image) != (Image *) NULL)))
3463  {
3464  char
3465  path[MagickPathExtent];
3466 
3467  GetPathComponent(image->filename,RootPath,path);
3468  if (*extension == '\0')
3469  (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.17g",
3470  path,(double) image->scene);
3471  else
3472  (void) FormatLocaleString(filename,MagickPathExtent,
3473  "%s-%.17g.%s",path,(double) image->scene,extension);
3474  }
3475  (void) CopyMagickString(image->filename,filename,MagickPathExtent);
3476  }
3477  if (IsPathAuthorized(rights,filename) == MagickFalse)
3478  ThrowPolicyException(filename,MagickFalse);
3479  }
3480  if (image_info->file != (FILE *) NULL)
3481  {
3482  blob_info->file_info.file=image_info->file;
3483  blob_info->type=FileStream;
3484  blob_info->exempt=MagickTrue;
3485  }
3486  else
3487  if (*type == 'r')
3488  {
3489  int
3490  file;
3491 
3492  blob_info->file_info.file=(FILE *) NULL;
3493  file=open_utf8(filename,flags,0);
3494  if (file >= 0)
3495  blob_info->file_info.file=fdopen(file,type);
3496  if (blob_info->file_info.file != (FILE *) NULL)
3497  {
3498  size_t
3499  count;
3500 
3501  unsigned char
3502  magick[3];
3503 
3504  blob_info->type=FileStream;
3505  (void) SetStreamBuffering(image_info,blob_info);
3506  (void) memset(magick,0,sizeof(magick));
3507  count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
3508  (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
3509 #if defined(MAGICKCORE_POSIX_SUPPORT)
3510  (void) fflush(blob_info->file_info.file);
3511 #endif
3512  (void) LogMagickEvent(BlobEvent,GetMagickModule(),
3513  " read %.17g magic header bytes",(double) count);
3514 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3515  if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
3516  ((int) magick[2] == 0x08))
3517  {
3518  gzFile
3519  gzfile = gzopen_utf8(filename,"rb");
3520 
3521  if (gzfile != (gzFile) NULL)
3522  {
3523  if (blob_info->file_info.file != (FILE *) NULL)
3524  (void) fclose(blob_info->file_info.file);
3525  blob_info->file_info.file=(FILE *) NULL;
3526  blob_info->file_info.gzfile=gzfile;
3527  blob_info->type=ZipStream;
3528  }
3529  }
3530 #endif
3531 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3532  if (strncmp((char *) magick,"BZh",3) == 0)
3533  {
3534  BZFILE
3535  *bzfile = BZ2_bzopen(filename,"r");
3536 
3537  if (bzfile != (BZFILE *) NULL)
3538  {
3539  if (blob_info->file_info.file != (FILE *) NULL)
3540  (void) fclose(blob_info->file_info.file);
3541  blob_info->file_info.file=(FILE *) NULL;
3542  blob_info->file_info.bzfile=bzfile;
3543  blob_info->type=BZipStream;
3544  }
3545  }
3546 #endif
3547  if (blob_info->type == FileStream)
3548  {
3549  const MagickInfo
3550  *magick_info;
3551 
3553  *sans_exception;
3554 
3555  size_t
3556  length;
3557 
3558  sans_exception=AcquireExceptionInfo();
3559  magick_info=GetMagickInfo(image_info->magick,sans_exception);
3560  sans_exception=DestroyExceptionInfo(sans_exception);
3561  length=(size_t) blob_info->properties.st_size;
3562  if ((magick_info != (const MagickInfo *) NULL) &&
3563  (GetMagickBlobSupport(magick_info) != MagickFalse) &&
3564  (AcquireMagickResource(MapResource,length) != MagickFalse))
3565  {
3566  void
3567  *blob;
3568 
3569  blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
3570  length);
3571  if (blob == (void *) NULL)
3572  RelinquishMagickResource(MapResource,length);
3573  else
3574  {
3575  /*
3576  Format supports blobs-- use memory-mapped I/O.
3577  */
3578  if (image_info->file != (FILE *) NULL)
3579  blob_info->exempt=MagickFalse;
3580  else
3581  {
3582  (void) fclose(blob_info->file_info.file);
3583  blob_info->file_info.file=(FILE *) NULL;
3584  }
3585  AttachBlob(blob_info,blob,length);
3586  blob_info->mapped=MagickTrue;
3587  }
3588  }
3589  }
3590  }
3591  }
3592  else
3593 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3594  if ((LocaleCompare(extension,"gz") == 0) ||
3595  (LocaleCompare(extension,"wmz") == 0) ||
3596  (LocaleCompare(extension,"svgz") == 0))
3597  {
3598  blob_info->file_info.gzfile=gzopen_utf8(filename,"wb");
3599  if (blob_info->file_info.gzfile != (gzFile) NULL)
3600  blob_info->type=ZipStream;
3601  }
3602  else
3603 #endif
3604 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3605  if (LocaleCompare(extension,"bz2") == 0)
3606  {
3607  blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
3608  if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3609  blob_info->type=BZipStream;
3610  }
3611  else
3612 #endif
3613  {
3614  int
3615  file;
3616 
3617  blob_info->file_info.file=(FILE *) NULL;
3618  file=open_utf8(filename,flags,P_MODE);
3619  if (file >= 0)
3620  blob_info->file_info.file=fdopen(file,type);
3621  if (blob_info->file_info.file != (FILE *) NULL)
3622  {
3623  blob_info->type=FileStream;
3624  (void) SetStreamBuffering(image_info,blob_info);
3625  }
3626  }
3627  if (IsPathAuthorized(rights,filename) == MagickFalse)
3628  ThrowPolicyException(filename,MagickFalse);
3629  blob_info->status=0;
3630  blob_info->error_number=0;
3631  if (blob_info->type != UndefinedStream)
3632  blob_info->size=GetBlobSize(image);
3633  else
3634  {
3635  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3636  return(MagickFalse);
3637  }
3638  return(MagickTrue);
3639 }
3640 ␌
3641 /*
3642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3643 % %
3644 % %
3645 % %
3646 + P i n g B l o b %
3647 % %
3648 % %
3649 % %
3650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3651 %
3652 % PingBlob() returns all the attributes of an image or image sequence except
3653 % for the pixels. It is much faster and consumes far less memory than
3654 % BlobToImage(). On failure, a NULL image is returned and exception
3655 % describes the reason for the failure.
3656 %
3657 % The format of the PingBlob method is:
3658 %
3659 % Image *PingBlob(const ImageInfo *image_info,const void *blob,
3660 % const size_t length,ExceptionInfo *exception)
3661 %
3662 % A description of each parameter follows:
3663 %
3664 % o image_info: the image info.
3665 %
3666 % o blob: the address of a character stream in one of the image formats
3667 % understood by ImageMagick.
3668 %
3669 % o length: This size_t integer reflects the length in bytes of the blob.
3670 %
3671 % o exception: return any errors or warnings in this structure.
3672 %
3673 */
3674 
3675 #if defined(__cplusplus) || defined(c_plusplus)
3676 extern "C" {
3677 #endif
3678 
3679 static size_t PingStream(const Image *magick_unused(image),
3680  const void *magick_unused(pixels),const size_t columns)
3681 {
3682  magick_unreferenced(image);
3683  magick_unreferenced(pixels);
3684  return(columns);
3685 }
3686 
3687 #if defined(__cplusplus) || defined(c_plusplus)
3688 }
3689 #endif
3690 
3691 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3692  const size_t length,ExceptionInfo *exception)
3693 {
3694  const MagickInfo
3695  *magick_info;
3696 
3697  Image
3698  *image;
3699 
3700  ImageInfo
3701  *clone_info,
3702  *ping_info;
3703 
3704  MagickBooleanType
3705  status;
3706 
3707  assert(image_info != (ImageInfo *) NULL);
3708  assert(image_info->signature == MagickCoreSignature);
3709  assert(exception != (ExceptionInfo *) NULL);
3710  if (IsEventLogging() != MagickFalse)
3711  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3712  image_info->filename);
3713  if ((blob == (const void *) NULL) || (length == 0))
3714  {
3715  (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3716  "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
3717  return((Image *) NULL);
3718  }
3719  ping_info=CloneImageInfo(image_info);
3720  ping_info->blob=(void *) blob;
3721  ping_info->length=length;
3722  ping_info->ping=MagickTrue;
3723  if (*ping_info->magick == '\0')
3724  (void) SetImageInfo(ping_info,0,exception);
3725  magick_info=GetMagickInfo(ping_info->magick,exception);
3726  if (magick_info == (const MagickInfo *) NULL)
3727  {
3728  (void) ThrowMagickException(exception,GetMagickModule(),
3729  MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
3730  ping_info->magick);
3731  ping_info=DestroyImageInfo(ping_info);
3732  return((Image *) NULL);
3733  }
3734  if (GetMagickBlobSupport(magick_info) != MagickFalse)
3735  {
3736  char
3737  filename[MagickPathExtent];
3738 
3739  /*
3740  Native blob support for this image format.
3741  */
3742  (void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
3743  (void) FormatLocaleString(ping_info->filename,MagickPathExtent,"%s:%s",
3744  ping_info->magick,filename);
3745  image=ReadStream(ping_info,&PingStream,exception);
3746  if (image != (Image *) NULL)
3747  (void) DetachBlob(image->blob);
3748  ping_info=DestroyImageInfo(ping_info);
3749  return(image);
3750  }
3751  /*
3752  Write blob to a temporary file on disk.
3753  */
3754  ping_info->blob=(void *) NULL;
3755  ping_info->length=0;
3756  *ping_info->filename='\0';
3757  status=BlobToFile(ping_info->filename,blob,length,exception);
3758  if (status == MagickFalse)
3759  {
3760  (void) RelinquishUniqueFileResource(ping_info->filename);
3761  ping_info=DestroyImageInfo(ping_info);
3762  return((Image *) NULL);
3763  }
3764  clone_info=CloneImageInfo(ping_info);
3765  (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
3766  ping_info->magick,ping_info->filename);
3767  image=ReadStream(clone_info,&PingStream,exception);
3768  if (image != (Image *) NULL)
3769  {
3770  Image
3771  *images;
3772 
3773  /*
3774  Restore original filenames and image format.
3775  */
3776  for (images=GetFirstImageInList(image); images != (Image *) NULL; )
3777  {
3778  (void) CopyMagickString(images->filename,image_info->filename,
3779  MagickPathExtent);
3780  (void) CopyMagickString(images->magick_filename,image_info->filename,
3781  MagickPathExtent);
3782  (void) CopyMagickString(images->magick,magick_info->name,
3783  MagickPathExtent);
3784  images=GetNextImageInList(images);
3785  }
3786  }
3787  clone_info=DestroyImageInfo(clone_info);
3788  (void) RelinquishUniqueFileResource(ping_info->filename);
3789  ping_info=DestroyImageInfo(ping_info);
3790  return(image);
3791 }
3792 ␌
3793 /*
3794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3795 % %
3796 % %
3797 % %
3798 + R e a d B l o b %
3799 % %
3800 % %
3801 % %
3802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3803 %
3804 % ReadBlob() reads data from the blob or image file and returns it. It
3805 % returns the number of bytes read. If length is zero, ReadBlob() returns
3806 % zero and has no other results. If length is greater than MAGICK_SSIZE_MAX,
3807 % the result is unspecified.
3808 %
3809 % The format of the ReadBlob method is:
3810 %
3811 % ssize_t ReadBlob(Image *image,const size_t length,void *data)
3812 %
3813 % A description of each parameter follows:
3814 %
3815 % o image: the image.
3816 %
3817 % o length: Specifies an integer representing the number of bytes to read
3818 % from the file.
3819 %
3820 % o data: Specifies an area to place the information requested from the
3821 % file.
3822 %
3823 */
3824 MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
3825 {
3826  BlobInfo
3827  *magick_restrict blob_info;
3828 
3829  int
3830  c;
3831 
3832  ssize_t
3833  count;
3834 
3835  unsigned char
3836  *q;
3837 
3838  assert(image != (Image *) NULL);
3839  assert(image->signature == MagickCoreSignature);
3840  assert(image->blob != (BlobInfo *) NULL);
3841  assert(image->blob->type != UndefinedStream);
3842  if (length == 0)
3843  return(0);
3844  assert(data != (void *) NULL);
3845  blob_info=image->blob;
3846  count=0;
3847  q=(unsigned char *) data;
3848  switch (blob_info->type)
3849  {
3850  case UndefinedStream:
3851  break;
3852  case StandardStream:
3853  case FileStream:
3854  case PipeStream:
3855  {
3856  switch (length)
3857  {
3858  default:
3859  {
3860  count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
3861  break;
3862  }
3863  case 4:
3864  {
3865  c=getc(blob_info->file_info.file);
3866  if (c == EOF)
3867  break;
3868  *q++=(unsigned char) c;
3869  count++;
3870  magick_fallthrough;
3871  }
3872  case 3:
3873  {
3874  c=getc(blob_info->file_info.file);
3875  if (c == EOF)
3876  break;
3877  *q++=(unsigned char) c;
3878  count++;
3879  magick_fallthrough;
3880  }
3881  case 2:
3882  {
3883  c=getc(blob_info->file_info.file);
3884  if (c == EOF)
3885  break;
3886  *q++=(unsigned char) c;
3887  count++;
3888  magick_fallthrough;
3889  }
3890  case 1:
3891  {
3892  c=getc(blob_info->file_info.file);
3893  if (c == EOF)
3894  break;
3895  *q++=(unsigned char) c;
3896  count++;
3897  magick_fallthrough;
3898  }
3899  case 0:
3900  break;
3901  }
3902  if ((count != (ssize_t) length) &&
3903  (ferror(blob_info->file_info.file) != 0))
3904  ThrowBlobException(blob_info);
3905  break;
3906  }
3907  case ZipStream:
3908  {
3909 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3910  int
3911  status;
3912 
3913  switch (length)
3914  {
3915  default:
3916  {
3917  size_t
3918  i;
3919 
3920  for (i=0; i < length; i+=(size_t) count)
3921  {
3922  count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
3923  (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3924  if (count <= 0)
3925  {
3926  count=0;
3927  if (errno != EINTR)
3928  break;
3929  }
3930  }
3931  count=(ssize_t) i;
3932  break;
3933  }
3934  case 4:
3935  {
3936  c=gzgetc(blob_info->file_info.gzfile);
3937  if (c == EOF)
3938  break;
3939  *q++=(unsigned char) c;
3940  count++;
3941  magick_fallthrough;
3942  }
3943  case 3:
3944  {
3945  c=gzgetc(blob_info->file_info.gzfile);
3946  if (c == EOF)
3947  break;
3948  *q++=(unsigned char) c;
3949  count++;
3950  magick_fallthrough;
3951  }
3952  case 2:
3953  {
3954  c=gzgetc(blob_info->file_info.gzfile);
3955  if (c == EOF)
3956  break;
3957  *q++=(unsigned char) c;
3958  count++;
3959  magick_fallthrough;
3960  }
3961  case 1:
3962  {
3963  c=gzgetc(blob_info->file_info.gzfile);
3964  if (c == EOF)
3965  break;
3966  *q++=(unsigned char) c;
3967  count++;
3968  }
3969  case 0:
3970  break;
3971  }
3972  status=Z_OK;
3973  (void) gzerror(blob_info->file_info.gzfile,&status);
3974  if ((count != (ssize_t) length) && (status != Z_OK))
3975  ThrowBlobException(blob_info);
3976  if (blob_info->eof == MagickFalse)
3977  blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
3978  MagickFalse;
3979 #endif
3980  break;
3981  }
3982  case BZipStream:
3983  {
3984 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3985  int
3986  status;
3987 
3988  size_t
3989  i;
3990 
3991  for (i=0; i < length; i+=(size_t) count)
3992  {
3993  count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,(int)
3994  MagickMin(length-i,MagickMaxBufferExtent));
3995  if (count <= 0)
3996  {
3997  count=0;
3998  if (errno != EINTR)
3999  break;
4000  }
4001  }
4002  count=(ssize_t) i;
4003  status=BZ_OK;
4004  (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
4005  if ((count != (ssize_t) length) && (status != BZ_OK))
4006  ThrowBlobException(blob_info);
4007 #endif
4008  break;
4009  }
4010  case FifoStream:
4011  break;
4012  case BlobStream:
4013  {
4014  const unsigned char
4015  *p;
4016 
4017  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4018  {
4019  blob_info->eof=MagickTrue;
4020  break;
4021  }
4022  p=blob_info->data+blob_info->offset;
4023  count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4024  blob_info->length-blob_info->offset);
4025  blob_info->offset+=count;
4026  if (count != (ssize_t) length)
4027  blob_info->eof=MagickTrue;
4028  (void) memcpy(q,p,(size_t) count);
4029  break;
4030  }
4031  case CustomStream:
4032  {
4033  if (blob_info->custom_stream->reader != (CustomStreamHandler) NULL)
4034  count=blob_info->custom_stream->reader(q,length,
4035  blob_info->custom_stream->data);
4036  break;
4037  }
4038  }
4039  return(count);
4040 }
4041 ␌
4042 /*
4043 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4044 % %
4045 % %
4046 % %
4047 + R e a d B l o b B y t e %
4048 % %
4049 % %
4050 % %
4051 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4052 %
4053 % ReadBlobByte() reads a single byte from the image file and returns it.
4054 %
4055 % The format of the ReadBlobByte method is:
4056 %
4057 % int ReadBlobByte(Image *image)
4058 %
4059 % A description of each parameter follows.
4060 %
4061 % o image: the image.
4062 %
4063 */
4064 MagickExport int ReadBlobByte(Image *image)
4065 {
4066  BlobInfo
4067  *magick_restrict blob_info;
4068 
4069  int
4070  c;
4071 
4072  assert(image != (Image *) NULL);
4073  assert(image->signature == MagickCoreSignature);
4074  assert(image->blob != (BlobInfo *) NULL);
4075  assert(image->blob->type != UndefinedStream);
4076  blob_info=image->blob;
4077  switch (blob_info->type)
4078  {
4079  case StandardStream:
4080  case FileStream:
4081  case PipeStream:
4082  {
4083  c=getc(blob_info->file_info.file);
4084  if (c == EOF)
4085  {
4086  if (ferror(blob_info->file_info.file) != 0)
4087  ThrowBlobException(blob_info);
4088  return(EOF);
4089  }
4090  break;
4091  }
4092  case BlobStream:
4093  {
4094  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4095  {
4096  blob_info->eof=MagickTrue;
4097  return(EOF);
4098  }
4099  c=(int) (*((unsigned char *) blob_info->data+blob_info->offset));
4100  blob_info->offset++;
4101  break;
4102  }
4103  default:
4104  {
4105  ssize_t
4106  count;
4107 
4108  unsigned char
4109  buffer[1];
4110 
4111  count=ReadBlob(image,1,buffer);
4112  if (count != 1)
4113  return(EOF);
4114  c=(int) *buffer;
4115  break;
4116  }
4117  }
4118  return(c);
4119 }
4120 ␌
4121 /*
4122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4123 % %
4124 % %
4125 % %
4126 + R e a d B l o b D o u b l e %
4127 % %
4128 % %
4129 % %
4130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4131 %
4132 % ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
4133 % specified by the endian member of the image structure.
4134 %
4135 % The format of the ReadBlobDouble method is:
4136 %
4137 % double ReadBlobDouble(Image *image)
4138 %
4139 % A description of each parameter follows.
4140 %
4141 % o image: the image.
4142 %
4143 */
4144 MagickExport double ReadBlobDouble(Image *image)
4145 {
4146  union
4147  {
4148  MagickSizeType
4149  unsigned_value;
4150 
4151  double
4152  double_value;
4153  } quantum;
4154 
4155  quantum.double_value=0.0;
4156  quantum.unsigned_value=ReadBlobLongLong(image);
4157  return(quantum.double_value);
4158 }
4159 ␌
4160 /*
4161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4162 % %
4163 % %
4164 % %
4165 + R e a d B l o b F l o a t %
4166 % %
4167 % %
4168 % %
4169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4170 %
4171 % ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
4172 % specified by the endian member of the image structure.
4173 %
4174 % The format of the ReadBlobFloat method is:
4175 %
4176 % float ReadBlobFloat(Image *image)
4177 %
4178 % A description of each parameter follows.
4179 %
4180 % o image: the image.
4181 %
4182 */
4183 MagickExport float ReadBlobFloat(Image *image)
4184 {
4185  union
4186  {
4187  unsigned int
4188  unsigned_value;
4189 
4190  float
4191  float_value;
4192  } quantum;
4193 
4194  quantum.float_value=0.0;
4195  quantum.unsigned_value=ReadBlobLong(image);
4196  return(quantum.float_value);
4197 }
4198 ␌
4199 /*
4200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4201 % %
4202 % %
4203 % %
4204 + R e a d B l o b L o n g %
4205 % %
4206 % %
4207 % %
4208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4209 %
4210 % ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
4211 % byte-order specified by the endian member of the image structure.
4212 %
4213 % The format of the ReadBlobLong method is:
4214 %
4215 % unsigned int ReadBlobLong(Image *image)
4216 %
4217 % A description of each parameter follows.
4218 %
4219 % o image: the image.
4220 %
4221 */
4222 MagickExport unsigned int ReadBlobLong(Image *image)
4223 {
4224  const unsigned char
4225  *p;
4226 
4227  ssize_t
4228  count;
4229 
4230  unsigned char
4231  buffer[4];
4232 
4233  unsigned int
4234  value;
4235 
4236  assert(image != (Image *) NULL);
4237  assert(image->signature == MagickCoreSignature);
4238  *buffer='\0';
4239  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4240  if (count != 4)
4241  return(0UL);
4242  if (image->endian == LSBEndian)
4243  {
4244  value=(unsigned int) (*p++);
4245  value|=(unsigned int) (*p++) << 8;
4246  value|=(unsigned int) (*p++) << 16;
4247  value|=(unsigned int) (*p++) << 24;
4248  return(value);
4249  }
4250  value=(unsigned int) (*p++) << 24;
4251  value|=(unsigned int) (*p++) << 16;
4252  value|=(unsigned int) (*p++) << 8;
4253  value|=(unsigned int) (*p++);
4254  return(value);
4255 }
4256 ␌
4257 /*
4258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4259 % %
4260 % %
4261 % %
4262 + R e a d B l o b L o n g L o n g %
4263 % %
4264 % %
4265 % %
4266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4267 %
4268 % ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
4269 % byte-order specified by the endian member of the image structure.
4270 %
4271 % The format of the ReadBlobLongLong method is:
4272 %
4273 % MagickSizeType ReadBlobLongLong(Image *image)
4274 %
4275 % A description of each parameter follows.
4276 %
4277 % o image: the image.
4278 %
4279 */
4280 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
4281 {
4282  MagickSizeType
4283  value;
4284 
4285  const unsigned char
4286  *p;
4287 
4288  ssize_t
4289  count;
4290 
4291  unsigned char
4292  buffer[8];
4293 
4294  assert(image != (Image *) NULL);
4295  assert(image->signature == MagickCoreSignature);
4296  *buffer='\0';
4297  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4298  if (count != 8)
4299  return(MagickULLConstant(0));
4300  if (image->endian == LSBEndian)
4301  {
4302  value=(MagickSizeType) (*p++);
4303  value|=(MagickSizeType) (*p++) << 8;
4304  value|=(MagickSizeType) (*p++) << 16;
4305  value|=(MagickSizeType) (*p++) << 24;
4306  value|=(MagickSizeType) (*p++) << 32;
4307  value|=(MagickSizeType) (*p++) << 40;
4308  value|=(MagickSizeType) (*p++) << 48;
4309  value|=(MagickSizeType) (*p++) << 56;
4310  return(value);
4311  }
4312  value=(MagickSizeType) (*p++) << 56;
4313  value|=(MagickSizeType) (*p++) << 48;
4314  value|=(MagickSizeType) (*p++) << 40;
4315  value|=(MagickSizeType) (*p++) << 32;
4316  value|=(MagickSizeType) (*p++) << 24;
4317  value|=(MagickSizeType) (*p++) << 16;
4318  value|=(MagickSizeType) (*p++) << 8;
4319  value|=(MagickSizeType) (*p++);
4320  return(value);
4321 }
4322 ␌
4323 /*
4324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4325 % %
4326 % %
4327 % %
4328 + R e a d B l o b S h o r t %
4329 % %
4330 % %
4331 % %
4332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4333 %
4334 % ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
4335 % specified by the endian member of the image structure.
4336 %
4337 % The format of the ReadBlobShort method is:
4338 %
4339 % unsigned short ReadBlobShort(Image *image)
4340 %
4341 % A description of each parameter follows.
4342 %
4343 % o image: the image.
4344 %
4345 */
4346 MagickExport unsigned short ReadBlobShort(Image *image)
4347 {
4348  const unsigned char
4349  *p;
4350 
4351  unsigned short
4352  value;
4353 
4354  ssize_t
4355  count;
4356 
4357  unsigned char
4358  buffer[2];
4359 
4360  assert(image != (Image *) NULL);
4361  assert(image->signature == MagickCoreSignature);
4362  *buffer='\0';
4363  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4364  if (count != 2)
4365  return((unsigned short) 0U);
4366  if (image->endian == LSBEndian)
4367  {
4368  value=(unsigned short) (*p++);
4369  value|=(unsigned short) (*p++) << 8;
4370  return(value);
4371  }
4372  value=(unsigned short) ((unsigned short) (*p++) << 8);
4373  value|=(unsigned short) (*p++);
4374  return(value);
4375 }
4376 ␌
4377 /*
4378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4379 % %
4380 % %
4381 % %
4382 + R e a d B l o b L S B L o n g %
4383 % %
4384 % %
4385 % %
4386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4387 %
4388 % ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
4389 % least-significant byte first order.
4390 %
4391 % The format of the ReadBlobLSBLong method is:
4392 %
4393 % unsigned int ReadBlobLSBLong(Image *image)
4394 %
4395 % A description of each parameter follows.
4396 %
4397 % o image: the image.
4398 %
4399 */
4400 MagickExport unsigned int ReadBlobLSBLong(Image *image)
4401 {
4402  const unsigned char
4403  *p;
4404 
4405  unsigned int
4406  value;
4407 
4408  ssize_t
4409  count;
4410 
4411  unsigned char
4412  buffer[4];
4413 
4414  assert(image != (Image *) NULL);
4415  assert(image->signature == MagickCoreSignature);
4416  *buffer='\0';
4417  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4418  if (count != 4)
4419  return(0U);
4420  value=(unsigned int) (*p++);
4421  value|=(unsigned int) (*p++) << 8;
4422  value|=(unsigned int) (*p++) << 16;
4423  value|=(unsigned int) (*p++) << 24;
4424  return(value);
4425 }
4426 ␌
4427 /*
4428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4429 % %
4430 % %
4431 % %
4432 + R e a d B l o b L S B S i g n e d L o n g %
4433 % %
4434 % %
4435 % %
4436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4437 %
4438 % ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
4439 % least-significant byte first order.
4440 %
4441 % The format of the ReadBlobLSBSignedLong method is:
4442 %
4443 % signed int ReadBlobLSBSignedLong(Image *image)
4444 %
4445 % A description of each parameter follows.
4446 %
4447 % o image: the image.
4448 %
4449 */
4450 MagickExport signed int ReadBlobLSBSignedLong(Image *image)
4451 {
4452  union
4453  {
4454  unsigned int
4455  unsigned_value;
4456 
4457  signed int
4458  signed_value;
4459  } quantum;
4460 
4461  quantum.unsigned_value=ReadBlobLSBLong(image);
4462  return(quantum.signed_value);
4463 }
4464 ␌
4465 /*
4466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4467 % %
4468 % %
4469 % %
4470 + R e a d B l o b L S B S h o r t %
4471 % %
4472 % %
4473 % %
4474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4475 %
4476 % ReadBlobLSBShort() reads a short value as a 16-bit quantity in
4477 % least-significant byte first order.
4478 %
4479 % The format of the ReadBlobLSBShort method is:
4480 %
4481 % unsigned short ReadBlobLSBShort(Image *image)
4482 %
4483 % A description of each parameter follows.
4484 %
4485 % o image: the image.
4486 %
4487 */
4488 MagickExport unsigned short ReadBlobLSBShort(Image *image)
4489 {
4490  const unsigned char
4491  *p;
4492 
4493  unsigned short
4494  value;
4495 
4496  ssize_t
4497  count;
4498 
4499  unsigned char
4500  buffer[2];
4501 
4502  assert(image != (Image *) NULL);
4503  assert(image->signature == MagickCoreSignature);
4504  *buffer='\0';
4505  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4506  if (count != 2)
4507  return((unsigned short) 0U);
4508  value=(unsigned short) (*p++);
4509  value|=(unsigned short) (*p++) << 8;
4510  return(value);
4511 }
4512 ␌
4513 /*
4514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4515 % %
4516 % %
4517 % %
4518 + R e a d B l o b L S B S i g n e d S h o r t %
4519 % %
4520 % %
4521 % %
4522 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4523 %
4524 % ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
4525 % least-significant byte-order.
4526 %
4527 % The format of the ReadBlobLSBSignedShort method is:
4528 %
4529 % signed short ReadBlobLSBSignedShort(Image *image)
4530 %
4531 % A description of each parameter follows.
4532 %
4533 % o image: the image.
4534 %
4535 */
4536 MagickExport signed short ReadBlobLSBSignedShort(Image *image)
4537 {
4538  union
4539  {
4540  unsigned short
4541  unsigned_value;
4542 
4543  signed short
4544  signed_value;
4545  } quantum;
4546 
4547  quantum.unsigned_value=ReadBlobLSBShort(image);
4548  return(quantum.signed_value);
4549 }
4550 ␌
4551 /*
4552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4553 % %
4554 % %
4555 % %
4556 + R e a d B l o b M S B L o n g %
4557 % %
4558 % %
4559 % %
4560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4561 %
4562 % ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
4563 % most-significant byte first order.
4564 %
4565 % The format of the ReadBlobMSBLong method is:
4566 %
4567 % unsigned int ReadBlobMSBLong(Image *image)
4568 %
4569 % A description of each parameter follows.
4570 %
4571 % o image: the image.
4572 %
4573 */
4574 MagickExport unsigned int ReadBlobMSBLong(Image *image)
4575 {
4576  const unsigned char
4577  *p;
4578 
4579  unsigned int
4580  value;
4581 
4582  ssize_t
4583  count;
4584 
4585  unsigned char
4586  buffer[4];
4587 
4588  assert(image != (Image *) NULL);
4589  assert(image->signature == MagickCoreSignature);
4590  *buffer='\0';
4591  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4592  if (count != 4)
4593  return(0UL);
4594  value=(unsigned int) (*p++) << 24;
4595  value|=(unsigned int) (*p++) << 16;
4596  value|=(unsigned int) (*p++) << 8;
4597  value|=(unsigned int) (*p++);
4598  return(value);
4599 }
4600 ␌
4601 /*
4602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4603 % %
4604 % %
4605 % %
4606 + R e a d B l o b M S B L o n g L o n g %
4607 % %
4608 % %
4609 % %
4610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4611 %
4612 % ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
4613 % in most-significant byte first order.
4614 %
4615 % The format of the ReadBlobMSBLongLong method is:
4616 %
4617 % unsigned int ReadBlobMSBLongLong(Image *image)
4618 %
4619 % A description of each parameter follows.
4620 %
4621 % o image: the image.
4622 %
4623 */
4624 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
4625 {
4626  const unsigned char
4627  *p;
4628 
4629  MagickSizeType
4630  value;
4631 
4632  ssize_t
4633  count;
4634 
4635  unsigned char
4636  buffer[8];
4637 
4638  assert(image != (Image *) NULL);
4639  assert(image->signature == MagickCoreSignature);
4640  *buffer='\0';
4641  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4642  if (count != 8)
4643  return(MagickULLConstant(0));
4644  value=(MagickSizeType) (*p++) << 56;
4645  value|=(MagickSizeType) (*p++) << 48;
4646  value|=(MagickSizeType) (*p++) << 40;
4647  value|=(MagickSizeType) (*p++) << 32;
4648  value|=(MagickSizeType) (*p++) << 24;
4649  value|=(MagickSizeType) (*p++) << 16;
4650  value|=(MagickSizeType) (*p++) << 8;
4651  value|=(MagickSizeType) (*p++);
4652  return(value);
4653 }
4654 ␌
4655 /*
4656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4657 % %
4658 % %
4659 % %
4660 + R e a d B l o b M S B S h o r t %
4661 % %
4662 % %
4663 % %
4664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4665 %
4666 % ReadBlobMSBShort() reads a short value as a 16-bit quantity in
4667 % most-significant byte first order.
4668 %
4669 % The format of the ReadBlobMSBShort method is:
4670 %
4671 % unsigned short ReadBlobMSBShort(Image *image)
4672 %
4673 % A description of each parameter follows.
4674 %
4675 % o image: the image.
4676 %
4677 */
4678 MagickExport unsigned short ReadBlobMSBShort(Image *image)
4679 {
4680  const unsigned char
4681  *p;
4682 
4683  unsigned short
4684  value;
4685 
4686  ssize_t
4687  count;
4688 
4689  unsigned char
4690  buffer[2];
4691 
4692  assert(image != (Image *) NULL);
4693  assert(image->signature == MagickCoreSignature);
4694  *buffer='\0';
4695  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4696  if (count != 2)
4697  return((unsigned short) 0U);
4698  value=(unsigned short) ((*p++) << 8);
4699  value|=(unsigned short) (*p++);
4700  return((unsigned short) (value & 0xffff));
4701 }
4702 ␌
4703 /*
4704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4705 % %
4706 % %
4707 % %
4708 + R e a d B l o b M S B S i g n e d L o n g %
4709 % %
4710 % %
4711 % %
4712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4713 %
4714 % ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4715 % most-significant byte-order.
4716 %
4717 % The format of the ReadBlobMSBSignedLong method is:
4718 %
4719 % signed int ReadBlobMSBSignedLong(Image *image)
4720 %
4721 % A description of each parameter follows.
4722 %
4723 % o image: the image.
4724 %
4725 */
4726 MagickExport signed int ReadBlobMSBSignedLong(Image *image)
4727 {
4728  union
4729  {
4730  unsigned int
4731  unsigned_value;
4732 
4733  signed int
4734  signed_value;
4735  } quantum;
4736 
4737  quantum.unsigned_value=ReadBlobMSBLong(image);
4738  return(quantum.signed_value);
4739 }
4740 ␌
4741 /*
4742 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4743 % %
4744 % %
4745 % %
4746 + R e a d B l o b M S B S i g n e d S h o r t %
4747 % %
4748 % %
4749 % %
4750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4751 %
4752 % ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4753 % most-significant byte-order.
4754 %
4755 % The format of the ReadBlobMSBSignedShort method is:
4756 %
4757 % signed short ReadBlobMSBSignedShort(Image *image)
4758 %
4759 % A description of each parameter follows.
4760 %
4761 % o image: the image.
4762 %
4763 */
4764 MagickExport signed short ReadBlobMSBSignedShort(Image *image)
4765 {
4766  union
4767  {
4768  unsigned short
4769  unsigned_value;
4770 
4771  signed short
4772  signed_value;
4773  } quantum;
4774 
4775  quantum.unsigned_value=ReadBlobMSBShort(image);
4776  return(quantum.signed_value);
4777 }
4778 ␌
4779 /*
4780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4781 % %
4782 % %
4783 % %
4784 + R e a d B l o b S i g n e d L o n g %
4785 % %
4786 % %
4787 % %
4788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4789 %
4790 % ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4791 % byte-order specified by the endian member of the image structure.
4792 %
4793 % The format of the ReadBlobSignedLong method is:
4794 %
4795 % signed int ReadBlobSignedLong(Image *image)
4796 %
4797 % A description of each parameter follows.
4798 %
4799 % o image: the image.
4800 %
4801 */
4802 MagickExport signed int ReadBlobSignedLong(Image *image)
4803 {
4804  union
4805  {
4806  unsigned int
4807  unsigned_value;
4808 
4809  signed int
4810  signed_value;
4811  } quantum;
4812 
4813  quantum.unsigned_value=ReadBlobLong(image);
4814  return(quantum.signed_value);
4815 }
4816 ␌
4817 /*
4818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4819 % %
4820 % %
4821 % %
4822 + R e a d B l o b S i g n e d S h o r t %
4823 % %
4824 % %
4825 % %
4826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4827 %
4828 % ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4829 % byte-order specified by the endian member of the image structure.
4830 %
4831 % The format of the ReadBlobSignedShort method is:
4832 %
4833 % signed short ReadBlobSignedShort(Image *image)
4834 %
4835 % A description of each parameter follows.
4836 %
4837 % o image: the image.
4838 %
4839 */
4840 MagickExport signed short ReadBlobSignedShort(Image *image)
4841 {
4842  union
4843  {
4844  unsigned short
4845  unsigned_value;
4846 
4847  signed short
4848  signed_value;
4849  } quantum;
4850 
4851  quantum.unsigned_value=ReadBlobShort(image);
4852  return(quantum.signed_value);
4853 }
4854 ␌
4855 /*
4856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4857 % %
4858 % %
4859 % %
4860 + R e a d B l o b S t r e a m %
4861 % %
4862 % %
4863 % %
4864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4865 %
4866 % ReadBlobStream() reads data from the blob or image file and returns it. It
4867 % returns a pointer to the data buffer you supply or to the image memory
4868 % buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4869 % returns a count of zero and has no other results. If length is greater than
4870 % MAGICK_SSIZE_MAX, the result is unspecified.
4871 %
4872 % The format of the ReadBlobStream method is:
4873 %
4874 % const void *ReadBlobStream(Image *image,const size_t length,
4875 % void *magick_restrict data,ssize_t *count)
4876 %
4877 % A description of each parameter follows:
4878 %
4879 % o image: the image.
4880 %
4881 % o length: Specifies an integer representing the number of bytes to read
4882 % from the file.
4883 %
4884 % o count: returns the number of bytes read.
4885 %
4886 % o data: Specifies an area to place the information requested from the
4887 % file.
4888 %
4889 */
4890 MagickExport magick_hot_spot const void *ReadBlobStream(Image *image,
4891  const size_t length,void *magick_restrict data,ssize_t *count)
4892 {
4893  BlobInfo
4894  *magick_restrict blob_info;
4895 
4896  assert(image != (Image *) NULL);
4897  assert(image->signature == MagickCoreSignature);
4898  assert(image->blob != (BlobInfo *) NULL);
4899  assert(image->blob->type != UndefinedStream);
4900  assert(count != (ssize_t *) NULL);
4901  blob_info=image->blob;
4902  if (blob_info->type != BlobStream)
4903  {
4904  assert(data != NULL);
4905  *count=ReadBlob(image,length,(unsigned char *) data);
4906  return(data);
4907  }
4908  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4909  {
4910  *count=0;
4911  blob_info->eof=MagickTrue;
4912  return(data);
4913  }
4914  data=blob_info->data+blob_info->offset;
4915  *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4916  blob_info->length-blob_info->offset);
4917  blob_info->offset+=(*count);
4918  if (*count != (ssize_t) length)
4919  blob_info->eof=MagickTrue;
4920  return(data);
4921 }
4922 ␌
4923 /*
4924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4925 % %
4926 % %
4927 % %
4928 + R e a d B l o b S t r i n g %
4929 % %
4930 % %
4931 % %
4932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4933 %
4934 % ReadBlobString() reads characters from a blob or file until a newline
4935 % character is read or an end-of-file condition is encountered.
4936 %
4937 % The format of the ReadBlobString method is:
4938 %
4939 % char *ReadBlobString(Image *image,char *string)
4940 %
4941 % A description of each parameter follows:
4942 %
4943 % o image: the image.
4944 %
4945 % o string: the address of a character buffer.
4946 %
4947 */
4948 MagickExport char *ReadBlobString(Image *image,char *string)
4949 {
4950  BlobInfo
4951  *magick_restrict blob_info;
4952 
4953  int
4954  c = -1;
4955 
4956  size_t
4957  i = 0;
4958 
4959  assert(image != (Image *) NULL);
4960  assert(image->signature == MagickCoreSignature);
4961  assert(image->blob != (BlobInfo *) NULL);
4962  assert(image->blob->type != UndefinedStream);
4963  if (IsEventLogging() != MagickFalse)
4964  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4965  *string='\0';
4966  blob_info=image->blob;
4967  switch (blob_info->type)
4968  {
4969  case UndefinedStream:
4970  break;
4971  case StandardStream:
4972  case FileStream:
4973  {
4974  char *p = fgets(string,MagickPathExtent,blob_info->file_info.file);
4975  if (p == (char *) NULL)
4976  {
4977  if (ferror(blob_info->file_info.file) != 0)
4978  ThrowBlobException(blob_info);
4979  return((char *) NULL);
4980  }
4981  i=strlen(string);
4982  break;
4983  }
4984  case ZipStream:
4985  {
4986 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4987  char *p = gzgets(blob_info->file_info.gzfile,string,MagickPathExtent);
4988  if (p == (char *) NULL)
4989  {
4990  int status = Z_OK;
4991  (void) gzerror(blob_info->file_info.gzfile,&status);
4992  if (status != Z_OK)
4993  ThrowBlobException(blob_info);
4994  return((char *) NULL);
4995  }
4996  i=strlen(string);
4997  break;
4998 #endif
4999  }
5000  default:
5001  {
5002  do
5003  {
5004  c=ReadBlobByte(image);
5005  if (c == EOF)
5006  {
5007  blob_info->eof=MagickTrue;
5008  break;
5009  }
5010  string[i++]=(char) c;
5011  if (c == '\n')
5012  break;
5013  } while (i < (MaxTextExtent-2));
5014  string[i]='\0';
5015  break;
5016  }
5017  }
5018  /*
5019  Strip trailing newline.
5020  */
5021  if ((string[i] == '\r') || (string[i] == '\n'))
5022  string[i]='\0';
5023  if (i >= 1)
5024  if ((string[i-1] == '\r') || (string[i-1] == '\n'))
5025  string[i-1]='\0';
5026  if ((*string == '\0') && (blob_info->eof != MagickFalse))
5027  return((char *) NULL);
5028  return(string);
5029 }
5030 ␌
5031 /*
5032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5033 % %
5034 % %
5035 % %
5036 + R e f e r e n c e B l o b %
5037 % %
5038 % %
5039 % %
5040 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5041 %
5042 % ReferenceBlob() increments the reference count associated with the pixel
5043 % blob returning a pointer to the blob.
5044 %
5045 % The format of the ReferenceBlob method is:
5046 %
5047 % BlobInfo ReferenceBlob(BlobInfo *blob_info)
5048 %
5049 % A description of each parameter follows:
5050 %
5051 % o blob_info: the blob_info.
5052 %
5053 */
5054 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
5055 {
5056  assert(blob != (BlobInfo *) NULL);
5057  assert(blob->signature == MagickCoreSignature);
5058  if (IsEventLogging() != MagickFalse)
5059  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5060  LockSemaphoreInfo(blob->semaphore);
5061  blob->reference_count++;
5062  UnlockSemaphoreInfo(blob->semaphore);
5063  return(blob);
5064 }
5065 ␌
5066 /*
5067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5068 % %
5069 % %
5070 % %
5071 + S e e k B l o b %
5072 % %
5073 % %
5074 % %
5075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5076 %
5077 % SeekBlob() sets the offset in bytes from the beginning of a blob or file
5078 % and returns the resulting offset.
5079 %
5080 % The format of the SeekBlob method is:
5081 %
5082 % MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
5083 % const int whence)
5084 %
5085 % A description of each parameter follows:
5086 %
5087 % o image: the image.
5088 %
5089 % o offset: Specifies an integer representing the offset in bytes.
5090 %
5091 % o whence: Specifies an integer representing how the offset is
5092 % treated relative to the beginning of the blob as follows:
5093 %
5094 % SEEK_SET Set position equal to offset bytes.
5095 % SEEK_CUR Set position to current location plus offset.
5096 % SEEK_END Set position to EOF plus offset.
5097 %
5098 */
5099 MagickExport MagickOffsetType SeekBlob(Image *image,
5100  const MagickOffsetType offset,const int whence)
5101 {
5102  BlobInfo
5103  *magick_restrict blob_info;
5104 
5105  assert(image != (Image *) NULL);
5106  assert(image->signature == MagickCoreSignature);
5107  assert(image->blob != (BlobInfo *) NULL);
5108  assert(image->blob->type != UndefinedStream);
5109  if (IsEventLogging() != MagickFalse)
5110  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5111  blob_info=image->blob;
5112  switch (blob_info->type)
5113  {
5114  case UndefinedStream:
5115  break;
5116  case StandardStream:
5117  case PipeStream:
5118  return(-1);
5119  case FileStream:
5120  {
5121  if ((offset < 0) && (whence == SEEK_SET))
5122  return(-1);
5123  if (fseek(blob_info->file_info.file,offset,whence) < 0)
5124  return(-1);
5125  blob_info->offset=TellBlob(image);
5126  break;
5127  }
5128  case ZipStream:
5129  {
5130 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5131  if (gzseek(blob_info->file_info.gzfile,(long) offset,whence) < 0)
5132  return(-1);
5133 #endif
5134  blob_info->offset=TellBlob(image);
5135  break;
5136  }
5137  case BZipStream:
5138  return(-1);
5139  case FifoStream:
5140  return(-1);
5141  case BlobStream:
5142  {
5143  switch (whence)
5144  {
5145  case SEEK_SET:
5146  default:
5147  {
5148  if (offset < 0)
5149  return(-1);
5150  blob_info->offset=offset;
5151  break;
5152  }
5153  case SEEK_CUR:
5154  {
5155  if (((offset > 0) && (blob_info->offset > (MAGICK_SSIZE_MAX-offset))) ||
5156  ((offset < 0) && (blob_info->offset < (MAGICK_SSIZE_MIN-offset))))
5157  {
5158  errno=EOVERFLOW;
5159  return(-1);
5160  }
5161  if ((blob_info->offset+offset) < 0)
5162  return(-1);
5163  blob_info->offset+=offset;
5164  break;
5165  }
5166  case SEEK_END:
5167  {
5168  if (((MagickOffsetType) blob_info->length+offset) < 0)
5169  return(-1);
5170  blob_info->offset=(MagickOffsetType) blob_info->length+offset;
5171  break;
5172  }
5173  }
5174  if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
5175  {
5176  blob_info->eof=MagickFalse;
5177  break;
5178  }
5179  break;
5180  }
5181  case CustomStream:
5182  {
5183  if (blob_info->custom_stream->seeker == (CustomStreamSeeker) NULL)
5184  return(-1);
5185  blob_info->offset=blob_info->custom_stream->seeker(offset,whence,
5186  blob_info->custom_stream->data);
5187  break;
5188  }
5189  }
5190  return(blob_info->offset);
5191 }
5192 ␌
5193 /*
5194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5195 % %
5196 % %
5197 % %
5198 + S e t B l o b E x e m p t %
5199 % %
5200 % %
5201 % %
5202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5203 %
5204 % SetBlobExempt() sets the blob exempt status.
5205 %
5206 % The format of the SetBlobExempt method is:
5207 %
5208 % MagickBooleanType SetBlobExempt(const Image *image,
5209 % const MagickBooleanType exempt)
5210 %
5211 % A description of each parameter follows:
5212 %
5213 % o image: the image.
5214 %
5215 % o exempt: Set to true if this blob is exempt from being closed.
5216 %
5217 */
5218 MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
5219 {
5220  assert(image != (const Image *) NULL);
5221  assert(image->signature == MagickCoreSignature);
5222  if (IsEventLogging() != MagickFalse)
5223  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5224  image->blob->exempt=exempt;
5225 }
5226 ␌
5227 /*
5228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5229 % %
5230 % %
5231 % %
5232 + S e t B l o b E x t e n t %
5233 % %
5234 % %
5235 % %
5236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5237 %
5238 % SetBlobExtent() ensures enough space is allocated for the blob. If the
5239 % method is successful, subsequent writes to bytes in the specified range are
5240 % guaranteed not to fail.
5241 %
5242 % The format of the SetBlobExtent method is:
5243 %
5244 % MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
5245 %
5246 % A description of each parameter follows:
5247 %
5248 % o image: the image.
5249 %
5250 % o extent: the blob maximum extent.
5251 %
5252 */
5253 MagickExport MagickBooleanType SetBlobExtent(Image *image,
5254  const MagickSizeType extent)
5255 {
5256  BlobInfo
5257  *magick_restrict blob_info;
5258 
5259  assert(image != (Image *) NULL);
5260  assert(image->signature == MagickCoreSignature);
5261  assert(image->blob != (BlobInfo *) NULL);
5262  assert(image->blob->type != UndefinedStream);
5263  if (IsEventLogging() != MagickFalse)
5264  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5265  blob_info=image->blob;
5266  switch (blob_info->type)
5267  {
5268  case UndefinedStream:
5269  break;
5270  case StandardStream:
5271  return(MagickFalse);
5272  case FileStream:
5273  {
5274  MagickOffsetType
5275  offset;
5276 
5277  ssize_t
5278  count;
5279 
5280  if (extent != (MagickSizeType) ((off_t) extent))
5281  return(MagickFalse);
5282  offset=SeekBlob(image,0,SEEK_END);
5283  if (offset < 0)
5284  return(MagickFalse);
5285  if ((MagickSizeType) offset >= extent)
5286  break;
5287  offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5288  if (offset < 0)
5289  break;
5290  count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5291  blob_info->file_info.file);
5292 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5293  if (blob_info->synchronize != MagickFalse)
5294  {
5295  int
5296  file;
5297 
5298  file=fileno(blob_info->file_info.file);
5299  if ((file == -1) || (offset < 0))
5300  return(MagickFalse);
5301  (void) posix_fallocate(file,offset,(MagickOffsetType) extent-offset);
5302  }
5303 #endif
5304  offset=SeekBlob(image,offset,SEEK_SET);
5305  if (count != 1)
5306  return(MagickFalse);
5307  break;
5308  }
5309  case PipeStream:
5310  case ZipStream:
5311  return(MagickFalse);
5312  case BZipStream:
5313  return(MagickFalse);
5314  case FifoStream:
5315  return(MagickFalse);
5316  case BlobStream:
5317  {
5318  if (extent != (MagickSizeType) ((size_t) extent))
5319  return(MagickFalse);
5320  if (blob_info->mapped != MagickFalse)
5321  {
5322  MagickOffsetType
5323  offset;
5324 
5325  ssize_t
5326  count;
5327 
5328  (void) UnmapBlob(blob_info->data,blob_info->length);
5329  RelinquishMagickResource(MapResource,blob_info->length);
5330  if (extent != (MagickSizeType) ((off_t) extent))
5331  return(MagickFalse);
5332  offset=SeekBlob(image,0,SEEK_END);
5333  if (offset < 0)
5334  return(MagickFalse);
5335  if ((MagickSizeType) offset >= extent)
5336  break;
5337  offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5338  count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5339  blob_info->file_info.file);
5340 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5341  if (blob_info->synchronize != MagickFalse)
5342  {
5343  int
5344  file;
5345 
5346  file=fileno(blob_info->file_info.file);
5347  if ((file == -1) || (offset < 0))
5348  return(MagickFalse);
5349  (void) posix_fallocate(file,offset,(MagickOffsetType) extent-
5350  offset);
5351  }
5352 #endif
5353  offset=SeekBlob(image,offset,SEEK_SET);
5354  if (count != 1)
5355  return(MagickFalse);
5356  (void) AcquireMagickResource(MapResource,extent);
5357  blob_info->data=(unsigned char*) MapBlob(fileno(
5358  blob_info->file_info.file),WriteMode,0,(size_t) extent);
5359  blob_info->extent=(size_t) extent;
5360  blob_info->length=(size_t) extent;
5361  (void) SyncBlob(image);
5362  break;
5363  }
5364  blob_info->extent=(size_t) extent;
5365  blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
5366  blob_info->extent+1,sizeof(*blob_info->data));
5367  (void) SyncBlob(image);
5368  if (blob_info->data == (unsigned char *) NULL)
5369  {
5370  (void) DetachBlob(blob_info);
5371  return(MagickFalse);
5372  }
5373  break;
5374  }
5375  case CustomStream:
5376  break;
5377  }
5378  return(MagickTrue);
5379 }
5380 ␌
5381 /*
5382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5383 % %
5384 % %
5385 % %
5386 + S e t C u s t o m S t r e a m D a t a %
5387 % %
5388 % %
5389 % %
5390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5391 %
5392 % SetCustomStreamData() sets the stream info data member.
5393 %
5394 % The format of the SetCustomStreamData method is:
5395 %
5396 % void SetCustomStreamData(CustomStreamInfo *custom_stream,void *)
5397 %
5398 % A description of each parameter follows:
5399 %
5400 % o custom_stream: the custom stream info.
5401 %
5402 % o data: an object containing information about the custom stream.
5403 %
5404 */
5405 MagickExport void SetCustomStreamData(CustomStreamInfo *custom_stream,
5406  void *data)
5407 {
5408  assert(custom_stream != (CustomStreamInfo *) NULL);
5409  assert(custom_stream->signature == MagickCoreSignature);
5410  custom_stream->data=data;
5411 }
5412 ␌
5413 /*
5414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5415 % %
5416 % %
5417 % %
5418 + S e t C u s t o m S t r e a m R e a d e r %
5419 % %
5420 % %
5421 % %
5422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5423 %
5424 % SetCustomStreamReader() sets the stream info reader member.
5425 %
5426 % The format of the SetCustomStreamReader method is:
5427 %
5428 % void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5429 % CustomStreamHandler reader)
5430 %
5431 % A description of each parameter follows:
5432 %
5433 % o custom_stream: the custom stream info.
5434 %
5435 % o reader: a function to read from the stream.
5436 %
5437 */
5438 MagickExport void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5439  CustomStreamHandler reader)
5440 {
5441  assert(custom_stream != (CustomStreamInfo *) NULL);
5442  assert(custom_stream->signature == MagickCoreSignature);
5443  custom_stream->reader=reader;
5444 }
5445 ␌
5446 /*
5447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5448 % %
5449 % %
5450 % %
5451 + S e t C u s t o m S t r e a m S e e k e r %
5452 % %
5453 % %
5454 % %
5455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5456 %
5457 % SetCustomStreamSeeker() sets the stream info seeker member.
5458 %
5459 % The format of the SetCustomStreamReader method is:
5460 %
5461 % void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5462 % CustomStreamSeeker seeker)
5463 %
5464 % A description of each parameter follows:
5465 %
5466 % o custom_stream: the custom stream info.
5467 %
5468 % o seeker: a function to seek in the custom stream.
5469 %
5470 */
5471 MagickExport void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5472  CustomStreamSeeker seeker)
5473 {
5474  assert(custom_stream != (CustomStreamInfo *) NULL);
5475  assert(custom_stream->signature == MagickCoreSignature);
5476  custom_stream->seeker=seeker;
5477 }
5478 ␌
5479 /*
5480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5481 % %
5482 % %
5483 % %
5484 + S e t C u s t o m S t r e a m T e l l e r %
5485 % %
5486 % %
5487 % %
5488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5489 %
5490 % SetCustomStreamTeller() sets the stream info teller member.
5491 %
5492 % The format of the SetCustomStreamTeller method is:
5493 %
5494 % void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5495 % CustomStreamTeller *teller)
5496 %
5497 % A description of each parameter follows:
5498 %
5499 % o custom_stream: the custom stream info.
5500 %
5501 % o teller: a function to set the position in the stream.
5502 %
5503 */
5504 MagickExport void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5505  CustomStreamTeller teller)
5506 {
5507  assert(custom_stream != (CustomStreamInfo *) NULL);
5508  assert(custom_stream->signature == MagickCoreSignature);
5509  custom_stream->teller=teller;
5510 }
5511 ␌
5512 /*
5513 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5514 % %
5515 % %
5516 % %
5517 + S e t C u s t o m S t r e a m W r i t e r %
5518 % %
5519 % %
5520 % %
5521 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5522 %
5523 % SetCustomStreamWriter() sets the stream info writer member.
5524 %
5525 % The format of the SetCustomStreamWriter method is:
5526 %
5527 % void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5528 % CustomStreamHandler *writer)
5529 %
5530 % A description of each parameter follows:
5531 %
5532 % o custom_stream: the custom stream info.
5533 %
5534 % o writer: a function to write to the custom stream.
5535 %
5536 */
5537 MagickExport void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5538  CustomStreamHandler writer)
5539 {
5540  assert(custom_stream != (CustomStreamInfo *) NULL);
5541  assert(custom_stream->signature == MagickCoreSignature);
5542  custom_stream->writer=writer;
5543 }
5544 ␌
5545 /*
5546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5547 % %
5548 % %
5549 % %
5550 + S y n c B l o b %
5551 % %
5552 % %
5553 % %
5554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5555 %
5556 % SyncBlob() flushes the datastream if it is a file or synchronizes the data
5557 % attributes if it is an blob. It returns 0 on success; otherwise, it returns
5558 % -1 and set errno to indicate the error.
5559 %
5560 % The format of the SyncBlob method is:
5561 %
5562 % int SyncBlob(const Image *image)
5563 %
5564 % A description of each parameter follows:
5565 %
5566 % o image: the image.
5567 %
5568 */
5569 static int SyncBlob(const Image *image)
5570 {
5571  BlobInfo
5572  *magick_restrict blob_info;
5573 
5574  int
5575  status;
5576 
5577  assert(image != (Image *) NULL);
5578  assert(image->signature == MagickCoreSignature);
5579  assert(image->blob != (BlobInfo *) NULL);
5580  if (IsEventLogging() != MagickFalse)
5581  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5582  if (EOFBlob(image) != 0)
5583  return(0);
5584  blob_info=image->blob;
5585  status=0;
5586  switch (blob_info->type)
5587  {
5588  case UndefinedStream:
5589  case StandardStream:
5590  break;
5591  case FileStream:
5592  case PipeStream:
5593  {
5594  status=fflush(blob_info->file_info.file);
5595  break;
5596  }
5597  case ZipStream:
5598  {
5599 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5600  (void) gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
5601 #endif
5602  break;
5603  }
5604  case BZipStream:
5605  {
5606 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5607  status=BZ2_bzflush(blob_info->file_info.bzfile);
5608 #endif
5609  break;
5610  }
5611  case FifoStream:
5612  break;
5613  case BlobStream:
5614  break;
5615  case CustomStream:
5616  break;
5617  }
5618  return(status);
5619 }
5620 ␌
5621 /*
5622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5623 % %
5624 % %
5625 % %
5626 + T e l l B l o b %
5627 % %
5628 % %
5629 % %
5630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5631 %
5632 % TellBlob() obtains the current value of the blob or file position.
5633 %
5634 % The format of the TellBlob method is:
5635 %
5636 % MagickOffsetType TellBlob(const Image *image)
5637 %
5638 % A description of each parameter follows:
5639 %
5640 % o image: the image.
5641 %
5642 */
5643 MagickExport MagickOffsetType TellBlob(const Image *image)
5644 {
5645  BlobInfo
5646  *magick_restrict blob_info;
5647 
5648  MagickOffsetType
5649  offset;
5650 
5651  assert(image != (Image *) NULL);
5652  assert(image->signature == MagickCoreSignature);
5653  assert(image->blob != (BlobInfo *) NULL);
5654  assert(image->blob->type != UndefinedStream);
5655  if (IsEventLogging() != MagickFalse)
5656  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5657  blob_info=image->blob;
5658  offset=(-1);
5659  switch (blob_info->type)
5660  {
5661  case UndefinedStream:
5662  case StandardStream:
5663  break;
5664  case FileStream:
5665  {
5666  offset=ftell(blob_info->file_info.file);
5667  break;
5668  }
5669  case PipeStream:
5670  break;
5671  case ZipStream:
5672  {
5673 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5674  offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
5675 #endif
5676  break;
5677  }
5678  case BZipStream:
5679  break;
5680  case FifoStream:
5681  break;
5682  case BlobStream:
5683  {
5684  offset=blob_info->offset;
5685  break;
5686  }
5687  case CustomStream:
5688  {
5689  if (blob_info->custom_stream->teller != (CustomStreamTeller) NULL)
5690  offset=blob_info->custom_stream->teller(blob_info->custom_stream->data);
5691  break;
5692  }
5693  }
5694  return(offset);
5695 }
5696 ␌
5697 /*
5698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5699 % %
5700 % %
5701 % %
5702 + U n m a p B l o b %
5703 % %
5704 % %
5705 % %
5706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5707 %
5708 % UnmapBlob() deallocates the binary large object previously allocated with
5709 % the MapBlob method.
5710 %
5711 % The format of the UnmapBlob method is:
5712 %
5713 % MagickBooleanType UnmapBlob(void *map,const size_t length)
5714 %
5715 % A description of each parameter follows:
5716 %
5717 % o map: the address of the binary large object.
5718 %
5719 % o length: the length of the binary large object.
5720 %
5721 */
5722 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
5723 {
5724 #if defined(MAGICKCORE_HAVE_MMAP)
5725  int
5726  status;
5727 
5728  status=munmap(map,length);
5729  return(status == -1 ? MagickFalse : MagickTrue);
5730 #else
5731  (void) map;
5732  (void) length;
5733  return(MagickFalse);
5734 #endif
5735 }
5736 ␌
5737 /*
5738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5739 % %
5740 % %
5741 % %
5742 + W r i t e B l o b %
5743 % %
5744 % %
5745 % %
5746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5747 %
5748 % WriteBlob() writes data to a blob or image file. It returns the number of
5749 % bytes written.
5750 %
5751 % The format of the WriteBlob method is:
5752 %
5753 % ssize_t WriteBlob(Image *image,const size_t length,const void *data)
5754 %
5755 % A description of each parameter follows:
5756 %
5757 % o image: the image.
5758 %
5759 % o length: Specifies an integer representing the number of bytes to
5760 % write to the file.
5761 %
5762 % o data: The address of the data to write to the blob or file.
5763 %
5764 */
5765 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
5766  const void *data)
5767 {
5768  BlobInfo
5769  *magick_restrict blob_info;
5770 
5771  int
5772  c;
5773 
5774  const unsigned char
5775  *p;
5776 
5777  unsigned char
5778  *q;
5779 
5780  ssize_t
5781  count;
5782 
5783  assert(image != (Image *) NULL);
5784  assert(image->signature == MagickCoreSignature);
5785  assert(image->blob != (BlobInfo *) NULL);
5786  assert(image->blob->type != UndefinedStream);
5787  if (length == 0)
5788  return(0);
5789  assert(data != (const void *) NULL);
5790  blob_info=image->blob;
5791  count=0;
5792  p=(const unsigned char *) data;
5793  q=(unsigned char *) data;
5794  switch (blob_info->type)
5795  {
5796  case UndefinedStream:
5797  break;
5798  case StandardStream:
5799  case FileStream:
5800  case PipeStream:
5801  {
5802  switch (length)
5803  {
5804  default:
5805  {
5806  count=(ssize_t) fwrite((const char *) data,1,length,
5807  blob_info->file_info.file);
5808  break;
5809  }
5810  case 4:
5811  {
5812  c=putc((int) *p++,blob_info->file_info.file);
5813  if (c == EOF)
5814  break;
5815  count++;
5816  magick_fallthrough;
5817  }
5818  case 3:
5819  {
5820  c=putc((int) *p++,blob_info->file_info.file);
5821  if (c == EOF)
5822  break;
5823  count++;
5824  magick_fallthrough;
5825  }
5826  case 2:
5827  {
5828  c=putc((int) *p++,blob_info->file_info.file);
5829  if (c == EOF)
5830  break;
5831  count++;
5832  magick_fallthrough;
5833  }
5834  case 1:
5835  {
5836  c=putc((int) *p++,blob_info->file_info.file);
5837  if (c == EOF)
5838  break;
5839  count++;
5840  magick_fallthrough;
5841  }
5842  case 0:
5843  break;
5844  }
5845  if ((count != (ssize_t) length) &&
5846  (ferror(blob_info->file_info.file) != 0))
5847  ThrowBlobException(blob_info);
5848  break;
5849  }
5850  case ZipStream:
5851  {
5852 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5853  int
5854  status;
5855 
5856  switch (length)
5857  {
5858  default:
5859  {
5860  size_t
5861  i;
5862 
5863  for (i=0; i < length; i+=(size_t) count)
5864  {
5865  count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
5866  (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
5867  if (count <= 0)
5868  {
5869  count=0;
5870  if (errno != EINTR)
5871  break;
5872  }
5873  }
5874  count=(ssize_t) i;
5875  break;
5876  }
5877  case 4:
5878  {
5879  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5880  if (c == EOF)
5881  break;
5882  count++;
5883  magick_fallthrough;
5884  }
5885  case 3:
5886  {
5887  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5888  if (c == EOF)
5889  break;
5890  count++;
5891  magick_fallthrough;
5892  }
5893  case 2:
5894  {
5895  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5896  if (c == EOF)
5897  break;
5898  count++;
5899  magick_fallthrough;
5900  }
5901  case 1:
5902  {
5903  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5904  if (c == EOF)
5905  break;
5906  count++;
5907  magick_fallthrough;
5908  }
5909  case 0:
5910  break;
5911  }
5912  status=Z_OK;
5913  (void) gzerror(blob_info->file_info.gzfile,&status);
5914  if ((count != (ssize_t) length) && (status != Z_OK))
5915  ThrowBlobException(blob_info);
5916 #endif
5917  break;
5918  }
5919  case BZipStream:
5920  {
5921 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5922  int
5923  status;
5924 
5925  size_t
5926  i;
5927 
5928  for (i=0; i < length; i+=(size_t) count)
5929  {
5930  count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
5931  (int) MagickMin(length-i,MagickMaxBufferExtent));
5932  if (count <= 0)
5933  {
5934  count=0;
5935  if (errno != EINTR)
5936  break;
5937  }
5938  }
5939  count=(ssize_t) i;
5940  status=BZ_OK;
5941  (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
5942  if ((count != (ssize_t) length) && (status != BZ_OK))
5943  ThrowBlobException(blob_info);
5944 #endif
5945  break;
5946  }
5947  case FifoStream:
5948  {
5949  count=(ssize_t) blob_info->stream(image,data,length);
5950  break;
5951  }
5952  case BlobStream:
5953  {
5954  MagickSizeType
5955  extent;
5956 
5957  if (blob_info->offset > (MagickOffsetType) (MAGICK_SSIZE_MAX-length))
5958  {
5959  errno=EOVERFLOW;
5960  return(0);
5961  }
5962  extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
5963  if (extent >= blob_info->extent)
5964  {
5965  extent+=blob_info->quantum+length;
5966  blob_info->quantum<<=1;
5967  if (SetBlobExtent(image,extent) == MagickFalse)
5968  return(0);
5969  }
5970  q=blob_info->data+blob_info->offset;
5971  (void) memcpy(q,p,length);
5972  blob_info->offset+=(MagickOffsetType) length;
5973  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
5974  blob_info->length=(size_t) blob_info->offset;
5975  count=(ssize_t) length;
5976  break;
5977  }
5978  case CustomStream:
5979  {
5980  if (blob_info->custom_stream->writer != (CustomStreamHandler) NULL)
5981  count=blob_info->custom_stream->writer((unsigned char *) data,
5982  length,blob_info->custom_stream->data);
5983  break;
5984  }
5985  }
5986  return(count);
5987 }
5988 ␌
5989 /*
5990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5991 % %
5992 % %
5993 % %
5994 + W r i t e B l o b B y t e %
5995 % %
5996 % %
5997 % %
5998 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5999 %
6000 % WriteBlobByte() write an integer to a blob. It returns the number of bytes
6001 % written (either 0 or 1);
6002 %
6003 % The format of the WriteBlobByte method is:
6004 %
6005 % ssize_t WriteBlobByte(Image *image,const unsigned char value)
6006 %
6007 % A description of each parameter follows.
6008 %
6009 % o image: the image.
6010 %
6011 % o value: Specifies the value to write.
6012 %
6013 */
6014 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
6015 {
6016  BlobInfo
6017  *magick_restrict blob_info;
6018 
6019  ssize_t
6020  count;
6021 
6022  assert(image != (Image *) NULL);
6023  assert(image->signature == MagickCoreSignature);
6024  assert(image->blob != (BlobInfo *) NULL);
6025  assert(image->blob->type != UndefinedStream);
6026  blob_info=image->blob;
6027  count=0;
6028  switch (blob_info->type)
6029  {
6030  case StandardStream:
6031  case FileStream:
6032  case PipeStream:
6033  {
6034  int
6035  c;
6036 
6037  c=putc((int) value,blob_info->file_info.file);
6038  if (c == EOF)
6039  {
6040  if (ferror(blob_info->file_info.file) != 0)
6041  ThrowBlobException(blob_info);
6042  break;
6043  }
6044  count++;
6045  break;
6046  }
6047  default:
6048  {
6049  count=WriteBlobStream(image,1,&value);
6050  break;
6051  }
6052  }
6053  return(count);
6054 }
6055 ␌
6056 /*
6057 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6058 % %
6059 % %
6060 % %
6061 + W r i t e B l o b F l o a t %
6062 % %
6063 % %
6064 % %
6065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6066 %
6067 % WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
6068 % specified by the endian member of the image structure.
6069 %
6070 % The format of the WriteBlobFloat method is:
6071 %
6072 % ssize_t WriteBlobFloat(Image *image,const float value)
6073 %
6074 % A description of each parameter follows.
6075 %
6076 % o image: the image.
6077 %
6078 % o value: Specifies the value to write.
6079 %
6080 */
6081 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
6082 {
6083  union
6084  {
6085  unsigned int
6086  unsigned_value;
6087 
6088  float
6089  float_value;
6090  } quantum;
6091 
6092  quantum.unsigned_value=0U;
6093  quantum.float_value=value;
6094  return(WriteBlobLong(image,quantum.unsigned_value));
6095 }
6096 ␌
6097 /*
6098 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6099 % %
6100 % %
6101 % %
6102 + W r i t e B l o b L o n g %
6103 % %
6104 % %
6105 % %
6106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6107 %
6108 % WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
6109 % byte-order specified by the endian member of the image structure.
6110 %
6111 % The format of the WriteBlobLong method is:
6112 %
6113 % ssize_t WriteBlobLong(Image *image,const unsigned int value)
6114 %
6115 % A description of each parameter follows.
6116 %
6117 % o image: the image.
6118 %
6119 % o value: Specifies the value to write.
6120 %
6121 */
6122 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
6123 {
6124  unsigned char
6125  buffer[4];
6126 
6127  assert(image != (Image *) NULL);
6128  assert(image->signature == MagickCoreSignature);
6129  if (image->endian == LSBEndian)
6130  {
6131  buffer[0]=(unsigned char) value;
6132  buffer[1]=(unsigned char) (value >> 8);
6133  buffer[2]=(unsigned char) (value >> 16);
6134  buffer[3]=(unsigned char) (value >> 24);
6135  return(WriteBlobStream(image,4,buffer));
6136  }
6137  buffer[0]=(unsigned char) (value >> 24);
6138  buffer[1]=(unsigned char) (value >> 16);
6139  buffer[2]=(unsigned char) (value >> 8);
6140  buffer[3]=(unsigned char) value;
6141  return(WriteBlobStream(image,4,buffer));
6142 }
6143 ␌
6144 /*
6145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6146 % %
6147 % %
6148 % %
6149 + W r i t e B l o b L o n g L o n g %
6150 % %
6151 % %
6152 % %
6153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6154 %
6155 % WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in the
6156 % byte-order specified by the endian member of the image structure.
6157 %
6158 % The format of the WriteBlobLongLong method is:
6159 %
6160 % ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
6161 %
6162 % A description of each parameter follows.
6163 %
6164 % o value: Specifies the value to write.
6165 %
6166 % o image: the image.
6167 %
6168 */
6169 MagickExport ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
6170 {
6171  unsigned char
6172  buffer[8];
6173 
6174  assert(image != (Image *) NULL);
6175  assert(image->signature == MagickCoreSignature);
6176  if (image->endian == LSBEndian)
6177  {
6178  buffer[0]=(unsigned char) value;
6179  buffer[1]=(unsigned char) (value >> 8);
6180  buffer[2]=(unsigned char) (value >> 16);
6181  buffer[3]=(unsigned char) (value >> 24);
6182  buffer[4]=(unsigned char) (value >> 32);
6183  buffer[5]=(unsigned char) (value >> 40);
6184  buffer[6]=(unsigned char) (value >> 48);
6185  buffer[7]=(unsigned char) (value >> 56);
6186  return(WriteBlobStream(image,8,buffer));
6187  }
6188  buffer[0]=(unsigned char) (value >> 56);
6189  buffer[1]=(unsigned char) (value >> 48);
6190  buffer[2]=(unsigned char) (value >> 40);
6191  buffer[3]=(unsigned char) (value >> 32);
6192  buffer[4]=(unsigned char) (value >> 24);
6193  buffer[5]=(unsigned char) (value >> 16);
6194  buffer[6]=(unsigned char) (value >> 8);
6195  buffer[7]=(unsigned char) value;
6196  return(WriteBlobStream(image,8,buffer));
6197 }
6198 ␌
6199 /*
6200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6201 % %
6202 % %
6203 % %
6204 + W r i t e B l o b S h o r t %
6205 % %
6206 % %
6207 % %
6208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6209 %
6210 % WriteBlobShort() writes a short value as a 16-bit quantity in the
6211 % byte-order specified by the endian member of the image structure.
6212 %
6213 % The format of the WriteBlobShort method is:
6214 %
6215 % ssize_t WriteBlobShort(Image *image,const unsigned short value)
6216 %
6217 % A description of each parameter follows.
6218 %
6219 % o image: the image.
6220 %
6221 % o value: Specifies the value to write.
6222 %
6223 */
6224 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
6225 {
6226  unsigned char
6227  buffer[2];
6228 
6229  assert(image != (Image *) NULL);
6230  assert(image->signature == MagickCoreSignature);
6231  if (image->endian == LSBEndian)
6232  {
6233  buffer[0]=(unsigned char) value;
6234  buffer[1]=(unsigned char) (value >> 8);
6235  return(WriteBlobStream(image,2,buffer));
6236  }
6237  buffer[0]=(unsigned char) (value >> 8);
6238  buffer[1]=(unsigned char) value;
6239  return(WriteBlobStream(image,2,buffer));
6240 }
6241 ␌
6242 /*
6243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6244 % %
6245 % %
6246 % %
6247 + W r i t e B l o b S i g n e d L o n g %
6248 % %
6249 % %
6250 % %
6251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6252 %
6253 % WriteBlobSignedLong() writes a signed value as a 32-bit quantity in the
6254 % byte-order specified by the endian member of the image structure.
6255 %
6256 % The format of the WriteBlobSignedLong method is:
6257 %
6258 % ssize_t WriteBlobSignedLong(Image *image,const signed int value)
6259 %
6260 % A description of each parameter follows.
6261 %
6262 % o image: the image.
6263 %
6264 % o value: Specifies the value to write.
6265 %
6266 */
6267 MagickExport ssize_t WriteBlobSignedLong(Image *image,const signed int value)
6268 {
6269  union
6270  {
6271  unsigned int
6272  unsigned_value;
6273 
6274  signed int
6275  signed_value;
6276  } quantum;
6277 
6278  unsigned char
6279  buffer[4];
6280 
6281  assert(image != (Image *) NULL);
6282  assert(image->signature == MagickCoreSignature);
6283  quantum.signed_value=value;
6284  if (image->endian == LSBEndian)
6285  {
6286  buffer[0]=(unsigned char) quantum.unsigned_value;
6287  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6288  buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6289  buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6290  return(WriteBlobStream(image,4,buffer));
6291  }
6292  buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
6293  buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
6294  buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
6295  buffer[3]=(unsigned char) quantum.unsigned_value;
6296  return(WriteBlobStream(image,4,buffer));
6297 }
6298 ␌
6299 /*
6300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6301 % %
6302 % %
6303 % %
6304 + W r i t e B l o b L S B L o n g %
6305 % %
6306 % %
6307 % %
6308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6309 %
6310 % WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
6311 % least-significant byte first order.
6312 %
6313 % The format of the WriteBlobLSBLong method is:
6314 %
6315 % ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6316 %
6317 % A description of each parameter follows.
6318 %
6319 % o image: the image.
6320 %
6321 % o value: Specifies the value to write.
6322 %
6323 */
6324 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6325 {
6326  unsigned char
6327  buffer[4];
6328 
6329  assert(image != (Image *) NULL);
6330  assert(image->signature == MagickCoreSignature);
6331  buffer[0]=(unsigned char) value;
6332  buffer[1]=(unsigned char) (value >> 8);
6333  buffer[2]=(unsigned char) (value >> 16);
6334  buffer[3]=(unsigned char) (value >> 24);
6335  return(WriteBlobStream(image,4,buffer));
6336 }
6337 ␌
6338 /*
6339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6340 % %
6341 % %
6342 % %
6343 + W r i t e B l o b L S B S h o r t %
6344 % %
6345 % %
6346 % %
6347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6348 %
6349 % WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
6350 % least-significant byte first order.
6351 %
6352 % The format of the WriteBlobLSBShort method is:
6353 %
6354 % ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6355 %
6356 % A description of each parameter follows.
6357 %
6358 % o image: the image.
6359 %
6360 % o value: Specifies the value to write.
6361 %
6362 */
6363 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6364 {
6365  unsigned char
6366  buffer[2];
6367 
6368  assert(image != (Image *) NULL);
6369  assert(image->signature == MagickCoreSignature);
6370  buffer[0]=(unsigned char) value;
6371  buffer[1]=(unsigned char) (value >> 8);
6372  return(WriteBlobStream(image,2,buffer));
6373 }
6374 ␌
6375 /*
6376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6377 % %
6378 % %
6379 % %
6380 + W r i t e B l o b L S B S i g n e d L o n g %
6381 % %
6382 % %
6383 % %
6384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6385 %
6386 % WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
6387 % least-significant byte first order.
6388 %
6389 % The format of the WriteBlobLSBSignedLong method is:
6390 %
6391 % ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6392 %
6393 % A description of each parameter follows.
6394 %
6395 % o image: the image.
6396 %
6397 % o value: Specifies the value to write.
6398 %
6399 */
6400 MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6401 {
6402  union
6403  {
6404  unsigned int
6405  unsigned_value;
6406 
6407  signed int
6408  signed_value;
6409  } quantum;
6410 
6411  unsigned char
6412  buffer[4];
6413 
6414  assert(image != (Image *) NULL);
6415  assert(image->signature == MagickCoreSignature);
6416  quantum.signed_value=value;
6417  buffer[0]=(unsigned char) quantum.unsigned_value;
6418  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6419  buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6420  buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6421  return(WriteBlobStream(image,4,buffer));
6422 }
6423 ␌
6424 /*
6425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6426 % %
6427 % %
6428 % %
6429 + W r i t e B l o b L S B S i g n e d S h o r t %
6430 % %
6431 % %
6432 % %
6433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6434 %
6435 % WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
6436 % in least-significant byte first order.
6437 %
6438 % The format of the WriteBlobLSBSignedShort method is:
6439 %
6440 % ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
6441 %
6442 % A description of each parameter follows.
6443 %
6444 % o image: the image.
6445 %
6446 % o value: Specifies the value to write.
6447 %
6448 */
6449 MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
6450  const signed short value)
6451 {
6452  union
6453  {
6454  unsigned short
6455  unsigned_value;
6456 
6457  signed short
6458  signed_value;
6459  } quantum;
6460 
6461  unsigned char
6462  buffer[2];
6463 
6464  assert(image != (Image *) NULL);
6465  assert(image->signature == MagickCoreSignature);
6466  quantum.signed_value=value;
6467  buffer[0]=(unsigned char) quantum.unsigned_value;
6468  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6469  return(WriteBlobStream(image,2,buffer));
6470 }
6471 ␌
6472 /*
6473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6474 % %
6475 % %
6476 % %
6477 + W r i t e B l o b M S B L o n g %
6478 % %
6479 % %
6480 % %
6481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6482 %
6483 % WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
6484 % most-significant byte first order.
6485 %
6486 % The format of the WriteBlobMSBLong method is:
6487 %
6488 % ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6489 %
6490 % A description of each parameter follows.
6491 %
6492 % o value: Specifies the value to write.
6493 %
6494 % o image: the image.
6495 %
6496 */
6497 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6498 {
6499  unsigned char
6500  buffer[4];
6501 
6502  assert(image != (Image *) NULL);
6503  assert(image->signature == MagickCoreSignature);
6504  buffer[0]=(unsigned char) (value >> 24);
6505  buffer[1]=(unsigned char) (value >> 16);
6506  buffer[2]=(unsigned char) (value >> 8);
6507  buffer[3]=(unsigned char) value;
6508  return(WriteBlobStream(image,4,buffer));
6509 }
6510 ␌
6511 /*
6512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6513 % %
6514 % %
6515 % %
6516 + W r i t e B l o b M S B S i g n e d S h o r t %
6517 % %
6518 % %
6519 % %
6520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6521 %
6522 % WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
6523 % in most-significant byte first order.
6524 %
6525 % The format of the WriteBlobMSBSignedShort method is:
6526 %
6527 % ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
6528 %
6529 % A description of each parameter follows.
6530 %
6531 % o image: the image.
6532 %
6533 % o value: Specifies the value to write.
6534 %
6535 */
6536 MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
6537  const signed short value)
6538 {
6539  union
6540  {
6541  unsigned short
6542  unsigned_value;
6543 
6544  signed short
6545  signed_value;
6546  } quantum;
6547 
6548  unsigned char
6549  buffer[2];
6550 
6551  assert(image != (Image *) NULL);
6552  assert(image->signature == MagickCoreSignature);
6553  quantum.signed_value=value;
6554  buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
6555  buffer[1]=(unsigned char) quantum.unsigned_value;
6556  return(WriteBlobStream(image,2,buffer));
6557 }
6558 ␌
6559 /*
6560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6561 % %
6562 % %
6563 % %
6564 + W r i t e B l o b M S B S h o r t %
6565 % %
6566 % %
6567 % %
6568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6569 %
6570 % WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
6571 % most-significant byte first order.
6572 %
6573 % The format of the WriteBlobMSBShort method is:
6574 %
6575 % ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6576 %
6577 % A description of each parameter follows.
6578 %
6579 % o value: Specifies the value to write.
6580 %
6581 % o file: Specifies the file to write the data to.
6582 %
6583 */
6584 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6585 {
6586  unsigned char
6587  buffer[2];
6588 
6589  assert(image != (Image *) NULL);
6590  assert(image->signature == MagickCoreSignature);
6591  buffer[0]=(unsigned char) (value >> 8);
6592  buffer[1]=(unsigned char) value;
6593  return(WriteBlobStream(image,2,buffer));
6594 }
6595 ␌
6596 /*
6597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6598 % %
6599 % %
6600 % %
6601 + W r i t e B l o b S t r i n g %
6602 % %
6603 % %
6604 % %
6605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6606 %
6607 % WriteBlobString() write a string to a blob. It returns the number of
6608 % characters written.
6609 %
6610 % The format of the WriteBlobString method is:
6611 %
6612 % ssize_t WriteBlobString(Image *image,const char *string)
6613 %
6614 % A description of each parameter follows.
6615 %
6616 % o image: the image.
6617 %
6618 % o string: Specifies the string to write.
6619 %
6620 */
6621 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
6622 {
6623  assert(image != (Image *) NULL);
6624  assert(image->signature == MagickCoreSignature);
6625  assert(string != (const char *) NULL);
6626  return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
6627 }
Definition: image.h:132
Definition: blob.c:121