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