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