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

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