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-2016 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%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
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/image-private.h"
57#include "MagickCore/list.h"
58#include "MagickCore/locale_.h"
59#include "MagickCore/log.h"
60#include "MagickCore/magick.h"
61#include "MagickCore/memory_.h"
62#include "MagickCore/nt-base-private.h"
63#include "MagickCore/option.h"
64#include "MagickCore/policy.h"
65#include "MagickCore/resource_.h"
66#include "MagickCore/semaphore.h"
67#include "MagickCore/string_.h"
68#include "MagickCore/string-private.h"
69#include "MagickCore/token.h"
70#include "MagickCore/utility.h"
71#include "MagickCore/utility-private.h"
72#if defined(MAGICKCORE_ZLIB_DELEGATE)
73#include "zlib.h"
74#endif
75#if defined(MAGICKCORE_BZLIB_DELEGATE)
76#include "bzlib.h"
77#endif
78
79/*
80  Define declarations.
81*/
82#define MagickMaxBlobExtent  (8*8192)
83#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
84# define MAP_ANONYMOUS  MAP_ANON
85#endif
86#if !defined(MAP_FAILED)
87#define MAP_FAILED  ((void *) -1)
88#endif
89#if defined(__OS2__)
90#include <io.h>
91#define _O_BINARY O_BINARY
92#endif
93
94/*
95  Typedef declarations.
96*/
97typedef union FileInfo
98{
99  FILE
100    *file;
101
102#if defined(MAGICKCORE_ZLIB_DELEGATE)
103  gzFile
104    gzfile;
105#endif
106
107#if defined(MAGICKCORE_BZLIB_DELEGATE)
108  BZFILE
109    *bzfile;
110#endif
111} FileInfo;
112
113struct _BlobInfo
114{
115  size_t
116    length,
117    extent,
118    quantum;
119
120  MagickBooleanType
121    mapped,
122    eof;
123
124  MagickOffsetType
125    offset;
126
127  MagickSizeType
128    size;
129
130  MagickBooleanType
131    exempt,
132    immutable,
133    synchronize,
134    status,
135    temporary;
136
137  StreamType
138    type;
139
140  FileInfo
141    file_info;
142
143  struct stat
144    properties;
145
146  StreamHandler
147    stream;
148
149  unsigned char
150    *data;
151
152  MagickBooleanType
153    debug;
154
155  SemaphoreInfo
156    *semaphore;
157
158  ssize_t
159    reference_count;
160
161  size_t
162    signature;
163};
164
165/*
166  Forward declarations.
167*/
168static int
169  SyncBlob(Image *);
170
171/*
172%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173%                                                                             %
174%                                                                             %
175%                                                                             %
176+   A t t a c h B l o b                                                       %
177%                                                                             %
178%                                                                             %
179%                                                                             %
180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181%
182%  AttachBlob() attaches a blob to the BlobInfo structure.
183%
184%  The format of the AttachBlob method is:
185%
186%      void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
187%
188%  A description of each parameter follows:
189%
190%    o blob_info: Specifies a pointer to a BlobInfo structure.
191%
192%    o blob: the address of a character stream in one of the image formats
193%      understood by ImageMagick.
194%
195%    o length: This size_t integer reflects the length in bytes of the blob.
196%
197*/
198MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
199  const size_t length)
200{
201  assert(blob_info != (BlobInfo *) NULL);
202  if (blob_info->debug != MagickFalse)
203    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
204  blob_info->length=length;
205  blob_info->extent=length;
206  blob_info->quantum=(size_t) MagickMaxBlobExtent;
207  blob_info->offset=0;
208  blob_info->type=BlobStream;
209  blob_info->file_info.file=(FILE *) NULL;
210  blob_info->data=(unsigned char *) blob;
211  blob_info->mapped=MagickFalse;
212  blob_info->immutable=MagickTrue;
213}
214
215/*
216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
217%                                                                             %
218%                                                                             %
219%                                                                             %
220+   B l o b T o F i l e                                                       %
221%                                                                             %
222%                                                                             %
223%                                                                             %
224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225%
226%  BlobToFile() writes a blob to a file.  It returns MagickFalse if an error
227%  occurs otherwise MagickTrue.
228%
229%  The format of the BlobToFile method is:
230%
231%       MagickBooleanType BlobToFile(char *filename,const void *blob,
232%         const size_t length,ExceptionInfo *exception)
233%
234%  A description of each parameter follows:
235%
236%    o filename: Write the blob to this file.
237%
238%    o blob: the address of a blob.
239%
240%    o length: This length in bytes of the blob.
241%
242%    o exception: return any errors or warnings in this structure.
243%
244*/
245MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
246  const size_t length,ExceptionInfo *exception)
247{
248  int
249    file;
250
251  register size_t
252    i;
253
254  ssize_t
255    count;
256
257  assert(filename != (const char *) NULL);
258  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
259  assert(blob != (const void *) NULL);
260  if (*filename == '\0')
261    file=AcquireUniqueFileResource(filename);
262  else
263    file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
264  if (file == -1)
265    {
266      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
267      return(MagickFalse);
268    }
269  for (i=0; i < length; i+=count)
270  {
271    count=write(file,(const char *) blob+i,MagickMin(length-i,SSIZE_MAX));
272    if (count <= 0)
273      {
274        count=0;
275        if (errno != EINTR)
276          break;
277      }
278  }
279  file=close(file);
280  if ((file == -1) || (i < length))
281    {
282      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
283      return(MagickFalse);
284    }
285  return(MagickTrue);
286}
287
288/*
289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290%                                                                             %
291%                                                                             %
292%                                                                             %
293%   B l o b T o I m a g e                                                     %
294%                                                                             %
295%                                                                             %
296%                                                                             %
297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
298%
299%  BlobToImage() implements direct to memory image formats.  It returns the
300%  blob as an image.
301%
302%  The format of the BlobToImage method is:
303%
304%      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
305%        const size_t length,ExceptionInfo *exception)
306%
307%  A description of each parameter follows:
308%
309%    o image_info: the image info.
310%
311%    o blob: the address of a character stream in one of the image formats
312%      understood by ImageMagick.
313%
314%    o length: This size_t integer reflects the length in bytes of the blob.
315%
316%    o exception: return any errors or warnings in this structure.
317%
318*/
319MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
320  const size_t length,ExceptionInfo *exception)
321{
322  const MagickInfo
323    *magick_info;
324
325  Image
326    *image;
327
328  ImageInfo
329    *blob_info,
330    *clone_info;
331
332  MagickBooleanType
333    status;
334
335  assert(image_info != (ImageInfo *) NULL);
336  assert(image_info->signature == MagickCoreSignature);
337  if (image_info->debug != MagickFalse)
338    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
339      image_info->filename);
340  assert(exception != (ExceptionInfo *) NULL);
341  if ((blob == (const void *) NULL) || (length == 0))
342    {
343      (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
344        "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
345      return((Image *) NULL);
346    }
347  blob_info=CloneImageInfo(image_info);
348  blob_info->blob=(void *) blob;
349  blob_info->length=length;
350  if (*blob_info->magick == '\0')
351    (void) SetImageInfo(blob_info,0,exception);
352  magick_info=GetMagickInfo(blob_info->magick,exception);
353  if (magick_info == (const MagickInfo *) NULL)
354    {
355      (void) ThrowMagickException(exception,GetMagickModule(),
356        MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
357        blob_info->magick);
358      blob_info=DestroyImageInfo(blob_info);
359      return((Image *) NULL);
360    }
361  if (GetMagickBlobSupport(magick_info) != MagickFalse)
362    {
363      /*
364        Native blob support for this image format.
365      */
366      (void) CopyMagickString(blob_info->filename,image_info->filename,
367        MagickPathExtent);
368      (void) CopyMagickString(blob_info->magick,image_info->magick,
369        MagickPathExtent);
370      image=ReadImage(blob_info,exception);
371      if (image != (Image *) NULL)
372        (void) DetachBlob(image->blob);
373      blob_info=DestroyImageInfo(blob_info);
374      return(image);
375    }
376  /*
377    Write blob to a temporary file on disk.
378  */
379  blob_info->blob=(void *) NULL;
380  blob_info->length=0;
381  *blob_info->filename='\0';
382  status=BlobToFile(blob_info->filename,blob,length,exception);
383  if (status == MagickFalse)
384    {
385      (void) RelinquishUniqueFileResource(blob_info->filename);
386      blob_info=DestroyImageInfo(blob_info);
387      return((Image *) NULL);
388    }
389  clone_info=CloneImageInfo(blob_info);
390  (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
391    blob_info->magick,blob_info->filename);
392  image=ReadImage(clone_info,exception);
393  if (image != (Image *) NULL)
394    {
395      Image
396        *images;
397
398      /*
399        Restore original filenames and image format.
400      */
401      for (images=GetFirstImageInList(image); images != (Image *) NULL; )
402      {
403        (void) CopyMagickString(images->filename,image_info->filename,
404          MagickPathExtent);
405        (void) CopyMagickString(images->magick_filename,image_info->filename,
406          MagickPathExtent);
407        (void) CopyMagickString(images->magick,magick_info->name,
408          MagickPathExtent);
409        images=GetNextImageInList(images);
410      }
411    }
412  clone_info=DestroyImageInfo(clone_info);
413  (void) RelinquishUniqueFileResource(blob_info->filename);
414  blob_info=DestroyImageInfo(blob_info);
415  return(image);
416}
417
418/*
419%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420%                                                                             %
421%                                                                             %
422%                                                                             %
423+   C l o n e B l o b I n f o                                                 %
424%                                                                             %
425%                                                                             %
426%                                                                             %
427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
428%
429%  CloneBlobInfo() makes a duplicate of the given blob info structure, or if
430%  blob info is NULL, a new one.
431%
432%  The format of the CloneBlobInfo method is:
433%
434%      BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
435%
436%  A description of each parameter follows:
437%
438%    o blob_info: the blob info.
439%
440*/
441MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
442{
443  BlobInfo
444    *clone_info;
445
446  clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
447  if (clone_info == (BlobInfo *) NULL)
448    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
449  GetBlobInfo(clone_info);
450  if (blob_info == (BlobInfo *) NULL)
451    return(clone_info);
452  clone_info->length=blob_info->length;
453  clone_info->extent=blob_info->extent;
454  clone_info->synchronize=blob_info->synchronize;
455  clone_info->quantum=blob_info->quantum;
456  clone_info->mapped=blob_info->mapped;
457  clone_info->eof=blob_info->eof;
458  clone_info->offset=blob_info->offset;
459  clone_info->size=blob_info->size;
460  clone_info->exempt=blob_info->exempt;
461  clone_info->immutable=blob_info->immutable;
462  clone_info->status=blob_info->status;
463  clone_info->temporary=blob_info->temporary;
464  clone_info->type=blob_info->type;
465  clone_info->file_info.file=blob_info->file_info.file;
466  clone_info->properties=blob_info->properties;
467  clone_info->stream=blob_info->stream;
468  clone_info->data=blob_info->data;
469  clone_info->debug=IsEventLogging();
470  clone_info->reference_count=1;
471  return(clone_info);
472}
473
474/*
475%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
476%                                                                             %
477%                                                                             %
478%                                                                             %
479+   C l o s e B l o b                                                         %
480%                                                                             %
481%                                                                             %
482%                                                                             %
483%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484%
485%  CloseBlob() closes a stream associated with the image.
486%
487%  The format of the CloseBlob method is:
488%
489%      MagickBooleanType CloseBlob(Image *image)
490%
491%  A description of each parameter follows:
492%
493%    o image: the image.
494%
495*/
496MagickExport MagickBooleanType CloseBlob(Image *image)
497{
498  int
499    status;
500
501  /*
502    Close image file.
503  */
504  assert(image != (Image *) NULL);
505  assert(image->signature == MagickCoreSignature);
506  if (image->debug != MagickFalse)
507    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
508  assert(image->blob != (BlobInfo *) NULL);
509  if (image->blob->type == UndefinedStream)
510    return(MagickTrue);
511  status=SyncBlob(image);
512  switch (image->blob->type)
513  {
514    case UndefinedStream:
515    case StandardStream:
516      break;
517    case FileStream:
518    case PipeStream:
519    {
520      if (image->blob->synchronize != MagickFalse)
521        status=fsync(fileno(image->blob->file_info.file));
522      status=ferror(image->blob->file_info.file);
523      break;
524    }
525    case ZipStream:
526    {
527#if defined(MAGICKCORE_ZLIB_DELEGATE)
528      (void) gzerror(image->blob->file_info.gzfile,&status);
529#endif
530      break;
531    }
532    case BZipStream:
533    {
534#if defined(MAGICKCORE_BZLIB_DELEGATE)
535      (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
536#endif
537      break;
538    }
539    case FifoStream:
540      break;
541    case BlobStream:
542    {
543      if ((image->blob->file_info.file != (FILE *) NULL) &&
544          (image->blob->synchronize != MagickFalse))
545        {
546          (void) fsync(fileno(image->blob->file_info.file));
547          status=ferror(image->blob->file_info.file);
548        }
549      break;
550    }
551  }
552  image->blob->status=status < 0 ? MagickTrue : MagickFalse;
553  image->blob->size=GetBlobSize(image);
554  image->extent=image->blob->size;
555  image->blob->eof=MagickFalse;
556  if (image->blob->exempt != MagickFalse)
557    {
558      image->blob->type=UndefinedStream;
559      return(image->blob->status);
560    }
561  switch (image->blob->type)
562  {
563    case UndefinedStream:
564    case StandardStream:
565      break;
566    case FileStream:
567    {
568      status=fclose(image->blob->file_info.file);
569      break;
570    }
571    case PipeStream:
572    {
573#if defined(MAGICKCORE_HAVE_PCLOSE)
574      status=pclose(image->blob->file_info.file);
575#endif
576      break;
577    }
578    case ZipStream:
579    {
580#if defined(MAGICKCORE_ZLIB_DELEGATE)
581      status=gzclose(image->blob->file_info.gzfile);
582#endif
583      break;
584    }
585    case BZipStream:
586    {
587#if defined(MAGICKCORE_BZLIB_DELEGATE)
588      BZ2_bzclose(image->blob->file_info.bzfile);
589#endif
590      break;
591    }
592    case FifoStream:
593      break;
594    case BlobStream:
595    {
596      if (image->blob->file_info.file != (FILE *) NULL)
597        status=fclose(image->blob->file_info.file);
598      break;
599    }
600  }
601  (void) DetachBlob(image->blob);
602  image->blob->status=status < 0 ? MagickTrue : MagickFalse;
603  return(image->blob->status);
604}
605
606/*
607%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608%                                                                             %
609%                                                                             %
610%                                                                             %
611+   D e s t r o y B l o b                                                     %
612%                                                                             %
613%                                                                             %
614%                                                                             %
615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616%
617%  DestroyBlob() deallocates memory associated with a blob.
618%
619%  The format of the DestroyBlob method is:
620%
621%      void DestroyBlob(Image *image)
622%
623%  A description of each parameter follows:
624%
625%    o image: the image.
626%
627*/
628MagickExport void DestroyBlob(Image *image)
629{
630  MagickBooleanType
631    destroy;
632
633  assert(image != (Image *) NULL);
634  assert(image->signature == MagickCoreSignature);
635  if (image->debug != MagickFalse)
636    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
637  assert(image->blob != (BlobInfo *) NULL);
638  assert(image->blob->signature == MagickCoreSignature);
639  destroy=MagickFalse;
640  LockSemaphoreInfo(image->blob->semaphore);
641  image->blob->reference_count--;
642  assert(image->blob->reference_count >= 0);
643  if (image->blob->reference_count == 0)
644    destroy=MagickTrue;
645  UnlockSemaphoreInfo(image->blob->semaphore);
646  if (destroy == MagickFalse)
647    return;
648  (void) CloseBlob(image);
649  if (image->blob->mapped != MagickFalse)
650    {
651      (void) UnmapBlob(image->blob->data,image->blob->length);
652      RelinquishMagickResource(MapResource,image->blob->length);
653    }
654  if (image->blob->semaphore != (SemaphoreInfo *) NULL)
655    RelinquishSemaphoreInfo(&image->blob->semaphore);
656  image->blob->signature=(~MagickCoreSignature);
657  image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
658}
659
660/*
661%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
662%                                                                             %
663%                                                                             %
664%                                                                             %
665+   D e t a c h B l o b                                                       %
666%                                                                             %
667%                                                                             %
668%                                                                             %
669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670%
671%  DetachBlob() detaches a blob from the BlobInfo structure.
672%
673%  The format of the DetachBlob method is:
674%
675%      void *DetachBlob(BlobInfo *blob_info)
676%
677%  A description of each parameter follows:
678%
679%    o blob_info: Specifies a pointer to a BlobInfo structure.
680%
681*/
682MagickExport void *DetachBlob(BlobInfo *blob_info)
683{
684  void
685    *data;
686
687  assert(blob_info != (BlobInfo *) NULL);
688  if (blob_info->debug != MagickFalse)
689    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
690  if (blob_info->mapped != MagickFalse)
691    {
692      (void) UnmapBlob(blob_info->data,blob_info->length);
693      blob_info->data=(unsigned char *) NULL;
694      RelinquishMagickResource(MapResource,blob_info->length);
695    }
696  blob_info->mapped=MagickFalse;
697  blob_info->length=0;
698  blob_info->offset=0;
699  blob_info->eof=MagickFalse;
700  blob_info->exempt=MagickFalse;
701  blob_info->immutable=MagickFalse;
702  blob_info->type=UndefinedStream;
703  blob_info->file_info.file=(FILE *) NULL;
704  data=blob_info->data;
705  blob_info->data=(unsigned char *) NULL;
706  blob_info->stream=(StreamHandler) NULL;
707  return(data);
708}
709
710/*
711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712%                                                                             %
713%                                                                             %
714%                                                                             %
715+   D i s a s s o c i a t e B l o b                                           %
716%                                                                             %
717%                                                                             %
718%                                                                             %
719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720%
721%  DisassociateBlob() disassociates the image stream.  It checks if the
722%  blob of the specified image is referenced by other images. If the reference
723%  count is higher then 1 a new blob is assigned to the specified image.
724%
725%  The format of the DisassociateBlob method is:
726%
727%      void DisassociateBlob(const Image *image)
728%
729%  A description of each parameter follows:
730%
731%    o image: the image.
732%
733*/
734MagickExport void DisassociateBlob(Image *image)
735{
736  BlobInfo
737    *blob;
738
739  MagickBooleanType
740    clone;
741
742  assert(image != (Image *) NULL);
743  assert(image->signature == MagickCoreSignature);
744  if (image->debug != MagickFalse)
745    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
746  assert(image->blob != (BlobInfo *) NULL);
747  assert(image->blob->signature == MagickCoreSignature);
748  clone=MagickFalse;
749  LockSemaphoreInfo(image->blob->semaphore);
750  assert(image->blob->reference_count >= 0);
751  if (image->blob->reference_count > 1)
752    clone=MagickTrue;
753  UnlockSemaphoreInfo(image->blob->semaphore);
754  if (clone == MagickFalse)
755    return;
756  blob=CloneBlobInfo(image->blob);
757  DestroyBlob(image);
758  image->blob=blob;
759}
760
761/*
762%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
763%                                                                             %
764%                                                                             %
765%                                                                             %
766+  D i s c a r d B l o b B y t e s                                            %
767%                                                                             %
768%                                                                             %
769%                                                                             %
770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
771%
772%  DiscardBlobBytes() discards bytes in a blob.
773%
774%  The format of the DiscardBlobBytes method is:
775%
776%      MagickBooleanType DiscardBlobBytes(Image *image,
777%        const MagickSizeType length)
778%
779%  A description of each parameter follows.
780%
781%    o image: the image.
782%
783%    o length:  the number of bytes to skip.
784%
785*/
786MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
787  const MagickSizeType length)
788{
789  register MagickOffsetType
790    i;
791
792  size_t
793    quantum;
794
795  ssize_t
796    count;
797
798  unsigned char
799    buffer[16384];
800
801  assert(image != (Image *) NULL);
802  assert(image->signature == MagickCoreSignature);
803  if (length != (MagickSizeType) ((MagickOffsetType) length))
804    return(MagickFalse);
805  count=0;
806  for (i=0; i < (MagickOffsetType) length; i+=count)
807  {
808    quantum=(size_t) MagickMin(length-i,sizeof(buffer));
809    (void) ReadBlobStream(image,quantum,buffer,&count);
810    if (count <= 0)
811      {
812        count=0;
813        if (errno != EINTR)
814          break;
815      }
816  }
817  return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
818}
819
820/*
821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822%                                                                             %
823%                                                                             %
824%                                                                             %
825+   D u p l i c a t e s B l o b                                               %
826%                                                                             %
827%                                                                             %
828%                                                                             %
829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830%
831%  DuplicateBlob() duplicates a blob descriptor.
832%
833%  The format of the DuplicateBlob method is:
834%
835%      void DuplicateBlob(Image *image,const Image *duplicate)
836%
837%  A description of each parameter follows:
838%
839%    o image: the image.
840%
841%    o duplicate: the duplicate image.
842%
843*/
844MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
845{
846  assert(image != (Image *) NULL);
847  assert(image->signature == MagickCoreSignature);
848  if (image->debug != MagickFalse)
849    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
850  assert(duplicate != (Image *) NULL);
851  assert(duplicate->signature == MagickCoreSignature);
852  DestroyBlob(image);
853  image->blob=ReferenceBlob(duplicate->blob);
854}
855
856/*
857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
858%                                                                             %
859%                                                                             %
860%                                                                             %
861+  E O F B l o b                                                              %
862%                                                                             %
863%                                                                             %
864%                                                                             %
865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866%
867%  EOFBlob() returns a non-zero value when EOF has been detected reading from
868%  a blob or file.
869%
870%  The format of the EOFBlob method is:
871%
872%      int EOFBlob(const Image *image)
873%
874%  A description of each parameter follows:
875%
876%    o image: the image.
877%
878*/
879MagickExport int EOFBlob(const Image *image)
880{
881  assert(image != (Image *) NULL);
882  assert(image->signature == MagickCoreSignature);
883  if (image->debug != MagickFalse)
884    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
885  assert(image->blob != (BlobInfo *) NULL);
886  assert(image->blob->type != UndefinedStream);
887  switch (image->blob->type)
888  {
889    case UndefinedStream:
890    case StandardStream:
891      break;
892    case FileStream:
893    case PipeStream:
894    {
895      image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
896        MagickFalse;
897      break;
898    }
899    case ZipStream:
900    {
901      image->blob->eof=MagickFalse;
902      break;
903    }
904    case BZipStream:
905    {
906#if defined(MAGICKCORE_BZLIB_DELEGATE)
907      int
908        status;
909
910      status=0;
911      (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
912      image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
913#endif
914      break;
915    }
916    case FifoStream:
917    {
918      image->blob->eof=MagickFalse;
919      break;
920    }
921    case BlobStream:
922      break;
923  }
924  return((int) image->blob->eof);
925}
926
927/*
928%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
929%                                                                             %
930%                                                                             %
931%                                                                             %
932%   F i l e T o B l o b                                                       %
933%                                                                             %
934%                                                                             %
935%                                                                             %
936%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
937%
938%  FileToBlob() returns the contents of a file as a buffer terminated with
939%  the '\0' character.  The length of the buffer (not including the extra
940%  terminating '\0' character) is returned via the 'length' parameter.  Free
941%  the buffer with RelinquishMagickMemory().
942%
943%  The format of the FileToBlob method is:
944%
945%      void *FileToBlob(const char *filename,const size_t extent,
946%        size_t *length,ExceptionInfo *exception)
947%
948%  A description of each parameter follows:
949%
950%    o blob:  FileToBlob() returns the contents of a file as a blob.  If
951%      an error occurs NULL is returned.
952%
953%    o filename: the filename.
954%
955%    o extent:  The maximum length of the blob.
956%
957%    o length: On return, this reflects the actual length of the blob.
958%
959%    o exception: return any errors or warnings in this structure.
960%
961*/
962MagickExport void *FileToBlob(const char *filename,const size_t extent,
963  size_t *length,ExceptionInfo *exception)
964{
965  int
966    file;
967
968  MagickOffsetType
969    offset;
970
971  register size_t
972    i;
973
974  ssize_t
975    count;
976
977  unsigned char
978    *blob;
979
980  void
981    *map;
982
983  assert(filename != (const char *) NULL);
984  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
985  assert(exception != (ExceptionInfo *) NULL);
986  *length=0;
987  file=fileno(stdin);
988  if (LocaleCompare(filename,"-") != 0)
989    file=open_utf8(filename,O_RDONLY | O_BINARY,0);
990  if (file == -1)
991    {
992      ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
993      return(NULL);
994    }
995  offset=(MagickOffsetType) lseek(file,0,SEEK_END);
996  count=0;
997  if ((file == fileno(stdin)) || (offset < 0) ||
998      (offset != (MagickOffsetType) ((ssize_t) offset)))
999    {
1000      size_t
1001        quantum;
1002
1003      struct stat
1004        file_stats;
1005
1006      /*
1007        Stream is not seekable.
1008      */
1009      offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1010      quantum=(size_t) MagickMaxBufferExtent;
1011      if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1012        quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1013      blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1014      for (i=0; blob != (unsigned char *) NULL; i+=count)
1015      {
1016        count=read(file,blob+i,quantum);
1017        if (count <= 0)
1018          {
1019            count=0;
1020            if (errno != EINTR)
1021              break;
1022          }
1023        if (~((size_t) i) < (quantum+1))
1024          {
1025            blob=(unsigned char *) RelinquishMagickMemory(blob);
1026            break;
1027          }
1028        blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1029          sizeof(*blob));
1030        if ((size_t) (i+count) >= extent)
1031          break;
1032      }
1033      if (LocaleCompare(filename,"-") != 0)
1034        file=close(file);
1035      if (blob == (unsigned char *) NULL)
1036        {
1037          (void) ThrowMagickException(exception,GetMagickModule(),
1038            ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1039          return(NULL);
1040        }
1041      if (file == -1)
1042        {
1043          blob=(unsigned char *) RelinquishMagickMemory(blob);
1044          ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1045          return(NULL);
1046        }
1047      *length=(size_t) MagickMin(i+count,extent);
1048      blob[*length]='\0';
1049      return(blob);
1050    }
1051  *length=(size_t) MagickMin(offset,(MagickOffsetType)
1052    MagickMin(extent,SSIZE_MAX));
1053  blob=(unsigned char *) NULL;
1054  if (~(*length) >= (MagickPathExtent-1))
1055    blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
1056      sizeof(*blob));
1057  if (blob == (unsigned char *) NULL)
1058    {
1059      file=close(file);
1060      (void) ThrowMagickException(exception,GetMagickModule(),
1061        ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1062      return(NULL);
1063    }
1064  map=MapBlob(file,ReadMode,0,*length);
1065  if (map != (unsigned char *) NULL)
1066    {
1067      (void) memcpy(blob,map,*length);
1068      (void) UnmapBlob(map,*length);
1069    }
1070  else
1071    {
1072      (void) lseek(file,0,SEEK_SET);
1073      for (i=0; i < *length; i+=count)
1074      {
1075        count=read(file,blob+i,(size_t) MagickMin(*length-i,SSIZE_MAX));
1076        if (count <= 0)
1077          {
1078            count=0;
1079            if (errno != EINTR)
1080              break;
1081          }
1082      }
1083      if (i < *length)
1084        {
1085          file=close(file)-1;
1086          blob=(unsigned char *) RelinquishMagickMemory(blob);
1087          ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1088          return(NULL);
1089        }
1090    }
1091  blob[*length]='\0';
1092  if (LocaleCompare(filename,"-") != 0)
1093    file=close(file);
1094  if (file == -1)
1095    {
1096      blob=(unsigned char *) RelinquishMagickMemory(blob);
1097      ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1098    }
1099  return(blob);
1100}
1101
1102/*
1103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1104%                                                                             %
1105%                                                                             %
1106%                                                                             %
1107%   F i l e T o I m a g e                                                     %
1108%                                                                             %
1109%                                                                             %
1110%                                                                             %
1111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1112%
1113%  FileToImage() write the contents of a file to an image.
1114%
1115%  The format of the FileToImage method is:
1116%
1117%      MagickBooleanType FileToImage(Image *,const char *filename)
1118%
1119%  A description of each parameter follows:
1120%
1121%    o image: the image.
1122%
1123%    o filename: the filename.
1124%
1125*/
1126
1127static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1128  const void *data)
1129{
1130  MagickSizeType
1131    extent;
1132
1133  register unsigned char
1134    *q;
1135
1136  assert(image->blob != (BlobInfo *) NULL);
1137  assert(image->blob->type != UndefinedStream);
1138  assert(data != NULL);
1139  if (image->blob->type != BlobStream)
1140    return(WriteBlob(image,length,(const unsigned char *) data));
1141  extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1142  if (extent >= image->blob->extent)
1143    {
1144      extent=image->blob->extent+image->blob->quantum+length;
1145      image->blob->quantum<<=1;
1146      if (SetBlobExtent(image,extent) == MagickFalse)
1147        return(0);
1148    }
1149  q=image->blob->data+image->blob->offset;
1150  (void) memcpy(q,data,length);
1151  image->blob->offset+=length;
1152  if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1153    image->blob->length=(size_t) image->blob->offset;
1154  return((ssize_t) length);
1155}
1156
1157MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1158  ExceptionInfo *exception)
1159{
1160  int
1161    file;
1162
1163  size_t
1164    length,
1165    quantum;
1166
1167  ssize_t
1168    count;
1169
1170  struct stat
1171    file_stats;
1172
1173  unsigned char
1174    *blob;
1175
1176  assert(image != (const Image *) NULL);
1177  assert(image->signature == MagickCoreSignature);
1178  assert(filename != (const char *) NULL);
1179  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1180  file=fileno(stdin);
1181  if (LocaleCompare(filename,"-") != 0)
1182    file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1183  if (file == -1)
1184    {
1185      ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1186      return(MagickFalse);
1187    }
1188  quantum=(size_t) MagickMaxBufferExtent;
1189  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1190    quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1191  blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1192  if (blob == (unsigned char *) NULL)
1193    {
1194      file=close(file);
1195      ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1196        filename);
1197      return(MagickFalse);
1198    }
1199  for ( ; ; )
1200  {
1201    count=read(file,blob,quantum);
1202    if (count <= 0)
1203      {
1204        count=0;
1205        if (errno != EINTR)
1206          break;
1207      }
1208    length=(size_t) count;
1209    count=WriteBlobStream(image,length,blob);
1210    if (count != (ssize_t) length)
1211      {
1212        ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1213        break;
1214      }
1215  }
1216  file=close(file);
1217  if (file == -1)
1218    ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1219  blob=(unsigned char *) RelinquishMagickMemory(blob);
1220  return(MagickTrue);
1221}
1222
1223/*
1224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1225%                                                                             %
1226%                                                                             %
1227%                                                                             %
1228+   G e t B l o b E r r o r                                                   %
1229%                                                                             %
1230%                                                                             %
1231%                                                                             %
1232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1233%
1234%  GetBlobError() returns MagickTrue if the blob associated with the specified
1235%  image encountered an error.
1236%
1237%  The format of the GetBlobError method is:
1238%
1239%       MagickBooleanType GetBlobError(const Image *image)
1240%
1241%  A description of each parameter follows:
1242%
1243%    o image: the image.
1244%
1245*/
1246MagickExport MagickBooleanType GetBlobError(const Image *image)
1247{
1248  assert(image != (const Image *) NULL);
1249  assert(image->signature == MagickCoreSignature);
1250  if (image->debug != MagickFalse)
1251    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1252  return(image->blob->status);
1253}
1254
1255/*
1256%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1257%                                                                             %
1258%                                                                             %
1259%                                                                             %
1260+   G e t B l o b F i l e H a n d l e                                         %
1261%                                                                             %
1262%                                                                             %
1263%                                                                             %
1264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1265%
1266%  GetBlobFileHandle() returns the file handle associated with the image blob.
1267%
1268%  The format of the GetBlobFile method is:
1269%
1270%      FILE *GetBlobFileHandle(const Image *image)
1271%
1272%  A description of each parameter follows:
1273%
1274%    o image: the image.
1275%
1276*/
1277MagickExport FILE *GetBlobFileHandle(const Image *image)
1278{
1279  assert(image != (const Image *) NULL);
1280  assert(image->signature == MagickCoreSignature);
1281  return(image->blob->file_info.file);
1282}
1283
1284/*
1285%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1286%                                                                             %
1287%                                                                             %
1288%                                                                             %
1289+   G e t B l o b I n f o                                                     %
1290%                                                                             %
1291%                                                                             %
1292%                                                                             %
1293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1294%
1295%  GetBlobInfo() initializes the BlobInfo structure.
1296%
1297%  The format of the GetBlobInfo method is:
1298%
1299%      void GetBlobInfo(BlobInfo *blob_info)
1300%
1301%  A description of each parameter follows:
1302%
1303%    o blob_info: Specifies a pointer to a BlobInfo structure.
1304%
1305*/
1306MagickExport void GetBlobInfo(BlobInfo *blob_info)
1307{
1308  assert(blob_info != (BlobInfo *) NULL);
1309  (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1310  blob_info->type=UndefinedStream;
1311  blob_info->quantum=(size_t) MagickMaxBlobExtent;
1312  blob_info->properties.st_mtime=time((time_t *) NULL);
1313  blob_info->properties.st_ctime=time((time_t *) NULL);
1314  blob_info->debug=IsEventLogging();
1315  blob_info->reference_count=1;
1316  blob_info->semaphore=AcquireSemaphoreInfo();
1317  blob_info->signature=MagickCoreSignature;
1318}
1319
1320/*
1321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1322%                                                                             %
1323%                                                                             %
1324%                                                                             %
1325%  G e t B l o b P r o p e r t i e s                                          %
1326%                                                                             %
1327%                                                                             %
1328%                                                                             %
1329%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1330%
1331%  GetBlobProperties() returns information about an image blob.
1332%
1333%  The format of the GetBlobProperties method is:
1334%
1335%      const struct stat *GetBlobProperties(const Image *image)
1336%
1337%  A description of each parameter follows:
1338%
1339%    o image: the image.
1340%
1341*/
1342MagickExport const struct stat *GetBlobProperties(const Image *image)
1343{
1344  assert(image != (Image *) NULL);
1345  assert(image->signature == MagickCoreSignature);
1346  if (image->debug != MagickFalse)
1347    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1348  return(&image->blob->properties);
1349}
1350
1351/*
1352%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1353%                                                                             %
1354%                                                                             %
1355%                                                                             %
1356+  G e t B l o b S i z e                                                      %
1357%                                                                             %
1358%                                                                             %
1359%                                                                             %
1360%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1361%
1362%  GetBlobSize() returns the current length of the image file or blob; zero is
1363%  returned if the size cannot be determined.
1364%
1365%  The format of the GetBlobSize method is:
1366%
1367%      MagickSizeType GetBlobSize(const Image *image)
1368%
1369%  A description of each parameter follows:
1370%
1371%    o image: the image.
1372%
1373*/
1374MagickExport MagickSizeType GetBlobSize(const Image *image)
1375{
1376  MagickSizeType
1377    extent;
1378
1379  assert(image != (Image *) NULL);
1380  assert(image->signature == MagickCoreSignature);
1381  if (image->debug != MagickFalse)
1382    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1383  assert(image->blob != (BlobInfo *) NULL);
1384  extent=0;
1385  switch (image->blob->type)
1386  {
1387    case UndefinedStream:
1388    {
1389      extent=image->blob->size;
1390      break;
1391    }
1392    case StandardStream:
1393    {
1394      extent=image->blob->size;
1395      break;
1396    }
1397    case FileStream:
1398    {
1399      if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
1400        extent=(MagickSizeType) image->blob->properties.st_size;
1401      break;
1402    }
1403    case PipeStream:
1404    {
1405      extent=image->blob->size;
1406      break;
1407    }
1408    case ZipStream:
1409    case BZipStream:
1410    {
1411      MagickBooleanType
1412        status;
1413
1414      status=GetPathAttributes(image->filename,&image->blob->properties);
1415      if (status != MagickFalse)
1416        extent=(MagickSizeType) image->blob->properties.st_size;
1417      break;
1418    }
1419    case FifoStream:
1420      break;
1421    case BlobStream:
1422    {
1423      extent=(MagickSizeType) image->blob->length;
1424      break;
1425    }
1426  }
1427  return(extent);
1428}
1429
1430/*
1431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1432%                                                                             %
1433%                                                                             %
1434%                                                                             %
1435+   G e t B l o b S t r e a m D a t a                                         %
1436%                                                                             %
1437%                                                                             %
1438%                                                                             %
1439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1440%
1441%  GetBlobStreamData() returns the stream data for the image.
1442%
1443%  The format of the GetBlobStreamData method is:
1444%
1445%      void *GetBlobStreamData(const Image *image)
1446%
1447%  A description of each parameter follows:
1448%
1449%    o image: the image.
1450%
1451*/
1452MagickExport void *GetBlobStreamData(const Image *image)
1453{
1454  assert(image != (const Image *) NULL);
1455  assert(image->signature == MagickCoreSignature);
1456  return(image->blob->data);
1457}
1458
1459/*
1460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1461%                                                                             %
1462%                                                                             %
1463%                                                                             %
1464+   G e t B l o b S t r e a m H a n d l e r                                   %
1465%                                                                             %
1466%                                                                             %
1467%                                                                             %
1468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1469%
1470%  GetBlobStreamHandler() returns the stream handler for the image.
1471%
1472%  The format of the GetBlobStreamHandler method is:
1473%
1474%      StreamHandler GetBlobStreamHandler(const Image *image)
1475%
1476%  A description of each parameter follows:
1477%
1478%    o image: the image.
1479%
1480*/
1481MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
1482{
1483  assert(image != (const Image *) NULL);
1484  assert(image->signature == MagickCoreSignature);
1485  if (image->debug != MagickFalse)
1486    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1487  return(image->blob->stream);
1488}
1489
1490/*
1491%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1492%                                                                             %
1493%                                                                             %
1494%                                                                             %
1495%   I m a g e T o B l o b                                                     %
1496%                                                                             %
1497%                                                                             %
1498%                                                                             %
1499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1500%
1501%  ImageToBlob() implements direct to memory image formats.  It returns the
1502%  image as a formatted blob and its length.  The magick member of the Image
1503%  structure determines the format of the returned blob (GIF, JPEG, PNG,
1504%  etc.).  This method is the equivalent of WriteImage(), but writes the
1505%  formatted "file" to a memory buffer rather than to an actual file.
1506%
1507%  The format of the ImageToBlob method is:
1508%
1509%      void *ImageToBlob(const ImageInfo *image_info,Image *image,
1510%        size_t *length,ExceptionInfo *exception)
1511%
1512%  A description of each parameter follows:
1513%
1514%    o image_info: the image info.
1515%
1516%    o image: the image.
1517%
1518%    o length: return the actual length of the blob.
1519%
1520%    o exception: return any errors or warnings in this structure.
1521%
1522*/
1523MagickExport void *ImageToBlob(const ImageInfo *image_info,
1524  Image *image,size_t *length,ExceptionInfo *exception)
1525{
1526  const MagickInfo
1527    *magick_info;
1528
1529  ImageInfo
1530    *blob_info;
1531
1532  MagickBooleanType
1533    status;
1534
1535  void
1536    *blob;
1537
1538  assert(image_info != (const ImageInfo *) NULL);
1539  assert(image_info->signature == MagickCoreSignature);
1540  if (image_info->debug != MagickFalse)
1541    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1542      image_info->filename);
1543  assert(image != (Image *) NULL);
1544  assert(image->signature == MagickCoreSignature);
1545  assert(exception != (ExceptionInfo *) NULL);
1546  *length=0;
1547  blob=(unsigned char *) NULL;
1548  blob_info=CloneImageInfo(image_info);
1549  blob_info->adjoin=MagickFalse;
1550  (void) SetImageInfo(blob_info,1,exception);
1551  if (*blob_info->magick != '\0')
1552    (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
1553  magick_info=GetMagickInfo(image->magick,exception);
1554  if (magick_info == (const MagickInfo *) NULL)
1555    {
1556      (void) ThrowMagickException(exception,GetMagickModule(),
1557        MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1558        image->magick);
1559      blob_info=DestroyImageInfo(blob_info);
1560      return(blob);
1561    }
1562  (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
1563  if (GetMagickBlobSupport(magick_info) != MagickFalse)
1564    {
1565      /*
1566        Native blob support for this image format.
1567      */
1568      blob_info->length=0;
1569      blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
1570        sizeof(unsigned char));
1571      if (blob_info->blob == NULL)
1572        (void) ThrowMagickException(exception,GetMagickModule(),
1573          ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1574      else
1575        {
1576          (void) CloseBlob(image);
1577          image->blob->exempt=MagickTrue;
1578          *image->filename='\0';
1579          status=WriteImage(blob_info,image,exception);
1580          *length=image->blob->length;
1581          blob=DetachBlob(image->blob);
1582          if (status == MagickFalse)
1583            blob=RelinquishMagickMemory(blob);
1584          else
1585            blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
1586        }
1587    }
1588  else
1589    {
1590      char
1591        unique[MagickPathExtent];
1592
1593      int
1594        file;
1595
1596      /*
1597        Write file to disk in blob image format.
1598      */
1599      file=AcquireUniqueFileResource(unique);
1600      if (file == -1)
1601        {
1602          ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1603            image_info->filename);
1604        }
1605      else
1606        {
1607          blob_info->file=fdopen(file,"wb");
1608          if (blob_info->file != (FILE *) NULL)
1609            {
1610              (void) FormatLocaleString(image->filename,MagickPathExtent,
1611                "%s:%s",image->magick,unique);
1612              status=WriteImage(blob_info,image,exception);
1613              (void) CloseBlob(image);
1614              (void) fclose(blob_info->file);
1615              if (status != MagickFalse)
1616                blob=FileToBlob(unique,~0UL,length,exception);
1617            }
1618          (void) RelinquishUniqueFileResource(unique);
1619        }
1620    }
1621  blob_info=DestroyImageInfo(blob_info);
1622  return(blob);
1623}
1624
1625/*
1626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1627%                                                                             %
1628%                                                                             %
1629%                                                                             %
1630%   I m a g e T o F i l e                                                     %
1631%                                                                             %
1632%                                                                             %
1633%                                                                             %
1634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1635%
1636%  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
1637%  occurs otherwise MagickTrue.
1638%
1639%  The format of the ImageToFile method is:
1640%
1641%       MagickBooleanType ImageToFile(Image *image,char *filename,
1642%         ExceptionInfo *exception)
1643%
1644%  A description of each parameter follows:
1645%
1646%    o image: the image.
1647%
1648%    o filename: Write the image to this file.
1649%
1650%    o exception: return any errors or warnings in this structure.
1651%
1652*/
1653MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1654  ExceptionInfo *exception)
1655{
1656  int
1657    file;
1658
1659  register const unsigned char
1660    *p;
1661
1662  register size_t
1663    i;
1664
1665  size_t
1666    length,
1667    quantum;
1668
1669  ssize_t
1670    count;
1671
1672  struct stat
1673    file_stats;
1674
1675  unsigned char
1676    *buffer;
1677
1678  assert(image != (Image *) NULL);
1679  assert(image->signature == MagickCoreSignature);
1680  assert(image->blob != (BlobInfo *) NULL);
1681  assert(image->blob->type != UndefinedStream);
1682  if (image->debug != MagickFalse)
1683    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1684  assert(filename != (const char *) NULL);
1685  if (*filename == '\0')
1686    file=AcquireUniqueFileResource(filename);
1687  else
1688    if (LocaleCompare(filename,"-") == 0)
1689      file=fileno(stdout);
1690    else
1691      file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1692  if (file == -1)
1693    {
1694      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1695      return(MagickFalse);
1696    }
1697  quantum=(size_t) MagickMaxBufferExtent;
1698  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1699    quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1700  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1701  if (buffer == (unsigned char *) NULL)
1702    {
1703      file=close(file)-1;
1704      (void) ThrowMagickException(exception,GetMagickModule(),
1705        ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1706      return(MagickFalse);
1707    }
1708  length=0;
1709  p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1710  for (i=0; count > 0; )
1711  {
1712    length=(size_t) count;
1713    for (i=0; i < length; i+=count)
1714    {
1715      count=write(file,p+i,(size_t) (length-i));
1716      if (count <= 0)
1717        {
1718          count=0;
1719          if (errno != EINTR)
1720            break;
1721        }
1722    }
1723    if (i < length)
1724      break;
1725    p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1726  }
1727  if (LocaleCompare(filename,"-") != 0)
1728    file=close(file);
1729  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1730  if ((file == -1) || (i < length))
1731    {
1732      if (file != -1)
1733        file=close(file);
1734      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1735      return(MagickFalse);
1736    }
1737  return(MagickTrue);
1738}
1739
1740/*
1741%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1742%                                                                             %
1743%                                                                             %
1744%                                                                             %
1745%   I m a g e s T o B l o b                                                   %
1746%                                                                             %
1747%                                                                             %
1748%                                                                             %
1749%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1750%
1751%  ImagesToBlob() implements direct to memory image formats.  It returns the
1752%  image sequence as a blob and its length.  The magick member of the ImageInfo
1753%  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
1754%
1755%  Note, some image formats do not permit multiple images to the same image
1756%  stream (e.g. JPEG).  in this instance, just the first image of the
1757%  sequence is returned as a blob.
1758%
1759%  The format of the ImagesToBlob method is:
1760%
1761%      void *ImagesToBlob(const ImageInfo *image_info,Image *images,
1762%        size_t *length,ExceptionInfo *exception)
1763%
1764%  A description of each parameter follows:
1765%
1766%    o image_info: the image info.
1767%
1768%    o images: the image list.
1769%
1770%    o length: return the actual length of the blob.
1771%
1772%    o exception: return any errors or warnings in this structure.
1773%
1774*/
1775MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
1776  size_t *length,ExceptionInfo *exception)
1777{
1778  const MagickInfo
1779    *magick_info;
1780
1781  ImageInfo
1782    *blob_info;
1783
1784  MagickBooleanType
1785    status;
1786
1787  void
1788    *blob;
1789
1790  assert(image_info != (const ImageInfo *) NULL);
1791  assert(image_info->signature == MagickCoreSignature);
1792  if (image_info->debug != MagickFalse)
1793    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1794      image_info->filename);
1795  assert(images != (Image *) NULL);
1796  assert(images->signature == MagickCoreSignature);
1797  assert(exception != (ExceptionInfo *) NULL);
1798  *length=0;
1799  blob=(unsigned char *) NULL;
1800  blob_info=CloneImageInfo(image_info);
1801  (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1802    exception);
1803  if (*blob_info->magick != '\0')
1804    (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
1805  magick_info=GetMagickInfo(images->magick,exception);
1806  if (magick_info == (const MagickInfo *) NULL)
1807    {
1808      (void) ThrowMagickException(exception,GetMagickModule(),
1809        MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1810        images->magick);
1811      blob_info=DestroyImageInfo(blob_info);
1812      return(blob);
1813    }
1814  if (GetMagickAdjoin(magick_info) == MagickFalse)
1815    {
1816      blob_info=DestroyImageInfo(blob_info);
1817      return(ImageToBlob(image_info,images,length,exception));
1818    }
1819  (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
1820  if (GetMagickBlobSupport(magick_info) != MagickFalse)
1821    {
1822      /*
1823        Native blob support for this images format.
1824      */
1825      blob_info->length=0;
1826      blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1827        sizeof(unsigned char));
1828      if (blob_info->blob == (void *) NULL)
1829        (void) ThrowMagickException(exception,GetMagickModule(),
1830          ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
1831      else
1832        {
1833          (void) CloseBlob(images);
1834          images->blob->exempt=MagickTrue;
1835          *images->filename='\0';
1836          status=WriteImages(blob_info,images,images->filename,exception);
1837          *length=images->blob->length;
1838          blob=DetachBlob(images->blob);
1839          if (status == MagickFalse)
1840            blob=RelinquishMagickMemory(blob);
1841          else
1842            blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
1843        }
1844    }
1845  else
1846    {
1847      char
1848        filename[MagickPathExtent],
1849        unique[MagickPathExtent];
1850
1851      int
1852        file;
1853
1854      /*
1855        Write file to disk in blob images format.
1856      */
1857      file=AcquireUniqueFileResource(unique);
1858      if (file == -1)
1859        {
1860          ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1861            image_info->filename);
1862        }
1863      else
1864        {
1865          blob_info->file=fdopen(file,"wb");
1866          if (blob_info->file != (FILE *) NULL)
1867            {
1868              (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
1869                images->magick,unique);
1870              status=WriteImages(blob_info,images,filename,exception);
1871              (void) CloseBlob(images);
1872              (void) fclose(blob_info->file);
1873              if (status != MagickFalse)
1874                blob=FileToBlob(unique,~0UL,length,exception);
1875            }
1876          (void) RelinquishUniqueFileResource(unique);
1877        }
1878    }
1879  blob_info=DestroyImageInfo(blob_info);
1880  return(blob);
1881}
1882/*
1883%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1884%                                                                             %
1885%                                                                             %
1886%                                                                             %
1887%   I n j e c t I m a g e B l o b                                             %
1888%                                                                             %
1889%                                                                             %
1890%                                                                             %
1891%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1892%
1893%  InjectImageBlob() injects the image with a copy of itself in the specified
1894%  format (e.g. inject JPEG into a PDF image).
1895%
1896%  The format of the InjectImageBlob method is:
1897%
1898%      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1899%        Image *image,Image *inject_image,const char *format,
1900%        ExceptionInfo *exception)
1901%
1902%  A description of each parameter follows:
1903%
1904%    o image_info: the image info..
1905%
1906%    o image: the image.
1907%
1908%    o inject_image: inject into the image stream.
1909%
1910%    o format: the image format.
1911%
1912%    o exception: return any errors or warnings in this structure.
1913%
1914*/
1915MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1916  Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1917{
1918  char
1919    filename[MagickPathExtent];
1920
1921  FILE
1922    *unique_file;
1923
1924  Image
1925    *byte_image;
1926
1927  ImageInfo
1928    *write_info;
1929
1930  int
1931    file;
1932
1933  MagickBooleanType
1934    status;
1935
1936  register ssize_t
1937    i;
1938
1939  size_t
1940    quantum;
1941
1942  ssize_t
1943    count;
1944
1945  struct stat
1946    file_stats;
1947
1948  unsigned char
1949    *buffer;
1950
1951  /*
1952    Write inject image to a temporary file.
1953  */
1954  assert(image_info != (ImageInfo *) NULL);
1955  assert(image_info->signature == MagickCoreSignature);
1956  assert(image != (Image *) NULL);
1957  assert(image->signature == MagickCoreSignature);
1958  if (image->debug != MagickFalse)
1959    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1960  assert(inject_image != (Image *) NULL);
1961  assert(inject_image->signature == MagickCoreSignature);
1962  assert(exception != (ExceptionInfo *) NULL);
1963  unique_file=(FILE *) NULL;
1964  file=AcquireUniqueFileResource(filename);
1965  if (file != -1)
1966    unique_file=fdopen(file,"wb");
1967  if ((file == -1) || (unique_file == (FILE *) NULL))
1968    {
1969      (void) CopyMagickString(image->filename,filename,MagickPathExtent);
1970      ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1971        image->filename);
1972      return(MagickFalse);
1973    }
1974  byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1975  if (byte_image == (Image *) NULL)
1976    {
1977      (void) fclose(unique_file);
1978      (void) RelinquishUniqueFileResource(filename);
1979      return(MagickFalse);
1980    }
1981  (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",format,
1982    filename);
1983  DestroyBlob(byte_image);
1984  byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1985  write_info=CloneImageInfo(image_info);
1986  SetImageInfoFile(write_info,unique_file);
1987  status=WriteImage(write_info,byte_image,exception);
1988  write_info=DestroyImageInfo(write_info);
1989  byte_image=DestroyImage(byte_image);
1990  (void) fclose(unique_file);
1991  if (status == MagickFalse)
1992    {
1993      (void) RelinquishUniqueFileResource(filename);
1994      return(MagickFalse);
1995    }
1996  /*
1997    Inject into image stream.
1998  */
1999  file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2000  if (file == -1)
2001    {
2002      (void) RelinquishUniqueFileResource(filename);
2003      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2004        image_info->filename);
2005      return(MagickFalse);
2006    }
2007  quantum=(size_t) MagickMaxBufferExtent;
2008  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2009    quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2010  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2011  if (buffer == (unsigned char *) NULL)
2012    {
2013      (void) RelinquishUniqueFileResource(filename);
2014      file=close(file);
2015      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2016        image->filename);
2017    }
2018  for (i=0; ; i+=count)
2019  {
2020    count=read(file,buffer,quantum);
2021    if (count <= 0)
2022      {
2023        count=0;
2024        if (errno != EINTR)
2025          break;
2026      }
2027    status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2028      MagickFalse;
2029  }
2030  file=close(file);
2031  if (file == -1)
2032    ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2033  (void) RelinquishUniqueFileResource(filename);
2034  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2035  return(status);
2036}
2037
2038/*
2039%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2040%                                                                             %
2041%                                                                             %
2042%                                                                             %
2043%   I s B l o b E x e m p t                                                   %
2044%                                                                             %
2045%                                                                             %
2046%                                                                             %
2047%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2048%
2049%  IsBlobExempt() returns true if the blob is exempt.
2050%
2051%  The format of the IsBlobExempt method is:
2052%
2053%       MagickBooleanType IsBlobExempt(const Image *image)
2054%
2055%  A description of each parameter follows:
2056%
2057%    o image: the image.
2058%
2059*/
2060MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2061{
2062  assert(image != (const Image *) NULL);
2063  assert(image->signature == MagickCoreSignature);
2064  if (image->debug != MagickFalse)
2065    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2066  return(image->blob->exempt);
2067}
2068
2069/*
2070%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2071%                                                                             %
2072%                                                                             %
2073%                                                                             %
2074%   I s B l o b S e e k a b l e                                               %
2075%                                                                             %
2076%                                                                             %
2077%                                                                             %
2078%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2079%
2080%  IsBlobSeekable() returns true if the blob is seekable.
2081%
2082%  The format of the IsBlobSeekable method is:
2083%
2084%       MagickBooleanType IsBlobSeekable(const Image *image)
2085%
2086%  A description of each parameter follows:
2087%
2088%    o image: the image.
2089%
2090*/
2091MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2092{
2093  MagickBooleanType
2094    seekable;
2095
2096  assert(image != (const Image *) NULL);
2097  assert(image->signature == MagickCoreSignature);
2098  if (image->debug != MagickFalse)
2099    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2100  switch (image->blob->type)
2101  {
2102    case FileStream:
2103    case BlobStream:
2104    case ZipStream:
2105    {
2106      seekable=MagickTrue;
2107      break;
2108    }
2109    default:
2110    {
2111      seekable=MagickFalse;
2112      break;
2113    }
2114  }
2115  return(seekable);
2116}
2117
2118/*
2119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2120%                                                                             %
2121%                                                                             %
2122%                                                                             %
2123%   I s B l o b T e m p o r a r y                                             %
2124%                                                                             %
2125%                                                                             %
2126%                                                                             %
2127%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2128%
2129%  IsBlobTemporary() returns true if the blob is temporary.
2130%
2131%  The format of the IsBlobTemporary method is:
2132%
2133%       MagickBooleanType IsBlobTemporary(const Image *image)
2134%
2135%  A description of each parameter follows:
2136%
2137%    o image: the image.
2138%
2139*/
2140MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2141{
2142  assert(image != (const Image *) NULL);
2143  assert(image->signature == MagickCoreSignature);
2144  if (image->debug != MagickFalse)
2145    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2146  return(image->blob->temporary);
2147}
2148
2149/*
2150%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2151%                                                                             %
2152%                                                                             %
2153%                                                                             %
2154+  M a p B l o b                                                              %
2155%                                                                             %
2156%                                                                             %
2157%                                                                             %
2158%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2159%
2160%  MapBlob() creates a mapping from a file to a binary large object.
2161%
2162%  The format of the MapBlob method is:
2163%
2164%      void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
2165%        const size_t length)
2166%
2167%  A description of each parameter follows:
2168%
2169%    o file: map this file descriptor.
2170%
2171%    o mode: ReadMode, WriteMode, or IOMode.
2172%
2173%    o offset: starting at this offset within the file.
2174%
2175%    o length: the length of the mapping is returned in this pointer.
2176%
2177*/
2178MagickExport void *MapBlob(int file,const MapMode mode,
2179  const MagickOffsetType offset,const size_t length)
2180{
2181#if defined(MAGICKCORE_HAVE_MMAP)
2182  int
2183    flags,
2184    protection;
2185
2186  void
2187    *map;
2188
2189  /*
2190    Map file.
2191  */
2192  flags=0;
2193  if (file == -1)
2194#if defined(MAP_ANONYMOUS)
2195    flags|=MAP_ANONYMOUS;
2196#else
2197    return(NULL);
2198#endif
2199  switch (mode)
2200  {
2201    case ReadMode:
2202    default:
2203    {
2204      protection=PROT_READ;
2205      flags|=MAP_PRIVATE;
2206      break;
2207    }
2208    case WriteMode:
2209    {
2210      protection=PROT_WRITE;
2211      flags|=MAP_SHARED;
2212      break;
2213    }
2214    case IOMode:
2215    {
2216      protection=PROT_READ | PROT_WRITE;
2217      flags|=MAP_SHARED;
2218      break;
2219    }
2220  }
2221#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2222  map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
2223#else
2224  map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,(off_t)
2225    offset);
2226  if (map == MAP_FAILED)
2227    map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
2228#endif
2229  if (map == MAP_FAILED)
2230    return(NULL);
2231  return(map);
2232#else
2233  (void) file;
2234  (void) mode;
2235  (void) offset;
2236  (void) length;
2237  return(NULL);
2238#endif
2239}
2240
2241/*
2242%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2243%                                                                             %
2244%                                                                             %
2245%                                                                             %
2246+  M S B O r d e r L o n g                                                    %
2247%                                                                             %
2248%                                                                             %
2249%                                                                             %
2250%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2251%
2252%  MSBOrderLong() converts a least-significant byte first buffer of integers to
2253%  most-significant byte first.
2254%
2255%  The format of the MSBOrderLong method is:
2256%
2257%      void MSBOrderLong(unsigned char *buffer,const size_t length)
2258%
2259%  A description of each parameter follows.
2260%
2261%   o  buffer:  Specifies a pointer to a buffer of integers.
2262%
2263%   o  length:  Specifies the length of the buffer.
2264%
2265*/
2266MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2267{
2268  int
2269    c;
2270
2271  register unsigned char
2272    *p,
2273    *q;
2274
2275  assert(buffer != (unsigned char *) NULL);
2276  q=buffer+length;
2277  while (buffer < q)
2278  {
2279    p=buffer+3;
2280    c=(int) (*p);
2281    *p=(*buffer);
2282    *buffer++=(unsigned char) c;
2283    p=buffer+1;
2284    c=(int) (*p);
2285    *p=(*buffer);
2286    *buffer++=(unsigned char) c;
2287    buffer+=2;
2288  }
2289}
2290
2291/*
2292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2293%                                                                             %
2294%                                                                             %
2295%                                                                             %
2296+  M S B O r d e r S h o r t                                                  %
2297%                                                                             %
2298%                                                                             %
2299%                                                                             %
2300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2301%
2302%  MSBOrderShort() converts a least-significant byte first buffer of integers
2303%  to most-significant byte first.
2304%
2305%  The format of the MSBOrderShort method is:
2306%
2307%      void MSBOrderShort(unsigned char *p,const size_t length)
2308%
2309%  A description of each parameter follows.
2310%
2311%   o  p:  Specifies a pointer to a buffer of integers.
2312%
2313%   o  length:  Specifies the length of the buffer.
2314%
2315*/
2316MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2317{
2318  int
2319    c;
2320
2321  register unsigned char
2322    *q;
2323
2324  assert(p != (unsigned char *) NULL);
2325  q=p+length;
2326  while (p < q)
2327  {
2328    c=(int) (*p);
2329    *p=(*(p+1));
2330    p++;
2331    *p++=(unsigned char) c;
2332  }
2333}
2334
2335/*
2336%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2337%                                                                             %
2338%                                                                             %
2339%                                                                             %
2340+   O p e n B l o b                                                           %
2341%                                                                             %
2342%                                                                             %
2343%                                                                             %
2344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2345%
2346%  OpenBlob() opens a file associated with the image.  A file name of '-' sets
2347%  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
2348%  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2349%  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
2350%  from a system command.
2351%
2352%  The format of the OpenBlob method is:
2353%
2354%       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2355%        const BlobMode mode,ExceptionInfo *exception)
2356%
2357%  A description of each parameter follows:
2358%
2359%    o image_info: the image info.
2360%
2361%    o image: the image.
2362%
2363%    o mode: the mode for opening the file.
2364%
2365*/
2366
2367static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
2368  Image *image)
2369{
2370  const char
2371    *option;
2372
2373  int
2374    status;
2375
2376  size_t
2377    size;
2378
2379  size=16384;
2380  option=GetImageOption(image_info,"stream:buffer-size");
2381  if (option != (const char *) NULL)
2382    size=StringToUnsignedLong(option);
2383  status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
2384    _IONBF : _IOFBF,size);
2385  return(status == 0 ? MagickTrue : MagickFalse);
2386}
2387
2388MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2389  Image *image,const BlobMode mode,ExceptionInfo *exception)
2390{
2391  char
2392    extension[MagickPathExtent],
2393    filename[MagickPathExtent];
2394
2395  const char
2396    *type;
2397
2398  MagickBooleanType
2399    status;
2400
2401  PolicyRights
2402    rights;
2403
2404  assert(image_info != (ImageInfo *) NULL);
2405  assert(image_info->signature == MagickCoreSignature);
2406  if (image_info->debug != MagickFalse)
2407    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2408      image_info->filename);
2409  assert(image != (Image *) NULL);
2410  assert(image->signature == MagickCoreSignature);
2411  if (image_info->blob != (void *) NULL)
2412    {
2413      if (image_info->stream != (StreamHandler) NULL)
2414        image->blob->stream=(StreamHandler) image_info->stream;
2415      AttachBlob(image->blob,image_info->blob,image_info->length);
2416      return(MagickTrue);
2417    }
2418  (void) DetachBlob(image->blob);
2419  switch (mode)
2420  {
2421    default: type="r"; break;
2422    case ReadBlobMode: type="r"; break;
2423    case ReadBinaryBlobMode: type="rb"; break;
2424    case WriteBlobMode: type="w"; break;
2425    case WriteBinaryBlobMode: type="w+b"; break;
2426    case AppendBlobMode: type="a"; break;
2427    case AppendBinaryBlobMode: type="a+b"; break;
2428  }
2429  if (*type != 'r')
2430    image->blob->synchronize=image_info->synchronize;
2431  if (image_info->stream != (StreamHandler) NULL)
2432    {
2433      image->blob->stream=(StreamHandler) image_info->stream;
2434      if (*type == 'w')
2435        {
2436          image->blob->type=FifoStream;
2437          return(MagickTrue);
2438        }
2439    }
2440  /*
2441    Open image file.
2442  */
2443  *filename='\0';
2444  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2445  rights=ReadPolicyRights;
2446  if (*type == 'w')
2447    rights=WritePolicyRights;
2448  if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2449    {
2450      errno=EPERM;
2451      (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2452        "NotAuthorized","`%s'",filename);
2453      return(MagickFalse);
2454    }
2455  if ((LocaleCompare(filename,"-") == 0) ||
2456      ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2457    {
2458      image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
2459#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2460      if (strchr(type,'b') != (char *) NULL)
2461        setmode(fileno(image->blob->file_info.file),_O_BINARY);
2462#endif
2463      image->blob->type=StandardStream;
2464      image->blob->exempt=MagickTrue;
2465      return(SetStreamBuffering(image_info,image));
2466    }
2467  if (LocaleNCompare(filename,"fd:",3) == 0)
2468    {
2469      char
2470        fileMode[MagickPathExtent];
2471
2472      *fileMode =(*type);
2473      fileMode[1]='\0';
2474      image->blob->file_info.file=fdopen(StringToLong(filename+3),fileMode);
2475#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2476      if (strchr(type,'b') != (char *) NULL)
2477        setmode(fileno(image->blob->file_info.file),_O_BINARY);
2478#endif
2479      image->blob->type=StandardStream;
2480      image->blob->exempt=MagickTrue;
2481      return(SetStreamBuffering(image_info,image));
2482    }
2483#if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
2484  if (*filename == '|')
2485    {
2486      char
2487        fileMode[MagickPathExtent],
2488        *sanitize_command;
2489
2490      /*
2491        Pipe image to or from a system command.
2492      */
2493#if defined(SIGPIPE)
2494      if (*type == 'w')
2495        (void) signal(SIGPIPE,SIG_IGN);
2496#endif
2497      *fileMode =(*type);
2498      fileMode[1]='\0';
2499      sanitize_command=SanitizeString(filename+1);
2500      image->blob->file_info.file=(FILE *) popen_utf8(sanitize_command,
2501        fileMode);
2502      sanitize_command=DestroyString(sanitize_command);
2503      if (image->blob->file_info.file == (FILE *) NULL)
2504        {
2505          ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2506          return(MagickFalse);
2507        }
2508      image->blob->type=PipeStream;
2509      image->blob->exempt=MagickTrue;
2510      return(SetStreamBuffering(image_info,image));
2511    }
2512#endif
2513  status=GetPathAttributes(filename,&image->blob->properties);
2514#if defined(S_ISFIFO)
2515  if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
2516    {
2517      image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2518      if (image->blob->file_info.file == (FILE *) NULL)
2519        {
2520          ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2521          return(MagickFalse);
2522        }
2523      image->blob->type=FileStream;
2524      image->blob->exempt=MagickTrue;
2525      return(SetStreamBuffering(image_info,image));
2526    }
2527#endif
2528  GetPathComponent(image->filename,ExtensionPath,extension);
2529  if (*type == 'w')
2530    {
2531      (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2532      if ((image_info->adjoin == MagickFalse) ||
2533          (strchr(filename,'%') != (char *) NULL))
2534        {
2535          /*
2536            Form filename for multi-part images.
2537          */
2538          (void) InterpretImageFilename(image_info,image,image->filename,(int)
2539            image->scene,filename,exception);
2540          if ((LocaleCompare(filename,image->filename) == 0) &&
2541              ((GetPreviousImageInList(image) != (Image *) NULL) ||
2542               (GetNextImageInList(image) != (Image *) NULL)))
2543            {
2544              char
2545                path[MagickPathExtent];
2546
2547              GetPathComponent(image->filename,RootPath,path);
2548              if (*extension == '\0')
2549                (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
2550                  path,(double) image->scene);
2551              else
2552                (void) FormatLocaleString(filename,MagickPathExtent,
2553                  "%s-%.20g.%s",path,(double) image->scene,extension);
2554            }
2555          (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2556#if defined(macintosh)
2557          SetApplicationType(filename,image_info->magick,'8BIM');
2558#endif
2559        }
2560    }
2561  if (image_info->file != (FILE *) NULL)
2562    {
2563      image->blob->file_info.file=image_info->file;
2564      image->blob->type=FileStream;
2565      image->blob->exempt=MagickTrue;
2566    }
2567  else
2568    if (*type == 'r')
2569      {
2570        image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2571        if (image->blob->file_info.file != (FILE *) NULL)
2572          {
2573            size_t
2574              count;
2575
2576            unsigned char
2577              magick[3];
2578
2579            image->blob->type=FileStream;
2580            (void) SetStreamBuffering(image_info,image);
2581            (void) ResetMagickMemory(magick,0,sizeof(magick));
2582            count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
2583            (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
2584#if defined(MAGICKCORE_POSIX_SUPPORT)
2585            (void) fflush(image->blob->file_info.file);
2586#endif
2587            (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2588               "  read %.20g magic header bytes",(double) count);
2589#if defined(MAGICKCORE_ZLIB_DELEGATE)
2590            if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2591                ((int) magick[2] == 0x08))
2592              {
2593                if (image->blob->file_info.file != (FILE *) NULL)
2594                  (void) fclose(image->blob->file_info.file);
2595                image->blob->file_info.file=(FILE *) NULL;
2596                image->blob->file_info.gzfile=gzopen(filename,type);
2597                if (image->blob->file_info.gzfile != (gzFile) NULL)
2598                  image->blob->type=ZipStream;
2599               }
2600#endif
2601#if defined(MAGICKCORE_BZLIB_DELEGATE)
2602            if (strncmp((char *) magick,"BZh",3) == 0)
2603              {
2604                if (image->blob->file_info.file != (FILE *) NULL)
2605                  (void) fclose(image->blob->file_info.file);
2606                image->blob->file_info.file=(FILE *) NULL;
2607                image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2608                if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2609                  image->blob->type=BZipStream;
2610              }
2611#endif
2612            if (image->blob->type == FileStream)
2613              {
2614                const MagickInfo
2615                  *magick_info;
2616
2617                ExceptionInfo
2618                  *sans_exception;
2619
2620                size_t
2621                  length;
2622
2623                sans_exception=AcquireExceptionInfo();
2624                magick_info=GetMagickInfo(image_info->magick,sans_exception);
2625                sans_exception=DestroyExceptionInfo(sans_exception);
2626                length=(size_t) image->blob->properties.st_size;
2627                if ((magick_info != (const MagickInfo *) NULL) &&
2628                    (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2629                    (length > MagickMaxBufferExtent) &&
2630                    (AcquireMagickResource(MapResource,length) != MagickFalse))
2631                  {
2632                    void
2633                      *blob;
2634
2635                    blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2636                      length);
2637                    if (blob == (void *) NULL)
2638                      RelinquishMagickResource(MapResource,length);
2639                    else
2640                      {
2641                        /*
2642                          Format supports blobs-- use memory-mapped I/O.
2643                        */
2644                        if (image_info->file != (FILE *) NULL)
2645                          image->blob->exempt=MagickFalse;
2646                        else
2647                          {
2648                            (void) fclose(image->blob->file_info.file);
2649                            image->blob->file_info.file=(FILE *) NULL;
2650                          }
2651                        AttachBlob(image->blob,blob,length);
2652                        image->blob->mapped=MagickTrue;
2653                      }
2654                  }
2655              }
2656          }
2657        }
2658      else
2659#if defined(MAGICKCORE_ZLIB_DELEGATE)
2660        if ((LocaleCompare(extension,"Z") == 0) ||
2661            (LocaleCompare(extension,"gz") == 0) ||
2662            (LocaleCompare(extension,"wmz") == 0) ||
2663            (LocaleCompare(extension,"svgz") == 0))
2664          {
2665            if (mode == WriteBinaryBlobMode)
2666              type="wb";
2667            image->blob->file_info.gzfile=gzopen(filename,type);
2668            if (image->blob->file_info.gzfile != (gzFile) NULL)
2669              image->blob->type=ZipStream;
2670          }
2671        else
2672#endif
2673#if defined(MAGICKCORE_BZLIB_DELEGATE)
2674          if (LocaleCompare(extension,"bz2") == 0)
2675            {
2676              image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2677              if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2678                image->blob->type=BZipStream;
2679            }
2680          else
2681#endif
2682            {
2683              image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2684              if (image->blob->file_info.file != (FILE *) NULL)
2685                {
2686                  image->blob->type=FileStream;
2687                  (void) SetStreamBuffering(image_info,image);
2688                }
2689       }
2690  image->blob->status=MagickFalse;
2691  if (image->blob->type != UndefinedStream)
2692    image->blob->size=GetBlobSize(image);
2693  else
2694    {
2695      ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2696      return(MagickFalse);
2697    }
2698  return(MagickTrue);
2699}
2700
2701/*
2702%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2703%                                                                             %
2704%                                                                             %
2705%                                                                             %
2706+   P i n g B l o b                                                           %
2707%                                                                             %
2708%                                                                             %
2709%                                                                             %
2710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2711%
2712%  PingBlob() returns all the attributes of an image or image sequence except
2713%  for the pixels.  It is much faster and consumes far less memory than
2714%  BlobToImage().  On failure, a NULL image is returned and exception
2715%  describes the reason for the failure.
2716%
2717%  The format of the PingBlob method is:
2718%
2719%      Image *PingBlob(const ImageInfo *image_info,const void *blob,
2720%        const size_t length,ExceptionInfo *exception)
2721%
2722%  A description of each parameter follows:
2723%
2724%    o image_info: the image info.
2725%
2726%    o blob: the address of a character stream in one of the image formats
2727%      understood by ImageMagick.
2728%
2729%    o length: This size_t integer reflects the length in bytes of the blob.
2730%
2731%    o exception: return any errors or warnings in this structure.
2732%
2733*/
2734
2735#if defined(__cplusplus) || defined(c_plusplus)
2736extern "C" {
2737#endif
2738
2739static size_t PingStream(const Image *magick_unused(image),
2740  const void *magick_unused(pixels),const size_t columns)
2741{
2742  magick_unreferenced(image);
2743  magick_unreferenced(pixels);
2744  return(columns);
2745}
2746
2747#if defined(__cplusplus) || defined(c_plusplus)
2748}
2749#endif
2750
2751MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2752  const size_t length,ExceptionInfo *exception)
2753{
2754  Image
2755    *image;
2756
2757  ImageInfo
2758    *ping_info;
2759
2760  assert(image_info != (ImageInfo *) NULL);
2761  assert(image_info->signature == MagickCoreSignature);
2762  if (image_info->debug != MagickFalse)
2763    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2764      image_info->filename);
2765  assert(exception != (ExceptionInfo *) NULL);
2766  if ((blob == (const void *) NULL) || (length == 0))
2767    {
2768      (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
2769        "UnrecognizedImageFormat","`%s'",image_info->magick);
2770      return((Image *) NULL);
2771    }
2772  ping_info=CloneImageInfo(image_info);
2773  ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2774  if (ping_info->blob == (const void *) NULL)
2775    {
2776      (void) ThrowMagickException(exception,GetMagickModule(),
2777        ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
2778      return((Image *) NULL);
2779    }
2780  (void) memcpy(ping_info->blob,blob,length);
2781  ping_info->length=length;
2782  ping_info->ping=MagickTrue;
2783  image=ReadStream(ping_info,&PingStream,exception);
2784  ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2785  ping_info=DestroyImageInfo(ping_info);
2786  return(image);
2787}
2788
2789/*
2790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2791%                                                                             %
2792%                                                                             %
2793%                                                                             %
2794+  R e a d B l o b                                                            %
2795%                                                                             %
2796%                                                                             %
2797%                                                                             %
2798%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2799%
2800%  ReadBlob() reads data from the blob or image file and returns it.  It
2801%  returns the number of bytes read. If length is zero, ReadBlob() returns
2802%  zero and has no other results. If length is greater than SSIZE_MAX, the
2803%  result is unspecified.
2804%
2805%  The format of the ReadBlob method is:
2806%
2807%      ssize_t ReadBlob(Image *image,const size_t length,void *data)
2808%
2809%  A description of each parameter follows:
2810%
2811%    o image: the image.
2812%
2813%    o length:  Specifies an integer representing the number of bytes to read
2814%      from the file.
2815%
2816%    o data:  Specifies an area to place the information requested from the
2817%      file.
2818%
2819*/
2820MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
2821{
2822  int
2823    c;
2824
2825  register unsigned char
2826    *q;
2827
2828  ssize_t
2829    count;
2830
2831  assert(image != (Image *) NULL);
2832  assert(image->signature == MagickCoreSignature);
2833  assert(image->blob != (BlobInfo *) NULL);
2834  assert(image->blob->type != UndefinedStream);
2835  if (length == 0)
2836    return(0);
2837  assert(data != (void *) NULL);
2838  count=0;
2839  q=(unsigned char *) data;
2840  switch (image->blob->type)
2841  {
2842    case UndefinedStream:
2843      break;
2844    case StandardStream:
2845    case FileStream:
2846    case PipeStream:
2847    {
2848      switch (length)
2849      {
2850        default:
2851        {
2852          count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
2853          break;
2854        }
2855        case 4:
2856        {
2857          c=getc(image->blob->file_info.file);
2858          if (c == EOF)
2859            break;
2860          *q++=(unsigned char) c;
2861          count++;
2862        }
2863        case 3:
2864        {
2865          c=getc(image->blob->file_info.file);
2866          if (c == EOF)
2867            break;
2868          *q++=(unsigned char) c;
2869          count++;
2870        }
2871        case 2:
2872        {
2873          c=getc(image->blob->file_info.file);
2874          if (c == EOF)
2875            break;
2876          *q++=(unsigned char) c;
2877          count++;
2878        }
2879        case 1:
2880        {
2881          c=getc(image->blob->file_info.file);
2882          if (c == EOF)
2883            break;
2884          *q++=(unsigned char) c;
2885          count++;
2886        }
2887        case 0:
2888          break;
2889      }
2890      break;
2891    }
2892    case ZipStream:
2893    {
2894#if defined(MAGICKCORE_ZLIB_DELEGATE)
2895      switch (length)
2896      {
2897        default:
2898        {
2899          count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
2900            (unsigned int) length);
2901          break;
2902        }
2903        case 4:
2904        {
2905          c=gzgetc(image->blob->file_info.gzfile);
2906          if (c == EOF)
2907            break;
2908          *q++=(unsigned char) c;
2909          count++;
2910        }
2911        case 3:
2912        {
2913          c=gzgetc(image->blob->file_info.gzfile);
2914          if (c == EOF)
2915            break;
2916          *q++=(unsigned char) c;
2917          count++;
2918        }
2919        case 2:
2920        {
2921          c=gzgetc(image->blob->file_info.gzfile);
2922          if (c == EOF)
2923            break;
2924          *q++=(unsigned char) c;
2925          count++;
2926        }
2927        case 1:
2928        {
2929          c=gzgetc(image->blob->file_info.gzfile);
2930          if (c == EOF)
2931            break;
2932          *q++=(unsigned char) c;
2933          count++;
2934        }
2935        case 0:
2936          break;
2937      }
2938#endif
2939      break;
2940    }
2941    case BZipStream:
2942    {
2943#if defined(MAGICKCORE_BZLIB_DELEGATE)
2944      count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
2945#endif
2946      break;
2947    }
2948    case FifoStream:
2949      break;
2950    case BlobStream:
2951    {
2952      register const unsigned char
2953        *p;
2954
2955      if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2956        {
2957          image->blob->eof=MagickTrue;
2958          break;
2959        }
2960      p=image->blob->data+image->blob->offset;
2961      count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
2962      image->blob->offset+=count;
2963      if (count != (ssize_t) length)
2964        image->blob->eof=MagickTrue;
2965      (void) memcpy(q,p,(size_t) count);
2966      break;
2967    }
2968  }
2969  return(count);
2970}
2971
2972/*
2973%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2974%                                                                             %
2975%                                                                             %
2976%                                                                             %
2977+  R e a d B l o b B y t e                                                    %
2978%                                                                             %
2979%                                                                             %
2980%                                                                             %
2981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2982%
2983%  ReadBlobByte() reads a single byte from the image file and returns it.
2984%
2985%  The format of the ReadBlobByte method is:
2986%
2987%      int ReadBlobByte(Image *image)
2988%
2989%  A description of each parameter follows.
2990%
2991%    o image: the image.
2992%
2993*/
2994MagickExport int ReadBlobByte(Image *image)
2995{
2996  register const unsigned char
2997    *p;
2998
2999  ssize_t
3000    count;
3001
3002  unsigned char
3003    buffer[1];
3004
3005  assert(image != (Image *) NULL);
3006  assert(image->signature == MagickCoreSignature);
3007  p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
3008  if (count != 1)
3009    return(EOF);
3010  return((int) (*p));
3011}
3012
3013/*
3014%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3015%                                                                             %
3016%                                                                             %
3017%                                                                             %
3018+  R e a d B l o b D o u b l e                                                %
3019%                                                                             %
3020%                                                                             %
3021%                                                                             %
3022%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3023%
3024%  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3025%  specified by the endian member of the image structure.
3026%
3027%  The format of the ReadBlobDouble method is:
3028%
3029%      double ReadBlobDouble(Image *image)
3030%
3031%  A description of each parameter follows.
3032%
3033%    o image: the image.
3034%
3035*/
3036MagickExport double ReadBlobDouble(Image *image)
3037{
3038  union
3039  {
3040    MagickSizeType
3041      unsigned_value;
3042
3043    double
3044      double_value;
3045  } quantum;
3046
3047  quantum.double_value=0.0;
3048  quantum.unsigned_value=ReadBlobLongLong(image);
3049  return(quantum.double_value);
3050}
3051
3052/*
3053%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3054%                                                                             %
3055%                                                                             %
3056%                                                                             %
3057+  R e a d B l o b F l o a t                                                  %
3058%                                                                             %
3059%                                                                             %
3060%                                                                             %
3061%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3062%
3063%  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3064%  specified by the endian member of the image structure.
3065%
3066%  The format of the ReadBlobFloat method is:
3067%
3068%      float ReadBlobFloat(Image *image)
3069%
3070%  A description of each parameter follows.
3071%
3072%    o image: the image.
3073%
3074*/
3075MagickExport float ReadBlobFloat(Image *image)
3076{
3077  union
3078  {
3079    unsigned int
3080      unsigned_value;
3081
3082    float
3083      float_value;
3084  } quantum;
3085
3086  quantum.float_value=0.0;
3087  quantum.unsigned_value=ReadBlobLong(image);
3088  return(quantum.float_value);
3089}
3090
3091/*
3092%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3093%                                                                             %
3094%                                                                             %
3095%                                                                             %
3096+  R e a d B l o b L o n g                                                    %
3097%                                                                             %
3098%                                                                             %
3099%                                                                             %
3100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3101%
3102%  ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
3103%  byte-order specified by the endian member of the image structure.
3104%
3105%  The format of the ReadBlobLong method is:
3106%
3107%      unsigned int ReadBlobLong(Image *image)
3108%
3109%  A description of each parameter follows.
3110%
3111%    o image: the image.
3112%
3113*/
3114MagickExport unsigned int ReadBlobLong(Image *image)
3115{
3116  register const unsigned char
3117    *p;
3118
3119  ssize_t
3120    count;
3121
3122  unsigned char
3123    buffer[4];
3124
3125  unsigned int
3126    value;
3127
3128  assert(image != (Image *) NULL);
3129  assert(image->signature == MagickCoreSignature);
3130  *buffer='\0';
3131  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3132  if (count != 4)
3133    return(0UL);
3134  if (image->endian == LSBEndian)
3135    {
3136      value=(unsigned int) (*p++);
3137      value|=(unsigned int) (*p++) << 8;
3138      value|=(unsigned int) (*p++) << 16;
3139      value|=(unsigned int) (*p++) << 24;
3140      return(value & 0xffffffff);
3141    }
3142  value=(unsigned int) (*p++) << 24;
3143  value|=(unsigned int) (*p++) << 16;
3144  value|=(unsigned int) (*p++) << 8;
3145  value|=(unsigned int) (*p++);
3146  return(value & 0xffffffff);
3147}
3148
3149/*
3150%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3151%                                                                             %
3152%                                                                             %
3153%                                                                             %
3154+  R e a d B l o b L o n g L o n g                                            %
3155%                                                                             %
3156%                                                                             %
3157%                                                                             %
3158%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3159%
3160%  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3161%  byte-order specified by the endian member of the image structure.
3162%
3163%  The format of the ReadBlobLongLong method is:
3164%
3165%      MagickSizeType ReadBlobLongLong(Image *image)
3166%
3167%  A description of each parameter follows.
3168%
3169%    o image: the image.
3170%
3171*/
3172MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3173{
3174  MagickSizeType
3175    value;
3176
3177  register const unsigned char
3178    *p;
3179
3180  ssize_t
3181    count;
3182
3183  unsigned char
3184    buffer[8];
3185
3186  assert(image != (Image *) NULL);
3187  assert(image->signature == MagickCoreSignature);
3188  *buffer='\0';
3189  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3190  if (count != 8)
3191    return(MagickULLConstant(0));
3192  if (image->endian == LSBEndian)
3193    {
3194      value=(MagickSizeType) (*p++);
3195      value|=(MagickSizeType) (*p++) << 8;
3196      value|=(MagickSizeType) (*p++) << 16;
3197      value|=(MagickSizeType) (*p++) << 24;
3198      value|=(MagickSizeType) (*p++) << 32;
3199      value|=(MagickSizeType) (*p++) << 40;
3200      value|=(MagickSizeType) (*p++) << 48;
3201      value|=(MagickSizeType) (*p++) << 56;
3202      return(value & MagickULLConstant(0xffffffffffffffff));
3203    }
3204  value=(MagickSizeType) (*p++) << 56;
3205  value|=(MagickSizeType) (*p++) << 48;
3206  value|=(MagickSizeType) (*p++) << 40;
3207  value|=(MagickSizeType) (*p++) << 32;
3208  value|=(MagickSizeType) (*p++) << 24;
3209  value|=(MagickSizeType) (*p++) << 16;
3210  value|=(MagickSizeType) (*p++) << 8;
3211  value|=(MagickSizeType) (*p++);
3212  return(value & MagickULLConstant(0xffffffffffffffff));
3213}
3214
3215/*
3216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3217%                                                                             %
3218%                                                                             %
3219%                                                                             %
3220+  R e a d B l o b S h o r t                                                  %
3221%                                                                             %
3222%                                                                             %
3223%                                                                             %
3224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3225%
3226%  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3227%  specified by the endian member of the image structure.
3228%
3229%  The format of the ReadBlobShort method is:
3230%
3231%      unsigned short ReadBlobShort(Image *image)
3232%
3233%  A description of each parameter follows.
3234%
3235%    o image: the image.
3236%
3237*/
3238MagickExport unsigned short ReadBlobShort(Image *image)
3239{
3240  register const unsigned char
3241    *p;
3242
3243  register unsigned short
3244    value;
3245
3246  ssize_t
3247    count;
3248
3249  unsigned char
3250    buffer[2];
3251
3252  assert(image != (Image *) NULL);
3253  assert(image->signature == MagickCoreSignature);
3254  *buffer='\0';
3255  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3256  if (count != 2)
3257    return((unsigned short) 0U);
3258  if (image->endian == LSBEndian)
3259    {
3260      value=(unsigned short) (*p++);
3261      value|=(unsigned short) (*p++) << 8;
3262      return(value);
3263    }
3264  value=(unsigned short) (*p++) << 8;
3265  value|=(unsigned short) (*p++);
3266  return(value);
3267}
3268
3269/*
3270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3271%                                                                             %
3272%                                                                             %
3273%                                                                             %
3274+  R e a d B l o b L S B L o n g                                              %
3275%                                                                             %
3276%                                                                             %
3277%                                                                             %
3278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3279%
3280%  ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
3281%  least-significant byte first order.
3282%
3283%  The format of the ReadBlobLSBLong method is:
3284%
3285%      unsigned int ReadBlobLSBLong(Image *image)
3286%
3287%  A description of each parameter follows.
3288%
3289%    o image: the image.
3290%
3291*/
3292MagickExport unsigned int ReadBlobLSBLong(Image *image)
3293{
3294  register const unsigned char
3295    *p;
3296
3297  register unsigned int
3298    value;
3299
3300  ssize_t
3301    count;
3302
3303  unsigned char
3304    buffer[4];
3305
3306  assert(image != (Image *) NULL);
3307  assert(image->signature == MagickCoreSignature);
3308  *buffer='\0';
3309  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3310  if (count != 4)
3311    return(0U);
3312  value=(unsigned int) (*p++);
3313  value|=(unsigned int) (*p++) << 8;
3314  value|=(unsigned int) (*p++) << 16;
3315  value|=(unsigned int) (*p++) << 24;
3316  return(value & 0xffffffff);
3317}
3318
3319/*
3320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3321%                                                                             %
3322%                                                                             %
3323%                                                                             %
3324+  R e a d B l o b L S B S i g n e d L o n g                                  %
3325%                                                                             %
3326%                                                                             %
3327%                                                                             %
3328%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3329%
3330%  ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
3331%  least-significant byte first order.
3332%
3333%  The format of the ReadBlobLSBSignedLong method is:
3334%
3335%      signed int ReadBlobLSBSignedLong(Image *image)
3336%
3337%  A description of each parameter follows.
3338%
3339%    o image: the image.
3340%
3341*/
3342MagickExport signed int ReadBlobLSBSignedLong(Image *image)
3343{
3344  union
3345  {
3346    unsigned int
3347      unsigned_value;
3348
3349    signed int
3350      signed_value;
3351  } quantum;
3352
3353  quantum.unsigned_value=ReadBlobLSBLong(image);
3354  return(quantum.signed_value);
3355}
3356
3357/*
3358%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3359%                                                                             %
3360%                                                                             %
3361%                                                                             %
3362+  R e a d B l o b L S B S h o r t                                            %
3363%                                                                             %
3364%                                                                             %
3365%                                                                             %
3366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3367%
3368%  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3369%  least-significant byte first order.
3370%
3371%  The format of the ReadBlobLSBShort method is:
3372%
3373%      unsigned short ReadBlobLSBShort(Image *image)
3374%
3375%  A description of each parameter follows.
3376%
3377%    o image: the image.
3378%
3379*/
3380MagickExport unsigned short ReadBlobLSBShort(Image *image)
3381{
3382  register const unsigned char
3383    *p;
3384
3385  register unsigned short
3386    value;
3387
3388  ssize_t
3389    count;
3390
3391  unsigned char
3392    buffer[2];
3393
3394  assert(image != (Image *) NULL);
3395  assert(image->signature == MagickCoreSignature);
3396  *buffer='\0';
3397  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3398  if (count != 2)
3399    return((unsigned short) 0U);
3400  value=(unsigned int) (*p++);
3401  value|=(unsigned int) (*p++) << 8;
3402  return(value & 0xffff);
3403}
3404
3405/*
3406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3407%                                                                             %
3408%                                                                             %
3409%                                                                             %
3410+  R e a d B l o b L S B S i g n e d S h o r t                                %
3411%                                                                             %
3412%                                                                             %
3413%                                                                             %
3414%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3415%
3416%  ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
3417%  least-significant byte-order.
3418%
3419%  The format of the ReadBlobLSBSignedShort method is:
3420%
3421%      signed short ReadBlobLSBSignedShort(Image *image)
3422%
3423%  A description of each parameter follows.
3424%
3425%    o image: the image.
3426%
3427*/
3428MagickExport signed short ReadBlobLSBSignedShort(Image *image)
3429{
3430  union
3431  {
3432    unsigned short
3433      unsigned_value;
3434
3435    signed short
3436      signed_value;
3437  } quantum;
3438
3439  quantum.unsigned_value=ReadBlobLSBShort(image);
3440  return(quantum.signed_value);
3441}
3442
3443/*
3444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3445%                                                                             %
3446%                                                                             %
3447%                                                                             %
3448+  R e a d B l o b M S B L o n g                                              %
3449%                                                                             %
3450%                                                                             %
3451%                                                                             %
3452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3453%
3454%  ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
3455%  most-significant byte first order.
3456%
3457%  The format of the ReadBlobMSBLong method is:
3458%
3459%      unsigned int ReadBlobMSBLong(Image *image)
3460%
3461%  A description of each parameter follows.
3462%
3463%    o image: the image.
3464%
3465*/
3466MagickExport unsigned int ReadBlobMSBLong(Image *image)
3467{
3468  register const unsigned char
3469    *p;
3470
3471  register unsigned int
3472    value;
3473
3474  ssize_t
3475    count;
3476
3477  unsigned char
3478    buffer[4];
3479
3480  assert(image != (Image *) NULL);
3481  assert(image->signature == MagickCoreSignature);
3482  *buffer='\0';
3483  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3484  if (count != 4)
3485    return(0UL);
3486  value=(unsigned int) (*p++) << 24;
3487  value|=(unsigned int) (*p++) << 16;
3488  value|=(unsigned int) (*p++) << 8;
3489  value|=(unsigned int) (*p++);
3490  return(value);
3491}
3492
3493/*
3494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3495%                                                                             %
3496%                                                                             %
3497%                                                                             %
3498+  R e a d B l o b M S B L o n g L o n g                                      %
3499%                                                                             %
3500%                                                                             %
3501%                                                                             %
3502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3503%
3504%  ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
3505%  in most-significant byte first order.
3506%
3507%  The format of the ReadBlobMSBLongLong method is:
3508%
3509%      unsigned int ReadBlobMSBLongLong(Image *image)
3510%
3511%  A description of each parameter follows.
3512%
3513%    o image: the image.
3514%
3515*/
3516MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3517{
3518  register const unsigned char
3519    *p;
3520
3521  register MagickSizeType
3522    value;
3523
3524  ssize_t
3525    count;
3526
3527  unsigned char
3528    buffer[8];
3529
3530  assert(image != (Image *) NULL);
3531  assert(image->signature == MagickCoreSignature);
3532  *buffer='\0';
3533  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3534  if (count != 8)
3535    return(MagickULLConstant(0));
3536  value=(MagickSizeType) (*p++) << 56;
3537  value|=(MagickSizeType) (*p++) << 48;
3538  value|=(MagickSizeType) (*p++) << 40;
3539  value|=(MagickSizeType) (*p++) << 32;
3540  value|=(MagickSizeType) (*p++) << 24;
3541  value|=(MagickSizeType) (*p++) << 16;
3542  value|=(MagickSizeType) (*p++) << 8;
3543  value|=(MagickSizeType) (*p++);
3544  return(value & MagickULLConstant(0xffffffffffffffff));
3545}
3546
3547/*
3548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3549%                                                                             %
3550%                                                                             %
3551%                                                                             %
3552+  R e a d B l o b M S B S h o r t                                            %
3553%                                                                             %
3554%                                                                             %
3555%                                                                             %
3556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3557%
3558%  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3559%  most-significant byte first order.
3560%
3561%  The format of the ReadBlobMSBShort method is:
3562%
3563%      unsigned short ReadBlobMSBShort(Image *image)
3564%
3565%  A description of each parameter follows.
3566%
3567%    o image: the image.
3568%
3569*/
3570MagickExport unsigned short ReadBlobMSBShort(Image *image)
3571{
3572  register const unsigned char
3573    *p;
3574
3575  register unsigned short
3576    value;
3577
3578  ssize_t
3579    count;
3580
3581  unsigned char
3582    buffer[2];
3583
3584  assert(image != (Image *) NULL);
3585  assert(image->signature == MagickCoreSignature);
3586  *buffer='\0';
3587  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3588  if (count != 2)
3589    return((unsigned short) 0U);
3590  value=(unsigned short) (*p++) << 8;
3591  value|=(unsigned short) (*p++);
3592  return(value & 0xffff);
3593}
3594
3595/*
3596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3597%                                                                             %
3598%                                                                             %
3599%                                                                             %
3600+  R e a d B l o b M S B S i g n e d L o n g                                  %
3601%                                                                             %
3602%                                                                             %
3603%                                                                             %
3604%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3605%
3606%  ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
3607%  most-significant byte-order.
3608%
3609%  The format of the ReadBlobMSBSignedLong method is:
3610%
3611%      signed int ReadBlobMSBSignedLong(Image *image)
3612%
3613%  A description of each parameter follows.
3614%
3615%    o image: the image.
3616%
3617*/
3618MagickExport signed int ReadBlobMSBSignedLong(Image *image)
3619{
3620  union
3621  {
3622    unsigned int
3623      unsigned_value;
3624
3625    signed int
3626      signed_value;
3627  } quantum;
3628
3629  quantum.unsigned_value=ReadBlobMSBLong(image);
3630  return(quantum.signed_value);
3631}
3632
3633/*
3634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3635%                                                                             %
3636%                                                                             %
3637%                                                                             %
3638+  R e a d B l o b M S B S i g n e d S h o r t                                %
3639%                                                                             %
3640%                                                                             %
3641%                                                                             %
3642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3643%
3644%  ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
3645%  most-significant byte-order.
3646%
3647%  The format of the ReadBlobMSBSignedShort method is:
3648%
3649%      signed short ReadBlobMSBSignedShort(Image *image)
3650%
3651%  A description of each parameter follows.
3652%
3653%    o image: the image.
3654%
3655*/
3656MagickExport signed short ReadBlobMSBSignedShort(Image *image)
3657{
3658  union
3659  {
3660    unsigned short
3661      unsigned_value;
3662
3663    signed short
3664      signed_value;
3665  } quantum;
3666
3667  quantum.unsigned_value=ReadBlobMSBShort(image);
3668  return(quantum.signed_value);
3669}
3670
3671/*
3672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3673%                                                                             %
3674%                                                                             %
3675%                                                                             %
3676+  R e a d B l o b S i g n e d L o n g                                        %
3677%                                                                             %
3678%                                                                             %
3679%                                                                             %
3680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3681%
3682%  ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
3683%  byte-order specified by the endian member of the image structure.
3684%
3685%  The format of the ReadBlobSignedLong method is:
3686%
3687%      signed int ReadBlobSignedLong(Image *image)
3688%
3689%  A description of each parameter follows.
3690%
3691%    o image: the image.
3692%
3693*/
3694MagickExport signed int ReadBlobSignedLong(Image *image)
3695{
3696  union
3697  {
3698    unsigned int
3699      unsigned_value;
3700
3701    signed int
3702      signed_value;
3703  } quantum;
3704
3705  quantum.unsigned_value=ReadBlobLong(image);
3706  return(quantum.signed_value);
3707}
3708
3709/*
3710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3711%                                                                             %
3712%                                                                             %
3713%                                                                             %
3714+  R e a d B l o b S i g n e d S h o r t                                      %
3715%                                                                             %
3716%                                                                             %
3717%                                                                             %
3718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3719%
3720%  ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
3721%  byte-order specified by the endian member of the image structure.
3722%
3723%  The format of the ReadBlobSignedShort method is:
3724%
3725%      signed short ReadBlobSignedShort(Image *image)
3726%
3727%  A description of each parameter follows.
3728%
3729%    o image: the image.
3730%
3731*/
3732MagickExport signed short ReadBlobSignedShort(Image *image)
3733{
3734  union
3735  {
3736    unsigned short
3737      unsigned_value;
3738
3739    signed short
3740      signed_value;
3741  } quantum;
3742
3743  quantum.unsigned_value=ReadBlobShort(image);
3744  return(quantum.signed_value);
3745}
3746
3747/*
3748%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3749%                                                                             %
3750%                                                                             %
3751%                                                                             %
3752+  R e a d B l o b S t r e a m                                                %
3753%                                                                             %
3754%                                                                             %
3755%                                                                             %
3756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3757%
3758%  ReadBlobStream() reads data from the blob or image file and returns it.  It
3759%  returns a pointer to the data buffer you supply or to the image memory
3760%  buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
3761%  returns a count of zero and has no other results. If length is greater than
3762%  SSIZE_MAX, the result is unspecified.
3763%
3764%  The format of the ReadBlobStream method is:
3765%
3766%      const void *ReadBlobStream(Image *image,const size_t length,void *data,
3767%        ssize_t *count)
3768%
3769%  A description of each parameter follows:
3770%
3771%    o image: the image.
3772%
3773%    o length:  Specifies an integer representing the number of bytes to read
3774%      from the file.
3775%
3776%    o count: returns the number of bytes read.
3777%
3778%    o data:  Specifies an area to place the information requested from the
3779%      file.
3780%
3781*/
3782MagickExport const void *ReadBlobStream(Image *image,const size_t length,
3783  void *data,ssize_t *count)
3784{
3785  assert(image != (Image *) NULL);
3786  assert(image->signature == MagickCoreSignature);
3787  assert(image->blob != (BlobInfo *) NULL);
3788  assert(image->blob->type != UndefinedStream);
3789  assert(count != (ssize_t *) NULL);
3790  if (image->blob->type != BlobStream)
3791    {
3792      assert(data != NULL);
3793      *count=ReadBlob(image,length,(unsigned char *) data);
3794      return(data);
3795    }
3796  if (image->blob->offset >= (MagickOffsetType) image->blob->length)
3797    {
3798      *count=0;
3799      image->blob->eof=MagickTrue;
3800      return(data);
3801    }
3802  data=image->blob->data+image->blob->offset;
3803  *count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
3804  image->blob->offset+=(*count);
3805  if (*count != (ssize_t) length)
3806    image->blob->eof=MagickTrue;
3807  return(data);
3808}
3809
3810/*
3811%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3812%                                                                             %
3813%                                                                             %
3814%                                                                             %
3815+   R e a d B l o b S t r i n g                                               %
3816%                                                                             %
3817%                                                                             %
3818%                                                                             %
3819%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3820%
3821%  ReadBlobString() reads characters from a blob or file until a newline
3822%  character is read or an end-of-file condition is encountered.
3823%
3824%  The format of the ReadBlobString method is:
3825%
3826%      char *ReadBlobString(Image *image,char *string)
3827%
3828%  A description of each parameter follows:
3829%
3830%    o image: the image.
3831%
3832%    o string: the address of a character buffer.
3833%
3834*/
3835MagickExport char *ReadBlobString(Image *image,char *string)
3836{
3837  register const unsigned char
3838    *p;
3839
3840  register ssize_t
3841    i;
3842
3843  ssize_t
3844    count;
3845
3846  unsigned char
3847    buffer[1];
3848
3849  assert(image != (Image *) NULL);
3850  assert(image->signature == MagickCoreSignature);
3851  for (i=0; i < (MagickPathExtent-1L); i++)
3852  {
3853    p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
3854    if (count != 1)
3855      {
3856        if (i == 0)
3857          return((char *) NULL);
3858        break;
3859      }
3860    string[i]=(char) (*p);
3861    if ((string[i] == '\r') || (string[i] == '\n'))
3862      break;
3863  }
3864  if (string[i] == '\r')
3865    (void) ReadBlobStream(image,1,buffer,&count);
3866  string[i]='\0';
3867  return(string);
3868}
3869
3870/*
3871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3872%                                                                             %
3873%                                                                             %
3874%                                                                             %
3875+   R e f e r e n c e B l o b                                                 %
3876%                                                                             %
3877%                                                                             %
3878%                                                                             %
3879%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3880%
3881%  ReferenceBlob() increments the reference count associated with the pixel
3882%  blob returning a pointer to the blob.
3883%
3884%  The format of the ReferenceBlob method is:
3885%
3886%      BlobInfo ReferenceBlob(BlobInfo *blob_info)
3887%
3888%  A description of each parameter follows:
3889%
3890%    o blob_info: the blob_info.
3891%
3892*/
3893MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3894{
3895  assert(blob != (BlobInfo *) NULL);
3896  assert(blob->signature == MagickCoreSignature);
3897  if (blob->debug != MagickFalse)
3898    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3899  LockSemaphoreInfo(blob->semaphore);
3900  blob->reference_count++;
3901  UnlockSemaphoreInfo(blob->semaphore);
3902  return(blob);
3903}
3904
3905/*
3906%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3907%                                                                             %
3908%                                                                             %
3909%                                                                             %
3910+  S e e k B l o b                                                            %
3911%                                                                             %
3912%                                                                             %
3913%                                                                             %
3914%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3915%
3916%  SeekBlob() sets the offset in bytes from the beginning of a blob or file
3917%  and returns the resulting offset.
3918%
3919%  The format of the SeekBlob method is:
3920%
3921%      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3922%        const int whence)
3923%
3924%  A description of each parameter follows:
3925%
3926%    o image: the image.
3927%
3928%    o offset:  Specifies an integer representing the offset in bytes.
3929%
3930%    o whence:  Specifies an integer representing how the offset is
3931%      treated relative to the beginning of the blob as follows:
3932%
3933%        SEEK_SET  Set position equal to offset bytes.
3934%        SEEK_CUR  Set position to current location plus offset.
3935%        SEEK_END  Set position to EOF plus offset.
3936%
3937*/
3938MagickExport MagickOffsetType SeekBlob(Image *image,
3939  const MagickOffsetType offset,const int whence)
3940{
3941  assert(image != (Image *) NULL);
3942  assert(image->signature == MagickCoreSignature);
3943  if (image->debug != MagickFalse)
3944    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3945  assert(image->blob != (BlobInfo *) NULL);
3946  assert(image->blob->type != UndefinedStream);
3947  switch (image->blob->type)
3948  {
3949    case UndefinedStream:
3950      break;
3951    case StandardStream:
3952      return(-1);
3953    case FileStream:
3954    {
3955      if ((offset < 0) && (whence == SEEK_SET))
3956        return(-1);
3957      if (fseek(image->blob->file_info.file,offset,whence) < 0)
3958        return(-1);
3959      image->blob->offset=TellBlob(image);
3960      break;
3961    }
3962    case PipeStream:
3963    case ZipStream:
3964    {
3965#if defined(MAGICKCORE_ZLIB_DELEGATE)
3966      if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
3967        return(-1);
3968#endif
3969      image->blob->offset=TellBlob(image);
3970      break;
3971    }
3972    case BZipStream:
3973      return(-1);
3974    case FifoStream:
3975      return(-1);
3976    case BlobStream:
3977    {
3978      switch (whence)
3979      {
3980        case SEEK_SET:
3981        default:
3982        {
3983          if (offset < 0)
3984            return(-1);
3985          image->blob->offset=offset;
3986          break;
3987        }
3988        case SEEK_CUR:
3989        {
3990          if ((image->blob->offset+offset) < 0)
3991            return(-1);
3992          image->blob->offset+=offset;
3993          break;
3994        }
3995        case SEEK_END:
3996        {
3997          if (((MagickOffsetType) image->blob->length+offset) < 0)
3998            return(-1);
3999          image->blob->offset=image->blob->length+offset;
4000          break;
4001        }
4002      }
4003      if (image->blob->offset < (MagickOffsetType)
4004          ((off_t) image->blob->length))
4005        {
4006          image->blob->eof=MagickFalse;
4007          break;
4008        }
4009      if (image->blob->offset < (MagickOffsetType)
4010          ((off_t) image->blob->extent))
4011        break;
4012      if (image->blob->immutable != MagickFalse)
4013        {
4014          image->blob->eof=MagickTrue;
4015          return(-1);
4016        }
4017      image->blob->extent=(size_t) (image->blob->offset+image->blob->quantum);
4018      image->blob->quantum<<=1;
4019      image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
4020        image->blob->extent+1,sizeof(*image->blob->data));
4021      (void) SyncBlob(image);
4022      if (image->blob->data == NULL)
4023        {
4024          (void) DetachBlob(image->blob);
4025          return(-1);
4026        }
4027      break;
4028    }
4029  }
4030  return(image->blob->offset);
4031}
4032
4033/*
4034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4035%                                                                             %
4036%                                                                             %
4037%                                                                             %
4038+   S e t B l o b E x e m p t                                                 %
4039%                                                                             %
4040%                                                                             %
4041%                                                                             %
4042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4043%
4044%  SetBlobExempt() sets the blob exempt status.
4045%
4046%  The format of the SetBlobExempt method is:
4047%
4048%      MagickBooleanType SetBlobExempt(const Image *image,
4049%        const MagickBooleanType exempt)
4050%
4051%  A description of each parameter follows:
4052%
4053%    o image: the image.
4054%
4055%    o exempt: Set to true if this blob is exempt from being closed.
4056%
4057*/
4058MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
4059{
4060  assert(image != (const Image *) NULL);
4061  assert(image->signature == MagickCoreSignature);
4062  if (image->debug != MagickFalse)
4063    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4064  image->blob->exempt=exempt;
4065}
4066
4067/*
4068%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4069%                                                                             %
4070%                                                                             %
4071%                                                                             %
4072+  S e t B l o b E x t e n t                                                  %
4073%                                                                             %
4074%                                                                             %
4075%                                                                             %
4076%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4077%
4078%  SetBlobExtent() ensures enough space is allocated for the blob.  If the
4079%  method is successful, subsequent writes to bytes in the specified range are
4080%  guaranteed not to fail.
4081%
4082%  The format of the SetBlobExtent method is:
4083%
4084%      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
4085%
4086%  A description of each parameter follows:
4087%
4088%    o image: the image.
4089%
4090%    o extent:  the blob maximum extent.
4091%
4092*/
4093MagickExport MagickBooleanType SetBlobExtent(Image *image,
4094  const MagickSizeType extent)
4095{
4096  assert(image != (Image *) NULL);
4097  assert(image->signature == MagickCoreSignature);
4098  if (image->debug != MagickFalse)
4099    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4100  assert(image->blob != (BlobInfo *) NULL);
4101  assert(image->blob->type != UndefinedStream);
4102  switch (image->blob->type)
4103  {
4104    case UndefinedStream:
4105      break;
4106    case StandardStream:
4107      return(MagickFalse);
4108    case FileStream:
4109    {
4110      MagickOffsetType
4111        offset;
4112
4113      ssize_t
4114        count;
4115
4116      if (extent != (MagickSizeType) ((off_t) extent))
4117        return(MagickFalse);
4118      offset=SeekBlob(image,0,SEEK_END);
4119      if (offset < 0)
4120        return(MagickFalse);
4121      if ((MagickSizeType) offset >= extent)
4122        break;
4123      offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4124      if (offset < 0)
4125        break;
4126      count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4127        image->blob->file_info.file);
4128#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4129      if (image->blob->synchronize != MagickFalse)
4130        {
4131          int
4132            file;
4133
4134          file=fileno(image->blob->file_info.file);
4135          if ((file == -1) || (offset < 0))
4136            return(MagickFalse);
4137          (void) posix_fallocate(file,offset,extent-offset);
4138        }
4139#endif
4140      offset=SeekBlob(image,offset,SEEK_SET);
4141      if (count != 1)
4142        return(MagickFalse);
4143      break;
4144    }
4145    case PipeStream:
4146    case ZipStream:
4147      return(MagickFalse);
4148    case BZipStream:
4149      return(MagickFalse);
4150    case FifoStream:
4151      return(MagickFalse);
4152    case BlobStream:
4153    {
4154      if (extent != (MagickSizeType) ((size_t) extent))
4155        return(MagickFalse);
4156      if (image->blob->mapped != MagickFalse)
4157        {
4158          MagickOffsetType
4159            offset;
4160
4161          ssize_t
4162            count;
4163
4164          (void) UnmapBlob(image->blob->data,image->blob->length);
4165          RelinquishMagickResource(MapResource,image->blob->length);
4166          if (extent != (MagickSizeType) ((off_t) extent))
4167            return(MagickFalse);
4168          offset=SeekBlob(image,0,SEEK_END);
4169          if (offset < 0)
4170            return(MagickFalse);
4171          if ((MagickSizeType) offset >= extent)
4172            break;
4173          offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4174          count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4175            image->blob->file_info.file);
4176#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4177          if (image->blob->synchronize != MagickFalse)
4178            {
4179              int
4180                file;
4181
4182              file=fileno(image->blob->file_info.file);
4183              if ((file == -1) || (offset < 0))
4184                return(MagickFalse);
4185              (void) posix_fallocate(file,offset,extent-offset);
4186            }
4187#endif
4188          offset=SeekBlob(image,offset,SEEK_SET);
4189          if (count != 1)
4190            return(MagickFalse);
4191          (void) AcquireMagickResource(MapResource,extent);
4192          image->blob->data=(unsigned char*) MapBlob(fileno(
4193            image->blob->file_info.file),WriteMode,0,(size_t) extent);
4194          image->blob->extent=(size_t) extent;
4195          image->blob->length=(size_t) extent;
4196          (void) SyncBlob(image);
4197          break;
4198        }
4199      image->blob->extent=(size_t) extent;
4200      image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
4201        image->blob->extent+1,sizeof(*image->blob->data));
4202      (void) SyncBlob(image);
4203      if (image->blob->data == (unsigned char *) NULL)
4204        {
4205          (void) DetachBlob(image->blob);
4206          return(MagickFalse);
4207        }
4208      break;
4209    }
4210  }
4211  return(MagickTrue);
4212}
4213
4214/*
4215%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4216%                                                                             %
4217%                                                                             %
4218%                                                                             %
4219+  S y n c B l o b                                                            %
4220%                                                                             %
4221%                                                                             %
4222%                                                                             %
4223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4224%
4225%  SyncBlob() flushes the datastream if it is a file or synchronizes the data
4226%  attributes if it is an blob.
4227%
4228%  The format of the SyncBlob method is:
4229%
4230%      int SyncBlob(Image *image)
4231%
4232%  A description of each parameter follows:
4233%
4234%    o image: the image.
4235%
4236*/
4237static int SyncBlob(Image *image)
4238{
4239  int
4240    status;
4241
4242  assert(image != (Image *) NULL);
4243  assert(image->signature == MagickCoreSignature);
4244  if (image->debug != MagickFalse)
4245    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4246  assert(image->blob != (BlobInfo *) NULL);
4247  assert(image->blob->type != UndefinedStream);
4248  status=0;
4249  switch (image->blob->type)
4250  {
4251    case UndefinedStream:
4252    case StandardStream:
4253      break;
4254    case FileStream:
4255    case PipeStream:
4256    {
4257      status=fflush(image->blob->file_info.file);
4258      break;
4259    }
4260    case ZipStream:
4261    {
4262#if defined(MAGICKCORE_ZLIB_DELEGATE)
4263      status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
4264#endif
4265      break;
4266    }
4267    case BZipStream:
4268    {
4269#if defined(MAGICKCORE_BZLIB_DELEGATE)
4270      status=BZ2_bzflush(image->blob->file_info.bzfile);
4271#endif
4272      break;
4273    }
4274    case FifoStream:
4275      break;
4276    case BlobStream:
4277      break;
4278  }
4279  return(status);
4280}
4281
4282/*
4283%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4284%                                                                             %
4285%                                                                             %
4286%                                                                             %
4287+  T e l l B l o b                                                            %
4288%                                                                             %
4289%                                                                             %
4290%                                                                             %
4291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4292%
4293%  TellBlob() obtains the current value of the blob or file position.
4294%
4295%  The format of the TellBlob method is:
4296%
4297%      MagickOffsetType TellBlob(const Image *image)
4298%
4299%  A description of each parameter follows:
4300%
4301%    o image: the image.
4302%
4303*/
4304MagickExport MagickOffsetType TellBlob(const Image *image)
4305{
4306  MagickOffsetType
4307    offset;
4308
4309  assert(image != (Image *) NULL);
4310  assert(image->signature == MagickCoreSignature);
4311  if (image->debug != MagickFalse)
4312    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4313  assert(image->blob != (BlobInfo *) NULL);
4314  assert(image->blob->type != UndefinedStream);
4315  offset=(-1);
4316  switch (image->blob->type)
4317  {
4318    case UndefinedStream:
4319    case StandardStream:
4320      break;
4321    case FileStream:
4322    {
4323      offset=ftell(image->blob->file_info.file);
4324      break;
4325    }
4326    case PipeStream:
4327      break;
4328    case ZipStream:
4329    {
4330#if defined(MAGICKCORE_ZLIB_DELEGATE)
4331      offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
4332#endif
4333      break;
4334    }
4335    case BZipStream:
4336      break;
4337    case FifoStream:
4338      break;
4339    case BlobStream:
4340    {
4341      offset=image->blob->offset;
4342      break;
4343    }
4344  }
4345  return(offset);
4346}
4347
4348/*
4349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4350%                                                                             %
4351%                                                                             %
4352%                                                                             %
4353+  U n m a p B l o b                                                          %
4354%                                                                             %
4355%                                                                             %
4356%                                                                             %
4357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4358%
4359%  UnmapBlob() deallocates the binary large object previously allocated with
4360%  the MapBlob method.
4361%
4362%  The format of the UnmapBlob method is:
4363%
4364%       MagickBooleanType UnmapBlob(void *map,const size_t length)
4365%
4366%  A description of each parameter follows:
4367%
4368%    o map: the address  of the binary large object.
4369%
4370%    o length: the length of the binary large object.
4371%
4372*/
4373MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4374{
4375#if defined(MAGICKCORE_HAVE_MMAP)
4376  int
4377    status;
4378
4379  status=munmap(map,length);
4380  return(status == -1 ? MagickFalse : MagickTrue);
4381#else
4382  (void) map;
4383  (void) length;
4384  return(MagickFalse);
4385#endif
4386}
4387
4388/*
4389%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4390%                                                                             %
4391%                                                                             %
4392%                                                                             %
4393+  W r i t e B l o b                                                          %
4394%                                                                             %
4395%                                                                             %
4396%                                                                             %
4397%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4398%
4399%  WriteBlob() writes data to a blob or image file.  It returns the number of
4400%  bytes written.
4401%
4402%  The format of the WriteBlob method is:
4403%
4404%      ssize_t WriteBlob(Image *image,const size_t length,const void *data)
4405%
4406%  A description of each parameter follows:
4407%
4408%    o image: the image.
4409%
4410%    o length:  Specifies an integer representing the number of bytes to
4411%      write to the file.
4412%
4413%    o data:  The address of the data to write to the blob or file.
4414%
4415*/
4416MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4417  const void *data)
4418{
4419  int
4420    c;
4421
4422  register const unsigned char
4423    *p;
4424
4425  ssize_t
4426    count;
4427
4428  assert(image != (Image *) NULL);
4429  assert(image->signature == MagickCoreSignature);
4430  assert(data != (const void *) NULL);
4431  assert(image->blob != (BlobInfo *) NULL);
4432  assert(image->blob->type != UndefinedStream);
4433  if (length == 0)
4434    return(0);
4435  count=0;
4436  p=(const unsigned char *) data;
4437  switch (image->blob->type)
4438  {
4439    case UndefinedStream:
4440      break;
4441    case StandardStream:
4442    case FileStream:
4443    case PipeStream:
4444    {
4445      switch (length)
4446      {
4447        default:
4448        {
4449          count=(ssize_t) fwrite((const char *) data,1,length,
4450            image->blob->file_info.file);
4451          break;
4452        }
4453        case 4:
4454        {
4455          c=putc((int) *p++,image->blob->file_info.file);
4456          if (c == EOF)
4457            break;
4458          count++;
4459        }
4460        case 3:
4461        {
4462          c=putc((int) *p++,image->blob->file_info.file);
4463          if (c == EOF)
4464            break;
4465          count++;
4466        }
4467        case 2:
4468        {
4469          c=putc((int) *p++,image->blob->file_info.file);
4470          if (c == EOF)
4471            break;
4472          count++;
4473        }
4474        case 1:
4475        {
4476          c=putc((int) *p++,image->blob->file_info.file);
4477          if (c == EOF)
4478            break;
4479          count++;
4480        }
4481        case 0:
4482          break;
4483      }
4484      break;
4485    }
4486    case ZipStream:
4487    {
4488#if defined(MAGICKCORE_ZLIB_DELEGATE)
4489      switch (length)
4490      {
4491        default:
4492        {
4493          count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
4494            (unsigned int) length);
4495          break;
4496        }
4497        case 4:
4498        {
4499          c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4500          if (c == EOF)
4501            break;
4502          count++;
4503        }
4504        case 3:
4505        {
4506          c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4507          if (c == EOF)
4508            break;
4509          count++;
4510        }
4511        case 2:
4512        {
4513          c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4514          if (c == EOF)
4515            break;
4516          count++;
4517        }
4518        case 1:
4519        {
4520          c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4521          if (c == EOF)
4522            break;
4523          count++;
4524        }
4525        case 0:
4526          break;
4527      }
4528#endif
4529      break;
4530    }
4531    case BZipStream:
4532    {
4533#if defined(MAGICKCORE_BZLIB_DELEGATE)
4534      count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
4535        (int) length);
4536#endif
4537      break;
4538    }
4539    case FifoStream:
4540    {
4541      count=(ssize_t) image->blob->stream(image,data,length);
4542      break;
4543    }
4544    case BlobStream:
4545    {
4546      register unsigned char
4547        *q;
4548
4549      if ((image->blob->offset+(MagickOffsetType) length) >=
4550          (MagickOffsetType) image->blob->extent)
4551        {
4552          if (image->blob->mapped != MagickFalse)
4553            return(0);
4554          image->blob->extent+=length+image->blob->quantum;
4555          image->blob->quantum<<=1;
4556          image->blob->data=(unsigned char *) ResizeQuantumMemory(
4557            image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4558          (void) SyncBlob(image);
4559          if (image->blob->data == (unsigned char *) NULL)
4560            {
4561              (void) DetachBlob(image->blob);
4562              return(0);
4563            }
4564        }
4565      q=image->blob->data+image->blob->offset;
4566      (void) memcpy(q,p,length);
4567      image->blob->offset+=length;
4568      if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4569        image->blob->length=(size_t) image->blob->offset;
4570      count=(ssize_t) length;
4571    }
4572  }
4573  return(count);
4574}
4575
4576/*
4577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4578%                                                                             %
4579%                                                                             %
4580%                                                                             %
4581+  W r i t e B l o b B y t e                                                  %
4582%                                                                             %
4583%                                                                             %
4584%                                                                             %
4585%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4586%
4587%  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
4588%  written (either 0 or 1);
4589%
4590%  The format of the WriteBlobByte method is:
4591%
4592%      ssize_t WriteBlobByte(Image *image,const unsigned char value)
4593%
4594%  A description of each parameter follows.
4595%
4596%    o image: the image.
4597%
4598%    o value: Specifies the value to write.
4599%
4600*/
4601MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4602{
4603  assert(image != (Image *) NULL);
4604  assert(image->signature == MagickCoreSignature);
4605  return(WriteBlobStream(image,1,&value));
4606}
4607
4608/*
4609%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4610%                                                                             %
4611%                                                                             %
4612%                                                                             %
4613+  W r i t e B l o b F l o a t                                                %
4614%                                                                             %
4615%                                                                             %
4616%                                                                             %
4617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4618%
4619%  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4620%  specified by the endian member of the image structure.
4621%
4622%  The format of the WriteBlobFloat method is:
4623%
4624%      ssize_t WriteBlobFloat(Image *image,const float value)
4625%
4626%  A description of each parameter follows.
4627%
4628%    o image: the image.
4629%
4630%    o value: Specifies the value to write.
4631%
4632*/
4633MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4634{
4635  union
4636  {
4637    unsigned int
4638      unsigned_value;
4639
4640    float
4641      float_value;
4642  } quantum;
4643
4644  quantum.unsigned_value=0U;
4645  quantum.float_value=value;
4646  return(WriteBlobLong(image,quantum.unsigned_value));
4647}
4648
4649/*
4650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4651%                                                                             %
4652%                                                                             %
4653%                                                                             %
4654+  W r i t e B l o b L o n g                                                  %
4655%                                                                             %
4656%                                                                             %
4657%                                                                             %
4658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4659%
4660%  WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
4661%  byte-order specified by the endian member of the image structure.
4662%
4663%  The format of the WriteBlobLong method is:
4664%
4665%      ssize_t WriteBlobLong(Image *image,const unsigned int value)
4666%
4667%  A description of each parameter follows.
4668%
4669%    o image: the image.
4670%
4671%    o value: Specifies the value to write.
4672%
4673*/
4674MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4675{
4676  unsigned char
4677    buffer[4];
4678
4679  assert(image != (Image *) NULL);
4680  assert(image->signature == MagickCoreSignature);
4681  if (image->endian == LSBEndian)
4682    {
4683      buffer[0]=(unsigned char) value;
4684      buffer[1]=(unsigned char) (value >> 8);
4685      buffer[2]=(unsigned char) (value >> 16);
4686      buffer[3]=(unsigned char) (value >> 24);
4687      return(WriteBlobStream(image,4,buffer));
4688    }
4689  buffer[0]=(unsigned char) (value >> 24);
4690  buffer[1]=(unsigned char) (value >> 16);
4691  buffer[2]=(unsigned char) (value >> 8);
4692  buffer[3]=(unsigned char) value;
4693  return(WriteBlobStream(image,4,buffer));
4694}
4695
4696/*
4697%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4698%                                                                             %
4699%                                                                             %
4700%                                                                             %
4701+   W r i t e B l o b S h o r t                                               %
4702%                                                                             %
4703%                                                                             %
4704%                                                                             %
4705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4706%
4707%  WriteBlobShort() writes a short value as a 16-bit quantity in the
4708%  byte-order specified by the endian member of the image structure.
4709%
4710%  The format of the WriteBlobShort method is:
4711%
4712%      ssize_t WriteBlobShort(Image *image,const unsigned short value)
4713%
4714%  A description of each parameter follows.
4715%
4716%    o image: the image.
4717%
4718%    o value:  Specifies the value to write.
4719%
4720*/
4721MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4722{
4723  unsigned char
4724    buffer[2];
4725
4726  assert(image != (Image *) NULL);
4727  assert(image->signature == MagickCoreSignature);
4728  if (image->endian == LSBEndian)
4729    {
4730      buffer[0]=(unsigned char) value;
4731      buffer[1]=(unsigned char) (value >> 8);
4732      return(WriteBlobStream(image,2,buffer));
4733    }
4734  buffer[0]=(unsigned char) (value >> 8);
4735  buffer[1]=(unsigned char) value;
4736  return(WriteBlobStream(image,2,buffer));
4737}
4738
4739/*
4740%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4741%                                                                             %
4742%                                                                             %
4743%                                                                             %
4744+  W r i t e B l o b L S B L o n g                                            %
4745%                                                                             %
4746%                                                                             %
4747%                                                                             %
4748%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4749%
4750%  WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
4751%  least-significant byte first order.
4752%
4753%  The format of the WriteBlobLSBLong method is:
4754%
4755%      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4756%
4757%  A description of each parameter follows.
4758%
4759%    o image: the image.
4760%
4761%    o value: Specifies the value to write.
4762%
4763*/
4764MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4765{
4766  unsigned char
4767    buffer[4];
4768
4769  assert(image != (Image *) NULL);
4770  assert(image->signature == MagickCoreSignature);
4771  buffer[0]=(unsigned char) value;
4772  buffer[1]=(unsigned char) (value >> 8);
4773  buffer[2]=(unsigned char) (value >> 16);
4774  buffer[3]=(unsigned char) (value >> 24);
4775  return(WriteBlobStream(image,4,buffer));
4776}
4777
4778/*
4779%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4780%                                                                             %
4781%                                                                             %
4782%                                                                             %
4783+   W r i t e B l o b L S B S h o r t                                         %
4784%                                                                             %
4785%                                                                             %
4786%                                                                             %
4787%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4788%
4789%  WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
4790%  least-significant byte first order.
4791%
4792%  The format of the WriteBlobLSBShort method is:
4793%
4794%      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4795%
4796%  A description of each parameter follows.
4797%
4798%    o image: the image.
4799%
4800%    o value:  Specifies the value to write.
4801%
4802*/
4803MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4804{
4805  unsigned char
4806    buffer[2];
4807
4808  assert(image != (Image *) NULL);
4809  assert(image->signature == MagickCoreSignature);
4810  buffer[0]=(unsigned char) value;
4811  buffer[1]=(unsigned char) (value >> 8);
4812  return(WriteBlobStream(image,2,buffer));
4813}
4814
4815/*
4816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4817%                                                                             %
4818%                                                                             %
4819%                                                                             %
4820+  W r i t e B l o b L S B S i g n e d L o n g                                %
4821%                                                                             %
4822%                                                                             %
4823%                                                                             %
4824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4825%
4826%  WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
4827%  least-significant byte first order.
4828%
4829%  The format of the WriteBlobLSBSignedLong method is:
4830%
4831%      ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
4832%
4833%  A description of each parameter follows.
4834%
4835%    o image: the image.
4836%
4837%    o value: Specifies the value to write.
4838%
4839*/
4840MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
4841{
4842  union
4843  {
4844    unsigned int
4845      unsigned_value;
4846
4847    signed int
4848      signed_value;
4849  } quantum;
4850
4851  unsigned char
4852    buffer[4];
4853
4854  assert(image != (Image *) NULL);
4855  assert(image->signature == MagickCoreSignature);
4856  quantum.signed_value=value;
4857  buffer[0]=(unsigned char) quantum.unsigned_value;
4858  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
4859  buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
4860  buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
4861  return(WriteBlobStream(image,4,buffer));
4862}
4863
4864/*
4865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4866%                                                                             %
4867%                                                                             %
4868%                                                                             %
4869+   W r i t e B l o b L S B S i g n e d S h o r t                             %
4870%                                                                             %
4871%                                                                             %
4872%                                                                             %
4873%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4874%
4875%  WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
4876%  in least-significant byte first order.
4877%
4878%  The format of the WriteBlobLSBSignedShort method is:
4879%
4880%      ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
4881%
4882%  A description of each parameter follows.
4883%
4884%    o image: the image.
4885%
4886%    o value:  Specifies the value to write.
4887%
4888*/
4889MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
4890  const signed short value)
4891{
4892  union
4893  {
4894    unsigned short
4895      unsigned_value;
4896
4897    signed short
4898      signed_value;
4899  } quantum;
4900
4901  unsigned char
4902    buffer[2];
4903
4904  assert(image != (Image *) NULL);
4905  assert(image->signature == MagickCoreSignature);
4906  quantum.signed_value=value;
4907  buffer[0]=(unsigned char) quantum.unsigned_value;
4908  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
4909  return(WriteBlobStream(image,2,buffer));
4910}
4911
4912/*
4913%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4914%                                                                             %
4915%                                                                             %
4916%                                                                             %
4917+  W r i t e B l o b M S B L o n g                                            %
4918%                                                                             %
4919%                                                                             %
4920%                                                                             %
4921%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4922%
4923%  WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
4924%  most-significant byte first order.
4925%
4926%  The format of the WriteBlobMSBLong method is:
4927%
4928%      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4929%
4930%  A description of each parameter follows.
4931%
4932%    o value:  Specifies the value to write.
4933%
4934%    o image: the image.
4935%
4936*/
4937MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4938{
4939  unsigned char
4940    buffer[4];
4941
4942  assert(image != (Image *) NULL);
4943  assert(image->signature == MagickCoreSignature);
4944  buffer[0]=(unsigned char) (value >> 24);
4945  buffer[1]=(unsigned char) (value >> 16);
4946  buffer[2]=(unsigned char) (value >> 8);
4947  buffer[3]=(unsigned char) value;
4948  return(WriteBlobStream(image,4,buffer));
4949}
4950
4951/*
4952%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4953%                                                                             %
4954%                                                                             %
4955%                                                                             %
4956+  W r i t e B l o b M S B L o n g L o n g                                    %
4957%                                                                             %
4958%                                                                             %
4959%                                                                             %
4960%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4961%
4962%  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4963%  most-significant byte first order.
4964%
4965%  The format of the WriteBlobMSBLongLong method is:
4966%
4967%      ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4968%
4969%  A description of each parameter follows.
4970%
4971%    o value:  Specifies the value to write.
4972%
4973%    o image: the image.
4974%
4975*/
4976MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4977  const MagickSizeType value)
4978{
4979  unsigned char
4980    buffer[8];
4981
4982  assert(image != (Image *) NULL);
4983  assert(image->signature == MagickCoreSignature);
4984  buffer[0]=(unsigned char) (value >> 56);
4985  buffer[1]=(unsigned char) (value >> 48);
4986  buffer[2]=(unsigned char) (value >> 40);
4987  buffer[3]=(unsigned char) (value >> 32);
4988  buffer[4]=(unsigned char) (value >> 24);
4989  buffer[5]=(unsigned char) (value >> 16);
4990  buffer[6]=(unsigned char) (value >> 8);
4991  buffer[7]=(unsigned char) value;
4992  return(WriteBlobStream(image,8,buffer));
4993}
4994
4995/*
4996%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4997%                                                                             %
4998%                                                                             %
4999%                                                                             %
5000+  W r i t e B l o b M S B S i g n e d L o n g                                %
5001%                                                                             %
5002%                                                                             %
5003%                                                                             %
5004%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5005%
5006%  WriteBlobMSBSignedLong() writes a signed value as a 32-bit quantity in
5007%  most-significant byte first order.
5008%
5009%  The format of the WriteBlobMSBSignedLong method is:
5010%
5011%      ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5012%
5013%  A description of each parameter follows.
5014%
5015%    o image: the image.
5016%
5017%    o value: Specifies the value to write.
5018%
5019*/
5020MagickExport ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5021{
5022  union
5023  {
5024    unsigned int
5025      unsigned_value;
5026
5027    signed int
5028      signed_value;
5029  } quantum;
5030
5031  unsigned char
5032    buffer[4];
5033
5034  assert(image != (Image *) NULL);
5035  assert(image->signature == MagickCoreSignature);
5036  quantum.signed_value=value;
5037  buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
5038  buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
5039  buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
5040  buffer[3]=(unsigned char) quantum.unsigned_value;
5041  return(WriteBlobStream(image,4,buffer));
5042}
5043
5044/*
5045%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5046%                                                                             %
5047%                                                                             %
5048%                                                                             %
5049+   W r i t e B l o b M S B S i g n e d S h o r t                             %
5050%                                                                             %
5051%                                                                             %
5052%                                                                             %
5053%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5054%
5055%  WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
5056%  in most-significant byte first order.
5057%
5058%  The format of the WriteBlobMSBSignedShort method is:
5059%
5060%      ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
5061%
5062%  A description of each parameter follows.
5063%
5064%    o image: the image.
5065%
5066%    o value:  Specifies the value to write.
5067%
5068*/
5069MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
5070  const signed short value)
5071{
5072  union
5073  {
5074    unsigned short
5075      unsigned_value;
5076
5077    signed short
5078      signed_value;
5079  } quantum;
5080
5081  unsigned char
5082    buffer[2];
5083
5084  assert(image != (Image *) NULL);
5085  assert(image->signature == MagickCoreSignature);
5086  quantum.signed_value=value;
5087  buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
5088  buffer[1]=(unsigned char) quantum.unsigned_value;
5089  return(WriteBlobStream(image,2,buffer));
5090}
5091
5092/*
5093%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5094%                                                                             %
5095%                                                                             %
5096%                                                                             %
5097+  W r i t e B l o b M S B S h o r t                                          %
5098%                                                                             %
5099%                                                                             %
5100%                                                                             %
5101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5102%
5103%  WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
5104%  most-significant byte first order.
5105%
5106%  The format of the WriteBlobMSBShort method is:
5107%
5108%      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5109%
5110%  A description of each parameter follows.
5111%
5112%   o  value:  Specifies the value to write.
5113%
5114%   o  file:  Specifies the file to write the data to.
5115%
5116*/
5117MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5118{
5119  unsigned char
5120    buffer[2];
5121
5122  assert(image != (Image *) NULL);
5123  assert(image->signature == MagickCoreSignature);
5124  buffer[0]=(unsigned char) (value >> 8);
5125  buffer[1]=(unsigned char) value;
5126  return(WriteBlobStream(image,2,buffer));
5127}
5128
5129/*
5130%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5131%                                                                             %
5132%                                                                             %
5133%                                                                             %
5134+  W r i t e B l o b S t r i n g                                              %
5135%                                                                             %
5136%                                                                             %
5137%                                                                             %
5138%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5139%
5140%  WriteBlobString() write a string to a blob.  It returns the number of
5141%  characters written.
5142%
5143%  The format of the WriteBlobString method is:
5144%
5145%      ssize_t WriteBlobString(Image *image,const char *string)
5146%
5147%  A description of each parameter follows.
5148%
5149%    o image: the image.
5150%
5151%    o string: Specifies the string to write.
5152%
5153*/
5154MagickExport ssize_t WriteBlobString(Image *image,const char *string)
5155{
5156  assert(image != (Image *) NULL);
5157  assert(image->signature == MagickCoreSignature);
5158  assert(string != (const char *) NULL);
5159  return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
5160}
5161