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