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