source: ImageMagick/trunk/magick/blob.c @ 3849

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