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