root/ImageMagick/trunk/magick/blob.c

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