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