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