blob: 3d60657336dd62e47a049cc75bbaf73d21326014 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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% %
cristy16af1cb2009-12-11 21:38:29 +000020% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% 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
cristy90823212009-12-12 20:48:33 +0000418 clone_info=(BlobInfo *) AcquireAlignedMemory(1,sizeof(*clone_info));
cristy3ed852e2009-09-05 21:47:34 +0000419 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)
3939%
3940% A description of each parameter follows.
3941%
3942% o image: the image.
3943%
3944% o value: Specifies the value to write.
3945%
3946*/
3947MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
3948{
3949 assert(image != (Image *) NULL);
3950 assert(image->signature == MagickSignature);
3951 return(WriteBlobStream(image,1,&value));
3952}
3953
3954/*
3955%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3956% %
3957% %
3958% %
3959+ W r i t e B l o b F l o a t %
3960% %
3961% %
3962% %
3963%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3964%
3965% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
3966% specified by the endian member of the image structure.
3967%
3968% The format of the WriteBlobFloat method is:
3969%
3970% ssize_t WriteBlobFloat(Image *image,const float value)
3971%
3972% A description of each parameter follows.
3973%
3974% o image: the image.
3975%
3976% o value: Specifies the value to write.
3977%
3978*/
3979MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
3980{
3981 union
3982 {
3983 unsigned int
3984 unsigned_value;
3985
3986 float
3987 float_value;
3988 } quantum;
3989
3990 quantum.unsigned_value=0U;
3991 quantum.float_value=value;
3992 return(WriteBlobLong(image,quantum.unsigned_value));
3993}
3994
3995/*
3996%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3997% %
3998% %
3999% %
4000+ W r i t e B l o b L o n g %
4001% %
4002% %
4003% %
4004%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4005%
4006% WriteBlobLong() writes a long value as a 32-bit quantity in the byte-order
4007% specified by the endian member of the image structure.
4008%
4009% The format of the WriteBlobLong method is:
4010%
4011% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4012%
4013% A description of each parameter follows.
4014%
4015% o image: the image.
4016%
4017% o value: Specifies the value to write.
4018%
4019*/
4020MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4021{
4022 unsigned char
4023 buffer[4];
4024
4025 assert(image != (Image *) NULL);
4026 assert(image->signature == MagickSignature);
4027 if (image->endian == LSBEndian)
4028 {
4029 buffer[0]=(unsigned char) value;
4030 buffer[1]=(unsigned char) (value >> 8);
4031 buffer[2]=(unsigned char) (value >> 16);
4032 buffer[3]=(unsigned char) (value >> 24);
4033 return(WriteBlobStream(image,4,buffer));
4034 }
4035 buffer[0]=(unsigned char) (value >> 24);
4036 buffer[1]=(unsigned char) (value >> 16);
4037 buffer[2]=(unsigned char) (value >> 8);
4038 buffer[3]=(unsigned char) value;
4039 return(WriteBlobStream(image,4,buffer));
4040}
4041
4042/*
4043%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4044% %
4045% %
4046% %
4047+ W r i t e B l o b S h o r t %
4048% %
4049% %
4050% %
4051%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4052%
4053% WriteBlobShort() writes a short value as a 16-bit quantity in the
4054% byte-order specified by the endian member of the image structure.
4055%
4056% The format of the WriteBlobShort method is:
4057%
4058% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4059%
4060% A description of each parameter follows.
4061%
4062% o image: the image.
4063%
4064% o value: Specifies the value to write.
4065%
4066*/
4067MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4068{
4069 unsigned char
4070 buffer[2];
4071
4072 assert(image != (Image *) NULL);
4073 assert(image->signature == MagickSignature);
4074 if (image->endian == LSBEndian)
4075 {
4076 buffer[0]=(unsigned char) value;
4077 buffer[1]=(unsigned char) (value >> 8);
4078 return(WriteBlobStream(image,2,buffer));
4079 }
4080 buffer[0]=(unsigned char) (value >> 8);
4081 buffer[1]=(unsigned char) value;
4082 return(WriteBlobStream(image,2,buffer));
4083}
4084
4085/*
4086%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4087% %
4088% %
4089% %
4090+ W r i t e B l o b L S B L o n g %
4091% %
4092% %
4093% %
4094%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4095%
4096% WriteBlobLSBLong() writes a long value as a 32-bit quantity in
4097% least-significant byte first order.
4098%
4099% The format of the WriteBlobLSBLong method is:
4100%
4101% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4102%
4103% A description of each parameter follows.
4104%
4105% o image: the image.
4106%
4107% o value: Specifies the value to write.
4108%
4109*/
4110MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4111{
4112 unsigned char
4113 buffer[4];
4114
4115 assert(image != (Image *) NULL);
4116 assert(image->signature == MagickSignature);
4117 buffer[0]=(unsigned char) value;
4118 buffer[1]=(unsigned char) (value >> 8);
4119 buffer[2]=(unsigned char) (value >> 16);
4120 buffer[3]=(unsigned char) (value >> 24);
4121 return(WriteBlobStream(image,4,buffer));
4122}
4123
4124/*
4125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4126% %
4127% %
4128% %
4129+ W r i t e B l o b L S B S h o r t %
4130% %
4131% %
4132% %
4133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4134%
4135% WriteBlobLSBShort() writes a long value as a 16-bit quantity in
4136% least-significant byte first order.
4137%
4138% The format of the WriteBlobLSBShort method is:
4139%
4140% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4141%
4142% A description of each parameter follows.
4143%
4144% o image: the image.
4145%
4146% o value: Specifies the value to write.
4147%
4148*/
4149MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4150{
4151 unsigned char
4152 buffer[2];
4153
4154 assert(image != (Image *) NULL);
4155 assert(image->signature == MagickSignature);
4156 buffer[0]=(unsigned char) value;
4157 buffer[1]=(unsigned char) (value >> 8);
4158 return(WriteBlobStream(image,2,buffer));
4159}
4160
4161/*
4162%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4163% %
4164% %
4165% %
4166+ W r i t e B l o b M S B L o n g %
4167% %
4168% %
4169% %
4170%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4171%
4172% WriteBlobMSBLong() writes a long value as a 32-bit quantity in
4173% most-significant byte first order.
4174%
4175% The format of the WriteBlobMSBLong method is:
4176%
4177% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4178%
4179% A description of each parameter follows.
4180%
4181% o value: Specifies the value to write.
4182%
4183% o image: the image.
4184%
4185*/
4186MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4187{
4188 unsigned char
4189 buffer[4];
4190
4191 assert(image != (Image *) NULL);
4192 assert(image->signature == MagickSignature);
4193 buffer[0]=(unsigned char) (value >> 24);
4194 buffer[1]=(unsigned char) (value >> 16);
4195 buffer[2]=(unsigned char) (value >> 8);
4196 buffer[3]=(unsigned char) value;
4197 return(WriteBlobStream(image,4,buffer));
4198}
4199
4200/*
4201%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4202% %
4203% %
4204% %
4205+ W r i t e B l o b M S B S h o r t %
4206% %
4207% %
4208% %
4209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4210%
4211% WriteBlobMSBShort() writes a long value as a 16-bit quantity in
4212% most-significant byte first order.
4213%
4214% The format of the WriteBlobMSBShort method is:
4215%
4216% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4217%
4218% A description of each parameter follows.
4219%
4220% o value: Specifies the value to write.
4221%
4222% o file: Specifies the file to write the data to.
4223%
4224*/
4225MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4226{
4227 unsigned char
4228 buffer[2];
4229
4230 assert(image != (Image *) NULL);
4231 assert(image->signature == MagickSignature);
4232 buffer[0]=(unsigned char) (value >> 8);
4233 buffer[1]=(unsigned char) value;
4234 return(WriteBlobStream(image,2,buffer));
4235}
4236
4237/*
4238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4239% %
4240% %
4241% %
4242+ W r i t e B l o b S t r i n g %
4243% %
4244% %
4245% %
4246%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4247%
4248% WriteBlobString() write a string to a blob. It returns the number of
4249% characters written.
4250%
4251% The format of the WriteBlobString method is:
4252%
4253% ssize_t WriteBlobString(Image *image,const char *string)
4254%
4255% A description of each parameter follows.
4256%
4257% o image: the image.
4258%
4259% o string: Specifies the string to write.
4260%
4261*/
4262MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4263{
4264 assert(image != (Image *) NULL);
4265 assert(image->signature == MagickSignature);
4266 assert(string != (const char *) NULL);
4267 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4268}