blob: 59688433c49307a7f9ec2f720710d68b7e36dbfd [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);
cristy2a9e7cb2010-03-05 02:15:05 +00002043#if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
2044 (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
2045 POSIX_MADV_WILLNEED);
2046#endif
cristy3ed852e2009-09-05 21:47:34 +00002047 break;
2048 }
2049 case IOMode:
2050 {
2051 protection=PROT_READ | PROT_WRITE;
2052 flags|=MAP_SHARED;
2053 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2054 (off_t) offset);
2055 break;
2056 }
2057 }
2058 if (map == (unsigned char *) MAP_FAILED)
2059 return((unsigned char *) NULL);
2060 return(map);
2061#else
2062 (void) file;
2063 (void) mode;
2064 (void) offset;
2065 (void) length;
2066 return((unsigned char *) NULL);
2067#endif
2068}
2069
2070/*
2071%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2072% %
2073% %
2074% %
2075+ M S B O r d e r L o n g %
2076% %
2077% %
2078% %
2079%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2080%
2081% MSBOrderLong() converts a least-significant byte first buffer of integers to
2082% most-significant byte first.
2083%
2084% The format of the MSBOrderLong method is:
2085%
2086% void MSBOrderLong(unsigned char *buffer,const size_t length)
2087%
2088% A description of each parameter follows.
2089%
2090% o buffer: Specifies a pointer to a buffer of integers.
2091%
2092% o length: Specifies the length of the buffer.
2093%
2094*/
2095MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2096{
2097 int
2098 c;
2099
2100 register unsigned char
2101 *p,
2102 *q;
2103
2104 assert(buffer != (unsigned char *) NULL);
2105 q=buffer+length;
2106 while (buffer < q)
2107 {
2108 p=buffer+3;
2109 c=(int) (*p);
2110 *p=(*buffer);
2111 *buffer++=(unsigned char) c;
2112 p=buffer+1;
2113 c=(int) (*p);
2114 *p=(*buffer);
2115 *buffer++=(unsigned char) c;
2116 buffer+=2;
2117 }
2118}
2119
2120/*
2121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2122% %
2123% %
2124% %
2125+ M S B O r d e r S h o r t %
2126% %
2127% %
2128% %
2129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2130%
2131% MSBOrderShort() converts a least-significant byte first buffer of integers
2132% to most-significant byte first.
2133%
2134% The format of the MSBOrderShort method is:
2135%
2136% void MSBOrderShort(unsigned char *p,const size_t length)
2137%
2138% A description of each parameter follows.
2139%
2140% o p: Specifies a pointer to a buffer of integers.
2141%
2142% o length: Specifies the length of the buffer.
2143%
2144*/
2145MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2146{
2147 int
2148 c;
2149
2150 register unsigned char
2151 *q;
2152
2153 assert(p != (unsigned char *) NULL);
2154 q=p+length;
2155 while (p < q)
2156 {
2157 c=(int) (*p);
2158 *p=(*(p+1));
2159 p++;
2160 *p++=(unsigned char) c;
2161 }
2162}
2163
2164/*
2165%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2166% %
2167% %
2168% %
2169+ O p e n B l o b %
2170% %
2171% %
2172% %
2173%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2174%
2175% OpenBlob() opens a file associated with the image. A file name of '-' sets
2176% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2177% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2178% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2179% from a system command.
2180%
2181% The format of the OpenBlob method is:
2182%
2183% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2184% const BlobMode mode,ExceptionInfo *exception)
2185%
2186% A description of each parameter follows:
2187%
2188% o image_info: the image info.
2189%
2190% o image: the image.
2191%
2192% o mode: the mode for opening the file.
2193%
2194*/
2195MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2196 Image *image,const BlobMode mode,ExceptionInfo *exception)
2197{
2198 char
2199 filename[MaxTextExtent];
2200
2201 const char
2202 *type;
2203
2204 MagickBooleanType
2205 status;
2206
2207 PolicyRights
2208 rights;
2209
2210 assert(image_info != (ImageInfo *) NULL);
2211 assert(image_info->signature == MagickSignature);
2212 if (image_info->debug != MagickFalse)
2213 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2214 image_info->filename);
2215 assert(image != (Image *) NULL);
2216 assert(image->signature == MagickSignature);
2217 if (image_info->blob != (void *) NULL)
2218 {
2219 if (image_info->stream != (StreamHandler) NULL)
2220 image->blob->stream=(StreamHandler) image_info->stream;
2221 AttachBlob(image->blob,image_info->blob,image_info->length);
2222 return(MagickTrue);
2223 }
2224 (void) DetachBlob(image->blob);
2225 switch (mode)
2226 {
2227 default: type="r"; break;
2228 case ReadBlobMode: type="r"; break;
2229 case ReadBinaryBlobMode: type="rb"; break;
2230 case WriteBlobMode: type="w"; break;
2231 case WriteBinaryBlobMode: type="w+b"; break;
2232 case AppendBlobMode: type="a"; break;
2233 case AppendBinaryBlobMode: type="a+b"; break;
2234 }
2235 if (*type != 'r')
2236 image->blob->synchronize=image_info->synchronize;
2237 if (image_info->stream != (StreamHandler) NULL)
2238 {
2239 image->blob->stream=(StreamHandler) image_info->stream;
2240 if (*type == 'w')
2241 {
2242 image->blob->type=FifoStream;
2243 return(MagickTrue);
2244 }
2245 }
2246 /*
2247 Open image file.
2248 */
2249 *filename='\0';
2250 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2251 rights=ReadPolicyRights;
2252 if (*type == 'w')
2253 rights=WritePolicyRights;
2254 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2255 {
cristya9197f62010-01-12 02:23:34 +00002256 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002257 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2258 "NotAuthorized","`%s'",filename);
2259 return(MagickFalse);
2260 }
2261 if ((LocaleCompare(filename,"-") == 0) ||
2262 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2263 {
2264 image->blob->file=(*type == 'r') ? stdin : stdout;
2265#if defined(__WINDOWS__) || defined(__OS2__)
2266 if (strchr(type,'b') != (char *) NULL)
2267 setmode(_fileno(image->blob->file),_O_BINARY);
2268#endif
2269 image->blob->type=StandardStream;
2270 image->blob->exempt=MagickTrue;
2271 return(MagickTrue);
2272 }
2273 if (LocaleNCompare(filename,"fd:",3) == 0)
2274 {
2275 char
2276 mode[MaxTextExtent];
2277
2278 *mode=(*type);
2279 mode[1]='\0';
cristyf2f27272009-12-17 14:48:46 +00002280 image->blob->file=fdopen(StringToLong(filename+3),mode);
cristy3ed852e2009-09-05 21:47:34 +00002281#if defined(__WINDOWS__) || defined(__OS2__)
2282 if (strchr(type,'b') != (char *) NULL)
2283 setmode(_fileno(image->blob->file),_O_BINARY);
2284#endif
2285 image->blob->type=StandardStream;
2286 image->blob->exempt=MagickTrue;
2287 return(MagickTrue);
2288 }
2289#if defined(MAGICKCORE_HAVE_POPEN)
2290 if (*filename == '|')
2291 {
2292 char
2293 mode[MaxTextExtent];
2294
2295 /*
2296 Pipe image to or from a system command.
2297 */
2298#if defined(SIGPIPE)
2299 if (*type == 'w')
2300 (void) signal(SIGPIPE,SIG_IGN);
2301#endif
2302 *mode=(*type);
2303 mode[1]='\0';
2304 image->blob->file=(FILE *) popen(filename+1,mode);
2305 if (image->blob->file == (FILE *) NULL)
2306 {
2307 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2308 return(MagickFalse);
2309 }
2310 image->blob->type=PipeStream;
2311 image->blob->exempt=MagickTrue;
2312 return(MagickTrue);
2313 }
2314#endif
2315 status=GetPathAttributes(filename,&image->blob->properties);
2316#if defined(S_ISFIFO)
2317 if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2318 {
2319 image->blob->file=(FILE *) OpenMagickStream(filename,type);
2320 if (image->blob->file == (FILE *) NULL)
2321 {
2322 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2323 return(MagickFalse);
2324 }
2325 image->blob->type=FileStream;
2326 image->blob->exempt=MagickTrue;
2327 return(MagickTrue);
2328 }
2329#endif
2330 if (*type == 'w')
2331 {
cristye8939e72010-02-03 17:05:25 +00002332 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristy40a08ad2010-02-09 02:27:44 +00002333 if (image_info->adjoin == MagickFalse)
cristye8939e72010-02-03 17:05:25 +00002334 {
2335 /*
2336 Form filename for multi-part images.
2337 */
2338 (void) InterpretImageFilename(image_info,image,image->filename,(int)
2339 image->scene,filename);
cristy498cab92010-02-09 17:08:05 +00002340 if ((LocaleCompare(filename,image->filename) == 0) &&
2341 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2342 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002343 {
cristybf7fa0d2010-02-04 00:51:10 +00002344 char
2345 extension[MaxTextExtent],
2346 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002347
cristybf7fa0d2010-02-04 00:51:10 +00002348 GetPathComponent(image->filename,RootPath,path);
2349 GetPathComponent(image->filename,ExtensionPath,extension);
2350 if (*extension == '\0')
2351 (void) FormatMagickString(filename,MaxTextExtent,"%s-%lu",
2352 path,image->scene);
2353 else
2354 (void) FormatMagickString(filename,MaxTextExtent,
2355 "%s-%lu.%s",path,image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002356 }
2357 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002358#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002359 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002360#endif
cristye8939e72010-02-03 17:05:25 +00002361 }
cristy3ed852e2009-09-05 21:47:34 +00002362 }
2363#if defined(MAGICKCORE_ZLIB_DELEGATE)
2364 if (((strlen(filename) > 2) &&
2365 (LocaleCompare(filename+strlen(filename)-2,".Z") == 0)) ||
2366 ((strlen(filename) > 3) &&
2367 (LocaleCompare(filename+strlen(filename)-3,".gz") == 0)) ||
2368 ((strlen(filename) > 4) &&
2369 (LocaleCompare(filename+strlen(filename)-4,".wmz") == 0)) ||
2370 ((strlen(filename) > 5) &&
2371 (LocaleCompare(filename+strlen(filename)-5,".svgz") == 0)))
2372 {
2373 image->blob->file=(FILE *) gzopen(filename,type);
2374 if (image->blob->file != (FILE *) NULL)
2375 image->blob->type=ZipStream;
2376 }
2377 else
2378#endif
2379#if defined(MAGICKCORE_BZLIB_DELEGATE)
2380 if ((strlen(filename) > 4) &&
2381 (LocaleCompare(filename+strlen(filename)-4,".bz2") == 0))
2382 {
2383 image->blob->file=(FILE *) BZ2_bzopen(filename,type);
2384 if (image->blob->file != (FILE *) NULL)
2385 image->blob->type=BZipStream;
2386 }
2387 else
2388#endif
2389 if (image_info->file != (FILE *) NULL)
2390 {
2391 image->blob->file=image_info->file;
2392 image->blob->type=FileStream;
2393 image->blob->exempt=MagickTrue;
2394 }
2395 else
2396 {
2397 image->blob->file=(FILE *) OpenMagickStream(filename,type);
2398 if (image->blob->file != (FILE *) NULL)
2399 {
2400 image->blob->type=FileStream;
2401#if defined(MAGICKCORE_HAVE_SETVBUF)
2402 (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,
2403 16384);
2404#endif
2405 if (*type == 'r')
2406 {
2407 size_t
2408 count;
2409
2410 unsigned char
2411 magick[3];
2412
2413 (void) ResetMagickMemory(magick,0,sizeof(magick));
2414 count=fread(magick,1,sizeof(magick),image->blob->file);
2415 (void) rewind(image->blob->file);
2416 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2417 " read %ld magic header bytes",(long) count);
2418#if defined(MAGICKCORE_ZLIB_DELEGATE)
2419 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2420 ((int) magick[2] == 0x08))
2421 {
2422 (void) fclose(image->blob->file);
2423 image->blob->file=(FILE *) gzopen(filename,type);
2424 if (image->blob->file != (FILE *) NULL)
2425 image->blob->type=ZipStream;
2426 }
2427#endif
2428#if defined(MAGICKCORE_BZLIB_DELEGATE)
2429 if (strncmp((char *) magick,"BZh",3) == 0)
2430 {
2431 (void) fclose(image->blob->file);
2432 image->blob->file=(FILE *) BZ2_bzopen(filename,type);
2433 if (image->blob->file != (FILE *) NULL)
2434 image->blob->type=BZipStream;
2435 }
2436#endif
2437 }
2438 }
2439 }
2440 if ((image->blob->type == FileStream) && (*type == 'r'))
2441 {
2442 const MagickInfo
2443 *magick_info;
2444
2445 ExceptionInfo
2446 *sans_exception;
2447
2448 struct stat
2449 *properties;
2450
2451 sans_exception=AcquireExceptionInfo();
2452 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2453 sans_exception=DestroyExceptionInfo(sans_exception);
2454 properties=(&image->blob->properties);
2455 if ((magick_info != (const MagickInfo *) NULL) &&
2456 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2457 (properties->st_size <= MagickMaxBufferExtent))
2458 {
2459 size_t
2460 length;
2461
2462 void
2463 *blob;
2464
2465 length=(size_t) properties->st_size;
2466 blob=MapBlob(fileno(image->blob->file),ReadMode,0,length);
2467 if (blob != (void *) NULL)
2468 {
2469 /*
2470 Format supports blobs-- use memory-mapped I/O.
2471 */
2472 if (image_info->file != (FILE *) NULL)
2473 image->blob->exempt=MagickFalse;
2474 else
2475 {
2476 (void) fclose(image->blob->file);
2477 image->blob->file=(FILE *) NULL;
2478 }
2479 AttachBlob(image->blob,blob,length);
2480 image->blob->mapped=MagickTrue;
2481 }
2482 }
2483 }
2484 image->blob->status=MagickFalse;
2485 if (image->blob->type != UndefinedStream)
2486 image->blob->size=GetBlobSize(image);
2487 else
2488 {
2489 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2490 return(MagickFalse);
2491 }
2492 return(MagickTrue);
2493}
2494
2495/*
2496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2497% %
2498% %
2499% %
2500+ P i n g B l o b %
2501% %
2502% %
2503% %
2504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2505%
2506% PingBlob() returns all the attributes of an image or image sequence except
2507% for the pixels. It is much faster and consumes far less memory than
2508% BlobToImage(). On failure, a NULL image is returned and exception
2509% describes the reason for the failure.
2510%
2511% The format of the PingBlob method is:
2512%
2513% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2514% const size_t length,ExceptionInfo *exception)
2515%
2516% A description of each parameter follows:
2517%
2518% o image_info: the image info.
2519%
2520% o blob: the address of a character stream in one of the image formats
2521% understood by ImageMagick.
2522%
2523% o length: This size_t integer reflects the length in bytes of the blob.
2524%
2525% o exception: return any errors or warnings in this structure.
2526%
2527*/
2528
2529#if defined(__cplusplus) || defined(c_plusplus)
2530extern "C" {
2531#endif
2532
2533static size_t PingStream(const Image *magick_unused(image),
2534 const void *magick_unused(pixels),const size_t columns)
2535{
2536 return(columns);
2537}
2538
2539#if defined(__cplusplus) || defined(c_plusplus)
2540}
2541#endif
2542
2543MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2544 const size_t length,ExceptionInfo *exception)
2545{
2546 Image
2547 *image;
2548
2549 ImageInfo
2550 *ping_info;
2551
2552 assert(image_info != (ImageInfo *) NULL);
2553 assert(image_info->signature == MagickSignature);
2554 if (image_info->debug != MagickFalse)
2555 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2556 image_info->filename);
2557 assert(exception != (ExceptionInfo *) NULL);
2558 if ((blob == (const void *) NULL) || (length == 0))
2559 {
2560 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
2561 "UnrecognizedImageFormat","`%s'",image_info->magick);
2562 return((Image *) NULL);
2563 }
2564 ping_info=CloneImageInfo(image_info);
2565 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2566 if (ping_info->blob == (const void *) NULL)
2567 {
2568 (void) ThrowMagickException(exception,GetMagickModule(),
2569 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
2570 return((Image *) NULL);
2571 }
2572 (void) CopyMagickMemory(ping_info->blob,blob,length);
2573 ping_info->length=length;
2574 ping_info->ping=MagickTrue;
2575 image=ReadStream(ping_info,&PingStream,exception);
2576 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2577 ping_info=DestroyImageInfo(ping_info);
2578 return(image);
2579}
2580
2581/*
2582%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2583% %
2584% %
2585% %
2586+ R e a d B l o b %
2587% %
2588% %
2589% %
2590%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2591%
2592% ReadBlob() reads data from the blob or image file and returns it. It
2593% returns the number of bytes read.
2594%
2595% The format of the ReadBlob method is:
2596%
2597% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2598%
2599% A description of each parameter follows:
2600%
2601% o image: the image.
2602%
2603% o length: Specifies an integer representing the number of bytes to read
2604% from the file.
2605%
2606% o data: Specifies an area to place the information requested from the
2607% file.
2608%
2609*/
2610MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2611 unsigned char *data)
2612{
2613 int
2614 c;
2615
2616 register unsigned char
2617 *q;
2618
2619 ssize_t
2620 count;
2621
2622 assert(image != (Image *) NULL);
2623 assert(image->signature == MagickSignature);
2624 assert(image->blob != (BlobInfo *) NULL);
2625 assert(image->blob->type != UndefinedStream);
2626 if (length == 0)
2627 return(0);
2628 assert(data != (void *) NULL);
2629 count=0;
2630 q=data;
2631 switch (image->blob->type)
2632 {
2633 case UndefinedStream:
2634 break;
2635 case FileStream:
2636 case StandardStream:
2637 case PipeStream:
2638 {
2639 switch (length)
2640 {
2641 default:
2642 {
2643 count=(ssize_t) fread(q,1,length,image->blob->file);
2644 break;
2645 }
2646 case 2:
2647 {
2648 c=getc(image->blob->file);
2649 if (c == EOF)
2650 break;
2651 *q++=(unsigned char) c;
2652 count++;
2653 }
2654 case 1:
2655 {
2656 c=getc(image->blob->file);
2657 if (c == EOF)
2658 break;
2659 *q++=(unsigned char) c;
2660 count++;
2661 }
2662 case 0:
2663 break;
2664 }
2665 break;
2666 }
2667 case ZipStream:
2668 {
2669#if defined(MAGICKCORE_ZLIB_DELEGATE)
2670 switch (length)
2671 {
2672 default:
2673 {
2674 count=(ssize_t) gzread(image->blob->file,q,(unsigned int) length);
2675 break;
2676 }
2677 case 2:
2678 {
2679 c=gzgetc(image->blob->file);
2680 if (c == EOF)
2681 break;
2682 *q++=(unsigned char) c;
2683 count++;
2684 }
2685 case 1:
2686 {
2687 c=gzgetc(image->blob->file);
2688 if (c == EOF)
2689 break;
2690 *q++=(unsigned char) c;
2691 count++;
2692 }
2693 case 0:
2694 break;
2695 }
2696#endif
2697 break;
2698 }
2699 case BZipStream:
2700 {
2701#if defined(MAGICKCORE_BZLIB_DELEGATE)
2702 count=(ssize_t) BZ2_bzread((BZFILE *) image->blob->file,q,(int) length);
2703#endif
2704 break;
2705 }
2706 case FifoStream:
2707 break;
2708 case BlobStream:
2709 {
2710 register const unsigned char
2711 *p;
2712
2713 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2714 {
2715 image->blob->eof=MagickTrue;
2716 break;
2717 }
2718 p=image->blob->data+image->blob->offset;
2719 count=(ssize_t) MagickMin(length,(size_t) (image->blob->length-
2720 image->blob->offset));
2721 image->blob->offset+=count;
2722 if (count != (ssize_t) length)
2723 image->blob->eof=MagickTrue;
2724 (void) CopyMagickMemory(q,p,(size_t) count);
2725 break;
2726 }
2727 }
2728 return(count);
2729}
2730
2731/*
2732%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2733% %
2734% %
2735% %
2736+ R e a d B l o b B y t e %
2737% %
2738% %
2739% %
2740%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2741%
2742% ReadBlobByte() reads a single byte from the image file and returns it.
2743%
2744% The format of the ReadBlobByte method is:
2745%
2746% int ReadBlobByte(Image *image)
2747%
2748% A description of each parameter follows.
2749%
2750% o image: the image.
2751%
2752*/
2753MagickExport int ReadBlobByte(Image *image)
2754{
2755 register const unsigned char
2756 *p;
2757
2758 ssize_t
2759 count;
2760
2761 unsigned char
2762 buffer[1];
2763
2764 assert(image != (Image *) NULL);
2765 assert(image->signature == MagickSignature);
2766 p=ReadBlobStream(image,1,buffer,&count);
2767 if (count != 1)
2768 return(EOF);
2769 return((int) (*p));
2770}
2771
2772/*
2773%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2774% %
2775% %
2776% %
2777+ R e a d B l o b D o u b l e %
2778% %
2779% %
2780% %
2781%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2782%
2783% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2784% specified by the endian member of the image structure.
2785%
2786% The format of the ReadBlobDouble method is:
2787%
2788% double ReadBlobDouble(Image *image)
2789%
2790% A description of each parameter follows.
2791%
2792% o image: the image.
2793%
2794*/
2795MagickExport double ReadBlobDouble(Image *image)
2796{
2797 union
2798 {
2799 MagickSizeType
2800 unsigned_value;
2801
2802 double
2803 double_value;
2804 } quantum;
2805
2806 quantum.double_value=0.0;
2807 quantum.unsigned_value=ReadBlobLongLong(image);
2808 return(quantum.double_value);
2809}
2810
2811/*
2812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2813% %
2814% %
2815% %
2816+ R e a d B l o b F l o a t %
2817% %
2818% %
2819% %
2820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2821%
2822% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2823% specified by the endian member of the image structure.
2824%
2825% The format of the ReadBlobFloat method is:
2826%
2827% float ReadBlobFloat(Image *image)
2828%
2829% A description of each parameter follows.
2830%
2831% o image: the image.
2832%
2833*/
2834MagickExport float ReadBlobFloat(Image *image)
2835{
2836 union
2837 {
2838 unsigned int
2839 unsigned_value;
2840
2841 float
2842 float_value;
2843 } quantum;
2844
2845 quantum.float_value=0.0;
2846 quantum.unsigned_value=ReadBlobLong(image);
2847 return(quantum.float_value);
2848}
2849
2850/*
2851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2852% %
2853% %
2854% %
2855+ R e a d B l o b L o n g %
2856% %
2857% %
2858% %
2859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2860%
2861% ReadBlobLong() reads a long value as a 32-bit quantity in the byte-order
2862% specified by the endian member of the image structure.
2863%
2864% The format of the ReadBlobLong method is:
2865%
2866% unsigned int ReadBlobLong(Image *image)
2867%
2868% A description of each parameter follows.
2869%
2870% o image: the image.
2871%
2872*/
2873MagickExport unsigned int ReadBlobLong(Image *image)
2874{
2875 register const unsigned char
2876 *p;
2877
2878 ssize_t
2879 count;
2880
2881 unsigned char
2882 buffer[4];
2883
2884 unsigned int
2885 value;
2886
2887 assert(image != (Image *) NULL);
2888 assert(image->signature == MagickSignature);
2889 *buffer='\0';
2890 p=ReadBlobStream(image,4,buffer,&count);
2891 if (count != 4)
2892 return(0UL);
2893 if (image->endian == LSBEndian)
2894 {
2895 value=(unsigned int) (*p++);
2896 value|=((unsigned int) (*p++)) << 8;
2897 value|=((unsigned int) (*p++)) << 16;
2898 value|=((unsigned int) (*p++)) << 24;
2899 return(value);
2900 }
2901 value=((unsigned int) (*p++)) << 24;
2902 value|=((unsigned int) (*p++)) << 16;
2903 value|=((unsigned int) (*p++)) << 8;
2904 value|=((unsigned int) (*p++));
2905 return(value);
2906}
2907
2908/*
2909%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2910% %
2911% %
2912% %
2913+ R e a d B l o b L o n g L o n g %
2914% %
2915% %
2916% %
2917%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2918%
2919% ReadBlobLongLong() reads a long value as a 64-bit quantity in the byte-order
2920% specified by the endian member of the image structure.
2921%
2922% The format of the ReadBlobLong method is:
2923%
2924% MagickSizeType ReadBlobLong(Image *image)
2925%
2926% A description of each parameter follows.
2927%
2928% o image: the image.
2929%
2930*/
2931MagickExport MagickSizeType ReadBlobLongLong(Image *image)
2932{
2933 register const unsigned char
2934 *p;
2935
2936 ssize_t
2937 count;
2938
2939 unsigned char
2940 buffer[8];
2941
2942 MagickSizeType
2943 value;
2944
2945 assert(image != (Image *) NULL);
2946 assert(image->signature == MagickSignature);
2947 *buffer='\0';
2948 p=ReadBlobStream(image,8,buffer,&count);
2949 if (count != 8)
2950 return(MagickULLConstant(0));
2951 if (image->endian == LSBEndian)
2952 {
2953 value=(MagickSizeType) (*p++);
2954 value|=((MagickSizeType) (*p++)) << 8;
2955 value|=((MagickSizeType) (*p++)) << 16;
2956 value|=((MagickSizeType) (*p++)) << 24;
2957 value|=((MagickSizeType) (*p++)) << 32;
2958 value|=((MagickSizeType) (*p++)) << 40;
2959 value|=((MagickSizeType) (*p++)) << 48;
2960 value|=((MagickSizeType) (*p++)) << 56;
2961 return(value & MagickULLConstant(0xffffffffffffffff));
2962 }
2963 value=((MagickSizeType) (*p++)) << 56;
2964 value|=((MagickSizeType) (*p++)) << 48;
2965 value|=((MagickSizeType) (*p++)) << 40;
2966 value|=((MagickSizeType) (*p++)) << 32;
2967 value|=((MagickSizeType) (*p++)) << 24;
2968 value|=((MagickSizeType) (*p++)) << 16;
2969 value|=((MagickSizeType) (*p++)) << 8;
2970 value|=((MagickSizeType) (*p++));
2971 return(value & MagickULLConstant(0xffffffffffffffff));
2972}
2973
2974/*
2975%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2976% %
2977% %
2978% %
2979+ R e a d B l o b S h o r t %
2980% %
2981% %
2982% %
2983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2984%
2985% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
2986% specified by the endian member of the image structure.
2987%
2988% The format of the ReadBlobShort method is:
2989%
2990% unsigned short ReadBlobShort(Image *image)
2991%
2992% A description of each parameter follows.
2993%
2994% o image: the image.
2995%
2996*/
2997MagickExport unsigned short ReadBlobShort(Image *image)
2998{
2999 register const unsigned char
3000 *p;
3001
3002 register unsigned int
3003 value;
3004
3005 ssize_t
3006 count;
3007
3008 unsigned char
3009 buffer[2];
3010
3011 assert(image != (Image *) NULL);
3012 assert(image->signature == MagickSignature);
3013 *buffer='\0';
3014 p=ReadBlobStream(image,2,buffer,&count);
3015 if (count != 2)
3016 return((unsigned short) 0U);
3017 if (image->endian == LSBEndian)
3018 {
3019 value=(unsigned int) (*p++);
3020 value|=((unsigned int) (*p++)) << 8;
3021 return((unsigned short) (value & 0xffff));
3022 }
3023 value=(unsigned int) ((*p++) << 8);
3024 value|=(unsigned int) (*p++);
3025 return((unsigned short) (value & 0xffff));
3026}
3027
3028/*
3029%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3030% %
3031% %
3032% %
3033+ R e a d B l o b L S B L o n g %
3034% %
3035% %
3036% %
3037%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3038%
3039% ReadBlobLSBLong() reads a long value as a 32-bit quantity in
3040% least-significant byte first order.
3041%
3042% The format of the ReadBlobLSBLong method is:
3043%
3044% unsigned int ReadBlobLSBLong(Image *image)
3045%
3046% A description of each parameter follows.
3047%
3048% o image: the image.
3049%
3050*/
3051MagickExport unsigned int ReadBlobLSBLong(Image *image)
3052{
3053 register const unsigned char
3054 *p;
3055
3056 register unsigned int
3057 value;
3058
3059 ssize_t
3060 count;
3061
3062 unsigned char
3063 buffer[4];
3064
3065 assert(image != (Image *) NULL);
3066 assert(image->signature == MagickSignature);
3067 *buffer='\0';
3068 p=ReadBlobStream(image,4,buffer,&count);
3069 if (count != 4)
3070 return(0U);
3071 value=(unsigned int) (*p++);
3072 value|=((unsigned int) (*p++)) << 8;
3073 value|=((unsigned int) (*p++)) << 16;
3074 value|=((unsigned int) (*p++)) << 24;
3075 return(value);
3076}
3077
3078/*
3079%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3080% %
3081% %
3082% %
3083+ R e a d B l o b L S B S h o r t %
3084% %
3085% %
3086% %
3087%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3088%
3089% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3090% least-significant byte first order.
3091%
3092% The format of the ReadBlobLSBShort method is:
3093%
3094% unsigned short ReadBlobLSBShort(Image *image)
3095%
3096% A description of each parameter follows.
3097%
3098% o image: the image.
3099%
3100*/
3101MagickExport unsigned short ReadBlobLSBShort(Image *image)
3102{
3103 register const unsigned char
3104 *p;
3105
3106 register unsigned int
3107 value;
3108
3109 ssize_t
3110 count;
3111
3112 unsigned char
3113 buffer[2];
3114
3115 assert(image != (Image *) NULL);
3116 assert(image->signature == MagickSignature);
3117 *buffer='\0';
3118 p=ReadBlobStream(image,2,buffer,&count);
3119 if (count != 2)
3120 return((unsigned short) 0U);
3121 value=(unsigned int) (*p++);
3122 value|=((unsigned int) ((*p++)) << 8);
3123 return((unsigned short) (value & 0xffff));
3124}
3125
3126/*
3127%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3128% %
3129% %
3130% %
3131+ R e a d B l o b M S B L o n g %
3132% %
3133% %
3134% %
3135%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3136%
3137% ReadBlobMSBLong() reads a long value as a 32-bit quantity in
3138% most-significant byte first order.
3139%
3140% The format of the ReadBlobMSBLong method is:
3141%
3142% unsigned int ReadBlobMSBLong(Image *image)
3143%
3144% A description of each parameter follows.
3145%
3146% o image: the image.
3147%
3148*/
3149MagickExport unsigned int ReadBlobMSBLong(Image *image)
3150{
3151 register const unsigned char
3152 *p;
3153
3154 register unsigned int
3155 value;
3156
3157 ssize_t
3158 count;
3159
3160 unsigned char
3161 buffer[4];
3162
3163 assert(image != (Image *) NULL);
3164 assert(image->signature == MagickSignature);
3165 *buffer='\0';
3166 p=ReadBlobStream(image,4,buffer,&count);
3167 if (count != 4)
3168 return(0UL);
3169 value=((unsigned int) (*p++) << 24);
3170 value|=((unsigned int) (*p++) << 16);
3171 value|=((unsigned int) (*p++) << 8);
3172 value|=(unsigned int) (*p++);
3173 return(value);
3174}
3175
3176/*
3177%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3178% %
3179% %
3180% %
cristy2d3d87f2010-03-01 00:23:08 +00003181+ R e a d B l o b M S B L o n g L o n g %
3182% %
3183% %
3184% %
3185%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3186%
3187% ReadBlobMSBLongLong() reads a long value as a 64-bit quantity in
3188% most-significant byte first order.
3189%
3190% The format of the ReadBlobMSBLongLong method is:
3191%
3192% unsigned int ReadBlobMSBLongLong(Image *image)
3193%
3194% A description of each parameter follows.
3195%
3196% o image: the image.
3197%
3198*/
3199MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3200{
3201 register const unsigned char
3202 *p;
3203
3204 register MagickSizeType
3205 value;
3206
3207 ssize_t
3208 count;
3209
3210 unsigned char
3211 buffer[4];
3212
3213 assert(image != (Image *) NULL);
3214 assert(image->signature == MagickSignature);
3215 *buffer='\0';
3216 p=ReadBlobStream(image,8,buffer,&count);
3217 if (count != 8)
3218 return(MagickULLConstant(0));
3219 value=((MagickSizeType) (*p++)) << 56;
3220 value|=((MagickSizeType) (*p++)) << 48;
3221 value|=((MagickSizeType) (*p++)) << 40;
3222 value|=((MagickSizeType) (*p++)) << 32;
3223 value|=((MagickSizeType) (*p++)) << 24;
3224 value|=((MagickSizeType) (*p++)) << 16;
3225 value|=((MagickSizeType) (*p++)) << 8;
3226 value|=((MagickSizeType) (*p++));
3227 return(value & MagickULLConstant(0xffffffffffffffff));
3228}
3229
3230/*
3231%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3232% %
3233% %
3234% %
cristy3ed852e2009-09-05 21:47:34 +00003235+ R e a d B l o b M S B S h o r t %
3236% %
3237% %
3238% %
3239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3240%
3241% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3242% most-significant byte first order.
3243%
3244% The format of the ReadBlobMSBShort method is:
3245%
3246% unsigned short ReadBlobMSBShort(Image *image)
3247%
3248% A description of each parameter follows.
3249%
3250% o image: the image.
3251%
3252*/
3253MagickExport unsigned short ReadBlobMSBShort(Image *image)
3254{
3255 register const unsigned char
3256 *p;
3257
3258 register unsigned int
3259 value;
3260
3261 ssize_t
3262 count;
3263
3264 unsigned char
3265 buffer[2];
3266
3267 assert(image != (Image *) NULL);
3268 assert(image->signature == MagickSignature);
3269 *buffer='\0';
3270 p=ReadBlobStream(image,2,buffer,&count);
3271 if (count != 2)
3272 return((unsigned short) 0U);
3273 value=(unsigned int) ((*p++) << 8);
3274 value|=(unsigned int) (*p++);
3275 return((unsigned short) (value & 0xffff));
3276}
3277
3278/*
3279%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3280% %
3281% %
3282% %
3283+ R e a d B l o b S t r i n g %
3284% %
3285% %
3286% %
3287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3288%
3289% ReadBlobString() reads characters from a blob or file until a newline
3290% character is read or an end-of-file condition is encountered.
3291%
3292% The format of the ReadBlobString method is:
3293%
3294% char *ReadBlobString(Image *image,char *string)
3295%
3296% A description of each parameter follows:
3297%
3298% o image: the image.
3299%
3300% o string: the address of a character buffer.
3301%
3302*/
3303MagickExport char *ReadBlobString(Image *image,char *string)
3304{
3305 register const unsigned char
3306 *p;
3307
3308 register long
3309 i;
3310
3311 ssize_t
3312 count;
3313
3314 unsigned char
3315 buffer[1];
3316
3317 assert(image != (Image *) NULL);
3318 assert(image->signature == MagickSignature);
3319 for (i=0; i < (MaxTextExtent-1L); i++)
3320 {
3321 p=ReadBlobStream(image,1,buffer,&count);
3322 if (count != 1)
3323 {
3324 if (i == 0)
3325 return((char *) NULL);
3326 break;
3327 }
3328 string[i]=(char) (*p);
3329 if ((string[i] == '\n') || (string[i] == '\r'))
3330 break;
3331 }
3332 string[i]='\0';
3333 return(string);
3334}
3335
3336/*
3337%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3338% %
3339% %
3340% %
3341+ R e f e r e n c e B l o b %
3342% %
3343% %
3344% %
3345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3346%
3347% ReferenceBlob() increments the reference count associated with the pixel
3348% blob returning a pointer to the blob.
3349%
3350% The format of the ReferenceBlob method is:
3351%
3352% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3353%
3354% A description of each parameter follows:
3355%
3356% o blob_info: the blob_info.
3357%
3358*/
3359MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3360{
3361 assert(blob != (BlobInfo *) NULL);
3362 assert(blob->signature == MagickSignature);
3363 if (blob->debug != MagickFalse)
3364 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003365 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003366 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003367 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003368 return(blob);
3369}
3370
3371/*
3372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3373% %
3374% %
3375% %
3376+ S e e k B l o b %
3377% %
3378% %
3379% %
3380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3381%
3382% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3383% and returns the resulting offset.
3384%
3385% The format of the SeekBlob method is:
3386%
3387% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3388% const int whence)
3389%
3390% A description of each parameter follows:
3391%
3392% o image: the image.
3393%
3394% o offset: Specifies an integer representing the offset in bytes.
3395%
3396% o whence: Specifies an integer representing how the offset is
3397% treated relative to the beginning of the blob as follows:
3398%
3399% SEEK_SET Set position equal to offset bytes.
3400% SEEK_CUR Set position to current location plus offset.
3401% SEEK_END Set position to EOF plus offset.
3402%
3403*/
3404MagickExport MagickOffsetType SeekBlob(Image *image,
3405 const MagickOffsetType offset,const int whence)
3406{
3407 assert(image != (Image *) NULL);
3408 assert(image->signature == MagickSignature);
3409 if (image->debug != MagickFalse)
3410 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3411 assert(image->blob != (BlobInfo *) NULL);
3412 assert(image->blob->type != UndefinedStream);
3413 switch (image->blob->type)
3414 {
3415 case UndefinedStream:
3416 break;
3417 case FileStream:
3418 {
3419 if (fseek(image->blob->file,offset,whence) < 0)
3420 return(-1);
3421 image->blob->offset=TellBlob(image);
3422 break;
3423 }
3424 case StandardStream:
3425 case PipeStream:
3426 case ZipStream:
3427 {
3428#if defined(MAGICKCORE_ZLIB_DELEGATE)
3429 if (gzseek(image->blob->file,(off_t) offset,whence) < 0)
3430 return(-1);
3431#endif
3432 image->blob->offset=TellBlob(image);
3433 break;
3434 }
3435 case BZipStream:
3436 return(-1);
3437 case FifoStream:
3438 return(-1);
3439 case BlobStream:
3440 {
3441 switch (whence)
3442 {
3443 case SEEK_SET:
3444 default:
3445 {
3446 if (offset < 0)
3447 return(-1);
3448 image->blob->offset=offset;
3449 break;
3450 }
3451 case SEEK_CUR:
3452 {
3453 if ((image->blob->offset+offset) < 0)
3454 return(-1);
3455 image->blob->offset+=offset;
3456 break;
3457 }
3458 case SEEK_END:
3459 {
3460 if (((MagickOffsetType) image->blob->length+offset) < 0)
3461 return(-1);
3462 image->blob->offset=image->blob->length+offset;
3463 break;
3464 }
3465 }
3466 if (image->blob->offset <= (MagickOffsetType)
3467 ((off_t) image->blob->length))
3468 image->blob->eof=MagickFalse;
3469 else
3470 if (image->blob->mapped != MagickFalse)
3471 return(-1);
3472 else
3473 {
3474 image->blob->extent=(size_t) (image->blob->offset+
3475 image->blob->quantum);
3476 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3477 image->blob->data,image->blob->extent+1,
3478 sizeof(*image->blob->data));
3479 (void) SyncBlob(image);
3480 if (image->blob->data == (unsigned char *) NULL)
3481 {
3482 (void) DetachBlob(image->blob);
3483 return(-1);
3484 }
3485 }
3486 break;
3487 }
3488 }
3489 return(image->blob->offset);
3490}
3491
3492/*
3493%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3494% %
3495% %
3496% %
3497+ S e t B l o b E x e m p t %
3498% %
3499% %
3500% %
3501%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3502%
3503% SetBlobExempt() sets the blob exempt status.
3504%
3505% The format of the SetBlobExempt method is:
3506%
3507% MagickBooleanType SetBlobExempt(const Image *image,
3508% const MagickBooleanType exempt)
3509%
3510% A description of each parameter follows:
3511%
3512% o image: the image.
3513%
3514% o exempt: Set to true if this blob is exempt from being closed.
3515%
3516*/
3517MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
3518{
3519 assert(image != (const Image *) NULL);
3520 assert(image->signature == MagickSignature);
3521 if (image->debug != MagickFalse)
3522 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3523 image->blob->exempt=exempt;
3524}
3525
3526/*
3527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3528% %
3529% %
3530% %
3531+ S e t B l o b E x t e n t %
3532% %
3533% %
3534% %
3535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3536%
3537% SetBlobExtent() ensures enough space is allocated for the blob. If the
3538% method is successful, subsequent writes to bytes in the specified range are
3539% guaranteed not to fail.
3540%
3541% The format of the SetBlobExtent method is:
3542%
3543% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3544%
3545% A description of each parameter follows:
3546%
3547% o image: the image.
3548%
3549% o extent: the blob maximum extent.
3550%
3551*/
3552MagickExport MagickBooleanType SetBlobExtent(Image *image,
3553 const MagickSizeType extent)
3554{
3555 assert(image != (Image *) NULL);
3556 assert(image->signature == MagickSignature);
3557 if (image->debug != MagickFalse)
3558 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3559 assert(image->blob != (BlobInfo *) NULL);
3560 assert(image->blob->type != UndefinedStream);
3561 switch (image->blob->type)
3562 {
3563 case UndefinedStream:
3564 break;
3565 case FileStream:
3566 {
3567 if (extent != (MagickSizeType) ((off_t) extent))
3568 return(MagickFalse);
3569#if !defined(MAGICKCORE_POSIX_FALLOCATE)
3570 return(MagickFalse);
3571#else
3572 {
3573 int
3574 status;
3575
3576 MagickOffsetType
3577 offset;
3578
3579 offset=TellBlob(image);
3580 status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3581 (off_t) (extent-offset));
3582 if (status != 0)
3583 return(MagickFalse);
3584 }
3585#endif
3586 break;
3587 }
3588 case StandardStream:
3589 case PipeStream:
3590 case ZipStream:
3591 return(MagickFalse);
3592 case BZipStream:
3593 return(MagickFalse);
3594 case FifoStream:
3595 return(MagickFalse);
3596 case BlobStream:
3597 {
3598 if (image->blob->mapped != MagickFalse)
3599 {
3600 if (image->blob->file == (FILE *) NULL)
3601 return(MagickFalse);
3602 (void) UnmapBlob(image->blob->data,image->blob->length);
3603#if !defined(MAGICKCORE_POSIX_FALLOCATE)
3604 return(MagickFalse);
3605#else
3606 {
3607 int
3608 status;
3609
3610 MagickOffsetType
3611 offset;
3612
3613 offset=TellBlob(image);
3614 status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3615 (off_t) (extent-offset));
3616 if (status != 0)
3617 return(MagickFalse);
3618 }
3619 image->blob->data=(unsigned char*) MapBlob(fileno(image->blob->file),
3620 WriteMode,0,(size_t) extent);
3621 image->blob->extent=(size_t) extent;
3622 image->blob->length=(size_t) extent;
3623 (void) SyncBlob(image);
3624 break;
3625#endif
3626 }
3627 if (extent != (MagickSizeType) ((size_t) extent))
3628 return(MagickFalse);
3629 image->blob->extent=(size_t) extent;
3630 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3631 image->blob->extent+1,sizeof(*image->blob->data));
3632 (void) SyncBlob(image);
3633 if (image->blob->data == (unsigned char *) NULL)
3634 {
3635 (void) DetachBlob(image->blob);
3636 return(MagickFalse);
3637 }
3638 break;
3639 }
3640 }
3641 return(MagickTrue);
3642}
3643
3644/*
3645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3646% %
3647% %
3648% %
3649+ S y n c B l o b %
3650% %
3651% %
3652% %
3653%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3654%
3655% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3656% attributes if it is an blob.
3657%
3658% The format of the SyncBlob method is:
3659%
3660% int SyncBlob(Image *image)
3661%
3662% A description of each parameter follows:
3663%
3664% o image: the image.
3665%
3666*/
3667static int SyncBlob(Image *image)
3668{
3669 int
3670 status;
3671
3672 assert(image != (Image *) NULL);
3673 assert(image->signature == MagickSignature);
3674 if (image->debug != MagickFalse)
3675 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3676 assert(image->blob != (BlobInfo *) NULL);
3677 assert(image->blob->type != UndefinedStream);
3678 status=0;
3679 switch (image->blob->type)
3680 {
3681 case UndefinedStream:
3682 break;
3683 case FileStream:
3684 case StandardStream:
3685 case PipeStream:
3686 {
3687 status=fflush(image->blob->file);
3688 break;
3689 }
3690 case ZipStream:
3691 {
3692#if defined(MAGICKCORE_ZLIB_DELEGATE)
3693 status=gzflush(image->blob->file,Z_SYNC_FLUSH);
3694#endif
3695 break;
3696 }
3697 case BZipStream:
3698 {
3699#if defined(MAGICKCORE_BZLIB_DELEGATE)
3700 status=BZ2_bzflush((BZFILE *) image->blob->file);
3701#endif
3702 break;
3703 }
3704 case FifoStream:
3705 break;
3706 case BlobStream:
3707 {
3708#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3709 if (image->blob->mapped != MagickFalse)
3710 status=msync(image->blob->data,image->blob->length,MS_SYNC);
3711#endif
3712 break;
3713 }
3714 }
3715 return(status);
3716}
3717
3718/*
3719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3720% %
3721% %
3722% %
3723+ T e l l B l o b %
3724% %
3725% %
3726% %
3727%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3728%
3729% TellBlob() obtains the current value of the blob or file position.
3730%
3731% The format of the TellBlob method is:
3732%
3733% MagickOffsetType TellBlob(const Image *image)
3734%
3735% A description of each parameter follows:
3736%
3737% o image: the image.
3738%
3739*/
3740MagickExport MagickOffsetType TellBlob(const Image *image)
3741{
3742 MagickOffsetType
3743 offset;
3744
3745 assert(image != (Image *) NULL);
3746 assert(image->signature == MagickSignature);
3747 if (image->debug != MagickFalse)
3748 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3749 assert(image->blob != (BlobInfo *) NULL);
3750 assert(image->blob->type != UndefinedStream);
3751 offset=(-1);
3752 switch (image->blob->type)
3753 {
3754 case UndefinedStream:
3755 break;
3756 case FileStream:
3757 {
3758 offset=ftell(image->blob->file);
3759 break;
3760 }
3761 case StandardStream:
3762 case PipeStream:
3763 break;
3764 case ZipStream:
3765 {
3766#if defined(MAGICKCORE_ZLIB_DELEGATE)
3767 offset=(MagickOffsetType) gztell(image->blob->file);
3768#endif
3769 break;
3770 }
3771 case BZipStream:
3772 break;
3773 case FifoStream:
3774 break;
3775 case BlobStream:
3776 {
3777 offset=image->blob->offset;
3778 break;
3779 }
3780 }
3781 return(offset);
3782}
3783
3784/*
3785%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3786% %
3787% %
3788% %
3789+ U n m a p B l o b %
3790% %
3791% %
3792% %
3793%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3794%
3795% UnmapBlob() deallocates the binary large object previously allocated with
3796% the MapBlob method.
3797%
3798% The format of the UnmapBlob method is:
3799%
3800% MagickBooleanType UnmapBlob(void *map,const size_t length)
3801%
3802% A description of each parameter follows:
3803%
3804% o map: the address of the binary large object.
3805%
3806% o length: the length of the binary large object.
3807%
3808*/
3809MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3810{
3811#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3812 int
3813 status;
3814
3815 status=munmap(map,length);
3816 return(status == -1 ? MagickFalse : MagickTrue);
3817#else
3818 (void) map;
3819 (void) length;
3820 return(MagickFalse);
3821#endif
3822}
3823
3824/*
3825%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3826% %
3827% %
3828% %
3829+ W r i t e B l o b %
3830% %
3831% %
3832% %
3833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3834%
3835% WriteBlob() writes data to a blob or image file. It returns the number of
3836% bytes written.
3837%
3838% The format of the WriteBlob method is:
3839%
3840% ssize_t WriteBlob(Image *image,const size_t length,
3841% const unsigned char *data)
3842%
3843% A description of each parameter follows:
3844%
3845% o image: the image.
3846%
3847% o length: Specifies an integer representing the number of bytes to
3848% write to the file.
3849%
3850% o data: The address of the data to write to the blob or file.
3851%
3852*/
3853MagickExport ssize_t WriteBlob(Image *image,const size_t length,
3854 const unsigned char *data)
3855{
3856 int
3857 c;
3858
3859 register const unsigned char
3860 *p;
3861
3862 ssize_t
3863 count;
3864
3865 assert(image != (Image *) NULL);
3866 assert(image->signature == MagickSignature);
3867 assert(data != (const unsigned char *) NULL);
3868 assert(image->blob != (BlobInfo *) NULL);
3869 assert(image->blob->type != UndefinedStream);
3870 if (length == 0)
3871 return(0);
3872 count=0;
3873 p=data;
3874 switch (image->blob->type)
3875 {
3876 case UndefinedStream:
3877 break;
3878 case FileStream:
3879 case StandardStream:
3880 case PipeStream:
3881 {
3882 switch (length)
3883 {
3884 default:
3885 {
3886 count=(ssize_t) fwrite((const char *) data,1,length,
3887 image->blob->file);
3888 break;
3889 }
3890 case 2:
3891 {
3892 c=putc((int) *p++,image->blob->file);
3893 if (c == EOF)
3894 break;
3895 count++;
3896 }
3897 case 1:
3898 {
3899 c=putc((int) *p++,image->blob->file);
3900 if (c == EOF)
3901 break;
3902 count++;
3903 }
3904 case 0:
3905 break;
3906 }
3907 break;
3908 }
3909 case ZipStream:
3910 {
3911#if defined(MAGICKCORE_ZLIB_DELEGATE)
3912 switch (length)
3913 {
3914 default:
3915 {
3916 count=(ssize_t) gzwrite(image->blob->file,(void *) data,
3917 (unsigned int) length);
3918 break;
3919 }
3920 case 2:
3921 {
3922 c=gzputc(image->blob->file,(int) *p++);
3923 if (c == EOF)
3924 break;
3925 count++;
3926 }
3927 case 1:
3928 {
3929 c=gzputc(image->blob->file,(int) *p++);
3930 if (c == EOF)
3931 break;
3932 count++;
3933 }
3934 case 0:
3935 break;
3936 }
3937#endif
3938 break;
3939 }
3940 case BZipStream:
3941 {
3942#if defined(MAGICKCORE_BZLIB_DELEGATE)
3943 count=(ssize_t) BZ2_bzwrite((BZFILE *) image->blob->file,(void *) data,
3944 (int) length);
3945#endif
3946 break;
3947 }
3948 case FifoStream:
3949 {
3950 count=(ssize_t) image->blob->stream(image,data,length);
3951 break;
3952 }
3953 case BlobStream:
3954 {
3955 register unsigned char
3956 *q;
3957
3958 if ((image->blob->offset+(MagickOffsetType) length) >=
3959 (MagickOffsetType) image->blob->extent)
3960 {
3961 if (image->blob->mapped != MagickFalse)
3962 return(0);
3963 image->blob->quantum<<=1;
3964 image->blob->extent+=length+image->blob->quantum;
3965 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3966 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
3967 (void) SyncBlob(image);
3968 if (image->blob->data == (unsigned char *) NULL)
3969 {
3970 (void) DetachBlob(image->blob);
3971 return(0);
3972 }
3973 }
3974 q=image->blob->data+image->blob->offset;
3975 (void) CopyMagickMemory(q,p,length);
3976 image->blob->offset+=length;
3977 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
3978 image->blob->length=(size_t) image->blob->offset;
3979 count=(ssize_t) length;
3980 }
3981 }
3982 return(count);
3983}
3984
3985/*
3986%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3987% %
3988% %
3989% %
3990+ W r i t e B l o b B y t e %
3991% %
3992% %
3993% %
3994%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3995%
3996% WriteBlobByte() write an integer to a blob. It returns the number of bytes
3997% written (either 0 or 1);
3998%
3999% The format of the WriteBlobByte method is:
4000%
4001% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4002%
4003% A description of each parameter follows.
4004%
4005% o image: the image.
4006%
4007% o value: Specifies the value to write.
4008%
4009*/
4010MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4011{
4012 assert(image != (Image *) NULL);
4013 assert(image->signature == MagickSignature);
4014 return(WriteBlobStream(image,1,&value));
4015}
4016
4017/*
4018%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4019% %
4020% %
4021% %
4022+ W r i t e B l o b F l o a t %
4023% %
4024% %
4025% %
4026%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4027%
4028% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4029% specified by the endian member of the image structure.
4030%
4031% The format of the WriteBlobFloat method is:
4032%
4033% ssize_t WriteBlobFloat(Image *image,const float value)
4034%
4035% A description of each parameter follows.
4036%
4037% o image: the image.
4038%
4039% o value: Specifies the value to write.
4040%
4041*/
4042MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4043{
4044 union
4045 {
4046 unsigned int
4047 unsigned_value;
4048
4049 float
4050 float_value;
4051 } quantum;
4052
4053 quantum.unsigned_value=0U;
4054 quantum.float_value=value;
4055 return(WriteBlobLong(image,quantum.unsigned_value));
4056}
4057
4058/*
4059%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4060% %
4061% %
4062% %
4063+ W r i t e B l o b L o n g %
4064% %
4065% %
4066% %
4067%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4068%
4069% WriteBlobLong() writes a long value as a 32-bit quantity in the byte-order
4070% specified by the endian member of the image structure.
4071%
4072% The format of the WriteBlobLong method is:
4073%
4074% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4075%
4076% A description of each parameter follows.
4077%
4078% o image: the image.
4079%
4080% o value: Specifies the value to write.
4081%
4082*/
4083MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4084{
4085 unsigned char
4086 buffer[4];
4087
4088 assert(image != (Image *) NULL);
4089 assert(image->signature == MagickSignature);
4090 if (image->endian == LSBEndian)
4091 {
4092 buffer[0]=(unsigned char) value;
4093 buffer[1]=(unsigned char) (value >> 8);
4094 buffer[2]=(unsigned char) (value >> 16);
4095 buffer[3]=(unsigned char) (value >> 24);
4096 return(WriteBlobStream(image,4,buffer));
4097 }
4098 buffer[0]=(unsigned char) (value >> 24);
4099 buffer[1]=(unsigned char) (value >> 16);
4100 buffer[2]=(unsigned char) (value >> 8);
4101 buffer[3]=(unsigned char) value;
4102 return(WriteBlobStream(image,4,buffer));
4103}
4104
4105/*
4106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4107% %
4108% %
4109% %
4110+ W r i t e B l o b S h o r t %
4111% %
4112% %
4113% %
4114%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4115%
4116% WriteBlobShort() writes a short value as a 16-bit quantity in the
4117% byte-order specified by the endian member of the image structure.
4118%
4119% The format of the WriteBlobShort method is:
4120%
4121% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4122%
4123% A description of each parameter follows.
4124%
4125% o image: the image.
4126%
4127% o value: Specifies the value to write.
4128%
4129*/
4130MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4131{
4132 unsigned char
4133 buffer[2];
4134
4135 assert(image != (Image *) NULL);
4136 assert(image->signature == MagickSignature);
4137 if (image->endian == LSBEndian)
4138 {
4139 buffer[0]=(unsigned char) value;
4140 buffer[1]=(unsigned char) (value >> 8);
4141 return(WriteBlobStream(image,2,buffer));
4142 }
4143 buffer[0]=(unsigned char) (value >> 8);
4144 buffer[1]=(unsigned char) value;
4145 return(WriteBlobStream(image,2,buffer));
4146}
4147
4148/*
4149%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4150% %
4151% %
4152% %
4153+ W r i t e B l o b L S B L o n g %
4154% %
4155% %
4156% %
4157%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4158%
4159% WriteBlobLSBLong() writes a long value as a 32-bit quantity in
4160% least-significant byte first order.
4161%
4162% The format of the WriteBlobLSBLong method is:
4163%
4164% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4165%
4166% A description of each parameter follows.
4167%
4168% o image: the image.
4169%
4170% o value: Specifies the value to write.
4171%
4172*/
4173MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4174{
4175 unsigned char
4176 buffer[4];
4177
4178 assert(image != (Image *) NULL);
4179 assert(image->signature == MagickSignature);
4180 buffer[0]=(unsigned char) value;
4181 buffer[1]=(unsigned char) (value >> 8);
4182 buffer[2]=(unsigned char) (value >> 16);
4183 buffer[3]=(unsigned char) (value >> 24);
4184 return(WriteBlobStream(image,4,buffer));
4185}
4186
4187/*
4188%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4189% %
4190% %
4191% %
4192+ W r i t e B l o b L S B S h o r t %
4193% %
4194% %
4195% %
4196%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4197%
4198% WriteBlobLSBShort() writes a long value as a 16-bit quantity in
4199% least-significant byte first order.
4200%
4201% The format of the WriteBlobLSBShort method is:
4202%
4203% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4204%
4205% A description of each parameter follows.
4206%
4207% o image: the image.
4208%
4209% o value: Specifies the value to write.
4210%
4211*/
4212MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4213{
4214 unsigned char
4215 buffer[2];
4216
4217 assert(image != (Image *) NULL);
4218 assert(image->signature == MagickSignature);
4219 buffer[0]=(unsigned char) value;
4220 buffer[1]=(unsigned char) (value >> 8);
4221 return(WriteBlobStream(image,2,buffer));
4222}
4223
4224/*
4225%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4226% %
4227% %
4228% %
4229+ W r i t e B l o b M S B L o n g %
4230% %
4231% %
4232% %
4233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4234%
4235% WriteBlobMSBLong() writes a long value as a 32-bit quantity in
4236% most-significant byte first order.
4237%
4238% The format of the WriteBlobMSBLong method is:
4239%
4240% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4241%
4242% A description of each parameter follows.
4243%
4244% o value: Specifies the value to write.
4245%
4246% o image: the image.
4247%
4248*/
4249MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4250{
4251 unsigned char
4252 buffer[4];
4253
4254 assert(image != (Image *) NULL);
4255 assert(image->signature == MagickSignature);
4256 buffer[0]=(unsigned char) (value >> 24);
4257 buffer[1]=(unsigned char) (value >> 16);
4258 buffer[2]=(unsigned char) (value >> 8);
4259 buffer[3]=(unsigned char) value;
4260 return(WriteBlobStream(image,4,buffer));
4261}
4262
4263/*
4264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4265% %
4266% %
4267% %
4268+ W r i t e B l o b M S B S h o r t %
4269% %
4270% %
4271% %
4272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4273%
4274% WriteBlobMSBShort() writes a long value as a 16-bit quantity in
4275% most-significant byte first order.
4276%
4277% The format of the WriteBlobMSBShort method is:
4278%
4279% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4280%
4281% A description of each parameter follows.
4282%
4283% o value: Specifies the value to write.
4284%
4285% o file: Specifies the file to write the data to.
4286%
4287*/
4288MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4289{
4290 unsigned char
4291 buffer[2];
4292
4293 assert(image != (Image *) NULL);
4294 assert(image->signature == MagickSignature);
4295 buffer[0]=(unsigned char) (value >> 8);
4296 buffer[1]=(unsigned char) value;
4297 return(WriteBlobStream(image,2,buffer));
4298}
4299
4300/*
4301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4302% %
4303% %
4304% %
4305+ W r i t e B l o b S t r i n g %
4306% %
4307% %
4308% %
4309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4310%
4311% WriteBlobString() write a string to a blob. It returns the number of
4312% characters written.
4313%
4314% The format of the WriteBlobString method is:
4315%
4316% ssize_t WriteBlobString(Image *image,const char *string)
4317%
4318% A description of each parameter follows.
4319%
4320% o image: the image.
4321%
4322% o string: Specifies the string to write.
4323%
4324*/
4325MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4326{
4327 assert(image != (Image *) NULL);
4328 assert(image->signature == MagickSignature);
4329 assert(string != (const char *) NULL);
4330 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4331}