blob: 1c9ae1a3a425136a276b1a4095774e4ccd036de9 [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%
874% FileToBlob() returns the contents of a file as a blob. It returns the
875% file as a blob and its length. If an error occurs, NULL is returned.
876%
877% The format of the FileToBlob method is:
878%
879% unsigned char *FileToBlob(const char *filename,const size_t extent,
880% size_t *length,ExceptionInfo *exception)
881%
882% A description of each parameter follows:
883%
884% o blob: FileToBlob() returns the contents of a file as a blob. If
885% an error occurs NULL is returned.
886%
887% o filename: the filename.
888%
889% o extent: The maximum length of the blob.
890%
891% o length: On return, this reflects the actual length of the blob.
892%
893% o exception: return any errors or warnings in this structure.
894%
895*/
896MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
897 size_t *length,ExceptionInfo *exception)
898{
899 int
900 file;
901
902 MagickOffsetType
903 offset;
904
905 register size_t
906 i;
907
908 ssize_t
909 count;
910
911 unsigned char
912 *blob;
913
914 void
915 *map;
916
917 assert(filename != (const char *) NULL);
918 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
919 assert(exception != (ExceptionInfo *) NULL);
920 *length=0;
921 file=fileno(stdin);
922 if (LocaleCompare(filename,"-") != 0)
923 file=open(filename,O_RDONLY | O_BINARY);
924 if (file == -1)
925 {
926 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
927 return((unsigned char *) NULL);
928 }
929 offset=(MagickOffsetType) MagickSeek(file,0,SEEK_END);
930 count=0;
931 if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset)))
932 {
933 size_t
934 quantum;
935
936 struct stat
937 file_info;
938
939 /*
940 Stream is not seekable.
941 */
942 quantum=(size_t) MagickMaxBufferExtent;
943 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
944 quantum=MagickMin((size_t) file_info.st_size,MagickMaxBufferExtent);
945 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
946 for (i=0; blob != (unsigned char *) NULL; i+=count)
947 {
948 count=(ssize_t) read(file,blob+i,quantum);
949 if (count <= 0)
950 {
951 count=0;
952 if (errno != EINTR)
953 break;
954 }
955 if (~(1UL*i) < (quantum+1))
956 {
957 blob=(unsigned char *) RelinquishMagickMemory(blob);
958 break;
959 }
960 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
961 sizeof(*blob));
962 if ((size_t) (i+count) >= extent)
963 break;
964 }
cristy54439632010-07-15 00:43:34 +0000965 if (LocaleCompare(filename,"-") != 0)
966 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +0000967 if (blob == (unsigned char *) NULL)
968 {
969 (void) ThrowMagickException(exception,GetMagickModule(),
970 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
971 return((unsigned char *) NULL);
972 }
cristya7cb4312010-06-26 00:47:03 +0000973 if (file == -1)
974 {
975 blob=(unsigned char *) RelinquishMagickMemory(blob);
976 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
977 return((unsigned char *) NULL);
978 }
cristy3ed852e2009-09-05 21:47:34 +0000979 *length=MagickMin(i+count,extent);
980 blob[*length]='\0';
981 return(blob);
982 }
983 *length=MagickMin((size_t) offset,extent);
984 blob=(unsigned char *) NULL;
985 if (~(*length) >= MaxTextExtent)
986 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
987 sizeof(*blob));
988 if (blob == (unsigned char *) NULL)
989 {
cristy54439632010-07-15 00:43:34 +0000990 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +0000991 (void) ThrowMagickException(exception,GetMagickModule(),
992 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
993 return((unsigned char *) NULL);
994 }
995 map=MapBlob(file,ReadMode,0,*length);
996 if (map != (unsigned char *) NULL)
997 {
cristy54aad5e2010-09-03 16:02:04 +0000998 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +0000999 (void) UnmapBlob(map,*length);
1000 }
1001 else
1002 {
1003 (void) MagickSeek(file,0,SEEK_SET);
1004 for (i=0; i < *length; i+=count)
1005 {
1006 count=(ssize_t) read(file,blob+i,MagickMin(*length-i,(size_t)
1007 SSIZE_MAX));
1008 if (count <= 0)
1009 {
1010 count=0;
1011 if (errno != EINTR)
1012 break;
1013 }
1014 }
1015 if (i < *length)
1016 {
1017 file=close(file)-1;
1018 blob=(unsigned char *) RelinquishMagickMemory(blob);
1019 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1020 return((unsigned char *) NULL);
1021 }
1022 }
cristy3ed852e2009-09-05 21:47:34 +00001023 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001024 if (LocaleCompare(filename,"-") != 0)
1025 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001026 if (file == -1)
1027 {
1028 blob=(unsigned char *) RelinquishMagickMemory(blob);
1029 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1030 }
cristy3ed852e2009-09-05 21:47:34 +00001031 return(blob);
1032}
1033
1034/*
1035%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1036% %
1037% %
1038% %
1039% F i l e T o I m a g e %
1040% %
1041% %
1042% %
1043%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1044%
1045% FileToImage() write the contents of a file to an image.
1046%
1047% The format of the FileToImage method is:
1048%
1049% MagickBooleanType FileToImage(Image *,const char *filename)
1050%
1051% A description of each parameter follows:
1052%
1053% o image: the image.
1054%
1055% o filename: the filename.
1056%
1057*/
1058
1059static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1060 const unsigned char *data)
1061{
1062 MagickSizeType
1063 extent;
1064
1065 register unsigned char
1066 *q;
1067
1068 assert(image->blob != (BlobInfo *) NULL);
1069 if (image->blob->type != BlobStream)
1070 return(WriteBlob(image,length,data));
1071 assert(image->blob->type != UndefinedStream);
1072 assert(data != (void *) NULL);
1073 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1074 if (extent >= image->blob->extent)
1075 {
1076 image->blob->quantum<<=1;
1077 extent=image->blob->extent+image->blob->quantum+length;
1078 if (SetBlobExtent(image,extent) == MagickFalse)
1079 return(0);
1080 }
1081 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001082 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001083 image->blob->offset+=length;
1084 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1085 image->blob->length=(size_t) image->blob->offset;
1086 return((ssize_t) length);
1087}
1088
1089MagickExport MagickBooleanType FileToImage(Image *image,const char *filename)
1090{
1091 int
1092 file;
1093
1094 size_t
1095 length,
1096 quantum;
1097
1098 ssize_t
1099 count;
1100
1101 struct stat
1102 file_info;
1103
1104 unsigned char
1105 *blob;
1106
1107 assert(image != (const Image *) NULL);
1108 assert(image->signature == MagickSignature);
1109 assert(filename != (const char *) NULL);
1110 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1111 file=open(filename,O_RDONLY | O_BINARY);
1112 if (file == -1)
1113 {
1114 ThrowFileException(&image->exception,BlobError,"UnableToOpenBlob",
1115 filename);
1116 return(MagickFalse);
1117 }
1118 quantum=(size_t) MagickMaxBufferExtent;
1119 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
1120 quantum=MagickMin((size_t) file_info.st_size,MagickMaxBufferExtent);
1121 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1122 if (blob == (unsigned char *) NULL)
1123 {
1124 ThrowFileException(&image->exception,ResourceLimitError,
1125 "MemoryAllocationFailed",filename);
1126 return(MagickFalse);
1127 }
1128 for ( ; ; )
1129 {
1130 count=(ssize_t) read(file,blob,quantum);
1131 if (count <= 0)
1132 {
1133 count=0;
1134 if (errno != EINTR)
1135 break;
1136 }
1137 length=(size_t) count;
1138 count=WriteBlobStream(image,length,blob);
1139 if (count != (ssize_t) length)
1140 {
1141 ThrowFileException(&image->exception,BlobError,"UnableToWriteBlob",
1142 filename);
1143 break;
1144 }
1145 }
cristya7cb4312010-06-26 00:47:03 +00001146 file=close(file);
1147 if (file == -1)
1148 ThrowFileException(&image->exception,BlobError,"UnableToWriteBlob",
1149 filename);
cristy3ed852e2009-09-05 21:47:34 +00001150 blob=(unsigned char *) RelinquishMagickMemory(blob);
1151 return(MagickTrue);
1152}
1153
1154/*
1155%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1156% %
1157% %
1158% %
1159+ G e t B l o b E r r o r %
1160% %
1161% %
1162% %
1163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164%
1165% GetBlobError() returns MagickTrue if the blob associated with the specified
1166% image encountered an error.
1167%
1168% The format of the GetBlobError method is:
1169%
1170% MagickBooleanType GetBlobError(const Image *image)
1171%
1172% A description of each parameter follows:
1173%
1174% o image: the image.
1175%
1176*/
1177MagickExport MagickBooleanType GetBlobError(const Image *image)
1178{
1179 assert(image != (const Image *) NULL);
1180 assert(image->signature == MagickSignature);
1181 if (image->debug != MagickFalse)
1182 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1183 return(image->blob->status);
1184}
1185
1186/*
1187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1188% %
1189% %
1190% %
1191+ G e t B l o b F i l e H a n d l e %
1192% %
1193% %
1194% %
1195%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196%
1197% GetBlobFileHandle() returns the file handle associated with the image blob.
1198%
1199% The format of the GetBlobFile method is:
1200%
1201% FILE *GetBlobFileHandle(const Image *image)
1202%
1203% A description of each parameter follows:
1204%
1205% o image: the image.
1206%
1207*/
1208MagickExport FILE *GetBlobFileHandle(const Image *image)
1209{
1210 assert(image != (const Image *) NULL);
1211 assert(image->signature == MagickSignature);
1212 return(image->blob->file);
1213}
1214
1215/*
1216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1217% %
1218% %
1219% %
1220+ G e t B l o b I n f o %
1221% %
1222% %
1223% %
1224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1225%
1226% GetBlobInfo() initializes the BlobInfo structure.
1227%
1228% The format of the GetBlobInfo method is:
1229%
1230% void GetBlobInfo(BlobInfo *blob_info)
1231%
1232% A description of each parameter follows:
1233%
1234% o blob_info: Specifies a pointer to a BlobInfo structure.
1235%
1236*/
1237MagickExport void GetBlobInfo(BlobInfo *blob_info)
1238{
1239 assert(blob_info != (BlobInfo *) NULL);
1240 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1241 blob_info->type=UndefinedStream;
1242 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1243 blob_info->properties.st_mtime=time((time_t *) NULL);
1244 blob_info->properties.st_ctime=time((time_t *) NULL);
1245 blob_info->debug=IsEventLogging();
1246 blob_info->reference_count=1;
1247 blob_info->semaphore=AllocateSemaphoreInfo();
1248 blob_info->signature=MagickSignature;
1249}
1250
1251/*
1252%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1253% %
1254% %
1255% %
1256% G e t B l o b P r o p e r t i e s %
1257% %
1258% %
1259% %
1260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1261%
1262% GetBlobProperties() returns information about an image blob.
1263%
1264% The format of the GetBlobProperties method is:
1265%
1266% const struct stat *GetBlobProperties(const Image *image)
1267%
1268% A description of each parameter follows:
1269%
1270% o image: the image.
1271%
1272*/
1273MagickExport const struct stat *GetBlobProperties(const Image *image)
1274{
1275 assert(image != (Image *) NULL);
1276 assert(image->signature == MagickSignature);
1277 if (image->debug != MagickFalse)
1278 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1279 return(&image->blob->properties);
1280}
1281
1282/*
1283%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1284% %
1285% %
1286% %
1287+ G e t B l o b S i z e %
1288% %
1289% %
1290% %
1291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1292%
1293% GetBlobSize() returns the current length of the image file or blob; zero is
1294% returned if the size cannot be determined.
1295%
1296% The format of the GetBlobSize method is:
1297%
1298% MagickSizeType GetBlobSize(const Image *image)
1299%
1300% A description of each parameter follows:
1301%
1302% o image: the image.
1303%
1304*/
1305MagickExport MagickSizeType GetBlobSize(const Image *image)
1306{
1307 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001308 extent;
cristy3ed852e2009-09-05 21:47:34 +00001309
1310 assert(image != (Image *) NULL);
1311 assert(image->signature == MagickSignature);
1312 if (image->debug != MagickFalse)
1313 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1314 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001315 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001316 switch (image->blob->type)
1317 {
1318 case UndefinedStream:
1319 {
cristy81b8ce52010-02-05 01:53:17 +00001320 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001321 break;
1322 }
1323 case FileStream:
1324 {
1325 if (fstat(fileno(image->blob->file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001326 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001327 break;
1328 }
1329 case StandardStream:
1330 case PipeStream:
1331 {
cristy81b8ce52010-02-05 01:53:17 +00001332 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001333 break;
1334 }
1335 case ZipStream:
1336 case BZipStream:
1337 {
1338 MagickBooleanType
1339 status;
1340
1341 status=GetPathAttributes(image->filename,&image->blob->properties);
1342 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001343 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001344 break;
1345 }
1346 case FifoStream:
1347 break;
1348 case BlobStream:
1349 {
cristy891dc792010-03-04 01:47:16 +00001350 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001351 break;
1352 }
1353 }
cristy81b8ce52010-02-05 01:53:17 +00001354 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001355}
1356
1357/*
1358%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1359% %
1360% %
1361% %
1362+ G e t B l o b S t r e a m D a t a %
1363% %
1364% %
1365% %
1366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1367%
1368% GetBlobStreamData() returns the stream data for the image.
1369%
1370% The format of the GetBlobStreamData method is:
1371%
1372% unsigned char *GetBlobStreamData(const Image *image)
1373%
1374% A description of each parameter follows:
1375%
1376% o image: the image.
1377%
1378*/
1379MagickExport unsigned char *GetBlobStreamData(const Image *image)
1380{
1381 assert(image != (const Image *) NULL);
1382 assert(image->signature == MagickSignature);
1383 return(image->blob->data);
1384}
1385
1386/*
1387%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1388% %
1389% %
1390% %
1391+ G e t B l o b S t r e a m H a n d l e r %
1392% %
1393% %
1394% %
1395%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1396%
1397% GetBlobStreamHandler() returns the stream handler for the image.
1398%
1399% The format of the GetBlobStreamHandler method is:
1400%
1401% StreamHandler GetBlobStreamHandler(const Image *image)
1402%
1403% A description of each parameter follows:
1404%
1405% o image: the image.
1406%
1407*/
1408MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
1409{
1410 assert(image != (const Image *) NULL);
1411 assert(image->signature == MagickSignature);
1412 if (image->debug != MagickFalse)
1413 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1414 return(image->blob->stream);
1415}
1416
1417/*
1418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1419% %
1420% %
1421% %
1422% I m a g e T o B l o b %
1423% %
1424% %
1425% %
1426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1427%
1428% ImageToBlob() implements direct to memory image formats. It returns the
1429% image as a blob and its length. The magick member of the ImageInfo structure
1430% determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1431%
1432% The format of the ImageToBlob method is:
1433%
1434% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1435% size_t *length,ExceptionInfo *exception)
1436%
1437% A description of each parameter follows:
1438%
1439% o image_info: the image info.
1440%
1441% o image: the image.
1442%
1443% o length: This pointer to a size_t integer sets the initial length of the
1444% blob. On return, it reflects the actual length of the blob.
1445%
1446% o exception: return any errors or warnings in this structure.
1447%
1448*/
1449MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1450 Image *image,size_t *length,ExceptionInfo *exception)
1451{
1452 const MagickInfo
1453 *magick_info;
1454
1455 ImageInfo
1456 *blob_info;
1457
1458 MagickBooleanType
1459 status;
1460
1461 unsigned char
1462 *blob;
1463
1464 assert(image_info != (const ImageInfo *) NULL);
1465 assert(image_info->signature == MagickSignature);
1466 if (image_info->debug != MagickFalse)
1467 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1468 image_info->filename);
1469 assert(image != (Image *) NULL);
1470 assert(image->signature == MagickSignature);
1471 assert(exception != (ExceptionInfo *) NULL);
1472 *length=0;
1473 blob=(unsigned char *) NULL;
1474 blob_info=CloneImageInfo(image_info);
1475 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001476 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001477 if (*blob_info->magick != '\0')
1478 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1479 magick_info=GetMagickInfo(image->magick,exception);
1480 if (magick_info == (const MagickInfo *) NULL)
1481 {
1482 (void) ThrowMagickException(exception,GetMagickModule(),
1483 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1484 image->filename);
1485 return(blob);
1486 }
1487 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1488 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1489 {
1490 /*
1491 Native blob support for this image format.
1492 */
1493 blob_info->length=0;
1494 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1495 sizeof(unsigned char));
1496 if (blob_info->blob == (void *) NULL)
1497 (void) ThrowMagickException(exception,GetMagickModule(),
1498 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1499 else
1500 {
1501 (void) CloseBlob(image);
1502 image->blob->exempt=MagickTrue;
1503 *image->filename='\0';
1504 status=WriteImage(blob_info,image);
1505 if ((status == MagickFalse) || (image->blob->length == 0))
1506 InheritException(exception,&image->exception);
1507 else
1508 {
1509 *length=image->blob->length;
1510 blob=DetachBlob(image->blob);
1511 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1512 sizeof(*blob));
1513 }
1514 }
1515 }
1516 else
1517 {
1518 char
1519 unique[MaxTextExtent];
1520
1521 int
1522 file;
1523
1524 /*
1525 Write file to disk in blob image format.
1526 */
1527 file=AcquireUniqueFileResource(unique);
1528 if (file == -1)
1529 {
1530 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1531 image_info->filename);
1532 }
1533 else
1534 {
1535 blob_info->file=fdopen(file,"wb");
1536 if (blob_info->file != (FILE *) NULL)
1537 {
1538 (void) FormatMagickString(image->filename,MaxTextExtent,"%s:%s",
1539 image->magick,unique);
1540 status=WriteImage(blob_info,image);
1541 (void) fclose(blob_info->file);
1542 if (status == MagickFalse)
1543 InheritException(exception,&image->exception);
1544 else
1545 blob=FileToBlob(image->filename,~0UL,length,exception);
1546 }
1547 (void) RelinquishUniqueFileResource(unique);
1548 }
1549 }
1550 blob_info=DestroyImageInfo(blob_info);
1551 return(blob);
1552}
1553
1554/*
1555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1556% %
1557% %
1558% %
1559% I m a g e T o F i l e %
1560% %
1561% %
1562% %
1563%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1564%
1565% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1566% occurs otherwise MagickTrue.
1567%
1568% The format of the ImageToFile method is:
1569%
1570% MagickBooleanType ImageToFile(Image *image,char *filename,
1571% ExceptionInfo *exception)
1572%
1573% A description of each parameter follows:
1574%
1575% o image: the image.
1576%
1577% o filename: Write the image to this file.
1578%
1579% o exception: return any errors or warnings in this structure.
1580%
1581*/
cristy3ed852e2009-09-05 21:47:34 +00001582MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1583 ExceptionInfo *exception)
1584{
1585 int
1586 file;
1587
1588 register const unsigned char
1589 *p;
1590
1591 register size_t
1592 i;
1593
1594 size_t
1595 length,
1596 quantum;
1597
1598 ssize_t
1599 count;
1600
1601 struct stat
1602 file_info;
1603
1604 unsigned char
1605 *buffer;
1606
1607 assert(image != (Image *) NULL);
1608 assert(image->signature == MagickSignature);
1609 assert(image->blob != (BlobInfo *) NULL);
1610 assert(image->blob->type != UndefinedStream);
1611 if (image->debug != MagickFalse)
1612 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1613 assert(filename != (const char *) NULL);
1614 if (*filename == '\0')
1615 file=AcquireUniqueFileResource(filename);
1616 else
1617 if (LocaleCompare(filename,"-") == 0)
1618 file=fileno(stdout);
1619 else
1620 file=open(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1621 if (file == -1)
1622 {
1623 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1624 return(MagickFalse);
1625 }
1626 quantum=(size_t) MagickMaxBufferExtent;
1627 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
1628 quantum=MagickMin((size_t) file_info.st_size,MagickMaxBufferExtent);
1629 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1630 if (buffer == (unsigned char *) NULL)
1631 {
1632 file=close(file)-1;
1633 (void) ThrowMagickException(exception,GetMagickModule(),
1634 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1635 return(MagickFalse);
1636 }
1637 length=0;
1638 p=ReadBlobStream(image,quantum,buffer,&count);
1639 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1640 {
1641 length=(size_t) count;
1642 for (i=0; i < length; i+=count)
1643 {
1644 count=write(file,p+i,(size_t) (length-i));
1645 if (count <= 0)
1646 {
1647 count=0;
1648 if (errno != EINTR)
1649 break;
1650 }
1651 }
1652 if (i < length)
1653 break;
1654 }
cristy54439632010-07-15 00:43:34 +00001655 if (LocaleCompare(filename,"-") != 0)
1656 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001657 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001658 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001659 {
1660 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1661 return(MagickFalse);
1662 }
1663 return(MagickTrue);
1664}
1665
1666/*
1667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1668% %
1669% %
1670% %
1671% I m a g e s T o B l o b %
1672% %
1673% %
1674% %
1675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1676%
1677% ImagesToBlob() implements direct to memory image formats. It returns the
1678% image sequence as a blob and its length. The magick member of the ImageInfo
1679% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1680%
1681% Note, some image formats do not permit multiple images to the same image
1682% stream (e.g. JPEG). in this instance, just the first image of the
1683% sequence is returned as a blob.
1684%
1685% The format of the ImagesToBlob method is:
1686%
1687% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1688% size_t *length,ExceptionInfo *exception)
1689%
1690% A description of each parameter follows:
1691%
1692% o image_info: the image info.
1693%
1694% o images: the image list.
1695%
1696% o length: This pointer to a size_t integer sets the initial length of the
1697% blob. On return, it reflects the actual length of the blob.
1698%
1699% o exception: return any errors or warnings in this structure.
1700%
1701*/
1702MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1703 Image *images,size_t *length,ExceptionInfo *exception)
1704{
1705 const MagickInfo
1706 *magick_info;
1707
1708 ImageInfo
1709 *blob_info;
1710
1711 MagickBooleanType
1712 status;
1713
1714 unsigned char
1715 *blob;
1716
1717 assert(image_info != (const ImageInfo *) NULL);
1718 assert(image_info->signature == MagickSignature);
1719 if (image_info->debug != MagickFalse)
1720 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1721 image_info->filename);
1722 assert(images != (Image *) NULL);
1723 assert(images->signature == MagickSignature);
1724 assert(exception != (ExceptionInfo *) NULL);
1725 *length=0;
1726 blob=(unsigned char *) NULL;
1727 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001728 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1729 exception);
cristy3ed852e2009-09-05 21:47:34 +00001730 if (*blob_info->magick != '\0')
1731 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1732 if (blob_info->adjoin == MagickFalse)
1733 {
1734 blob_info=DestroyImageInfo(blob_info);
1735 return(ImageToBlob(image_info,images,length,exception));
1736 }
1737 magick_info=GetMagickInfo(images->magick,exception);
1738 if (magick_info == (const MagickInfo *) NULL)
1739 {
1740 (void) ThrowMagickException(exception,GetMagickModule(),
1741 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1742 images->filename);
1743 return(blob);
1744 }
1745 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1746 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1747 {
1748 /*
1749 Native blob support for this images format.
1750 */
1751 blob_info->length=0;
1752 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1753 sizeof(unsigned char));
1754 if (blob_info->blob == (void *) NULL)
1755 (void) ThrowMagickException(exception,GetMagickModule(),
1756 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
1757 else
1758 {
1759 images->blob->exempt=MagickTrue;
1760 *images->filename='\0';
1761 status=WriteImages(blob_info,images,images->filename,exception);
1762 if ((status == MagickFalse) || (images->blob->length == 0))
1763 InheritException(exception,&images->exception);
1764 else
1765 {
1766 *length=images->blob->length;
1767 blob=DetachBlob(images->blob);
1768 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1769 sizeof(*blob));
1770 }
1771 }
1772 }
1773 else
1774 {
1775 char
1776 filename[MaxTextExtent],
1777 unique[MaxTextExtent];
1778
1779 int
1780 file;
1781
1782 /*
1783 Write file to disk in blob images format.
1784 */
1785 file=AcquireUniqueFileResource(unique);
1786 if (file == -1)
1787 {
1788 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1789 image_info->filename);
1790 }
1791 else
1792 {
1793 blob_info->file=fdopen(file,"wb");
1794 if (blob_info->file != (FILE *) NULL)
1795 {
1796 (void) FormatMagickString(filename,MaxTextExtent,"%s:%s",
1797 images->magick,unique);
1798 status=WriteImages(blob_info,images,filename,exception);
1799 (void) fclose(blob_info->file);
1800 if (status == MagickFalse)
1801 InheritException(exception,&images->exception);
1802 else
1803 blob=FileToBlob(images->filename,~0UL,length,exception);
1804 }
1805 (void) RelinquishUniqueFileResource(unique);
1806 }
1807 }
1808 blob_info=DestroyImageInfo(blob_info);
1809 return(blob);
1810}
1811/*
1812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1813% %
1814% %
1815% %
1816% I n j e c t I m a g e B l o b %
1817% %
1818% %
1819% %
1820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1821%
1822% InjectImageBlob() injects the image with a copy of itself in the specified
1823% format (e.g. inject JPEG into a PDF image).
1824%
1825% The format of the InjectImageBlob method is:
1826%
1827% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1828% Image *image,Image *inject_image,const char *format,
1829% ExceptionInfo *exception)
1830%
1831% A description of each parameter follows:
1832%
1833% o image_info: the image info..
1834%
1835% o image: the image.
1836%
1837% o inject_image: inject into the image stream.
1838%
1839% o format: the image format.
1840%
1841% o exception: return any errors or warnings in this structure.
1842%
1843*/
1844MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1845 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1846{
1847 char
1848 filename[MaxTextExtent];
1849
1850 FILE
1851 *unique_file;
1852
1853 Image
1854 *byte_image;
1855
1856 ImageInfo
1857 *write_info;
1858
1859 int
1860 file;
1861
1862 MagickBooleanType
1863 status;
1864
cristybb503372010-05-27 20:51:26 +00001865 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001866 i;
1867
1868 size_t
1869 quantum;
1870
1871 ssize_t
1872 count;
1873
1874 struct stat
1875 file_info;
1876
1877 unsigned char
1878 *buffer;
1879
1880 /*
1881 Write inject image to a temporary file.
1882 */
1883 assert(image_info != (ImageInfo *) NULL);
1884 assert(image_info->signature == MagickSignature);
1885 assert(image != (Image *) NULL);
1886 assert(image->signature == MagickSignature);
1887 if (image->debug != MagickFalse)
1888 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1889 assert(inject_image != (Image *) NULL);
1890 assert(inject_image->signature == MagickSignature);
1891 assert(exception != (ExceptionInfo *) NULL);
1892 unique_file=(FILE *) NULL;
1893 file=AcquireUniqueFileResource(filename);
1894 if (file != -1)
1895 unique_file=fdopen(file,"wb");
1896 if ((file == -1) || (unique_file == (FILE *) NULL))
1897 {
1898 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1899 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1900 image->filename);
1901 return(MagickFalse);
1902 }
1903 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1904 if (byte_image == (Image *) NULL)
1905 {
1906 (void) fclose(unique_file);
1907 (void) RelinquishUniqueFileResource(filename);
1908 return(MagickFalse);
1909 }
1910 (void) FormatMagickString(byte_image->filename,MaxTextExtent,"%s:%s",format,
1911 filename);
1912 DestroyBlob(byte_image);
1913 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1914 write_info=CloneImageInfo(image_info);
1915 SetImageInfoFile(write_info,unique_file);
1916 status=WriteImage(write_info,byte_image);
1917 write_info=DestroyImageInfo(write_info);
1918 byte_image=DestroyImage(byte_image);
1919 (void) fclose(unique_file);
1920 if (status == MagickFalse)
1921 {
1922 (void) RelinquishUniqueFileResource(filename);
1923 return(MagickFalse);
1924 }
1925 /*
1926 Inject into image stream.
1927 */
1928 file=open(filename,O_RDONLY | O_BINARY);
1929 if (file == -1)
1930 {
1931 (void) RelinquishUniqueFileResource(filename);
1932 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1933 image_info->filename);
1934 return(MagickFalse);
1935 }
1936 quantum=(size_t) MagickMaxBufferExtent;
1937 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
1938 quantum=MagickMin((size_t) file_info.st_size,MagickMaxBufferExtent);
1939 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1940 if (buffer == (unsigned char *) NULL)
1941 {
1942 (void) RelinquishUniqueFileResource(filename);
1943 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1944 image->filename);
1945 }
1946 for (i=0; ; i+=count)
1947 {
1948 count=(ssize_t) read(file,buffer,quantum);
1949 if (count <= 0)
1950 {
1951 count=0;
1952 if (errno != EINTR)
1953 break;
1954 }
1955 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1956 MagickFalse;
1957 }
cristya7cb4312010-06-26 00:47:03 +00001958 file=close(file);
1959 if (file == -1)
1960 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001961 (void) RelinquishUniqueFileResource(filename);
1962 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1963 return(status);
1964}
1965
1966/*
1967%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1968% %
1969% %
1970% %
1971+ I s B l o b E x e m p t %
1972% %
1973% %
1974% %
1975%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1976%
1977% IsBlobExempt() returns true if the blob is exempt.
1978%
1979% The format of the IsBlobExempt method is:
1980%
1981% MagickBooleanType IsBlobExempt(const Image *image)
1982%
1983% A description of each parameter follows:
1984%
1985% o image: the image.
1986%
1987*/
1988MagickExport MagickBooleanType IsBlobExempt(const Image *image)
1989{
1990 assert(image != (const Image *) NULL);
1991 assert(image->signature == MagickSignature);
1992 if (image->debug != MagickFalse)
1993 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1994 return(image->blob->exempt);
1995}
1996
1997/*
1998%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1999% %
2000% %
2001% %
2002+ I s B l o b S e e k a b l e %
2003% %
2004% %
2005% %
2006%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2007%
2008% IsBlobSeekable() returns true if the blob is seekable.
2009%
2010% The format of the IsBlobSeekable method is:
2011%
2012% MagickBooleanType IsBlobSeekable(const Image *image)
2013%
2014% A description of each parameter follows:
2015%
2016% o image: the image.
2017%
2018*/
2019MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2020{
2021 MagickBooleanType
2022 seekable;
2023
2024 assert(image != (const Image *) NULL);
2025 assert(image->signature == MagickSignature);
2026 if (image->debug != MagickFalse)
2027 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2028 seekable=(image->blob->type == FileStream) ||
2029 (image->blob->type == BlobStream) ? MagickTrue : MagickFalse;
2030 return(seekable);
2031}
2032
2033/*
2034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2035% %
2036% %
2037% %
2038+ I s B l o b T e m p o r a r y %
2039% %
2040% %
2041% %
2042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2043%
2044% IsBlobTemporary() returns true if the blob is temporary.
2045%
2046% The format of the IsBlobTemporary method is:
2047%
2048% MagickBooleanType IsBlobTemporary(const Image *image)
2049%
2050% A description of each parameter follows:
2051%
2052% o image: the image.
2053%
2054*/
2055MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2056{
2057 assert(image != (const Image *) NULL);
2058 assert(image->signature == MagickSignature);
2059 if (image->debug != MagickFalse)
2060 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2061 return(image->blob->temporary);
2062}
2063
2064/*
2065%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2066% %
2067% %
2068% %
2069+ M a p B l o b %
2070% %
2071% %
2072% %
2073%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2074%
2075% MapBlob() creates a mapping from a file to a binary large object.
2076%
2077% The format of the MapBlob method is:
2078%
2079% unsigned char *MapBlob(int file,const MapMode mode,
2080% const MagickOffsetType offset,const size_t length)
2081%
2082% A description of each parameter follows:
2083%
2084% o file: map this file descriptor.
2085%
2086% o mode: ReadMode, WriteMode, or IOMode.
2087%
2088% o offset: starting at this offset within the file.
2089%
2090% o length: the length of the mapping is returned in this pointer.
2091%
2092*/
2093MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2094 const MagickOffsetType offset,const size_t length)
2095{
2096#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
2097 int
2098 flags,
2099 protection;
2100
2101 unsigned char
2102 *map;
2103
2104 /*
2105 Map file.
2106 */
2107 flags=0;
2108 if (file == -1)
2109#if defined(MAP_ANONYMOUS)
2110 flags|=MAP_ANONYMOUS;
2111#else
2112 return((unsigned char *) NULL);
2113#endif
2114 switch (mode)
2115 {
2116 case ReadMode:
2117 default:
2118 {
2119 protection=PROT_READ;
2120 flags|=MAP_PRIVATE;
2121 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2122 (off_t) offset);
2123 break;
2124 }
2125 case WriteMode:
2126 {
2127 protection=PROT_WRITE;
2128 flags|=MAP_SHARED;
2129 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2130 (off_t) offset);
cristy2a9e7cb2010-03-05 02:15:05 +00002131#if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
2132 (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
2133 POSIX_MADV_WILLNEED);
2134#endif
cristy3ed852e2009-09-05 21:47:34 +00002135 break;
2136 }
2137 case IOMode:
2138 {
2139 protection=PROT_READ | PROT_WRITE;
2140 flags|=MAP_SHARED;
2141 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2142 (off_t) offset);
2143 break;
2144 }
2145 }
2146 if (map == (unsigned char *) MAP_FAILED)
2147 return((unsigned char *) NULL);
2148 return(map);
2149#else
2150 (void) file;
2151 (void) mode;
2152 (void) offset;
2153 (void) length;
2154 return((unsigned char *) NULL);
2155#endif
2156}
2157
2158/*
2159%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2160% %
2161% %
2162% %
2163+ M S B O r d e r L o n g %
2164% %
2165% %
2166% %
2167%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2168%
2169% MSBOrderLong() converts a least-significant byte first buffer of integers to
2170% most-significant byte first.
2171%
2172% The format of the MSBOrderLong method is:
2173%
2174% void MSBOrderLong(unsigned char *buffer,const size_t length)
2175%
2176% A description of each parameter follows.
2177%
2178% o buffer: Specifies a pointer to a buffer of integers.
2179%
2180% o length: Specifies the length of the buffer.
2181%
2182*/
2183MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2184{
2185 int
2186 c;
2187
2188 register unsigned char
2189 *p,
2190 *q;
2191
2192 assert(buffer != (unsigned char *) NULL);
2193 q=buffer+length;
2194 while (buffer < q)
2195 {
2196 p=buffer+3;
2197 c=(int) (*p);
2198 *p=(*buffer);
2199 *buffer++=(unsigned char) c;
2200 p=buffer+1;
2201 c=(int) (*p);
2202 *p=(*buffer);
2203 *buffer++=(unsigned char) c;
2204 buffer+=2;
2205 }
2206}
2207
2208/*
2209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2210% %
2211% %
2212% %
2213+ M S B O r d e r S h o r t %
2214% %
2215% %
2216% %
2217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2218%
2219% MSBOrderShort() converts a least-significant byte first buffer of integers
2220% to most-significant byte first.
2221%
2222% The format of the MSBOrderShort method is:
2223%
2224% void MSBOrderShort(unsigned char *p,const size_t length)
2225%
2226% A description of each parameter follows.
2227%
2228% o p: Specifies a pointer to a buffer of integers.
2229%
2230% o length: Specifies the length of the buffer.
2231%
2232*/
2233MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2234{
2235 int
2236 c;
2237
2238 register unsigned char
2239 *q;
2240
2241 assert(p != (unsigned char *) NULL);
2242 q=p+length;
2243 while (p < q)
2244 {
2245 c=(int) (*p);
2246 *p=(*(p+1));
2247 p++;
2248 *p++=(unsigned char) c;
2249 }
2250}
2251
2252/*
2253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2254% %
2255% %
2256% %
2257+ O p e n B l o b %
2258% %
2259% %
2260% %
2261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2262%
2263% OpenBlob() opens a file associated with the image. A file name of '-' sets
2264% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2265% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2266% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2267% from a system command.
2268%
2269% The format of the OpenBlob method is:
2270%
2271% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2272% const BlobMode mode,ExceptionInfo *exception)
2273%
2274% A description of each parameter follows:
2275%
2276% o image_info: the image info.
2277%
2278% o image: the image.
2279%
2280% o mode: the mode for opening the file.
2281%
2282*/
2283MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2284 Image *image,const BlobMode mode,ExceptionInfo *exception)
2285{
2286 char
cristybf6a7092010-06-11 02:12:15 +00002287 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002288 filename[MaxTextExtent];
2289
2290 const char
2291 *type;
2292
2293 MagickBooleanType
2294 status;
2295
2296 PolicyRights
2297 rights;
2298
2299 assert(image_info != (ImageInfo *) NULL);
2300 assert(image_info->signature == MagickSignature);
2301 if (image_info->debug != MagickFalse)
2302 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2303 image_info->filename);
2304 assert(image != (Image *) NULL);
2305 assert(image->signature == MagickSignature);
2306 if (image_info->blob != (void *) NULL)
2307 {
2308 if (image_info->stream != (StreamHandler) NULL)
2309 image->blob->stream=(StreamHandler) image_info->stream;
2310 AttachBlob(image->blob,image_info->blob,image_info->length);
2311 return(MagickTrue);
2312 }
2313 (void) DetachBlob(image->blob);
2314 switch (mode)
2315 {
2316 default: type="r"; break;
2317 case ReadBlobMode: type="r"; break;
2318 case ReadBinaryBlobMode: type="rb"; break;
2319 case WriteBlobMode: type="w"; break;
2320 case WriteBinaryBlobMode: type="w+b"; break;
2321 case AppendBlobMode: type="a"; break;
2322 case AppendBinaryBlobMode: type="a+b"; break;
2323 }
2324 if (*type != 'r')
2325 image->blob->synchronize=image_info->synchronize;
2326 if (image_info->stream != (StreamHandler) NULL)
2327 {
2328 image->blob->stream=(StreamHandler) image_info->stream;
2329 if (*type == 'w')
2330 {
2331 image->blob->type=FifoStream;
2332 return(MagickTrue);
2333 }
2334 }
2335 /*
2336 Open image file.
2337 */
2338 *filename='\0';
2339 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2340 rights=ReadPolicyRights;
2341 if (*type == 'w')
2342 rights=WritePolicyRights;
2343 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2344 {
cristya9197f62010-01-12 02:23:34 +00002345 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002346 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2347 "NotAuthorized","`%s'",filename);
2348 return(MagickFalse);
2349 }
2350 if ((LocaleCompare(filename,"-") == 0) ||
2351 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2352 {
2353 image->blob->file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002354#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002355 if (strchr(type,'b') != (char *) NULL)
2356 setmode(_fileno(image->blob->file),_O_BINARY);
2357#endif
2358 image->blob->type=StandardStream;
2359 image->blob->exempt=MagickTrue;
2360 return(MagickTrue);
2361 }
2362 if (LocaleNCompare(filename,"fd:",3) == 0)
2363 {
2364 char
2365 mode[MaxTextExtent];
2366
2367 *mode=(*type);
2368 mode[1]='\0';
cristyf2f27272009-12-17 14:48:46 +00002369 image->blob->file=fdopen(StringToLong(filename+3),mode);
cristy0157aea2010-04-24 21:12:18 +00002370#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002371 if (strchr(type,'b') != (char *) NULL)
2372 setmode(_fileno(image->blob->file),_O_BINARY);
2373#endif
2374 image->blob->type=StandardStream;
2375 image->blob->exempt=MagickTrue;
2376 return(MagickTrue);
2377 }
2378#if defined(MAGICKCORE_HAVE_POPEN)
2379 if (*filename == '|')
2380 {
2381 char
2382 mode[MaxTextExtent];
2383
2384 /*
2385 Pipe image to or from a system command.
2386 */
2387#if defined(SIGPIPE)
2388 if (*type == 'w')
2389 (void) signal(SIGPIPE,SIG_IGN);
2390#endif
2391 *mode=(*type);
2392 mode[1]='\0';
2393 image->blob->file=(FILE *) popen(filename+1,mode);
2394 if (image->blob->file == (FILE *) NULL)
2395 {
2396 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2397 return(MagickFalse);
2398 }
2399 image->blob->type=PipeStream;
2400 image->blob->exempt=MagickTrue;
2401 return(MagickTrue);
2402 }
2403#endif
2404 status=GetPathAttributes(filename,&image->blob->properties);
2405#if defined(S_ISFIFO)
2406 if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2407 {
2408 image->blob->file=(FILE *) OpenMagickStream(filename,type);
2409 if (image->blob->file == (FILE *) NULL)
2410 {
2411 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2412 return(MagickFalse);
2413 }
2414 image->blob->type=FileStream;
2415 image->blob->exempt=MagickTrue;
2416 return(MagickTrue);
2417 }
2418#endif
cristybf6a7092010-06-11 02:12:15 +00002419 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002420 if (*type == 'w')
2421 {
cristye8939e72010-02-03 17:05:25 +00002422 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002423 if ((image_info->adjoin == MagickFalse) ||
2424 (IsGlob(filename) != MagickFalse))
cristye8939e72010-02-03 17:05:25 +00002425 {
2426 /*
2427 Form filename for multi-part images.
2428 */
2429 (void) InterpretImageFilename(image_info,image,image->filename,(int)
2430 image->scene,filename);
cristy498cab92010-02-09 17:08:05 +00002431 if ((LocaleCompare(filename,image->filename) == 0) &&
2432 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2433 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002434 {
cristybf7fa0d2010-02-04 00:51:10 +00002435 char
cristybf7fa0d2010-02-04 00:51:10 +00002436 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002437
cristybf7fa0d2010-02-04 00:51:10 +00002438 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002439 if (*extension == '\0')
cristye8c25f92010-06-03 00:53:06 +00002440 (void) FormatMagickString(filename,MaxTextExtent,"%s-%.20g",
2441 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002442 else
2443 (void) FormatMagickString(filename,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002444 "%s-%.20g.%s",path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002445 }
2446 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002447#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002448 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002449#endif
cristye8939e72010-02-03 17:05:25 +00002450 }
cristy3ed852e2009-09-05 21:47:34 +00002451 }
cristybf6a7092010-06-11 02:12:15 +00002452 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002453 {
cristybf6a7092010-06-11 02:12:15 +00002454 image->blob->file=image_info->file;
2455 image->blob->type=FileStream;
2456 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002457 }
2458 else
cristybf6a7092010-06-11 02:12:15 +00002459 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002460 {
cristybf6a7092010-06-11 02:12:15 +00002461 image->blob->file=(FILE *) OpenMagickStream(filename,type);
cristy3ed852e2009-09-05 21:47:34 +00002462 if (image->blob->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002463 {
2464 size_t
cristybf6a7092010-06-11 02:12:15 +00002465 count;
cristy3ed852e2009-09-05 21:47:34 +00002466
cristybf6a7092010-06-11 02:12:15 +00002467 unsigned char
2468 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002469
cristybf6a7092010-06-11 02:12:15 +00002470 image->blob->type=FileStream;
2471#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyf55846d2010-09-17 19:01:10 +00002472 (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002473#endif
2474 (void) ResetMagickMemory(magick,0,sizeof(magick));
2475 count=fread(magick,1,sizeof(magick),image->blob->file);
2476 (void) rewind(image->blob->file);
2477 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2478 " read %.20g magic header bytes",(double) count);
2479#if defined(MAGICKCORE_ZLIB_DELEGATE)
2480 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2481 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002482 {
cristybf6a7092010-06-11 02:12:15 +00002483 (void) fclose(image->blob->file);
2484 image->blob->file=(FILE *) gzopen(filename,type);
2485 if (image->blob->file != (FILE *) NULL)
2486 image->blob->type=ZipStream;
2487 }
2488#endif
2489#if defined(MAGICKCORE_BZLIB_DELEGATE)
2490 if (strncmp((char *) magick,"BZh",3) == 0)
2491 {
2492 (void) fclose(image->blob->file);
2493 image->blob->file=(FILE *) BZ2_bzopen(filename,type);
2494 if (image->blob->file != (FILE *) NULL)
2495 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002496 }
cristybf6a7092010-06-11 02:12:15 +00002497#endif
cristyc6c589d2010-07-06 01:34:57 +00002498 if (image->blob->type == FileStream)
2499 {
2500 const MagickInfo
2501 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002502
cristyc6c589d2010-07-06 01:34:57 +00002503 ExceptionInfo
2504 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002505
cristyc6c589d2010-07-06 01:34:57 +00002506 struct stat
2507 *properties;
cristybf6a7092010-06-11 02:12:15 +00002508
cristyc6c589d2010-07-06 01:34:57 +00002509 sans_exception=AcquireExceptionInfo();
2510 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2511 sans_exception=DestroyExceptionInfo(sans_exception);
2512 properties=(&image->blob->properties);
2513 if ((magick_info != (const MagickInfo *) NULL) &&
2514 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2515 (properties->st_size <= MagickMaxBufferExtent))
2516 {
2517 size_t
2518 length;
cristybf6a7092010-06-11 02:12:15 +00002519
cristyc6c589d2010-07-06 01:34:57 +00002520 void
2521 *blob;
cristybf6a7092010-06-11 02:12:15 +00002522
cristyc6c589d2010-07-06 01:34:57 +00002523 length=(size_t) properties->st_size;
2524 blob=MapBlob(fileno(image->blob->file),ReadMode,0,length);
2525 if (blob != (void *) NULL)
2526 {
2527 /*
2528 Format supports blobs-- use memory-mapped I/O.
2529 */
2530 if (image_info->file != (FILE *) NULL)
2531 image->blob->exempt=MagickFalse;
2532 else
2533 {
2534 (void) fclose(image->blob->file);
2535 image->blob->file=(FILE *) NULL;
2536 }
2537 AttachBlob(image->blob,blob,length);
2538 image->blob->mapped=MagickTrue;
2539 }
2540 }
2541 }
cristy3ed852e2009-09-05 21:47:34 +00002542 }
cristybf6a7092010-06-11 02:12:15 +00002543 }
2544 else
2545#if defined(MAGICKCORE_ZLIB_DELEGATE)
2546 if ((LocaleCompare(extension,"Z") == 0) ||
2547 (LocaleCompare(extension,"gz") == 0) ||
2548 (LocaleCompare(extension,"wmz") == 0) ||
2549 (LocaleCompare(extension,"svgz") == 0))
2550 {
2551 if (mode == WriteBinaryBlobMode)
2552 type="wb";
2553 image->blob->file=(FILE *) gzopen(filename,type);
2554 if (image->blob->file != (FILE *) NULL)
2555 image->blob->type=ZipStream;
2556 }
2557 else
2558#endif
2559#if defined(MAGICKCORE_BZLIB_DELEGATE)
2560 if (LocaleCompare(extension,".bz2") == 0)
2561 {
2562 image->blob->file=(FILE *) BZ2_bzopen(filename,type);
2563 if (image->blob->file != (FILE *) NULL)
2564 image->blob->type=BZipStream;
2565 }
2566 else
2567#endif
2568 {
2569 image->blob->file=(FILE *) OpenMagickStream(filename,type);
2570 if (image->blob->file != (FILE *) NULL)
2571 {
2572 image->blob->type=FileStream;
2573#if defined(MAGICKCORE_HAVE_SETVBUF)
2574 (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,
2575 16384);
2576#endif
2577 }
2578 }
cristy3ed852e2009-09-05 21:47:34 +00002579 image->blob->status=MagickFalse;
2580 if (image->blob->type != UndefinedStream)
2581 image->blob->size=GetBlobSize(image);
2582 else
2583 {
2584 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2585 return(MagickFalse);
2586 }
2587 return(MagickTrue);
2588}
2589
2590/*
2591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2592% %
2593% %
2594% %
2595+ P i n g B l o b %
2596% %
2597% %
2598% %
2599%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2600%
2601% PingBlob() returns all the attributes of an image or image sequence except
2602% for the pixels. It is much faster and consumes far less memory than
2603% BlobToImage(). On failure, a NULL image is returned and exception
2604% describes the reason for the failure.
2605%
2606% The format of the PingBlob method is:
2607%
2608% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2609% const size_t length,ExceptionInfo *exception)
2610%
2611% A description of each parameter follows:
2612%
2613% o image_info: the image info.
2614%
2615% o blob: the address of a character stream in one of the image formats
2616% understood by ImageMagick.
2617%
2618% o length: This size_t integer reflects the length in bytes of the blob.
2619%
2620% o exception: return any errors or warnings in this structure.
2621%
2622*/
2623
2624#if defined(__cplusplus) || defined(c_plusplus)
2625extern "C" {
2626#endif
2627
2628static size_t PingStream(const Image *magick_unused(image),
2629 const void *magick_unused(pixels),const size_t columns)
2630{
2631 return(columns);
2632}
2633
2634#if defined(__cplusplus) || defined(c_plusplus)
2635}
2636#endif
2637
2638MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2639 const size_t length,ExceptionInfo *exception)
2640{
2641 Image
2642 *image;
2643
2644 ImageInfo
2645 *ping_info;
2646
2647 assert(image_info != (ImageInfo *) NULL);
2648 assert(image_info->signature == MagickSignature);
2649 if (image_info->debug != MagickFalse)
2650 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2651 image_info->filename);
2652 assert(exception != (ExceptionInfo *) NULL);
2653 if ((blob == (const void *) NULL) || (length == 0))
2654 {
2655 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
2656 "UnrecognizedImageFormat","`%s'",image_info->magick);
2657 return((Image *) NULL);
2658 }
2659 ping_info=CloneImageInfo(image_info);
2660 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2661 if (ping_info->blob == (const void *) NULL)
2662 {
2663 (void) ThrowMagickException(exception,GetMagickModule(),
2664 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
2665 return((Image *) NULL);
2666 }
cristy54aad5e2010-09-03 16:02:04 +00002667 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002668 ping_info->length=length;
2669 ping_info->ping=MagickTrue;
2670 image=ReadStream(ping_info,&PingStream,exception);
2671 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2672 ping_info=DestroyImageInfo(ping_info);
2673 return(image);
2674}
2675
2676/*
2677%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2678% %
2679% %
2680% %
2681+ R e a d B l o b %
2682% %
2683% %
2684% %
2685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2686%
2687% ReadBlob() reads data from the blob or image file and returns it. It
2688% returns the number of bytes read.
2689%
2690% The format of the ReadBlob method is:
2691%
2692% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2693%
2694% A description of each parameter follows:
2695%
2696% o image: the image.
2697%
2698% o length: Specifies an integer representing the number of bytes to read
2699% from the file.
2700%
2701% o data: Specifies an area to place the information requested from the
2702% file.
2703%
2704*/
2705MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2706 unsigned char *data)
2707{
2708 int
2709 c;
2710
2711 register unsigned char
2712 *q;
2713
2714 ssize_t
2715 count;
2716
2717 assert(image != (Image *) NULL);
2718 assert(image->signature == MagickSignature);
2719 assert(image->blob != (BlobInfo *) NULL);
2720 assert(image->blob->type != UndefinedStream);
2721 if (length == 0)
2722 return(0);
2723 assert(data != (void *) NULL);
2724 count=0;
2725 q=data;
2726 switch (image->blob->type)
2727 {
2728 case UndefinedStream:
2729 break;
2730 case FileStream:
2731 case StandardStream:
2732 case PipeStream:
2733 {
2734 switch (length)
2735 {
2736 default:
2737 {
2738 count=(ssize_t) fread(q,1,length,image->blob->file);
2739 break;
2740 }
2741 case 2:
2742 {
2743 c=getc(image->blob->file);
2744 if (c == EOF)
2745 break;
2746 *q++=(unsigned char) c;
2747 count++;
2748 }
2749 case 1:
2750 {
2751 c=getc(image->blob->file);
2752 if (c == EOF)
2753 break;
2754 *q++=(unsigned char) c;
2755 count++;
2756 }
2757 case 0:
2758 break;
2759 }
2760 break;
2761 }
2762 case ZipStream:
2763 {
2764#if defined(MAGICKCORE_ZLIB_DELEGATE)
2765 switch (length)
2766 {
2767 default:
2768 {
2769 count=(ssize_t) gzread(image->blob->file,q,(unsigned int) length);
2770 break;
2771 }
2772 case 2:
2773 {
2774 c=gzgetc(image->blob->file);
2775 if (c == EOF)
2776 break;
2777 *q++=(unsigned char) c;
2778 count++;
2779 }
2780 case 1:
2781 {
2782 c=gzgetc(image->blob->file);
2783 if (c == EOF)
2784 break;
2785 *q++=(unsigned char) c;
2786 count++;
2787 }
2788 case 0:
2789 break;
2790 }
2791#endif
2792 break;
2793 }
2794 case BZipStream:
2795 {
2796#if defined(MAGICKCORE_BZLIB_DELEGATE)
2797 count=(ssize_t) BZ2_bzread((BZFILE *) image->blob->file,q,(int) length);
2798#endif
2799 break;
2800 }
2801 case FifoStream:
2802 break;
2803 case BlobStream:
2804 {
2805 register const unsigned char
2806 *p;
2807
2808 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2809 {
2810 image->blob->eof=MagickTrue;
2811 break;
2812 }
2813 p=image->blob->data+image->blob->offset;
2814 count=(ssize_t) MagickMin(length,(size_t) (image->blob->length-
2815 image->blob->offset));
2816 image->blob->offset+=count;
2817 if (count != (ssize_t) length)
2818 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002819 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002820 break;
2821 }
2822 }
2823 return(count);
2824}
2825
2826/*
2827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2828% %
2829% %
2830% %
2831+ R e a d B l o b B y t e %
2832% %
2833% %
2834% %
2835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2836%
2837% ReadBlobByte() reads a single byte from the image file and returns it.
2838%
2839% The format of the ReadBlobByte method is:
2840%
2841% int ReadBlobByte(Image *image)
2842%
2843% A description of each parameter follows.
2844%
2845% o image: the image.
2846%
2847*/
2848MagickExport int ReadBlobByte(Image *image)
2849{
2850 register const unsigned char
2851 *p;
2852
2853 ssize_t
2854 count;
2855
2856 unsigned char
2857 buffer[1];
2858
2859 assert(image != (Image *) NULL);
2860 assert(image->signature == MagickSignature);
2861 p=ReadBlobStream(image,1,buffer,&count);
2862 if (count != 1)
2863 return(EOF);
2864 return((int) (*p));
2865}
2866
2867/*
2868%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2869% %
2870% %
2871% %
2872+ R e a d B l o b D o u b l e %
2873% %
2874% %
2875% %
2876%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2877%
2878% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2879% specified by the endian member of the image structure.
2880%
2881% The format of the ReadBlobDouble method is:
2882%
2883% double ReadBlobDouble(Image *image)
2884%
2885% A description of each parameter follows.
2886%
2887% o image: the image.
2888%
2889*/
2890MagickExport double ReadBlobDouble(Image *image)
2891{
2892 union
2893 {
2894 MagickSizeType
2895 unsigned_value;
2896
2897 double
2898 double_value;
2899 } quantum;
2900
2901 quantum.double_value=0.0;
2902 quantum.unsigned_value=ReadBlobLongLong(image);
2903 return(quantum.double_value);
2904}
2905
2906/*
2907%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2908% %
2909% %
2910% %
2911+ R e a d B l o b F l o a t %
2912% %
2913% %
2914% %
2915%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2916%
2917% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2918% specified by the endian member of the image structure.
2919%
2920% The format of the ReadBlobFloat method is:
2921%
2922% float ReadBlobFloat(Image *image)
2923%
2924% A description of each parameter follows.
2925%
2926% o image: the image.
2927%
2928*/
2929MagickExport float ReadBlobFloat(Image *image)
2930{
2931 union
2932 {
2933 unsigned int
2934 unsigned_value;
2935
2936 float
2937 float_value;
2938 } quantum;
2939
2940 quantum.float_value=0.0;
2941 quantum.unsigned_value=ReadBlobLong(image);
2942 return(quantum.float_value);
2943}
2944
2945/*
2946%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2947% %
2948% %
2949% %
2950+ R e a d B l o b L o n g %
2951% %
2952% %
2953% %
2954%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2955%
cristybb503372010-05-27 20:51:26 +00002956% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00002957% specified by the endian member of the image structure.
2958%
2959% The format of the ReadBlobLong method is:
2960%
2961% unsigned int ReadBlobLong(Image *image)
2962%
2963% A description of each parameter follows.
2964%
2965% o image: the image.
2966%
2967*/
2968MagickExport unsigned int ReadBlobLong(Image *image)
2969{
2970 register const unsigned char
2971 *p;
2972
2973 ssize_t
2974 count;
2975
2976 unsigned char
2977 buffer[4];
2978
2979 unsigned int
2980 value;
2981
2982 assert(image != (Image *) NULL);
2983 assert(image->signature == MagickSignature);
2984 *buffer='\0';
2985 p=ReadBlobStream(image,4,buffer,&count);
2986 if (count != 4)
2987 return(0UL);
2988 if (image->endian == LSBEndian)
2989 {
2990 value=(unsigned int) (*p++);
2991 value|=((unsigned int) (*p++)) << 8;
2992 value|=((unsigned int) (*p++)) << 16;
2993 value|=((unsigned int) (*p++)) << 24;
2994 return(value);
2995 }
2996 value=((unsigned int) (*p++)) << 24;
2997 value|=((unsigned int) (*p++)) << 16;
2998 value|=((unsigned int) (*p++)) << 8;
2999 value|=((unsigned int) (*p++));
3000 return(value);
3001}
3002
3003/*
3004%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3005% %
3006% %
3007% %
3008+ R e a d B l o b L o n g L o n g %
3009% %
3010% %
3011% %
3012%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3013%
cristy4cb162a2010-05-30 03:04:47 +00003014% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3015% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003016%
cristy4cb162a2010-05-30 03:04:47 +00003017% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003018%
cristy4cb162a2010-05-30 03:04:47 +00003019% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003020%
3021% A description of each parameter follows.
3022%
3023% o image: the image.
3024%
3025*/
3026MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3027{
cristy0286d852010-10-12 18:38:07 +00003028 MagickSizeType
3029 value;
3030
cristy3ed852e2009-09-05 21:47:34 +00003031 register const unsigned char
3032 *p;
3033
3034 ssize_t
3035 count;
3036
3037 unsigned char
3038 buffer[8];
3039
cristy3ed852e2009-09-05 21:47:34 +00003040 assert(image != (Image *) NULL);
3041 assert(image->signature == MagickSignature);
3042 *buffer='\0';
3043 p=ReadBlobStream(image,8,buffer,&count);
3044 if (count != 8)
3045 return(MagickULLConstant(0));
3046 if (image->endian == LSBEndian)
3047 {
3048 value=(MagickSizeType) (*p++);
3049 value|=((MagickSizeType) (*p++)) << 8;
3050 value|=((MagickSizeType) (*p++)) << 16;
3051 value|=((MagickSizeType) (*p++)) << 24;
3052 value|=((MagickSizeType) (*p++)) << 32;
3053 value|=((MagickSizeType) (*p++)) << 40;
3054 value|=((MagickSizeType) (*p++)) << 48;
3055 value|=((MagickSizeType) (*p++)) << 56;
3056 return(value & MagickULLConstant(0xffffffffffffffff));
3057 }
3058 value=((MagickSizeType) (*p++)) << 56;
3059 value|=((MagickSizeType) (*p++)) << 48;
3060 value|=((MagickSizeType) (*p++)) << 40;
3061 value|=((MagickSizeType) (*p++)) << 32;
3062 value|=((MagickSizeType) (*p++)) << 24;
3063 value|=((MagickSizeType) (*p++)) << 16;
3064 value|=((MagickSizeType) (*p++)) << 8;
3065 value|=((MagickSizeType) (*p++));
3066 return(value & MagickULLConstant(0xffffffffffffffff));
3067}
3068
3069/*
3070%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3071% %
3072% %
3073% %
3074+ R e a d B l o b S h o r t %
3075% %
3076% %
3077% %
3078%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3079%
3080% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3081% specified by the endian member of the image structure.
3082%
3083% The format of the ReadBlobShort method is:
3084%
3085% unsigned short ReadBlobShort(Image *image)
3086%
3087% A description of each parameter follows.
3088%
3089% o image: the image.
3090%
3091*/
3092MagickExport unsigned short ReadBlobShort(Image *image)
3093{
3094 register const unsigned char
3095 *p;
3096
3097 register unsigned int
3098 value;
3099
3100 ssize_t
3101 count;
3102
3103 unsigned char
3104 buffer[2];
3105
3106 assert(image != (Image *) NULL);
3107 assert(image->signature == MagickSignature);
3108 *buffer='\0';
3109 p=ReadBlobStream(image,2,buffer,&count);
3110 if (count != 2)
3111 return((unsigned short) 0U);
3112 if (image->endian == LSBEndian)
3113 {
3114 value=(unsigned int) (*p++);
3115 value|=((unsigned int) (*p++)) << 8;
3116 return((unsigned short) (value & 0xffff));
3117 }
3118 value=(unsigned int) ((*p++) << 8);
3119 value|=(unsigned int) (*p++);
3120 return((unsigned short) (value & 0xffff));
3121}
3122
3123/*
3124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3125% %
3126% %
3127% %
3128+ R e a d B l o b L S B L o n g %
3129% %
3130% %
3131% %
3132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3133%
cristybb503372010-05-27 20:51:26 +00003134% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003135% least-significant byte first order.
3136%
3137% The format of the ReadBlobLSBLong method is:
3138%
3139% unsigned int ReadBlobLSBLong(Image *image)
3140%
3141% A description of each parameter follows.
3142%
3143% o image: the image.
3144%
3145*/
3146MagickExport unsigned int ReadBlobLSBLong(Image *image)
3147{
3148 register const unsigned char
3149 *p;
3150
3151 register unsigned int
3152 value;
3153
3154 ssize_t
3155 count;
3156
3157 unsigned char
3158 buffer[4];
3159
3160 assert(image != (Image *) NULL);
3161 assert(image->signature == MagickSignature);
3162 *buffer='\0';
3163 p=ReadBlobStream(image,4,buffer,&count);
3164 if (count != 4)
3165 return(0U);
3166 value=(unsigned int) (*p++);
3167 value|=((unsigned int) (*p++)) << 8;
3168 value|=((unsigned int) (*p++)) << 16;
3169 value|=((unsigned int) (*p++)) << 24;
3170 return(value);
3171}
3172
3173/*
3174%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3175% %
3176% %
3177% %
3178+ R e a d B l o b L S B S h o r t %
3179% %
3180% %
3181% %
3182%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3183%
3184% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3185% least-significant byte first order.
3186%
3187% The format of the ReadBlobLSBShort method is:
3188%
3189% unsigned short ReadBlobLSBShort(Image *image)
3190%
3191% A description of each parameter follows.
3192%
3193% o image: the image.
3194%
3195*/
3196MagickExport unsigned short ReadBlobLSBShort(Image *image)
3197{
3198 register const unsigned char
3199 *p;
3200
3201 register unsigned int
3202 value;
3203
3204 ssize_t
3205 count;
3206
3207 unsigned char
3208 buffer[2];
3209
3210 assert(image != (Image *) NULL);
3211 assert(image->signature == MagickSignature);
3212 *buffer='\0';
3213 p=ReadBlobStream(image,2,buffer,&count);
3214 if (count != 2)
3215 return((unsigned short) 0U);
3216 value=(unsigned int) (*p++);
3217 value|=((unsigned int) ((*p++)) << 8);
3218 return((unsigned short) (value & 0xffff));
3219}
3220
3221/*
3222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3223% %
3224% %
3225% %
3226+ R e a d B l o b M S B L o n g %
3227% %
3228% %
3229% %
3230%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3231%
cristybb503372010-05-27 20:51:26 +00003232% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003233% most-significant byte first order.
3234%
3235% The format of the ReadBlobMSBLong method is:
3236%
3237% unsigned int ReadBlobMSBLong(Image *image)
3238%
3239% A description of each parameter follows.
3240%
3241% o image: the image.
3242%
3243*/
3244MagickExport unsigned int ReadBlobMSBLong(Image *image)
3245{
3246 register const unsigned char
3247 *p;
3248
3249 register unsigned int
3250 value;
3251
3252 ssize_t
3253 count;
3254
3255 unsigned char
3256 buffer[4];
3257
3258 assert(image != (Image *) NULL);
3259 assert(image->signature == MagickSignature);
3260 *buffer='\0';
3261 p=ReadBlobStream(image,4,buffer,&count);
3262 if (count != 4)
3263 return(0UL);
3264 value=((unsigned int) (*p++) << 24);
3265 value|=((unsigned int) (*p++) << 16);
3266 value|=((unsigned int) (*p++) << 8);
3267 value|=(unsigned int) (*p++);
3268 return(value);
3269}
3270
3271/*
3272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3273% %
3274% %
3275% %
cristy2d3d87f2010-03-01 00:23:08 +00003276+ R e a d B l o b M S B L o n g L o n g %
3277% %
3278% %
3279% %
3280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3281%
cristybb503372010-05-27 20:51:26 +00003282% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003283% most-significant byte first order.
3284%
3285% The format of the ReadBlobMSBLongLong method is:
3286%
3287% unsigned int ReadBlobMSBLongLong(Image *image)
3288%
3289% A description of each parameter follows.
3290%
3291% o image: the image.
3292%
3293*/
3294MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3295{
3296 register const unsigned char
3297 *p;
3298
3299 register MagickSizeType
3300 value;
3301
3302 ssize_t
3303 count;
3304
3305 unsigned char
cristy0286d852010-10-12 18:38:07 +00003306 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003307
3308 assert(image != (Image *) NULL);
3309 assert(image->signature == MagickSignature);
3310 *buffer='\0';
3311 p=ReadBlobStream(image,8,buffer,&count);
3312 if (count != 8)
3313 return(MagickULLConstant(0));
3314 value=((MagickSizeType) (*p++)) << 56;
3315 value|=((MagickSizeType) (*p++)) << 48;
3316 value|=((MagickSizeType) (*p++)) << 40;
3317 value|=((MagickSizeType) (*p++)) << 32;
3318 value|=((MagickSizeType) (*p++)) << 24;
3319 value|=((MagickSizeType) (*p++)) << 16;
3320 value|=((MagickSizeType) (*p++)) << 8;
3321 value|=((MagickSizeType) (*p++));
3322 return(value & MagickULLConstant(0xffffffffffffffff));
3323}
3324
3325/*
3326%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3327% %
3328% %
3329% %
cristy3ed852e2009-09-05 21:47:34 +00003330+ R e a d B l o b M S B S h o r t %
3331% %
3332% %
3333% %
3334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3335%
3336% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3337% most-significant byte first order.
3338%
3339% The format of the ReadBlobMSBShort method is:
3340%
3341% unsigned short ReadBlobMSBShort(Image *image)
3342%
3343% A description of each parameter follows.
3344%
3345% o image: the image.
3346%
3347*/
3348MagickExport unsigned short ReadBlobMSBShort(Image *image)
3349{
3350 register const unsigned char
3351 *p;
3352
3353 register unsigned int
3354 value;
3355
3356 ssize_t
3357 count;
3358
3359 unsigned char
3360 buffer[2];
3361
3362 assert(image != (Image *) NULL);
3363 assert(image->signature == MagickSignature);
3364 *buffer='\0';
3365 p=ReadBlobStream(image,2,buffer,&count);
3366 if (count != 2)
3367 return((unsigned short) 0U);
3368 value=(unsigned int) ((*p++) << 8);
3369 value|=(unsigned int) (*p++);
3370 return((unsigned short) (value & 0xffff));
3371}
3372
3373/*
3374%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3375% %
3376% %
3377% %
3378+ R e a d B l o b S t r i n g %
3379% %
3380% %
3381% %
3382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3383%
3384% ReadBlobString() reads characters from a blob or file until a newline
3385% character is read or an end-of-file condition is encountered.
3386%
3387% The format of the ReadBlobString method is:
3388%
3389% char *ReadBlobString(Image *image,char *string)
3390%
3391% A description of each parameter follows:
3392%
3393% o image: the image.
3394%
3395% o string: the address of a character buffer.
3396%
3397*/
3398MagickExport char *ReadBlobString(Image *image,char *string)
3399{
3400 register const unsigned char
3401 *p;
3402
cristybb503372010-05-27 20:51:26 +00003403 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003404 i;
3405
3406 ssize_t
3407 count;
3408
3409 unsigned char
3410 buffer[1];
3411
3412 assert(image != (Image *) NULL);
3413 assert(image->signature == MagickSignature);
3414 for (i=0; i < (MaxTextExtent-1L); i++)
3415 {
3416 p=ReadBlobStream(image,1,buffer,&count);
3417 if (count != 1)
3418 {
3419 if (i == 0)
3420 return((char *) NULL);
3421 break;
3422 }
3423 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003424 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003425 break;
3426 }
cristy2b5db102010-06-09 01:07:28 +00003427 if (string[i] == '\r')
3428 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003429 string[i]='\0';
3430 return(string);
3431}
3432
3433/*
3434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3435% %
3436% %
3437% %
3438+ R e f e r e n c e B l o b %
3439% %
3440% %
3441% %
3442%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3443%
3444% ReferenceBlob() increments the reference count associated with the pixel
3445% blob returning a pointer to the blob.
3446%
3447% The format of the ReferenceBlob method is:
3448%
3449% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3450%
3451% A description of each parameter follows:
3452%
3453% o blob_info: the blob_info.
3454%
3455*/
3456MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3457{
3458 assert(blob != (BlobInfo *) NULL);
3459 assert(blob->signature == MagickSignature);
3460 if (blob->debug != MagickFalse)
3461 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003462 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003463 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003464 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003465 return(blob);
3466}
3467
3468/*
3469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3470% %
3471% %
3472% %
3473+ S e e k B l o b %
3474% %
3475% %
3476% %
3477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3478%
3479% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3480% and returns the resulting offset.
3481%
3482% The format of the SeekBlob method is:
3483%
3484% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3485% const int whence)
3486%
3487% A description of each parameter follows:
3488%
3489% o image: the image.
3490%
3491% o offset: Specifies an integer representing the offset in bytes.
3492%
3493% o whence: Specifies an integer representing how the offset is
3494% treated relative to the beginning of the blob as follows:
3495%
3496% SEEK_SET Set position equal to offset bytes.
3497% SEEK_CUR Set position to current location plus offset.
3498% SEEK_END Set position to EOF plus offset.
3499%
3500*/
3501MagickExport MagickOffsetType SeekBlob(Image *image,
3502 const MagickOffsetType offset,const int whence)
3503{
3504 assert(image != (Image *) NULL);
3505 assert(image->signature == MagickSignature);
3506 if (image->debug != MagickFalse)
3507 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3508 assert(image->blob != (BlobInfo *) NULL);
3509 assert(image->blob->type != UndefinedStream);
3510 switch (image->blob->type)
3511 {
3512 case UndefinedStream:
3513 break;
3514 case FileStream:
3515 {
cristyecd0ab52010-05-30 14:59:20 +00003516 if (fseek(image->blob->file,(long) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003517 return(-1);
3518 image->blob->offset=TellBlob(image);
3519 break;
3520 }
3521 case StandardStream:
3522 case PipeStream:
3523 case ZipStream:
3524 {
3525#if defined(MAGICKCORE_ZLIB_DELEGATE)
3526 if (gzseek(image->blob->file,(off_t) offset,whence) < 0)
3527 return(-1);
3528#endif
3529 image->blob->offset=TellBlob(image);
3530 break;
3531 }
3532 case BZipStream:
3533 return(-1);
3534 case FifoStream:
3535 return(-1);
3536 case BlobStream:
3537 {
3538 switch (whence)
3539 {
3540 case SEEK_SET:
3541 default:
3542 {
3543 if (offset < 0)
3544 return(-1);
3545 image->blob->offset=offset;
3546 break;
3547 }
3548 case SEEK_CUR:
3549 {
3550 if ((image->blob->offset+offset) < 0)
3551 return(-1);
3552 image->blob->offset+=offset;
3553 break;
3554 }
3555 case SEEK_END:
3556 {
3557 if (((MagickOffsetType) image->blob->length+offset) < 0)
3558 return(-1);
3559 image->blob->offset=image->blob->length+offset;
3560 break;
3561 }
3562 }
3563 if (image->blob->offset <= (MagickOffsetType)
3564 ((off_t) image->blob->length))
3565 image->blob->eof=MagickFalse;
3566 else
3567 if (image->blob->mapped != MagickFalse)
3568 return(-1);
3569 else
3570 {
3571 image->blob->extent=(size_t) (image->blob->offset+
3572 image->blob->quantum);
3573 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3574 image->blob->data,image->blob->extent+1,
3575 sizeof(*image->blob->data));
3576 (void) SyncBlob(image);
3577 if (image->blob->data == (unsigned char *) NULL)
3578 {
3579 (void) DetachBlob(image->blob);
3580 return(-1);
3581 }
3582 }
3583 break;
3584 }
3585 }
3586 return(image->blob->offset);
3587}
3588
3589/*
3590%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3591% %
3592% %
3593% %
3594+ S e t B l o b E x e m p t %
3595% %
3596% %
3597% %
3598%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3599%
3600% SetBlobExempt() sets the blob exempt status.
3601%
3602% The format of the SetBlobExempt method is:
3603%
3604% MagickBooleanType SetBlobExempt(const Image *image,
3605% const MagickBooleanType exempt)
3606%
3607% A description of each parameter follows:
3608%
3609% o image: the image.
3610%
3611% o exempt: Set to true if this blob is exempt from being closed.
3612%
3613*/
3614MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
3615{
3616 assert(image != (const Image *) NULL);
3617 assert(image->signature == MagickSignature);
3618 if (image->debug != MagickFalse)
3619 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3620 image->blob->exempt=exempt;
3621}
3622
3623/*
3624%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3625% %
3626% %
3627% %
3628+ S e t B l o b E x t e n t %
3629% %
3630% %
3631% %
3632%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3633%
3634% SetBlobExtent() ensures enough space is allocated for the blob. If the
3635% method is successful, subsequent writes to bytes in the specified range are
3636% guaranteed not to fail.
3637%
3638% The format of the SetBlobExtent method is:
3639%
3640% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3641%
3642% A description of each parameter follows:
3643%
3644% o image: the image.
3645%
3646% o extent: the blob maximum extent.
3647%
3648*/
3649MagickExport MagickBooleanType SetBlobExtent(Image *image,
3650 const MagickSizeType extent)
3651{
3652 assert(image != (Image *) NULL);
3653 assert(image->signature == MagickSignature);
3654 if (image->debug != MagickFalse)
3655 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3656 assert(image->blob != (BlobInfo *) NULL);
3657 assert(image->blob->type != UndefinedStream);
3658 switch (image->blob->type)
3659 {
3660 case UndefinedStream:
3661 break;
3662 case FileStream:
3663 {
3664 if (extent != (MagickSizeType) ((off_t) extent))
3665 return(MagickFalse);
3666#if !defined(MAGICKCORE_POSIX_FALLOCATE)
3667 return(MagickFalse);
3668#else
3669 {
3670 int
3671 status;
3672
3673 MagickOffsetType
3674 offset;
3675
3676 offset=TellBlob(image);
3677 status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3678 (off_t) (extent-offset));
3679 if (status != 0)
3680 return(MagickFalse);
3681 }
3682#endif
3683 break;
3684 }
3685 case StandardStream:
3686 case PipeStream:
3687 case ZipStream:
3688 return(MagickFalse);
3689 case BZipStream:
3690 return(MagickFalse);
3691 case FifoStream:
3692 return(MagickFalse);
3693 case BlobStream:
3694 {
3695 if (image->blob->mapped != MagickFalse)
3696 {
3697 if (image->blob->file == (FILE *) NULL)
3698 return(MagickFalse);
3699 (void) UnmapBlob(image->blob->data,image->blob->length);
3700#if !defined(MAGICKCORE_POSIX_FALLOCATE)
3701 return(MagickFalse);
3702#else
3703 {
3704 int
3705 status;
3706
3707 MagickOffsetType
3708 offset;
3709
3710 offset=TellBlob(image);
3711 status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3712 (off_t) (extent-offset));
3713 if (status != 0)
3714 return(MagickFalse);
3715 }
3716 image->blob->data=(unsigned char*) MapBlob(fileno(image->blob->file),
3717 WriteMode,0,(size_t) extent);
3718 image->blob->extent=(size_t) extent;
3719 image->blob->length=(size_t) extent;
3720 (void) SyncBlob(image);
3721 break;
3722#endif
3723 }
3724 if (extent != (MagickSizeType) ((size_t) extent))
3725 return(MagickFalse);
3726 image->blob->extent=(size_t) extent;
3727 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3728 image->blob->extent+1,sizeof(*image->blob->data));
3729 (void) SyncBlob(image);
3730 if (image->blob->data == (unsigned char *) NULL)
3731 {
3732 (void) DetachBlob(image->blob);
3733 return(MagickFalse);
3734 }
3735 break;
3736 }
3737 }
3738 return(MagickTrue);
3739}
3740
3741/*
3742%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3743% %
3744% %
3745% %
3746+ S y n c B l o b %
3747% %
3748% %
3749% %
3750%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3751%
3752% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3753% attributes if it is an blob.
3754%
3755% The format of the SyncBlob method is:
3756%
3757% int SyncBlob(Image *image)
3758%
3759% A description of each parameter follows:
3760%
3761% o image: the image.
3762%
3763*/
3764static int SyncBlob(Image *image)
3765{
3766 int
3767 status;
3768
3769 assert(image != (Image *) NULL);
3770 assert(image->signature == MagickSignature);
3771 if (image->debug != MagickFalse)
3772 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3773 assert(image->blob != (BlobInfo *) NULL);
3774 assert(image->blob->type != UndefinedStream);
3775 status=0;
3776 switch (image->blob->type)
3777 {
3778 case UndefinedStream:
3779 break;
3780 case FileStream:
3781 case StandardStream:
3782 case PipeStream:
3783 {
3784 status=fflush(image->blob->file);
3785 break;
3786 }
3787 case ZipStream:
3788 {
3789#if defined(MAGICKCORE_ZLIB_DELEGATE)
3790 status=gzflush(image->blob->file,Z_SYNC_FLUSH);
3791#endif
3792 break;
3793 }
3794 case BZipStream:
3795 {
3796#if defined(MAGICKCORE_BZLIB_DELEGATE)
3797 status=BZ2_bzflush((BZFILE *) image->blob->file);
3798#endif
3799 break;
3800 }
3801 case FifoStream:
3802 break;
3803 case BlobStream:
3804 {
3805#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3806 if (image->blob->mapped != MagickFalse)
3807 status=msync(image->blob->data,image->blob->length,MS_SYNC);
3808#endif
3809 break;
3810 }
3811 }
3812 return(status);
3813}
3814
3815/*
3816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3817% %
3818% %
3819% %
3820+ T e l l B l o b %
3821% %
3822% %
3823% %
3824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3825%
3826% TellBlob() obtains the current value of the blob or file position.
3827%
3828% The format of the TellBlob method is:
3829%
3830% MagickOffsetType TellBlob(const Image *image)
3831%
3832% A description of each parameter follows:
3833%
3834% o image: the image.
3835%
3836*/
3837MagickExport MagickOffsetType TellBlob(const Image *image)
3838{
3839 MagickOffsetType
3840 offset;
3841
3842 assert(image != (Image *) NULL);
3843 assert(image->signature == MagickSignature);
3844 if (image->debug != MagickFalse)
3845 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3846 assert(image->blob != (BlobInfo *) NULL);
3847 assert(image->blob->type != UndefinedStream);
3848 offset=(-1);
3849 switch (image->blob->type)
3850 {
3851 case UndefinedStream:
3852 break;
3853 case FileStream:
3854 {
3855 offset=ftell(image->blob->file);
3856 break;
3857 }
3858 case StandardStream:
3859 case PipeStream:
3860 break;
3861 case ZipStream:
3862 {
3863#if defined(MAGICKCORE_ZLIB_DELEGATE)
3864 offset=(MagickOffsetType) gztell(image->blob->file);
3865#endif
3866 break;
3867 }
3868 case BZipStream:
3869 break;
3870 case FifoStream:
3871 break;
3872 case BlobStream:
3873 {
3874 offset=image->blob->offset;
3875 break;
3876 }
3877 }
3878 return(offset);
3879}
3880
3881/*
3882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3883% %
3884% %
3885% %
3886+ U n m a p B l o b %
3887% %
3888% %
3889% %
3890%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3891%
3892% UnmapBlob() deallocates the binary large object previously allocated with
3893% the MapBlob method.
3894%
3895% The format of the UnmapBlob method is:
3896%
3897% MagickBooleanType UnmapBlob(void *map,const size_t length)
3898%
3899% A description of each parameter follows:
3900%
3901% o map: the address of the binary large object.
3902%
3903% o length: the length of the binary large object.
3904%
3905*/
3906MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3907{
3908#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3909 int
3910 status;
3911
3912 status=munmap(map,length);
3913 return(status == -1 ? MagickFalse : MagickTrue);
3914#else
3915 (void) map;
3916 (void) length;
3917 return(MagickFalse);
3918#endif
3919}
3920
3921/*
3922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3923% %
3924% %
3925% %
3926+ W r i t e B l o b %
3927% %
3928% %
3929% %
3930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3931%
3932% WriteBlob() writes data to a blob or image file. It returns the number of
3933% bytes written.
3934%
3935% The format of the WriteBlob method is:
3936%
3937% ssize_t WriteBlob(Image *image,const size_t length,
3938% const unsigned char *data)
3939%
3940% A description of each parameter follows:
3941%
3942% o image: the image.
3943%
3944% o length: Specifies an integer representing the number of bytes to
3945% write to the file.
3946%
3947% o data: The address of the data to write to the blob or file.
3948%
3949*/
3950MagickExport ssize_t WriteBlob(Image *image,const size_t length,
3951 const unsigned char *data)
3952{
3953 int
3954 c;
3955
3956 register const unsigned char
3957 *p;
3958
3959 ssize_t
3960 count;
3961
3962 assert(image != (Image *) NULL);
3963 assert(image->signature == MagickSignature);
3964 assert(data != (const unsigned char *) NULL);
3965 assert(image->blob != (BlobInfo *) NULL);
3966 assert(image->blob->type != UndefinedStream);
3967 if (length == 0)
3968 return(0);
3969 count=0;
3970 p=data;
3971 switch (image->blob->type)
3972 {
3973 case UndefinedStream:
3974 break;
3975 case FileStream:
3976 case StandardStream:
3977 case PipeStream:
3978 {
3979 switch (length)
3980 {
3981 default:
3982 {
3983 count=(ssize_t) fwrite((const char *) data,1,length,
3984 image->blob->file);
3985 break;
3986 }
3987 case 2:
3988 {
3989 c=putc((int) *p++,image->blob->file);
3990 if (c == EOF)
3991 break;
3992 count++;
3993 }
3994 case 1:
3995 {
3996 c=putc((int) *p++,image->blob->file);
3997 if (c == EOF)
3998 break;
3999 count++;
4000 }
4001 case 0:
4002 break;
4003 }
4004 break;
4005 }
4006 case ZipStream:
4007 {
4008#if defined(MAGICKCORE_ZLIB_DELEGATE)
4009 switch (length)
4010 {
4011 default:
4012 {
4013 count=(ssize_t) gzwrite(image->blob->file,(void *) data,
4014 (unsigned int) length);
4015 break;
4016 }
4017 case 2:
4018 {
4019 c=gzputc(image->blob->file,(int) *p++);
4020 if (c == EOF)
4021 break;
4022 count++;
4023 }
4024 case 1:
4025 {
4026 c=gzputc(image->blob->file,(int) *p++);
4027 if (c == EOF)
4028 break;
4029 count++;
4030 }
4031 case 0:
4032 break;
4033 }
4034#endif
4035 break;
4036 }
4037 case BZipStream:
4038 {
4039#if defined(MAGICKCORE_BZLIB_DELEGATE)
4040 count=(ssize_t) BZ2_bzwrite((BZFILE *) image->blob->file,(void *) data,
4041 (int) length);
4042#endif
4043 break;
4044 }
4045 case FifoStream:
4046 {
4047 count=(ssize_t) image->blob->stream(image,data,length);
4048 break;
4049 }
4050 case BlobStream:
4051 {
4052 register unsigned char
4053 *q;
4054
4055 if ((image->blob->offset+(MagickOffsetType) length) >=
4056 (MagickOffsetType) image->blob->extent)
4057 {
4058 if (image->blob->mapped != MagickFalse)
4059 return(0);
4060 image->blob->quantum<<=1;
4061 image->blob->extent+=length+image->blob->quantum;
4062 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4063 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4064 (void) SyncBlob(image);
4065 if (image->blob->data == (unsigned char *) NULL)
4066 {
4067 (void) DetachBlob(image->blob);
4068 return(0);
4069 }
4070 }
4071 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004072 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004073 image->blob->offset+=length;
4074 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4075 image->blob->length=(size_t) image->blob->offset;
4076 count=(ssize_t) length;
4077 }
4078 }
4079 return(count);
4080}
4081
4082/*
4083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4084% %
4085% %
4086% %
4087+ W r i t e B l o b B y t e %
4088% %
4089% %
4090% %
4091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4092%
4093% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4094% written (either 0 or 1);
4095%
4096% The format of the WriteBlobByte method is:
4097%
4098% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4099%
4100% A description of each parameter follows.
4101%
4102% o image: the image.
4103%
4104% o value: Specifies the value to write.
4105%
4106*/
4107MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4108{
4109 assert(image != (Image *) NULL);
4110 assert(image->signature == MagickSignature);
4111 return(WriteBlobStream(image,1,&value));
4112}
4113
4114/*
4115%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4116% %
4117% %
4118% %
4119+ W r i t e B l o b F l o a t %
4120% %
4121% %
4122% %
4123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4124%
4125% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4126% specified by the endian member of the image structure.
4127%
4128% The format of the WriteBlobFloat method is:
4129%
4130% ssize_t WriteBlobFloat(Image *image,const float value)
4131%
4132% A description of each parameter follows.
4133%
4134% o image: the image.
4135%
4136% o value: Specifies the value to write.
4137%
4138*/
4139MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4140{
4141 union
4142 {
4143 unsigned int
4144 unsigned_value;
4145
4146 float
4147 float_value;
4148 } quantum;
4149
4150 quantum.unsigned_value=0U;
4151 quantum.float_value=value;
4152 return(WriteBlobLong(image,quantum.unsigned_value));
4153}
4154
4155/*
4156%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4157% %
4158% %
4159% %
4160+ W r i t e B l o b L o n g %
4161% %
4162% %
4163% %
4164%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4165%
cristybb503372010-05-27 20:51:26 +00004166% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004167% specified by the endian member of the image structure.
4168%
4169% The format of the WriteBlobLong method is:
4170%
4171% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4172%
4173% A description of each parameter follows.
4174%
4175% o image: the image.
4176%
4177% o value: Specifies the value to write.
4178%
4179*/
4180MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4181{
4182 unsigned char
4183 buffer[4];
4184
4185 assert(image != (Image *) NULL);
4186 assert(image->signature == MagickSignature);
4187 if (image->endian == LSBEndian)
4188 {
4189 buffer[0]=(unsigned char) value;
4190 buffer[1]=(unsigned char) (value >> 8);
4191 buffer[2]=(unsigned char) (value >> 16);
4192 buffer[3]=(unsigned char) (value >> 24);
4193 return(WriteBlobStream(image,4,buffer));
4194 }
4195 buffer[0]=(unsigned char) (value >> 24);
4196 buffer[1]=(unsigned char) (value >> 16);
4197 buffer[2]=(unsigned char) (value >> 8);
4198 buffer[3]=(unsigned char) value;
4199 return(WriteBlobStream(image,4,buffer));
4200}
4201
4202/*
4203%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4204% %
4205% %
4206% %
4207+ W r i t e B l o b S h o r t %
4208% %
4209% %
4210% %
4211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4212%
4213% WriteBlobShort() writes a short value as a 16-bit quantity in the
4214% byte-order specified by the endian member of the image structure.
4215%
4216% The format of the WriteBlobShort method is:
4217%
4218% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4219%
4220% A description of each parameter follows.
4221%
4222% o image: the image.
4223%
4224% o value: Specifies the value to write.
4225%
4226*/
4227MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4228{
4229 unsigned char
4230 buffer[2];
4231
4232 assert(image != (Image *) NULL);
4233 assert(image->signature == MagickSignature);
4234 if (image->endian == LSBEndian)
4235 {
4236 buffer[0]=(unsigned char) value;
4237 buffer[1]=(unsigned char) (value >> 8);
4238 return(WriteBlobStream(image,2,buffer));
4239 }
4240 buffer[0]=(unsigned char) (value >> 8);
4241 buffer[1]=(unsigned char) value;
4242 return(WriteBlobStream(image,2,buffer));
4243}
4244
4245/*
4246%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4247% %
4248% %
4249% %
4250+ W r i t e B l o b L S B L o n g %
4251% %
4252% %
4253% %
4254%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4255%
cristybb503372010-05-27 20:51:26 +00004256% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004257% least-significant byte first order.
4258%
4259% The format of the WriteBlobLSBLong method is:
4260%
4261% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4262%
4263% A description of each parameter follows.
4264%
4265% o image: the image.
4266%
4267% o value: Specifies the value to write.
4268%
4269*/
4270MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4271{
4272 unsigned char
4273 buffer[4];
4274
4275 assert(image != (Image *) NULL);
4276 assert(image->signature == MagickSignature);
4277 buffer[0]=(unsigned char) value;
4278 buffer[1]=(unsigned char) (value >> 8);
4279 buffer[2]=(unsigned char) (value >> 16);
4280 buffer[3]=(unsigned char) (value >> 24);
4281 return(WriteBlobStream(image,4,buffer));
4282}
4283
4284/*
4285%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4286% %
4287% %
4288% %
4289+ W r i t e B l o b L S B S h o r t %
4290% %
4291% %
4292% %
4293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4294%
cristybb503372010-05-27 20:51:26 +00004295% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004296% least-significant byte first order.
4297%
4298% The format of the WriteBlobLSBShort method is:
4299%
4300% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4301%
4302% A description of each parameter follows.
4303%
4304% o image: the image.
4305%
4306% o value: Specifies the value to write.
4307%
4308*/
4309MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4310{
4311 unsigned char
4312 buffer[2];
4313
4314 assert(image != (Image *) NULL);
4315 assert(image->signature == MagickSignature);
4316 buffer[0]=(unsigned char) value;
4317 buffer[1]=(unsigned char) (value >> 8);
4318 return(WriteBlobStream(image,2,buffer));
4319}
4320
4321/*
4322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4323% %
4324% %
4325% %
4326+ W r i t e B l o b M S B L o n g %
4327% %
4328% %
4329% %
4330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4331%
cristybb503372010-05-27 20:51:26 +00004332% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004333% most-significant byte first order.
4334%
4335% The format of the WriteBlobMSBLong method is:
4336%
4337% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4338%
4339% A description of each parameter follows.
4340%
4341% o value: Specifies the value to write.
4342%
4343% o image: the image.
4344%
4345*/
4346MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4347{
4348 unsigned char
4349 buffer[4];
4350
4351 assert(image != (Image *) NULL);
4352 assert(image->signature == MagickSignature);
4353 buffer[0]=(unsigned char) (value >> 24);
4354 buffer[1]=(unsigned char) (value >> 16);
4355 buffer[2]=(unsigned char) (value >> 8);
4356 buffer[3]=(unsigned char) value;
4357 return(WriteBlobStream(image,4,buffer));
4358}
4359
4360/*
4361%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4362% %
4363% %
4364% %
cristy2ca49922010-03-06 02:54:01 +00004365+ W r i t e B l o b M S B L o n g L o n g %
4366% %
4367% %
4368% %
4369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4370%
4371% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4372% most-significant byte first order.
4373%
4374% The format of the WriteBlobMSBLongLong method is:
4375%
4376% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4377%
4378% A description of each parameter follows.
4379%
4380% o value: Specifies the value to write.
4381%
4382% o image: the image.
4383%
4384*/
4385MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4386 const MagickSizeType value)
4387{
4388 unsigned char
4389 buffer[8];
4390
4391 assert(image != (Image *) NULL);
4392 assert(image->signature == MagickSignature);
4393 buffer[0]=(unsigned char) (value >> 56);
4394 buffer[1]=(unsigned char) (value >> 48);
4395 buffer[2]=(unsigned char) (value >> 40);
4396 buffer[3]=(unsigned char) (value >> 32);
4397 buffer[4]=(unsigned char) (value >> 24);
4398 buffer[5]=(unsigned char) (value >> 16);
4399 buffer[6]=(unsigned char) (value >> 8);
4400 buffer[7]=(unsigned char) value;
4401 return(WriteBlobStream(image,8,buffer));
4402}
4403
4404/*
4405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4406% %
4407% %
4408% %
cristy3ed852e2009-09-05 21:47:34 +00004409+ W r i t e B l o b M S B S h o r t %
4410% %
4411% %
4412% %
4413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4414%
cristybb503372010-05-27 20:51:26 +00004415% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004416% most-significant byte first order.
4417%
4418% The format of the WriteBlobMSBShort method is:
4419%
4420% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4421%
4422% A description of each parameter follows.
4423%
4424% o value: Specifies the value to write.
4425%
4426% o file: Specifies the file to write the data to.
4427%
4428*/
4429MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4430{
4431 unsigned char
4432 buffer[2];
4433
4434 assert(image != (Image *) NULL);
4435 assert(image->signature == MagickSignature);
4436 buffer[0]=(unsigned char) (value >> 8);
4437 buffer[1]=(unsigned char) value;
4438 return(WriteBlobStream(image,2,buffer));
4439}
4440
4441/*
4442%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4443% %
4444% %
4445% %
4446+ W r i t e B l o b S t r i n g %
4447% %
4448% %
4449% %
4450%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4451%
4452% WriteBlobString() write a string to a blob. It returns the number of
4453% characters written.
4454%
4455% The format of the WriteBlobString method is:
4456%
4457% ssize_t WriteBlobString(Image *image,const char *string)
4458%
4459% A description of each parameter follows.
4460%
4461% o image: the image.
4462%
4463% o string: Specifies the string to write.
4464%
4465*/
4466MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4467{
4468 assert(image != (Image *) NULL);
4469 assert(image->signature == MagickSignature);
4470 assert(string != (const char *) NULL);
4471 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4472}