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