root/ImageMagick/trunk/magick/blob.c

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