blob: 9d086f7d34c269a1399f29d94c618cc6d71bd796 [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% %
cristy45ef08f2012-12-07 13:13:34 +000020% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
cristy4c08aed2011-07-01 19:47:50 +000043#include "MagickCore/studio.h"
cristyd2d11ec2012-03-28 13:53:49 +000044#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000045#include "MagickCore/blob.h"
46#include "MagickCore/blob-private.h"
47#include "MagickCore/cache.h"
48#include "MagickCore/client.h"
49#include "MagickCore/constitute.h"
50#include "MagickCore/delegate.h"
51#include "MagickCore/exception.h"
52#include "MagickCore/exception-private.h"
53#include "MagickCore/image-private.h"
54#include "MagickCore/list.h"
55#include "MagickCore/locale_.h"
56#include "MagickCore/log.h"
57#include "MagickCore/magick.h"
58#include "MagickCore/memory_.h"
59#include "MagickCore/policy.h"
60#include "MagickCore/resource_.h"
61#include "MagickCore/semaphore.h"
62#include "MagickCore/string_.h"
63#include "MagickCore/string-private.h"
64#include "MagickCore/token.h"
65#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000066#include "MagickCore/utility-private.h"
cristy3ed852e2009-09-05 21:47:34 +000067#if defined(MAGICKCORE_ZLIB_DELEGATE)
68#include "zlib.h"
69#endif
70#if defined(MAGICKCORE_BZLIB_DELEGATE)
71#include "bzlib.h"
72#endif
73
74/*
75 Define declarations.
76*/
77#define MagickMaxBlobExtent 65541
cristy3ed852e2009-09-05 21:47:34 +000078#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
79# define MAP_ANONYMOUS MAP_ANON
80#endif
81#if !defined(MAP_FAILED)
82#define MAP_FAILED ((void *) -1)
83#endif
84#if !defined(MS_SYNC)
85#define MS_SYNC 0x04
86#endif
87#if defined(__OS2__)
88#include <io.h>
89#define _O_BINARY O_BINARY
90#endif
91
92/*
93 Typedef declarations.
94*/
cristye7b28372012-06-17 13:59:06 +000095typedef union FileInfo
96{
97 FILE
98 *file;
99
100#if defined(MAGICKCORE_ZLIB_DELEGATE)
101 gzFile
102 gzfile;
103#endif
104
105#if defined(MAGICKCORE_BZLIB_DELEGATE)
106 BZFILE
107 *bzfile;
108#endif
109} FileInfo;
110
cristy3ed852e2009-09-05 21:47:34 +0000111struct _BlobInfo
112{
113 size_t
114 length,
115 extent,
116 quantum;
117
118 MagickBooleanType
119 mapped,
120 eof;
121
122 MagickOffsetType
123 offset;
124
125 MagickSizeType
126 size;
127
128 MagickBooleanType
129 exempt,
130 synchronize,
131 status,
132 temporary;
133
134 StreamType
135 type;
136
cristye7b28372012-06-17 13:59:06 +0000137 FileInfo
138 file_info;
cristy3ed852e2009-09-05 21:47:34 +0000139
140 struct stat
141 properties;
142
143 StreamHandler
144 stream;
145
146 unsigned char
147 *data;
148
149 MagickBooleanType
150 debug;
151
152 SemaphoreInfo
153 *semaphore;
154
cristybb503372010-05-27 20:51:26 +0000155 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000156 reference_count;
157
cristybb503372010-05-27 20:51:26 +0000158 size_t
cristy3ed852e2009-09-05 21:47:34 +0000159 signature;
160};
161
162/*
163 Forward declarations.
164*/
165static int
166 SyncBlob(Image *);
167
168/*
169%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170% %
171% %
172% %
173+ A t t a c h B l o b %
174% %
175% %
176% %
177%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178%
179% AttachBlob() attaches a blob to the BlobInfo structure.
180%
181% The format of the AttachBlob method is:
182%
183% void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
184%
185% A description of each parameter follows:
186%
187% o blob_info: Specifies a pointer to a BlobInfo structure.
188%
189% o blob: the address of a character stream in one of the image formats
190% understood by ImageMagick.
191%
192% o length: This size_t integer reflects the length in bytes of the blob.
193%
194*/
195MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
196 const size_t length)
197{
198 assert(blob_info != (BlobInfo *) NULL);
199 if (blob_info->debug != MagickFalse)
200 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
201 blob_info->length=length;
202 blob_info->extent=length;
203 blob_info->quantum=(size_t) MagickMaxBlobExtent;
204 blob_info->offset=0;
205 blob_info->type=BlobStream;
cristye7b28372012-06-17 13:59:06 +0000206 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000207 blob_info->data=(unsigned char *) blob;
208 blob_info->mapped=MagickFalse;
209}
210
211/*
212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213% %
214% %
215% %
216+ B l o b T o F i l e %
217% %
218% %
219% %
220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221%
222% BlobToFile() writes a blob to a file. It returns MagickFalse if an error
223% occurs otherwise MagickTrue.
224%
225% The format of the BlobToFile method is:
226%
227% MagickBooleanType BlobToFile(char *filename,const void *blob,
228% const size_t length,ExceptionInfo *exception)
229%
230% A description of each parameter follows:
231%
232% o filename: Write the blob to this file.
233%
234% o blob: the address of a blob.
235%
236% o length: This length in bytes of the blob.
237%
238% o exception: return any errors or warnings in this structure.
239%
240*/
241
cristy7753b2a2011-02-19 18:36:52 +0000242static inline MagickSizeType MagickMin(const MagickSizeType x,
243 const MagickSizeType y)
cristy3ed852e2009-09-05 21:47:34 +0000244{
245 if (x < y)
246 return(x);
247 return(y);
248}
249
250MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
251 const size_t length,ExceptionInfo *exception)
252{
253 int
254 file;
255
256 register size_t
257 i;
258
259 ssize_t
260 count;
261
262 assert(filename != (const char *) NULL);
263 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
264 assert(blob != (const void *) NULL);
265 if (*filename == '\0')
266 file=AcquireUniqueFileResource(filename);
267 else
cristy18c6c272011-09-23 14:40:37 +0000268 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +0000269 if (file == -1)
270 {
271 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
272 return(MagickFalse);
273 }
274 for (i=0; i < length; i+=count)
275 {
cristy7753b2a2011-02-19 18:36:52 +0000276 count=(ssize_t) write(file,(const char *) blob+i,(size_t) MagickMin(length-
277 i,(MagickSizeType) SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +0000278 if (count <= 0)
279 {
280 count=0;
281 if (errno != EINTR)
282 break;
283 }
284 }
cristya7cb4312010-06-26 00:47:03 +0000285 file=close(file);
286 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +0000287 {
288 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
289 return(MagickFalse);
290 }
291 return(MagickTrue);
292}
293
294/*
295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296% %
297% %
298% %
299% B l o b T o I m a g e %
300% %
301% %
302% %
303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
304%
305% BlobToImage() implements direct to memory image formats. It returns the
306% blob as an image.
307%
308% The format of the BlobToImage method is:
309%
310% Image *BlobToImage(const ImageInfo *image_info,const void *blob,
311% const size_t length,ExceptionInfo *exception)
312%
313% A description of each parameter follows:
314%
315% o image_info: the image info.
316%
317% o blob: the address of a character stream in one of the image formats
318% understood by ImageMagick.
319%
320% o length: This size_t integer reflects the length in bytes of the blob.
321%
322% o exception: return any errors or warnings in this structure.
323%
324*/
325MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
326 const size_t length,ExceptionInfo *exception)
327{
328 const MagickInfo
329 *magick_info;
330
331 Image
332 *image;
333
334 ImageInfo
335 *blob_info,
336 *clone_info;
337
338 MagickBooleanType
339 status;
340
341 assert(image_info != (ImageInfo *) NULL);
342 assert(image_info->signature == MagickSignature);
343 if (image_info->debug != MagickFalse)
344 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
345 image_info->filename);
346 assert(exception != (ExceptionInfo *) NULL);
347 if ((blob == (const void *) NULL) || (length == 0))
348 {
349 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
anthonye5b39652012-04-21 05:37:29 +0000350 "ZeroLengthBlobNotPermitted","'%s'",image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +0000351 return((Image *) NULL);
352 }
353 blob_info=CloneImageInfo(image_info);
354 blob_info->blob=(void *) blob;
355 blob_info->length=length;
356 if (*blob_info->magick == '\0')
cristyd965a422010-03-03 17:47:35 +0000357 (void) SetImageInfo(blob_info,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000358 magick_info=GetMagickInfo(blob_info->magick,exception);
359 if (magick_info == (const MagickInfo *) NULL)
360 {
361 blob_info=DestroyImageInfo(blob_info);
362 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000363 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'",
cristy3ed852e2009-09-05 21:47:34 +0000364 image_info->filename);
365 return((Image *) NULL);
366 }
367 if (GetMagickBlobSupport(magick_info) != MagickFalse)
368 {
369 /*
370 Native blob support for this image format.
371 */
372 (void) CopyMagickString(blob_info->filename,image_info->filename,
373 MaxTextExtent);
374 (void) CopyMagickString(blob_info->magick,image_info->magick,
375 MaxTextExtent);
376 image=ReadImage(blob_info,exception);
377 if (image != (Image *) NULL)
378 (void) DetachBlob(image->blob);
379 blob_info=DestroyImageInfo(blob_info);
380 return(image);
381 }
382 /*
383 Write blob to a temporary file on disk.
384 */
385 blob_info->blob=(void *) NULL;
386 blob_info->length=0;
387 *blob_info->filename='\0';
388 status=BlobToFile(blob_info->filename,blob,length,exception);
389 if (status == MagickFalse)
390 {
391 (void) RelinquishUniqueFileResource(blob_info->filename);
392 blob_info=DestroyImageInfo(blob_info);
393 return((Image *) NULL);
394 }
395 clone_info=CloneImageInfo(blob_info);
cristyb51dff52011-05-19 16:55:47 +0000396 (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +0000397 blob_info->magick,blob_info->filename);
398 image=ReadImage(clone_info,exception);
cristy540a22c2012-06-10 15:22:16 +0000399 if (image != (Image *) NULL)
400 {
401 Image
402 *images;
403
404 /*
405 Restore original filenames.
406 */
407 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
408 {
cristy540a22c2012-06-10 15:22:16 +0000409 (void) CopyMagickMemory(images->filename,image_info->filename,
410 sizeof(images->filename));
cristybe674a62012-08-14 12:38:33 +0000411 (void) CopyMagickMemory(images->magick_filename,image_info->filename,
412 sizeof(images->magick_filename));
cristy540a22c2012-06-10 15:22:16 +0000413 images=GetNextImageInList(images);
414 }
415 }
cristy3ed852e2009-09-05 21:47:34 +0000416 clone_info=DestroyImageInfo(clone_info);
417 (void) RelinquishUniqueFileResource(blob_info->filename);
418 blob_info=DestroyImageInfo(blob_info);
419 return(image);
420}
421
422/*
423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
424% %
425% %
426% %
427+ C l o n e B l o b I n f o %
428% %
429% %
430% %
431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432%
433% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
434% blob info is NULL, a new one.
435%
436% The format of the CloneBlobInfo method is:
437%
438% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
439%
440% A description of each parameter follows:
441%
442% o blob_info: the blob info.
443%
444*/
445MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
446{
447 BlobInfo
448 *clone_info;
449
cristy73bd4a52010-10-05 11:24:23 +0000450 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
cristy3ed852e2009-09-05 21:47:34 +0000451 if (clone_info == (BlobInfo *) NULL)
452 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
453 GetBlobInfo(clone_info);
454 if (blob_info == (BlobInfo *) NULL)
455 return(clone_info);
456 clone_info->length=blob_info->length;
457 clone_info->extent=blob_info->extent;
458 clone_info->synchronize=blob_info->synchronize;
459 clone_info->quantum=blob_info->quantum;
460 clone_info->mapped=blob_info->mapped;
461 clone_info->eof=blob_info->eof;
462 clone_info->offset=blob_info->offset;
463 clone_info->size=blob_info->size;
464 clone_info->exempt=blob_info->exempt;
465 clone_info->status=blob_info->status;
466 clone_info->temporary=blob_info->temporary;
467 clone_info->type=blob_info->type;
cristye7b28372012-06-17 13:59:06 +0000468 clone_info->file_info.file=blob_info->file_info.file;
cristy3ed852e2009-09-05 21:47:34 +0000469 clone_info->properties=blob_info->properties;
470 clone_info->stream=blob_info->stream;
471 clone_info->data=blob_info->data;
472 clone_info->debug=IsEventLogging();
473 clone_info->reference_count=1;
474 return(clone_info);
475}
476
477/*
478%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
479% %
480% %
481% %
482+ C l o s e B l o b %
483% %
484% %
485% %
486%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
487%
488% CloseBlob() closes a stream associated with the image.
489%
490% The format of the CloseBlob method is:
491%
492% MagickBooleanType CloseBlob(Image *image)
493%
494% A description of each parameter follows:
495%
496% o image: the image.
497%
498*/
499MagickExport MagickBooleanType CloseBlob(Image *image)
500{
501 int
502 status;
503
504 /*
505 Close image file.
506 */
507 assert(image != (Image *) NULL);
508 assert(image->signature == MagickSignature);
509 if (image->debug != MagickFalse)
510 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
511 assert(image->blob != (BlobInfo *) NULL);
512 if (image->blob->type == UndefinedStream)
513 return(MagickTrue);
514 if (image->blob->synchronize != MagickFalse)
515 SyncBlob(image);
516 image->blob->size=GetBlobSize(image);
cristy81b8ce52010-02-05 01:53:17 +0000517 image->extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +0000518 image->blob->eof=MagickFalse;
519 if (image->blob->exempt != MagickFalse)
520 {
521 image->blob->type=UndefinedStream;
522 return(MagickTrue);
523 }
524 status=0;
525 switch (image->blob->type)
526 {
527 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000528 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000529 break;
530 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000531 case PipeStream:
532 {
cristye7b28372012-06-17 13:59:06 +0000533 status=ferror(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000534 break;
535 }
536 case ZipStream:
537 {
538#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000539 (void) gzerror(image->blob->file_info.gzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000540#endif
541 break;
542 }
543 case BZipStream:
544 {
545#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000546 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000547#endif
548 break;
549 }
550 case FifoStream:
551 case BlobStream:
552 break;
553 }
554 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
555 switch (image->blob->type)
556 {
557 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000558 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000559 break;
560 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000561 {
562 if (image->blob->synchronize != MagickFalse)
cristyff483372010-10-16 17:00:58 +0000563 {
cristye7b28372012-06-17 13:59:06 +0000564 status=fflush(image->blob->file_info.file);
565 status=fsync(fileno(image->blob->file_info.file));
cristyff483372010-10-16 17:00:58 +0000566 }
cristye7b28372012-06-17 13:59:06 +0000567 status=fclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000568 break;
569 }
570 case PipeStream:
571 {
572#if defined(MAGICKCORE_HAVE_PCLOSE)
cristye7b28372012-06-17 13:59:06 +0000573 status=pclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000574#endif
575 break;
576 }
577 case ZipStream:
578 {
579#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000580 status=gzclose(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +0000581#endif
582 break;
583 }
584 case BZipStream:
585 {
586#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000587 BZ2_bzclose(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +0000588#endif
589 break;
590 }
591 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000592 break;
cristyff483372010-10-16 17:00:58 +0000593 case BlobStream:
594 {
cristye7b28372012-06-17 13:59:06 +0000595 if (image->blob->file_info.file != (FILE *) NULL)
cristyff483372010-10-16 17:00:58 +0000596 {
597 if (image->blob->synchronize != MagickFalse)
cristye7b28372012-06-17 13:59:06 +0000598 (void) fsync(fileno(image->blob->file_info.file));
599 status=fclose(image->blob->file_info.file);
cristyff483372010-10-16 17:00:58 +0000600 }
601 break;
602 }
cristy3ed852e2009-09-05 21:47:34 +0000603 }
604 (void) DetachBlob(image->blob);
605 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
606 return(image->blob->status);
607}
608
609/*
610%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611% %
612% %
613% %
614+ D e s t r o y B l o b %
615% %
616% %
617% %
618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619%
620% DestroyBlob() deallocates memory associated with a blob.
621%
622% The format of the DestroyBlob method is:
623%
624% void DestroyBlob(Image *image)
625%
626% A description of each parameter follows:
627%
628% o image: the image.
629%
630*/
631MagickExport void DestroyBlob(Image *image)
632{
633 MagickBooleanType
634 destroy;
635
636 assert(image != (Image *) NULL);
637 assert(image->signature == MagickSignature);
638 if (image->debug != MagickFalse)
639 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
640 assert(image->blob != (BlobInfo *) NULL);
641 assert(image->blob->signature == MagickSignature);
642 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000643 LockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000644 image->blob->reference_count--;
645 assert(image->blob->reference_count >= 0);
646 if (image->blob->reference_count == 0)
647 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000648 UnlockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000649 if (destroy == MagickFalse)
650 return;
651 (void) CloseBlob(image);
652 if (image->blob->mapped != MagickFalse)
653 (void) UnmapBlob(image->blob->data,image->blob->length);
654 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
655 DestroySemaphoreInfo(&image->blob->semaphore);
656 image->blob->signature=(~MagickSignature);
657 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
658}
659
660/*
661%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
662% %
663% %
664% %
665+ D e t a c h B l o b %
666% %
667% %
668% %
669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670%
671% DetachBlob() detaches a blob from the BlobInfo structure.
672%
673% The format of the DetachBlob method is:
674%
675% unsigned char *DetachBlob(BlobInfo *blob_info)
676%
677% A description of each parameter follows:
678%
679% o blob_info: Specifies a pointer to a BlobInfo structure.
680%
681*/
682MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
683{
684 unsigned char
685 *data;
686
687 assert(blob_info != (BlobInfo *) NULL);
688 if (blob_info->debug != MagickFalse)
689 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
690 if (blob_info->mapped != MagickFalse)
691 (void) UnmapBlob(blob_info->data,blob_info->length);
692 blob_info->mapped=MagickFalse;
693 blob_info->length=0;
694 blob_info->offset=0;
695 blob_info->eof=MagickFalse;
696 blob_info->exempt=MagickFalse;
697 blob_info->type=UndefinedStream;
cristye7b28372012-06-17 13:59:06 +0000698 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000699 data=blob_info->data;
700 blob_info->data=(unsigned char *) NULL;
701 blob_info->stream=(StreamHandler) NULL;
702 return(data);
703}
704
705/*
706%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707% %
708% %
709% %
cristyc1af14f2010-09-16 20:01:21 +0000710+ D i s c a r d B l o b B y t e s %
711% %
712% %
713% %
714%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715%
716% DiscardBlobBytes() discards bytes in a blob.
717%
718% The format of the DiscardBlobBytes method is:
719%
720% MagickBooleanType DiscardBlobBytes(Image *image,const size_t length)
721%
722% A description of each parameter follows.
723%
724% o image: the image.
725%
726% o length: the number of bytes to skip.
727%
728*/
729
730static inline const unsigned char *ReadBlobStream(Image *image,
731 const size_t length,unsigned char *data,ssize_t *count)
732{
733 assert(count != (ssize_t *) NULL);
734 assert(image->blob != (BlobInfo *) NULL);
735 if (image->blob->type != BlobStream)
736 {
737 *count=ReadBlob(image,length,data);
738 return(data);
739 }
740 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
741 {
742 *count=0;
743 image->blob->eof=MagickTrue;
744 return(data);
745 }
746 data=image->blob->data+image->blob->offset;
cristy7753b2a2011-02-19 18:36:52 +0000747 *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
cristyc1af14f2010-09-16 20:01:21 +0000748 image->blob->offset));
749 image->blob->offset+=(*count);
750 if (*count != (ssize_t) length)
751 image->blob->eof=MagickTrue;
752 return(data);
753}
754
755MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
cristy7753b2a2011-02-19 18:36:52 +0000756 const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000757{
cristy7753b2a2011-02-19 18:36:52 +0000758 register MagickOffsetType
cristyc1af14f2010-09-16 20:01:21 +0000759 i;
760
761 size_t
762 quantum;
763
764 ssize_t
765 count;
766
767 unsigned char
cristyf55846d2010-09-17 19:01:10 +0000768 buffer[16384];
cristyc1af14f2010-09-16 20:01:21 +0000769
770 assert(image != (Image *) NULL);
771 assert(image->signature == MagickSignature);
772 count=0;
cristy7753b2a2011-02-19 18:36:52 +0000773 for (i=0; i < (MagickOffsetType) length; i+=count)
cristyc1af14f2010-09-16 20:01:21 +0000774 {
cristy7753b2a2011-02-19 18:36:52 +0000775 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
cristyc1af14f2010-09-16 20:01:21 +0000776 (void) ReadBlobStream(image,quantum,buffer,&count);
777 if (count <= 0)
778 {
779 count=0;
780 if (errno != EINTR)
781 break;
782 }
783 }
cristy7753b2a2011-02-19 18:36:52 +0000784 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
cristyc1af14f2010-09-16 20:01:21 +0000785}
786
787/*
788%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789% %
790% %
791% %
cristy3ed852e2009-09-05 21:47:34 +0000792+ D u p l i c a t e s B l o b %
793% %
794% %
795% %
796%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
797%
798% DuplicateBlob() duplicates a blob descriptor.
799%
800% The format of the DuplicateBlob method is:
801%
802% void DuplicateBlob(Image *image,const Image *duplicate)
803%
804% A description of each parameter follows:
805%
806% o image: the image.
807%
808% o duplicate: the duplicate image.
809%
810*/
811MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
812{
813 assert(image != (Image *) NULL);
814 assert(image->signature == MagickSignature);
815 if (image->debug != MagickFalse)
816 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
817 assert(duplicate != (Image *) NULL);
818 assert(duplicate->signature == MagickSignature);
819 DestroyBlob(image);
820 image->blob=ReferenceBlob(duplicate->blob);
821}
822
823/*
824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825% %
826% %
827% %
828+ E O F B l o b %
829% %
830% %
831% %
832%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833%
834% EOFBlob() returns a non-zero value when EOF has been detected reading from
835% a blob or file.
836%
837% The format of the EOFBlob method is:
838%
839% int EOFBlob(const Image *image)
840%
841% A description of each parameter follows:
842%
843% o image: the image.
844%
845*/
846MagickExport int EOFBlob(const Image *image)
847{
848 assert(image != (Image *) NULL);
849 assert(image->signature == MagickSignature);
850 if (image->debug != MagickFalse)
851 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
852 assert(image->blob != (BlobInfo *) NULL);
853 assert(image->blob->type != UndefinedStream);
854 switch (image->blob->type)
855 {
856 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000857 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000858 break;
859 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000860 case PipeStream:
861 {
cristye7b28372012-06-17 13:59:06 +0000862 image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
cristy95888612012-04-04 21:56:52 +0000863 MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000864 break;
865 }
866 case ZipStream:
867 {
868 image->blob->eof=MagickFalse;
869 break;
870 }
871 case BZipStream:
872 {
873#if defined(MAGICKCORE_BZLIB_DELEGATE)
874 int
875 status;
876
877 status=0;
cristye7b28372012-06-17 13:59:06 +0000878 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000879 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
880#endif
881 break;
882 }
883 case FifoStream:
884 {
885 image->blob->eof=MagickFalse;
886 break;
887 }
888 case BlobStream:
889 break;
890 }
891 return((int) image->blob->eof);
892}
893
894/*
895%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
896% %
897% %
898% %
899+ F i l e T o B l o b %
900% %
901% %
902% %
903%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
904%
cristy178edaf2011-01-23 03:42:39 +0000905% FileToBlob() returns the contents of a file as a buffer terminated with
906% the '\0' character. The length of the buffer (not including the extra
907% terminating '\0' character) is returned via the 'length' parameter. Free
908% the buffer with RelinquishMagickMemory().
cristy3ed852e2009-09-05 21:47:34 +0000909%
910% The format of the FileToBlob method is:
911%
912% unsigned char *FileToBlob(const char *filename,const size_t extent,
913% size_t *length,ExceptionInfo *exception)
914%
915% A description of each parameter follows:
916%
917% o blob: FileToBlob() returns the contents of a file as a blob. If
918% an error occurs NULL is returned.
919%
920% o filename: the filename.
921%
922% o extent: The maximum length of the blob.
923%
924% o length: On return, this reflects the actual length of the blob.
925%
926% o exception: return any errors or warnings in this structure.
927%
928*/
929MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
930 size_t *length,ExceptionInfo *exception)
931{
932 int
933 file;
934
935 MagickOffsetType
936 offset;
937
938 register size_t
939 i;
940
941 ssize_t
942 count;
943
944 unsigned char
945 *blob;
946
947 void
948 *map;
949
950 assert(filename != (const char *) NULL);
951 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
952 assert(exception != (ExceptionInfo *) NULL);
953 *length=0;
954 file=fileno(stdin);
955 if (LocaleCompare(filename,"-") != 0)
cristy18c6c272011-09-23 14:40:37 +0000956 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +0000957 if (file == -1)
958 {
959 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
960 return((unsigned char *) NULL);
961 }
cristy7f317702011-02-18 20:40:28 +0000962 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
cristy3ed852e2009-09-05 21:47:34 +0000963 count=0;
964 if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset)))
965 {
966 size_t
967 quantum;
968
969 struct stat
cristye7b28372012-06-17 13:59:06 +0000970 file_stats;
cristy3ed852e2009-09-05 21:47:34 +0000971
972 /*
973 Stream is not seekable.
974 */
975 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +0000976 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
977 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +0000978 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +0000979 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
980 for (i=0; blob != (unsigned char *) NULL; i+=count)
981 {
982 count=(ssize_t) read(file,blob+i,quantum);
983 if (count <= 0)
984 {
985 count=0;
986 if (errno != EINTR)
987 break;
988 }
cristy9c66d8c2012-08-10 11:05:36 +0000989 if (~((size_t) i) < (quantum+1))
cristy3ed852e2009-09-05 21:47:34 +0000990 {
991 blob=(unsigned char *) RelinquishMagickMemory(blob);
992 break;
993 }
994 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
995 sizeof(*blob));
996 if ((size_t) (i+count) >= extent)
997 break;
998 }
cristy54439632010-07-15 00:43:34 +0000999 if (LocaleCompare(filename,"-") != 0)
1000 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001001 if (blob == (unsigned char *) NULL)
1002 {
1003 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001004 ResourceLimitError,"MemoryAllocationFailed","'%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001005 return((unsigned char *) NULL);
1006 }
cristya7cb4312010-06-26 00:47:03 +00001007 if (file == -1)
1008 {
1009 blob=(unsigned char *) RelinquishMagickMemory(blob);
1010 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1011 return((unsigned char *) NULL);
1012 }
cristy7753b2a2011-02-19 18:36:52 +00001013 *length=(size_t) MagickMin(i+count,extent);
cristy3ed852e2009-09-05 21:47:34 +00001014 blob[*length]='\0';
1015 return(blob);
1016 }
cristy7753b2a2011-02-19 18:36:52 +00001017 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
cristy3ed852e2009-09-05 21:47:34 +00001018 blob=(unsigned char *) NULL;
cristy37e0b382011-06-07 13:31:21 +00001019 if (~(*length) >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +00001020 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1021 sizeof(*blob));
1022 if (blob == (unsigned char *) NULL)
1023 {
cristy54439632010-07-15 00:43:34 +00001024 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001025 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001026 ResourceLimitError,"MemoryAllocationFailed","'%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001027 return((unsigned char *) NULL);
1028 }
1029 map=MapBlob(file,ReadMode,0,*length);
1030 if (map != (unsigned char *) NULL)
1031 {
cristy54aad5e2010-09-03 16:02:04 +00001032 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +00001033 (void) UnmapBlob(map,*length);
1034 }
1035 else
1036 {
cristy7f317702011-02-18 20:40:28 +00001037 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001038 for (i=0; i < *length; i+=count)
1039 {
cristy7753b2a2011-02-19 18:36:52 +00001040 count=(ssize_t) read(file,blob+i,(size_t) MagickMin(*length-i,
1041 (MagickSizeType) SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001042 if (count <= 0)
1043 {
1044 count=0;
1045 if (errno != EINTR)
1046 break;
1047 }
1048 }
1049 if (i < *length)
1050 {
1051 file=close(file)-1;
1052 blob=(unsigned char *) RelinquishMagickMemory(blob);
1053 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1054 return((unsigned char *) NULL);
1055 }
1056 }
cristy3ed852e2009-09-05 21:47:34 +00001057 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001058 if (LocaleCompare(filename,"-") != 0)
1059 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001060 if (file == -1)
1061 {
1062 blob=(unsigned char *) RelinquishMagickMemory(blob);
1063 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1064 }
cristy3ed852e2009-09-05 21:47:34 +00001065 return(blob);
1066}
1067
1068/*
1069%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1070% %
1071% %
1072% %
1073% F i l e T o I m a g e %
1074% %
1075% %
1076% %
1077%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1078%
1079% FileToImage() write the contents of a file to an image.
1080%
1081% The format of the FileToImage method is:
1082%
1083% MagickBooleanType FileToImage(Image *,const char *filename)
1084%
1085% A description of each parameter follows:
1086%
1087% o image: the image.
1088%
1089% o filename: the filename.
1090%
1091*/
1092
1093static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1094 const unsigned char *data)
1095{
1096 MagickSizeType
1097 extent;
1098
1099 register unsigned char
1100 *q;
1101
1102 assert(image->blob != (BlobInfo *) NULL);
1103 if (image->blob->type != BlobStream)
1104 return(WriteBlob(image,length,data));
1105 assert(image->blob->type != UndefinedStream);
1106 assert(data != (void *) NULL);
1107 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1108 if (extent >= image->blob->extent)
1109 {
1110 image->blob->quantum<<=1;
1111 extent=image->blob->extent+image->blob->quantum+length;
1112 if (SetBlobExtent(image,extent) == MagickFalse)
1113 return(0);
1114 }
1115 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001116 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001117 image->blob->offset+=length;
1118 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1119 image->blob->length=(size_t) image->blob->offset;
1120 return((ssize_t) length);
1121}
1122
cristyc82a27b2011-10-21 01:07:16 +00001123MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1124 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001125{
1126 int
1127 file;
1128
1129 size_t
1130 length,
1131 quantum;
1132
1133 ssize_t
1134 count;
1135
1136 struct stat
cristye7b28372012-06-17 13:59:06 +00001137 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001138
1139 unsigned char
1140 *blob;
1141
1142 assert(image != (const Image *) NULL);
1143 assert(image->signature == MagickSignature);
1144 assert(filename != (const char *) NULL);
1145 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
cristy18c6c272011-09-23 14:40:37 +00001146 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001147 if (file == -1)
1148 {
cristyc82a27b2011-10-21 01:07:16 +00001149 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001150 return(MagickFalse);
1151 }
1152 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001153 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1154 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001155 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1156 if (blob == (unsigned char *) NULL)
1157 {
cristyc82a27b2011-10-21 01:07:16 +00001158 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1159 filename);
cristy3ed852e2009-09-05 21:47:34 +00001160 return(MagickFalse);
1161 }
1162 for ( ; ; )
1163 {
1164 count=(ssize_t) read(file,blob,quantum);
1165 if (count <= 0)
1166 {
1167 count=0;
1168 if (errno != EINTR)
1169 break;
1170 }
1171 length=(size_t) count;
1172 count=WriteBlobStream(image,length,blob);
1173 if (count != (ssize_t) length)
1174 {
cristyc82a27b2011-10-21 01:07:16 +00001175 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001176 break;
1177 }
1178 }
cristya7cb4312010-06-26 00:47:03 +00001179 file=close(file);
1180 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001181 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001182 blob=(unsigned char *) RelinquishMagickMemory(blob);
1183 return(MagickTrue);
1184}
1185
1186/*
1187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1188% %
1189% %
1190% %
1191+ G e t B l o b E r r o r %
1192% %
1193% %
1194% %
1195%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196%
1197% GetBlobError() returns MagickTrue if the blob associated with the specified
1198% image encountered an error.
1199%
1200% The format of the GetBlobError method is:
1201%
1202% MagickBooleanType GetBlobError(const Image *image)
1203%
1204% A description of each parameter follows:
1205%
1206% o image: the image.
1207%
1208*/
cristy7832dc22011-09-05 01:21:53 +00001209MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001210{
1211 assert(image != (const Image *) NULL);
1212 assert(image->signature == MagickSignature);
1213 if (image->debug != MagickFalse)
1214 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1215 return(image->blob->status);
1216}
1217
1218/*
1219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1220% %
1221% %
1222% %
1223+ G e t B l o b F i l e H a n d l e %
1224% %
1225% %
1226% %
1227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1228%
1229% GetBlobFileHandle() returns the file handle associated with the image blob.
1230%
1231% The format of the GetBlobFile method is:
1232%
1233% FILE *GetBlobFileHandle(const Image *image)
1234%
1235% A description of each parameter follows:
1236%
1237% o image: the image.
1238%
1239*/
1240MagickExport FILE *GetBlobFileHandle(const Image *image)
1241{
1242 assert(image != (const Image *) NULL);
1243 assert(image->signature == MagickSignature);
cristye7b28372012-06-17 13:59:06 +00001244 return(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001245}
1246
1247/*
1248%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1249% %
1250% %
1251% %
1252+ G e t B l o b I n f o %
1253% %
1254% %
1255% %
1256%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1257%
1258% GetBlobInfo() initializes the BlobInfo structure.
1259%
1260% The format of the GetBlobInfo method is:
1261%
1262% void GetBlobInfo(BlobInfo *blob_info)
1263%
1264% A description of each parameter follows:
1265%
1266% o blob_info: Specifies a pointer to a BlobInfo structure.
1267%
1268*/
cristy7832dc22011-09-05 01:21:53 +00001269MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001270{
1271 assert(blob_info != (BlobInfo *) NULL);
1272 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1273 blob_info->type=UndefinedStream;
1274 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1275 blob_info->properties.st_mtime=time((time_t *) NULL);
1276 blob_info->properties.st_ctime=time((time_t *) NULL);
1277 blob_info->debug=IsEventLogging();
1278 blob_info->reference_count=1;
1279 blob_info->semaphore=AllocateSemaphoreInfo();
1280 blob_info->signature=MagickSignature;
1281}
1282
1283/*
1284%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1285% %
1286% %
1287% %
1288% G e t B l o b P r o p e r t i e s %
1289% %
1290% %
1291% %
1292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293%
1294% GetBlobProperties() returns information about an image blob.
1295%
1296% The format of the GetBlobProperties method is:
1297%
1298% const struct stat *GetBlobProperties(const Image *image)
1299%
1300% A description of each parameter follows:
1301%
1302% o image: the image.
1303%
1304*/
cristy7832dc22011-09-05 01:21:53 +00001305MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001306{
1307 assert(image != (Image *) NULL);
1308 assert(image->signature == MagickSignature);
1309 if (image->debug != MagickFalse)
1310 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1311 return(&image->blob->properties);
1312}
1313
1314/*
1315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1316% %
1317% %
1318% %
1319+ G e t B l o b S i z e %
1320% %
1321% %
1322% %
1323%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1324%
1325% GetBlobSize() returns the current length of the image file or blob; zero is
1326% returned if the size cannot be determined.
1327%
1328% The format of the GetBlobSize method is:
1329%
1330% MagickSizeType GetBlobSize(const Image *image)
1331%
1332% A description of each parameter follows:
1333%
1334% o image: the image.
1335%
1336*/
1337MagickExport MagickSizeType GetBlobSize(const Image *image)
1338{
1339 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001340 extent;
cristy3ed852e2009-09-05 21:47:34 +00001341
1342 assert(image != (Image *) NULL);
1343 assert(image->signature == MagickSignature);
1344 if (image->debug != MagickFalse)
1345 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1346 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001347 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001348 switch (image->blob->type)
1349 {
1350 case UndefinedStream:
1351 {
cristy81b8ce52010-02-05 01:53:17 +00001352 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001353 break;
1354 }
cristybc20d112012-07-29 20:27:00 +00001355 case StandardStream:
1356 {
1357 extent=image->blob->size;
1358 break;
1359 }
cristy3ed852e2009-09-05 21:47:34 +00001360 case FileStream:
1361 {
cristye7b28372012-06-17 13:59:06 +00001362 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001363 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001364 break;
1365 }
cristy3ed852e2009-09-05 21:47:34 +00001366 case PipeStream:
1367 {
cristy81b8ce52010-02-05 01:53:17 +00001368 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001369 break;
1370 }
1371 case ZipStream:
1372 case BZipStream:
1373 {
1374 MagickBooleanType
1375 status;
1376
1377 status=GetPathAttributes(image->filename,&image->blob->properties);
1378 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001379 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001380 break;
1381 }
1382 case FifoStream:
1383 break;
1384 case BlobStream:
1385 {
cristy891dc792010-03-04 01:47:16 +00001386 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001387 break;
1388 }
1389 }
cristy81b8ce52010-02-05 01:53:17 +00001390 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001391}
1392
1393/*
1394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1395% %
1396% %
1397% %
1398+ G e t B l o b S t r e a m D a t a %
1399% %
1400% %
1401% %
1402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1403%
1404% GetBlobStreamData() returns the stream data for the image.
1405%
1406% The format of the GetBlobStreamData method is:
1407%
1408% unsigned char *GetBlobStreamData(const Image *image)
1409%
1410% A description of each parameter follows:
1411%
1412% o image: the image.
1413%
1414*/
1415MagickExport unsigned char *GetBlobStreamData(const Image *image)
1416{
1417 assert(image != (const Image *) NULL);
1418 assert(image->signature == MagickSignature);
1419 return(image->blob->data);
1420}
1421
1422/*
1423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1424% %
1425% %
1426% %
1427+ G e t B l o b S t r e a m H a n d l e r %
1428% %
1429% %
1430% %
1431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1432%
1433% GetBlobStreamHandler() returns the stream handler for the image.
1434%
1435% The format of the GetBlobStreamHandler method is:
1436%
1437% StreamHandler GetBlobStreamHandler(const Image *image)
1438%
1439% A description of each parameter follows:
1440%
1441% o image: the image.
1442%
1443*/
cristy7832dc22011-09-05 01:21:53 +00001444MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001445{
1446 assert(image != (const Image *) NULL);
1447 assert(image->signature == MagickSignature);
1448 if (image->debug != MagickFalse)
1449 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1450 return(image->blob->stream);
1451}
1452
1453/*
1454%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1455% %
1456% %
1457% %
1458% I m a g e T o B l o b %
1459% %
1460% %
1461% %
1462%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1463%
1464% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001465% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001466% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001467% etc.). This method is the equivalent of WriteImage(), but writes the
1468% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001469%
1470% The format of the ImageToBlob method is:
1471%
1472% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1473% size_t *length,ExceptionInfo *exception)
1474%
1475% A description of each parameter follows:
1476%
1477% o image_info: the image info.
1478%
1479% o image: the image.
1480%
1481% o length: This pointer to a size_t integer sets the initial length of the
1482% blob. On return, it reflects the actual length of the blob.
1483%
1484% o exception: return any errors or warnings in this structure.
1485%
1486*/
1487MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1488 Image *image,size_t *length,ExceptionInfo *exception)
1489{
1490 const MagickInfo
1491 *magick_info;
1492
1493 ImageInfo
1494 *blob_info;
1495
1496 MagickBooleanType
1497 status;
1498
1499 unsigned char
1500 *blob;
1501
1502 assert(image_info != (const ImageInfo *) NULL);
1503 assert(image_info->signature == MagickSignature);
1504 if (image_info->debug != MagickFalse)
1505 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1506 image_info->filename);
1507 assert(image != (Image *) NULL);
1508 assert(image->signature == MagickSignature);
1509 assert(exception != (ExceptionInfo *) NULL);
1510 *length=0;
1511 blob=(unsigned char *) NULL;
1512 blob_info=CloneImageInfo(image_info);
1513 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001514 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001515 if (*blob_info->magick != '\0')
1516 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1517 magick_info=GetMagickInfo(image->magick,exception);
1518 if (magick_info == (const MagickInfo *) NULL)
1519 {
1520 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001521 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'",
cristy3ed852e2009-09-05 21:47:34 +00001522 image->filename);
1523 return(blob);
1524 }
1525 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1526 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1527 {
1528 /*
1529 Native blob support for this image format.
1530 */
1531 blob_info->length=0;
1532 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1533 sizeof(unsigned char));
1534 if (blob_info->blob == (void *) NULL)
1535 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001536 ResourceLimitError,"MemoryAllocationFailed","'%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001537 else
1538 {
1539 (void) CloseBlob(image);
1540 image->blob->exempt=MagickTrue;
1541 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001542 status=WriteImage(blob_info,image,exception);
cristyc42554f2012-08-22 12:00:43 +00001543 *length=image->blob->length;
1544 blob=DetachBlob(image->blob);
cristy6e50f9e2012-08-22 16:30:29 +00001545 if (status == MagickFalse)
1546 blob=(unsigned char *) RelinquishMagickMemory(blob);
1547 else
1548 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1549 sizeof(*blob));
cristy3ed852e2009-09-05 21:47:34 +00001550 }
1551 }
1552 else
1553 {
1554 char
1555 unique[MaxTextExtent];
1556
1557 int
1558 file;
1559
1560 /*
1561 Write file to disk in blob image format.
1562 */
1563 file=AcquireUniqueFileResource(unique);
1564 if (file == -1)
1565 {
1566 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1567 image_info->filename);
1568 }
1569 else
1570 {
1571 blob_info->file=fdopen(file,"wb");
1572 if (blob_info->file != (FILE *) NULL)
1573 {
cristyb51dff52011-05-19 16:55:47 +00001574 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001575 image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001576 status=WriteImage(blob_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001577 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001578 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001579 blob=FileToBlob(image->filename,~0UL,length,exception);
1580 }
1581 (void) RelinquishUniqueFileResource(unique);
1582 }
1583 }
1584 blob_info=DestroyImageInfo(blob_info);
1585 return(blob);
1586}
1587
1588/*
1589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1590% %
1591% %
1592% %
1593% I m a g e T o F i l e %
1594% %
1595% %
1596% %
1597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1598%
1599% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1600% occurs otherwise MagickTrue.
1601%
1602% The format of the ImageToFile method is:
1603%
1604% MagickBooleanType ImageToFile(Image *image,char *filename,
1605% ExceptionInfo *exception)
1606%
1607% A description of each parameter follows:
1608%
1609% o image: the image.
1610%
1611% o filename: Write the image to this file.
1612%
1613% o exception: return any errors or warnings in this structure.
1614%
1615*/
cristy3ed852e2009-09-05 21:47:34 +00001616MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1617 ExceptionInfo *exception)
1618{
1619 int
1620 file;
1621
1622 register const unsigned char
1623 *p;
1624
1625 register size_t
1626 i;
1627
1628 size_t
1629 length,
1630 quantum;
1631
1632 ssize_t
1633 count;
1634
1635 struct stat
cristye7b28372012-06-17 13:59:06 +00001636 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001637
1638 unsigned char
1639 *buffer;
1640
1641 assert(image != (Image *) NULL);
1642 assert(image->signature == MagickSignature);
1643 assert(image->blob != (BlobInfo *) NULL);
1644 assert(image->blob->type != UndefinedStream);
1645 if (image->debug != MagickFalse)
1646 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1647 assert(filename != (const char *) NULL);
1648 if (*filename == '\0')
1649 file=AcquireUniqueFileResource(filename);
1650 else
1651 if (LocaleCompare(filename,"-") == 0)
1652 file=fileno(stdout);
1653 else
cristyb70aab92012-01-31 15:04:04 +00001654 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001655 if (file == -1)
1656 {
1657 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1658 return(MagickFalse);
1659 }
1660 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001661 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1662 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001663 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001664 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1665 if (buffer == (unsigned char *) NULL)
1666 {
1667 file=close(file)-1;
1668 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001669 ResourceLimitError,"MemoryAllocationError","'%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001670 return(MagickFalse);
1671 }
1672 length=0;
1673 p=ReadBlobStream(image,quantum,buffer,&count);
1674 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1675 {
1676 length=(size_t) count;
1677 for (i=0; i < length; i+=count)
1678 {
1679 count=write(file,p+i,(size_t) (length-i));
1680 if (count <= 0)
1681 {
1682 count=0;
1683 if (errno != EINTR)
1684 break;
1685 }
1686 }
1687 if (i < length)
1688 break;
1689 }
cristy54439632010-07-15 00:43:34 +00001690 if (LocaleCompare(filename,"-") != 0)
1691 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001692 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001693 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001694 {
1695 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1696 return(MagickFalse);
1697 }
1698 return(MagickTrue);
1699}
1700
1701/*
1702%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1703% %
1704% %
1705% %
1706% I m a g e s T o B l o b %
1707% %
1708% %
1709% %
1710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1711%
1712% ImagesToBlob() implements direct to memory image formats. It returns the
1713% image sequence as a blob and its length. The magick member of the ImageInfo
1714% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1715%
1716% Note, some image formats do not permit multiple images to the same image
1717% stream (e.g. JPEG). in this instance, just the first image of the
1718% sequence is returned as a blob.
1719%
1720% The format of the ImagesToBlob method is:
1721%
1722% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1723% size_t *length,ExceptionInfo *exception)
1724%
1725% A description of each parameter follows:
1726%
1727% o image_info: the image info.
1728%
1729% o images: the image list.
1730%
1731% o length: This pointer to a size_t integer sets the initial length of the
1732% blob. On return, it reflects the actual length of the blob.
1733%
1734% o exception: return any errors or warnings in this structure.
1735%
1736*/
1737MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1738 Image *images,size_t *length,ExceptionInfo *exception)
1739{
1740 const MagickInfo
1741 *magick_info;
1742
1743 ImageInfo
1744 *blob_info;
1745
1746 MagickBooleanType
1747 status;
1748
1749 unsigned char
1750 *blob;
1751
1752 assert(image_info != (const ImageInfo *) NULL);
1753 assert(image_info->signature == MagickSignature);
1754 if (image_info->debug != MagickFalse)
1755 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1756 image_info->filename);
1757 assert(images != (Image *) NULL);
1758 assert(images->signature == MagickSignature);
1759 assert(exception != (ExceptionInfo *) NULL);
1760 *length=0;
1761 blob=(unsigned char *) NULL;
1762 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001763 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1764 exception);
cristy3ed852e2009-09-05 21:47:34 +00001765 if (*blob_info->magick != '\0')
1766 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1767 if (blob_info->adjoin == MagickFalse)
1768 {
1769 blob_info=DestroyImageInfo(blob_info);
1770 return(ImageToBlob(image_info,images,length,exception));
1771 }
1772 magick_info=GetMagickInfo(images->magick,exception);
1773 if (magick_info == (const MagickInfo *) NULL)
1774 {
1775 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001776 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'",
cristy3ed852e2009-09-05 21:47:34 +00001777 images->filename);
1778 return(blob);
1779 }
1780 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1781 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1782 {
1783 /*
1784 Native blob support for this images format.
1785 */
1786 blob_info->length=0;
1787 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1788 sizeof(unsigned char));
1789 if (blob_info->blob == (void *) NULL)
1790 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001791 ResourceLimitError,"MemoryAllocationFailed","'%s'",images->filename);
cristy3ed852e2009-09-05 21:47:34 +00001792 else
1793 {
1794 images->blob->exempt=MagickTrue;
1795 *images->filename='\0';
1796 status=WriteImages(blob_info,images,images->filename,exception);
cristyb24e2402011-10-07 00:48:39 +00001797 if ((status != MagickFalse) && (images->blob->length != 0))
cristy3ed852e2009-09-05 21:47:34 +00001798 {
1799 *length=images->blob->length;
1800 blob=DetachBlob(images->blob);
1801 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1802 sizeof(*blob));
1803 }
1804 }
1805 }
1806 else
1807 {
1808 char
1809 filename[MaxTextExtent],
1810 unique[MaxTextExtent];
1811
1812 int
1813 file;
1814
1815 /*
1816 Write file to disk in blob images format.
1817 */
1818 file=AcquireUniqueFileResource(unique);
1819 if (file == -1)
1820 {
1821 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1822 image_info->filename);
1823 }
1824 else
1825 {
1826 blob_info->file=fdopen(file,"wb");
1827 if (blob_info->file != (FILE *) NULL)
1828 {
cristyb51dff52011-05-19 16:55:47 +00001829 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001830 images->magick,unique);
1831 status=WriteImages(blob_info,images,filename,exception);
1832 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001833 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001834 blob=FileToBlob(images->filename,~0UL,length,exception);
1835 }
1836 (void) RelinquishUniqueFileResource(unique);
1837 }
1838 }
1839 blob_info=DestroyImageInfo(blob_info);
1840 return(blob);
1841}
1842/*
1843%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1844% %
1845% %
1846% %
1847% I n j e c t I m a g e B l o b %
1848% %
1849% %
1850% %
1851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1852%
1853% InjectImageBlob() injects the image with a copy of itself in the specified
1854% format (e.g. inject JPEG into a PDF image).
1855%
1856% The format of the InjectImageBlob method is:
1857%
1858% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1859% Image *image,Image *inject_image,const char *format,
1860% ExceptionInfo *exception)
1861%
1862% A description of each parameter follows:
1863%
1864% o image_info: the image info..
1865%
1866% o image: the image.
1867%
1868% o inject_image: inject into the image stream.
1869%
1870% o format: the image format.
1871%
1872% o exception: return any errors or warnings in this structure.
1873%
1874*/
1875MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1876 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1877{
1878 char
1879 filename[MaxTextExtent];
1880
1881 FILE
1882 *unique_file;
1883
1884 Image
1885 *byte_image;
1886
1887 ImageInfo
1888 *write_info;
1889
1890 int
1891 file;
1892
1893 MagickBooleanType
1894 status;
1895
cristybb503372010-05-27 20:51:26 +00001896 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001897 i;
1898
1899 size_t
1900 quantum;
1901
1902 ssize_t
1903 count;
1904
1905 struct stat
cristye7b28372012-06-17 13:59:06 +00001906 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001907
1908 unsigned char
1909 *buffer;
1910
1911 /*
1912 Write inject image to a temporary file.
1913 */
1914 assert(image_info != (ImageInfo *) NULL);
1915 assert(image_info->signature == MagickSignature);
1916 assert(image != (Image *) NULL);
1917 assert(image->signature == MagickSignature);
1918 if (image->debug != MagickFalse)
1919 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1920 assert(inject_image != (Image *) NULL);
1921 assert(inject_image->signature == MagickSignature);
1922 assert(exception != (ExceptionInfo *) NULL);
1923 unique_file=(FILE *) NULL;
1924 file=AcquireUniqueFileResource(filename);
1925 if (file != -1)
1926 unique_file=fdopen(file,"wb");
1927 if ((file == -1) || (unique_file == (FILE *) NULL))
1928 {
1929 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1930 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1931 image->filename);
1932 return(MagickFalse);
1933 }
1934 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1935 if (byte_image == (Image *) NULL)
1936 {
1937 (void) fclose(unique_file);
1938 (void) RelinquishUniqueFileResource(filename);
1939 return(MagickFalse);
1940 }
cristyb51dff52011-05-19 16:55:47 +00001941 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001942 filename);
1943 DestroyBlob(byte_image);
1944 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1945 write_info=CloneImageInfo(image_info);
1946 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001947 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001948 write_info=DestroyImageInfo(write_info);
1949 byte_image=DestroyImage(byte_image);
1950 (void) fclose(unique_file);
1951 if (status == MagickFalse)
1952 {
1953 (void) RelinquishUniqueFileResource(filename);
1954 return(MagickFalse);
1955 }
1956 /*
1957 Inject into image stream.
1958 */
cristy18c6c272011-09-23 14:40:37 +00001959 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001960 if (file == -1)
1961 {
1962 (void) RelinquishUniqueFileResource(filename);
1963 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1964 image_info->filename);
1965 return(MagickFalse);
1966 }
1967 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001968 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1969 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001970 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1971 if (buffer == (unsigned char *) NULL)
1972 {
1973 (void) RelinquishUniqueFileResource(filename);
1974 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1975 image->filename);
1976 }
1977 for (i=0; ; i+=count)
1978 {
1979 count=(ssize_t) read(file,buffer,quantum);
1980 if (count <= 0)
1981 {
1982 count=0;
1983 if (errno != EINTR)
1984 break;
1985 }
1986 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1987 MagickFalse;
1988 }
cristya7cb4312010-06-26 00:47:03 +00001989 file=close(file);
1990 if (file == -1)
1991 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001992 (void) RelinquishUniqueFileResource(filename);
1993 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1994 return(status);
1995}
1996
1997/*
1998%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1999% %
2000% %
2001% %
2002+ I s B l o b E x e m p t %
2003% %
2004% %
2005% %
2006%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2007%
2008% IsBlobExempt() returns true if the blob is exempt.
2009%
2010% The format of the IsBlobExempt method is:
2011%
2012% MagickBooleanType IsBlobExempt(const Image *image)
2013%
2014% A description of each parameter follows:
2015%
2016% o image: the image.
2017%
2018*/
cristy7832dc22011-09-05 01:21:53 +00002019MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002020{
2021 assert(image != (const Image *) NULL);
2022 assert(image->signature == MagickSignature);
2023 if (image->debug != MagickFalse)
2024 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2025 return(image->blob->exempt);
2026}
2027
2028/*
2029%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2030% %
2031% %
2032% %
2033+ I s B l o b S e e k a b l e %
2034% %
2035% %
2036% %
2037%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2038%
2039% IsBlobSeekable() returns true if the blob is seekable.
2040%
2041% The format of the IsBlobSeekable method is:
2042%
2043% MagickBooleanType IsBlobSeekable(const Image *image)
2044%
2045% A description of each parameter follows:
2046%
2047% o image: the image.
2048%
2049*/
cristy7832dc22011-09-05 01:21:53 +00002050MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002051{
2052 MagickBooleanType
2053 seekable;
2054
2055 assert(image != (const Image *) NULL);
2056 assert(image->signature == MagickSignature);
2057 if (image->debug != MagickFalse)
2058 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002059 switch (image->blob->type)
2060 {
2061 case FileStream:
2062 case BlobStream:
2063 case ZipStream:
2064 {
2065 seekable=MagickTrue;
2066 break;
2067 }
2068 default:
2069 {
2070 seekable=MagickFalse;
2071 break;
2072 }
2073 }
cristy3ed852e2009-09-05 21:47:34 +00002074 return(seekable);
2075}
2076
2077/*
2078%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2079% %
2080% %
2081% %
2082+ I s B l o b T e m p o r a r y %
2083% %
2084% %
2085% %
2086%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2087%
2088% IsBlobTemporary() returns true if the blob is temporary.
2089%
2090% The format of the IsBlobTemporary method is:
2091%
2092% MagickBooleanType IsBlobTemporary(const Image *image)
2093%
2094% A description of each parameter follows:
2095%
2096% o image: the image.
2097%
2098*/
cristy7832dc22011-09-05 01:21:53 +00002099MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002100{
2101 assert(image != (const Image *) NULL);
2102 assert(image->signature == MagickSignature);
2103 if (image->debug != MagickFalse)
2104 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2105 return(image->blob->temporary);
2106}
2107
2108/*
2109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2110% %
2111% %
2112% %
2113+ M a p B l o b %
2114% %
2115% %
2116% %
2117%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2118%
2119% MapBlob() creates a mapping from a file to a binary large object.
2120%
2121% The format of the MapBlob method is:
2122%
2123% unsigned char *MapBlob(int file,const MapMode mode,
2124% const MagickOffsetType offset,const size_t length)
2125%
2126% A description of each parameter follows:
2127%
2128% o file: map this file descriptor.
2129%
2130% o mode: ReadMode, WriteMode, or IOMode.
2131%
2132% o offset: starting at this offset within the file.
2133%
2134% o length: the length of the mapping is returned in this pointer.
2135%
2136*/
2137MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2138 const MagickOffsetType offset,const size_t length)
2139{
2140#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
2141 int
2142 flags,
2143 protection;
2144
2145 unsigned char
2146 *map;
2147
2148 /*
2149 Map file.
2150 */
2151 flags=0;
2152 if (file == -1)
2153#if defined(MAP_ANONYMOUS)
2154 flags|=MAP_ANONYMOUS;
2155#else
2156 return((unsigned char *) NULL);
2157#endif
2158 switch (mode)
2159 {
2160 case ReadMode:
2161 default:
2162 {
2163 protection=PROT_READ;
2164 flags|=MAP_PRIVATE;
2165 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2166 (off_t) offset);
2167 break;
2168 }
2169 case WriteMode:
2170 {
2171 protection=PROT_WRITE;
2172 flags|=MAP_SHARED;
2173 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2174 (off_t) offset);
cristy2a9e7cb2010-03-05 02:15:05 +00002175#if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
2176 (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
2177 POSIX_MADV_WILLNEED);
2178#endif
cristy3ed852e2009-09-05 21:47:34 +00002179 break;
2180 }
2181 case IOMode:
2182 {
2183 protection=PROT_READ | PROT_WRITE;
2184 flags|=MAP_SHARED;
2185 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2186 (off_t) offset);
2187 break;
2188 }
2189 }
2190 if (map == (unsigned char *) MAP_FAILED)
2191 return((unsigned char *) NULL);
2192 return(map);
2193#else
2194 (void) file;
2195 (void) mode;
2196 (void) offset;
2197 (void) length;
2198 return((unsigned char *) NULL);
2199#endif
2200}
2201
2202/*
2203%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2204% %
2205% %
2206% %
2207+ M S B O r d e r L o n g %
2208% %
2209% %
2210% %
2211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2212%
2213% MSBOrderLong() converts a least-significant byte first buffer of integers to
2214% most-significant byte first.
2215%
2216% The format of the MSBOrderLong method is:
2217%
2218% void MSBOrderLong(unsigned char *buffer,const size_t length)
2219%
2220% A description of each parameter follows.
2221%
2222% o buffer: Specifies a pointer to a buffer of integers.
2223%
2224% o length: Specifies the length of the buffer.
2225%
2226*/
2227MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2228{
2229 int
2230 c;
2231
2232 register unsigned char
2233 *p,
2234 *q;
2235
2236 assert(buffer != (unsigned char *) NULL);
2237 q=buffer+length;
2238 while (buffer < q)
2239 {
2240 p=buffer+3;
2241 c=(int) (*p);
2242 *p=(*buffer);
2243 *buffer++=(unsigned char) c;
2244 p=buffer+1;
2245 c=(int) (*p);
2246 *p=(*buffer);
2247 *buffer++=(unsigned char) c;
2248 buffer+=2;
2249 }
2250}
2251
2252/*
2253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2254% %
2255% %
2256% %
2257+ M S B O r d e r S h o r t %
2258% %
2259% %
2260% %
2261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2262%
2263% MSBOrderShort() converts a least-significant byte first buffer of integers
2264% to most-significant byte first.
2265%
2266% The format of the MSBOrderShort method is:
2267%
2268% void MSBOrderShort(unsigned char *p,const size_t length)
2269%
2270% A description of each parameter follows.
2271%
2272% o p: Specifies a pointer to a buffer of integers.
2273%
2274% o length: Specifies the length of the buffer.
2275%
2276*/
2277MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2278{
2279 int
2280 c;
2281
2282 register unsigned char
2283 *q;
2284
2285 assert(p != (unsigned char *) NULL);
2286 q=p+length;
2287 while (p < q)
2288 {
2289 c=(int) (*p);
2290 *p=(*(p+1));
2291 p++;
2292 *p++=(unsigned char) c;
2293 }
2294}
2295
2296/*
2297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2298% %
2299% %
2300% %
2301+ O p e n B l o b %
2302% %
2303% %
2304% %
2305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2306%
2307% OpenBlob() opens a file associated with the image. A file name of '-' sets
2308% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2309% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2310% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2311% from a system command.
2312%
2313% The format of the OpenBlob method is:
2314%
2315% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2316% const BlobMode mode,ExceptionInfo *exception)
2317%
2318% A description of each parameter follows:
2319%
2320% o image_info: the image info.
2321%
2322% o image: the image.
2323%
2324% o mode: the mode for opening the file.
2325%
2326*/
2327MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2328 Image *image,const BlobMode mode,ExceptionInfo *exception)
2329{
2330 char
cristybf6a7092010-06-11 02:12:15 +00002331 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002332 filename[MaxTextExtent];
2333
2334 const char
2335 *type;
2336
2337 MagickBooleanType
2338 status;
2339
2340 PolicyRights
2341 rights;
2342
2343 assert(image_info != (ImageInfo *) NULL);
2344 assert(image_info->signature == MagickSignature);
2345 if (image_info->debug != MagickFalse)
2346 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2347 image_info->filename);
2348 assert(image != (Image *) NULL);
2349 assert(image->signature == MagickSignature);
2350 if (image_info->blob != (void *) NULL)
2351 {
2352 if (image_info->stream != (StreamHandler) NULL)
2353 image->blob->stream=(StreamHandler) image_info->stream;
2354 AttachBlob(image->blob,image_info->blob,image_info->length);
2355 return(MagickTrue);
2356 }
2357 (void) DetachBlob(image->blob);
2358 switch (mode)
2359 {
2360 default: type="r"; break;
2361 case ReadBlobMode: type="r"; break;
2362 case ReadBinaryBlobMode: type="rb"; break;
2363 case WriteBlobMode: type="w"; break;
2364 case WriteBinaryBlobMode: type="w+b"; break;
2365 case AppendBlobMode: type="a"; break;
2366 case AppendBinaryBlobMode: type="a+b"; break;
2367 }
2368 if (*type != 'r')
2369 image->blob->synchronize=image_info->synchronize;
2370 if (image_info->stream != (StreamHandler) NULL)
2371 {
2372 image->blob->stream=(StreamHandler) image_info->stream;
2373 if (*type == 'w')
2374 {
2375 image->blob->type=FifoStream;
2376 return(MagickTrue);
2377 }
2378 }
2379 /*
2380 Open image file.
2381 */
2382 *filename='\0';
2383 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2384 rights=ReadPolicyRights;
2385 if (*type == 'w')
2386 rights=WritePolicyRights;
2387 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2388 {
cristya9197f62010-01-12 02:23:34 +00002389 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002390 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
anthonye5b39652012-04-21 05:37:29 +00002391 "NotAuthorized","'%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00002392 return(MagickFalse);
2393 }
2394 if ((LocaleCompare(filename,"-") == 0) ||
2395 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2396 {
cristye7b28372012-06-17 13:59:06 +00002397 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002398#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002399 if (strchr(type,'b') != (char *) NULL)
cristye7b28372012-06-17 13:59:06 +00002400 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002401#endif
2402 image->blob->type=StandardStream;
2403 image->blob->exempt=MagickTrue;
2404 return(MagickTrue);
2405 }
cristybc20d112012-07-29 20:27:00 +00002406 if (LocaleNCompare(filename,"fd:",3) == 0)
2407 {
2408 char
2409 mode[MaxTextExtent];
2410
2411 *mode=(*type);
2412 mode[1]='\0';
2413 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2414#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2415 if (strchr(type,'b') != (char *) NULL)
2416 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2417#endif
2418 image->blob->type=StandardStream;
2419 image->blob->exempt=MagickTrue;
2420 return(MagickTrue);
2421 }
cristy3ed852e2009-09-05 21:47:34 +00002422#if defined(MAGICKCORE_HAVE_POPEN)
2423 if (*filename == '|')
2424 {
2425 char
2426 mode[MaxTextExtent];
2427
2428 /*
2429 Pipe image to or from a system command.
2430 */
2431#if defined(SIGPIPE)
2432 if (*type == 'w')
2433 (void) signal(SIGPIPE,SIG_IGN);
2434#endif
2435 *mode=(*type);
2436 mode[1]='\0';
cristye7b28372012-06-17 13:59:06 +00002437 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2438 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002439 {
2440 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2441 return(MagickFalse);
2442 }
2443 image->blob->type=PipeStream;
2444 image->blob->exempt=MagickTrue;
2445 return(MagickTrue);
2446 }
2447#endif
2448 status=GetPathAttributes(filename,&image->blob->properties);
2449#if defined(S_ISFIFO)
2450 if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2451 {
cristye7b28372012-06-17 13:59:06 +00002452 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2453 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002454 {
2455 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2456 return(MagickFalse);
2457 }
2458 image->blob->type=FileStream;
2459 image->blob->exempt=MagickTrue;
2460 return(MagickTrue);
2461 }
2462#endif
cristybf6a7092010-06-11 02:12:15 +00002463 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002464 if (*type == 'w')
2465 {
cristye8939e72010-02-03 17:05:25 +00002466 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002467 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002468 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002469 {
2470 /*
2471 Form filename for multi-part images.
2472 */
2473 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002474 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002475 if ((LocaleCompare(filename,image->filename) == 0) &&
2476 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2477 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002478 {
cristybf7fa0d2010-02-04 00:51:10 +00002479 char
cristybf7fa0d2010-02-04 00:51:10 +00002480 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002481
cristybf7fa0d2010-02-04 00:51:10 +00002482 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002483 if (*extension == '\0')
cristyb51dff52011-05-19 16:55:47 +00002484 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002485 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002486 else
cristyb51dff52011-05-19 16:55:47 +00002487 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002488 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002489 }
2490 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002491#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002492 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002493#endif
cristye8939e72010-02-03 17:05:25 +00002494 }
cristy3ed852e2009-09-05 21:47:34 +00002495 }
cristybf6a7092010-06-11 02:12:15 +00002496 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002497 {
cristye7b28372012-06-17 13:59:06 +00002498 image->blob->file_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002499 image->blob->type=FileStream;
2500 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002501 }
2502 else
cristybf6a7092010-06-11 02:12:15 +00002503 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002504 {
cristye7b28372012-06-17 13:59:06 +00002505 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2506 if (image->blob->file_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002507 {
2508 size_t
cristybf6a7092010-06-11 02:12:15 +00002509 count;
cristy3ed852e2009-09-05 21:47:34 +00002510
cristybf6a7092010-06-11 02:12:15 +00002511 unsigned char
2512 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002513
cristybf6a7092010-06-11 02:12:15 +00002514 image->blob->type=FileStream;
2515#if defined(MAGICKCORE_HAVE_SETVBUF)
cristye7b28372012-06-17 13:59:06 +00002516 (void) setvbuf(image->blob->file_info.file,(char *) NULL,
cristy95888612012-04-04 21:56:52 +00002517 (int) _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002518#endif
2519 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristye7b28372012-06-17 13:59:06 +00002520 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
2521 (void) rewind(image->blob->file_info.file);
cristybf6a7092010-06-11 02:12:15 +00002522 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2523 " read %.20g magic header bytes",(double) count);
2524#if defined(MAGICKCORE_ZLIB_DELEGATE)
2525 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2526 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002527 {
cristye7b28372012-06-17 13:59:06 +00002528 (void) fclose(image->blob->file_info.file);
2529 image->blob->file_info.gzfile=gzopen(filename,type);
2530 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002531 image->blob->type=ZipStream;
2532 }
2533#endif
2534#if defined(MAGICKCORE_BZLIB_DELEGATE)
2535 if (strncmp((char *) magick,"BZh",3) == 0)
2536 {
cristye7b28372012-06-17 13:59:06 +00002537 (void) fclose(image->blob->file_info.file);
2538 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2539 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002540 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002541 }
cristybf6a7092010-06-11 02:12:15 +00002542#endif
cristyc6c589d2010-07-06 01:34:57 +00002543 if (image->blob->type == FileStream)
2544 {
2545 const MagickInfo
2546 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002547
cristyc6c589d2010-07-06 01:34:57 +00002548 ExceptionInfo
2549 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002550
cristyc6c589d2010-07-06 01:34:57 +00002551 struct stat
2552 *properties;
cristybf6a7092010-06-11 02:12:15 +00002553
cristyc6c589d2010-07-06 01:34:57 +00002554 sans_exception=AcquireExceptionInfo();
2555 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2556 sans_exception=DestroyExceptionInfo(sans_exception);
2557 properties=(&image->blob->properties);
2558 if ((magick_info != (const MagickInfo *) NULL) &&
2559 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2560 (properties->st_size <= MagickMaxBufferExtent))
2561 {
2562 size_t
2563 length;
cristybf6a7092010-06-11 02:12:15 +00002564
cristyc6c589d2010-07-06 01:34:57 +00002565 void
2566 *blob;
cristybf6a7092010-06-11 02:12:15 +00002567
cristyc6c589d2010-07-06 01:34:57 +00002568 length=(size_t) properties->st_size;
cristye7b28372012-06-17 13:59:06 +00002569 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,
cristy95888612012-04-04 21:56:52 +00002570 0,length);
cristyc6c589d2010-07-06 01:34:57 +00002571 if (blob != (void *) NULL)
2572 {
2573 /*
2574 Format supports blobs-- use memory-mapped I/O.
2575 */
2576 if (image_info->file != (FILE *) NULL)
2577 image->blob->exempt=MagickFalse;
2578 else
2579 {
cristye7b28372012-06-17 13:59:06 +00002580 (void) fclose(image->blob->file_info.file);
2581 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002582 }
2583 AttachBlob(image->blob,blob,length);
2584 image->blob->mapped=MagickTrue;
2585 }
2586 }
2587 }
cristy3ed852e2009-09-05 21:47:34 +00002588 }
cristybf6a7092010-06-11 02:12:15 +00002589 }
2590 else
2591#if defined(MAGICKCORE_ZLIB_DELEGATE)
2592 if ((LocaleCompare(extension,"Z") == 0) ||
2593 (LocaleCompare(extension,"gz") == 0) ||
2594 (LocaleCompare(extension,"wmz") == 0) ||
2595 (LocaleCompare(extension,"svgz") == 0))
2596 {
2597 if (mode == WriteBinaryBlobMode)
2598 type="wb";
cristye7b28372012-06-17 13:59:06 +00002599 image->blob->file_info.gzfile=gzopen(filename,type);
2600 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002601 image->blob->type=ZipStream;
2602 }
2603 else
2604#endif
2605#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002606 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002607 {
cristye7b28372012-06-17 13:59:06 +00002608 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2609 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002610 image->blob->type=BZipStream;
2611 }
2612 else
2613#endif
2614 {
cristye7b28372012-06-17 13:59:06 +00002615 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2616 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002617 {
2618 image->blob->type=FileStream;
2619#if defined(MAGICKCORE_HAVE_SETVBUF)
cristye7b28372012-06-17 13:59:06 +00002620 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int) _IOFBF,
cristybf6a7092010-06-11 02:12:15 +00002621 16384);
2622#endif
2623 }
2624 }
cristy3ed852e2009-09-05 21:47:34 +00002625 image->blob->status=MagickFalse;
2626 if (image->blob->type != UndefinedStream)
2627 image->blob->size=GetBlobSize(image);
2628 else
2629 {
2630 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2631 return(MagickFalse);
2632 }
2633 return(MagickTrue);
2634}
2635
2636/*
2637%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2638% %
2639% %
2640% %
2641+ P i n g B l o b %
2642% %
2643% %
2644% %
2645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2646%
2647% PingBlob() returns all the attributes of an image or image sequence except
2648% for the pixels. It is much faster and consumes far less memory than
2649% BlobToImage(). On failure, a NULL image is returned and exception
2650% describes the reason for the failure.
2651%
2652% The format of the PingBlob method is:
2653%
2654% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2655% const size_t length,ExceptionInfo *exception)
2656%
2657% A description of each parameter follows:
2658%
2659% o image_info: the image info.
2660%
2661% o blob: the address of a character stream in one of the image formats
2662% understood by ImageMagick.
2663%
2664% o length: This size_t integer reflects the length in bytes of the blob.
2665%
2666% o exception: return any errors or warnings in this structure.
2667%
2668*/
2669
2670#if defined(__cplusplus) || defined(c_plusplus)
2671extern "C" {
2672#endif
2673
2674static size_t PingStream(const Image *magick_unused(image),
2675 const void *magick_unused(pixels),const size_t columns)
2676{
2677 return(columns);
2678}
2679
2680#if defined(__cplusplus) || defined(c_plusplus)
2681}
2682#endif
2683
2684MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2685 const size_t length,ExceptionInfo *exception)
2686{
2687 Image
2688 *image;
2689
2690 ImageInfo
2691 *ping_info;
2692
2693 assert(image_info != (ImageInfo *) NULL);
2694 assert(image_info->signature == MagickSignature);
2695 if (image_info->debug != MagickFalse)
2696 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2697 image_info->filename);
2698 assert(exception != (ExceptionInfo *) NULL);
2699 if ((blob == (const void *) NULL) || (length == 0))
2700 {
2701 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
anthonye5b39652012-04-21 05:37:29 +00002702 "UnrecognizedImageFormat","'%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002703 return((Image *) NULL);
2704 }
2705 ping_info=CloneImageInfo(image_info);
2706 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2707 if (ping_info->blob == (const void *) NULL)
2708 {
2709 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00002710 ResourceLimitFatalError,"MemoryAllocationFailed","'%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002711 return((Image *) NULL);
2712 }
cristy54aad5e2010-09-03 16:02:04 +00002713 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002714 ping_info->length=length;
2715 ping_info->ping=MagickTrue;
2716 image=ReadStream(ping_info,&PingStream,exception);
2717 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2718 ping_info=DestroyImageInfo(ping_info);
2719 return(image);
2720}
2721
2722/*
2723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2724% %
2725% %
2726% %
2727+ R e a d B l o b %
2728% %
2729% %
2730% %
2731%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2732%
2733% ReadBlob() reads data from the blob or image file and returns it. It
2734% returns the number of bytes read.
2735%
2736% The format of the ReadBlob method is:
2737%
2738% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2739%
2740% A description of each parameter follows:
2741%
2742% o image: the image.
2743%
2744% o length: Specifies an integer representing the number of bytes to read
2745% from the file.
2746%
2747% o data: Specifies an area to place the information requested from the
2748% file.
2749%
2750*/
2751MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2752 unsigned char *data)
2753{
2754 int
2755 c;
2756
2757 register unsigned char
2758 *q;
2759
2760 ssize_t
2761 count;
2762
2763 assert(image != (Image *) NULL);
2764 assert(image->signature == MagickSignature);
2765 assert(image->blob != (BlobInfo *) NULL);
2766 assert(image->blob->type != UndefinedStream);
2767 if (length == 0)
2768 return(0);
2769 assert(data != (void *) NULL);
2770 count=0;
2771 q=data;
2772 switch (image->blob->type)
2773 {
2774 case UndefinedStream:
2775 break;
cristy3ed852e2009-09-05 21:47:34 +00002776 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002777 {
cristye4085b12012-10-20 22:52:08 +00002778 register ssize_t
2779 i;
2780
2781 count=0;
2782 for (i=0; i < (ssize_t) length; i+=count)
2783 {
cristy8e3de442012-10-20 22:57:32 +00002784 count=read(fileno(image->blob->file_info.file),q+i,(size_t) MagickMin(
2785 length-i,SSIZE_MAX));
cristya2538e12012-10-21 00:41:31 +00002786 if (count <= 0)
cristye4085b12012-10-20 22:52:08 +00002787 {
cristya2538e12012-10-21 00:41:31 +00002788 count=0;
2789 if (errno != EINTR)
2790 break;
cristye4085b12012-10-20 22:52:08 +00002791 }
2792 }
2793 count=i;
cristybc20d112012-07-29 20:27:00 +00002794 break;
2795 }
2796 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002797 case PipeStream:
2798 {
2799 switch (length)
2800 {
2801 default:
2802 {
cristye7b28372012-06-17 13:59:06 +00002803 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002804 break;
2805 }
2806 case 2:
2807 {
cristye7b28372012-06-17 13:59:06 +00002808 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002809 if (c == EOF)
2810 break;
2811 *q++=(unsigned char) c;
2812 count++;
2813 }
2814 case 1:
2815 {
cristye7b28372012-06-17 13:59:06 +00002816 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002817 if (c == EOF)
2818 break;
2819 *q++=(unsigned char) c;
2820 count++;
2821 }
2822 case 0:
2823 break;
2824 }
2825 break;
2826 }
2827 case ZipStream:
2828 {
2829#if defined(MAGICKCORE_ZLIB_DELEGATE)
2830 switch (length)
2831 {
2832 default:
2833 {
cristye7b28372012-06-17 13:59:06 +00002834 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002835 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002836 break;
2837 }
2838 case 2:
2839 {
cristye7b28372012-06-17 13:59:06 +00002840 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002841 if (c == EOF)
2842 break;
2843 *q++=(unsigned char) c;
2844 count++;
2845 }
2846 case 1:
2847 {
cristye7b28372012-06-17 13:59:06 +00002848 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002849 if (c == EOF)
2850 break;
2851 *q++=(unsigned char) c;
2852 count++;
2853 }
2854 case 0:
2855 break;
2856 }
2857#endif
2858 break;
2859 }
2860 case BZipStream:
2861 {
2862#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00002863 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,
cristy95888612012-04-04 21:56:52 +00002864 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00002865#endif
2866 break;
2867 }
2868 case FifoStream:
2869 break;
2870 case BlobStream:
2871 {
2872 register const unsigned char
2873 *p;
2874
2875 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2876 {
2877 image->blob->eof=MagickTrue;
2878 break;
2879 }
2880 p=image->blob->data+image->blob->offset;
cristye7b28372012-06-17 13:59:06 +00002881 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2882 image->blob->offset));
cristy3ed852e2009-09-05 21:47:34 +00002883 image->blob->offset+=count;
2884 if (count != (ssize_t) length)
2885 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002886 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002887 break;
2888 }
2889 }
2890 return(count);
2891}
2892
2893/*
2894%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2895% %
2896% %
2897% %
2898+ R e a d B l o b B y t e %
2899% %
2900% %
2901% %
2902%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2903%
2904% ReadBlobByte() reads a single byte from the image file and returns it.
2905%
2906% The format of the ReadBlobByte method is:
2907%
2908% int ReadBlobByte(Image *image)
2909%
2910% A description of each parameter follows.
2911%
2912% o image: the image.
2913%
2914*/
2915MagickExport int ReadBlobByte(Image *image)
2916{
2917 register const unsigned char
2918 *p;
2919
2920 ssize_t
2921 count;
2922
2923 unsigned char
2924 buffer[1];
2925
2926 assert(image != (Image *) NULL);
2927 assert(image->signature == MagickSignature);
2928 p=ReadBlobStream(image,1,buffer,&count);
2929 if (count != 1)
2930 return(EOF);
2931 return((int) (*p));
2932}
2933
2934/*
2935%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2936% %
2937% %
2938% %
2939+ R e a d B l o b D o u b l e %
2940% %
2941% %
2942% %
2943%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2944%
2945% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2946% specified by the endian member of the image structure.
2947%
2948% The format of the ReadBlobDouble method is:
2949%
2950% double ReadBlobDouble(Image *image)
2951%
2952% A description of each parameter follows.
2953%
2954% o image: the image.
2955%
2956*/
2957MagickExport double ReadBlobDouble(Image *image)
2958{
2959 union
2960 {
2961 MagickSizeType
2962 unsigned_value;
2963
2964 double
2965 double_value;
2966 } quantum;
2967
2968 quantum.double_value=0.0;
2969 quantum.unsigned_value=ReadBlobLongLong(image);
2970 return(quantum.double_value);
2971}
2972
2973/*
2974%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2975% %
2976% %
2977% %
2978+ R e a d B l o b F l o a t %
2979% %
2980% %
2981% %
2982%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2983%
2984% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2985% specified by the endian member of the image structure.
2986%
2987% The format of the ReadBlobFloat method is:
2988%
2989% float ReadBlobFloat(Image *image)
2990%
2991% A description of each parameter follows.
2992%
2993% o image: the image.
2994%
2995*/
2996MagickExport float ReadBlobFloat(Image *image)
2997{
2998 union
2999 {
3000 unsigned int
3001 unsigned_value;
3002
3003 float
3004 float_value;
3005 } quantum;
3006
3007 quantum.float_value=0.0;
3008 quantum.unsigned_value=ReadBlobLong(image);
3009 return(quantum.float_value);
3010}
3011
3012/*
3013%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3014% %
3015% %
3016% %
3017+ R e a d B l o b L o n g %
3018% %
3019% %
3020% %
3021%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3022%
cristybb503372010-05-27 20:51:26 +00003023% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003024% specified by the endian member of the image structure.
3025%
3026% The format of the ReadBlobLong method is:
3027%
3028% unsigned int ReadBlobLong(Image *image)
3029%
3030% A description of each parameter follows.
3031%
3032% o image: the image.
3033%
3034*/
3035MagickExport unsigned int ReadBlobLong(Image *image)
3036{
3037 register const unsigned char
3038 *p;
3039
3040 ssize_t
3041 count;
3042
3043 unsigned char
3044 buffer[4];
3045
3046 unsigned int
3047 value;
3048
3049 assert(image != (Image *) NULL);
3050 assert(image->signature == MagickSignature);
3051 *buffer='\0';
3052 p=ReadBlobStream(image,4,buffer,&count);
3053 if (count != 4)
3054 return(0UL);
3055 if (image->endian == LSBEndian)
3056 {
3057 value=(unsigned int) (*p++);
3058 value|=((unsigned int) (*p++)) << 8;
3059 value|=((unsigned int) (*p++)) << 16;
3060 value|=((unsigned int) (*p++)) << 24;
3061 return(value);
3062 }
3063 value=((unsigned int) (*p++)) << 24;
3064 value|=((unsigned int) (*p++)) << 16;
3065 value|=((unsigned int) (*p++)) << 8;
3066 value|=((unsigned int) (*p++));
3067 return(value);
3068}
3069
3070/*
3071%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3072% %
3073% %
3074% %
3075+ R e a d B l o b L o n g L o n g %
3076% %
3077% %
3078% %
3079%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3080%
cristy4cb162a2010-05-30 03:04:47 +00003081% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3082% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003083%
cristy4cb162a2010-05-30 03:04:47 +00003084% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003085%
cristy4cb162a2010-05-30 03:04:47 +00003086% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003087%
3088% A description of each parameter follows.
3089%
3090% o image: the image.
3091%
3092*/
3093MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3094{
cristy0286d852010-10-12 18:38:07 +00003095 MagickSizeType
3096 value;
3097
cristy3ed852e2009-09-05 21:47:34 +00003098 register const unsigned char
3099 *p;
3100
3101 ssize_t
3102 count;
3103
3104 unsigned char
3105 buffer[8];
3106
cristy3ed852e2009-09-05 21:47:34 +00003107 assert(image != (Image *) NULL);
3108 assert(image->signature == MagickSignature);
3109 *buffer='\0';
3110 p=ReadBlobStream(image,8,buffer,&count);
3111 if (count != 8)
3112 return(MagickULLConstant(0));
3113 if (image->endian == LSBEndian)
3114 {
3115 value=(MagickSizeType) (*p++);
3116 value|=((MagickSizeType) (*p++)) << 8;
3117 value|=((MagickSizeType) (*p++)) << 16;
3118 value|=((MagickSizeType) (*p++)) << 24;
3119 value|=((MagickSizeType) (*p++)) << 32;
3120 value|=((MagickSizeType) (*p++)) << 40;
3121 value|=((MagickSizeType) (*p++)) << 48;
3122 value|=((MagickSizeType) (*p++)) << 56;
3123 return(value & MagickULLConstant(0xffffffffffffffff));
3124 }
3125 value=((MagickSizeType) (*p++)) << 56;
3126 value|=((MagickSizeType) (*p++)) << 48;
3127 value|=((MagickSizeType) (*p++)) << 40;
3128 value|=((MagickSizeType) (*p++)) << 32;
3129 value|=((MagickSizeType) (*p++)) << 24;
3130 value|=((MagickSizeType) (*p++)) << 16;
3131 value|=((MagickSizeType) (*p++)) << 8;
3132 value|=((MagickSizeType) (*p++));
3133 return(value & MagickULLConstant(0xffffffffffffffff));
3134}
3135
3136/*
3137%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3138% %
3139% %
3140% %
3141+ R e a d B l o b S h o r t %
3142% %
3143% %
3144% %
3145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3146%
3147% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3148% specified by the endian member of the image structure.
3149%
3150% The format of the ReadBlobShort method is:
3151%
3152% unsigned short ReadBlobShort(Image *image)
3153%
3154% A description of each parameter follows.
3155%
3156% o image: the image.
3157%
3158*/
3159MagickExport unsigned short ReadBlobShort(Image *image)
3160{
3161 register const unsigned char
3162 *p;
3163
3164 register unsigned int
3165 value;
3166
3167 ssize_t
3168 count;
3169
3170 unsigned char
3171 buffer[2];
3172
3173 assert(image != (Image *) NULL);
3174 assert(image->signature == MagickSignature);
3175 *buffer='\0';
3176 p=ReadBlobStream(image,2,buffer,&count);
3177 if (count != 2)
3178 return((unsigned short) 0U);
3179 if (image->endian == LSBEndian)
3180 {
3181 value=(unsigned int) (*p++);
3182 value|=((unsigned int) (*p++)) << 8;
3183 return((unsigned short) (value & 0xffff));
3184 }
3185 value=(unsigned int) ((*p++) << 8);
3186 value|=(unsigned int) (*p++);
3187 return((unsigned short) (value & 0xffff));
3188}
3189
3190/*
3191%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3192% %
3193% %
3194% %
3195+ R e a d B l o b L S B L o n g %
3196% %
3197% %
3198% %
3199%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3200%
cristybb503372010-05-27 20:51:26 +00003201% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003202% least-significant byte first order.
3203%
3204% The format of the ReadBlobLSBLong method is:
3205%
3206% unsigned int ReadBlobLSBLong(Image *image)
3207%
3208% A description of each parameter follows.
3209%
3210% o image: the image.
3211%
3212*/
3213MagickExport unsigned int ReadBlobLSBLong(Image *image)
3214{
3215 register const unsigned char
3216 *p;
3217
3218 register unsigned int
3219 value;
3220
3221 ssize_t
3222 count;
3223
3224 unsigned char
3225 buffer[4];
3226
3227 assert(image != (Image *) NULL);
3228 assert(image->signature == MagickSignature);
3229 *buffer='\0';
3230 p=ReadBlobStream(image,4,buffer,&count);
3231 if (count != 4)
3232 return(0U);
3233 value=(unsigned int) (*p++);
3234 value|=((unsigned int) (*p++)) << 8;
3235 value|=((unsigned int) (*p++)) << 16;
3236 value|=((unsigned int) (*p++)) << 24;
3237 return(value);
3238}
3239
3240/*
3241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3242% %
3243% %
3244% %
3245+ R e a d B l o b L S B S h o r t %
3246% %
3247% %
3248% %
3249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3250%
3251% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3252% least-significant byte first order.
3253%
3254% The format of the ReadBlobLSBShort method is:
3255%
3256% unsigned short ReadBlobLSBShort(Image *image)
3257%
3258% A description of each parameter follows.
3259%
3260% o image: the image.
3261%
3262*/
3263MagickExport unsigned short ReadBlobLSBShort(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[2];
3276
3277 assert(image != (Image *) NULL);
3278 assert(image->signature == MagickSignature);
3279 *buffer='\0';
3280 p=ReadBlobStream(image,2,buffer,&count);
3281 if (count != 2)
3282 return((unsigned short) 0U);
3283 value=(unsigned int) (*p++);
3284 value|=((unsigned int) ((*p++)) << 8);
3285 return((unsigned short) (value & 0xffff));
3286}
3287
3288/*
3289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3290% %
3291% %
3292% %
3293+ R e a d B l o b M S B L o n g %
3294% %
3295% %
3296% %
3297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3298%
cristybb503372010-05-27 20:51:26 +00003299% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003300% most-significant byte first order.
3301%
3302% The format of the ReadBlobMSBLong method is:
3303%
3304% unsigned int ReadBlobMSBLong(Image *image)
3305%
3306% A description of each parameter follows.
3307%
3308% o image: the image.
3309%
3310*/
3311MagickExport unsigned int ReadBlobMSBLong(Image *image)
3312{
3313 register const unsigned char
3314 *p;
3315
3316 register unsigned int
3317 value;
3318
3319 ssize_t
3320 count;
3321
3322 unsigned char
3323 buffer[4];
3324
3325 assert(image != (Image *) NULL);
3326 assert(image->signature == MagickSignature);
3327 *buffer='\0';
3328 p=ReadBlobStream(image,4,buffer,&count);
3329 if (count != 4)
3330 return(0UL);
3331 value=((unsigned int) (*p++) << 24);
3332 value|=((unsigned int) (*p++) << 16);
3333 value|=((unsigned int) (*p++) << 8);
3334 value|=(unsigned int) (*p++);
3335 return(value);
3336}
3337
3338/*
3339%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3340% %
3341% %
3342% %
cristy2d3d87f2010-03-01 00:23:08 +00003343+ R e a d B l o b M S B L o n g L o n g %
3344% %
3345% %
3346% %
3347%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3348%
cristybb503372010-05-27 20:51:26 +00003349% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003350% most-significant byte first order.
3351%
3352% The format of the ReadBlobMSBLongLong method is:
3353%
3354% unsigned int ReadBlobMSBLongLong(Image *image)
3355%
3356% A description of each parameter follows.
3357%
3358% o image: the image.
3359%
3360*/
3361MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3362{
3363 register const unsigned char
3364 *p;
3365
3366 register MagickSizeType
3367 value;
3368
3369 ssize_t
3370 count;
3371
3372 unsigned char
cristy0286d852010-10-12 18:38:07 +00003373 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003374
3375 assert(image != (Image *) NULL);
3376 assert(image->signature == MagickSignature);
3377 *buffer='\0';
3378 p=ReadBlobStream(image,8,buffer,&count);
3379 if (count != 8)
3380 return(MagickULLConstant(0));
3381 value=((MagickSizeType) (*p++)) << 56;
3382 value|=((MagickSizeType) (*p++)) << 48;
3383 value|=((MagickSizeType) (*p++)) << 40;
3384 value|=((MagickSizeType) (*p++)) << 32;
3385 value|=((MagickSizeType) (*p++)) << 24;
3386 value|=((MagickSizeType) (*p++)) << 16;
3387 value|=((MagickSizeType) (*p++)) << 8;
3388 value|=((MagickSizeType) (*p++));
3389 return(value & MagickULLConstant(0xffffffffffffffff));
3390}
3391
3392/*
3393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3394% %
3395% %
3396% %
cristy3ed852e2009-09-05 21:47:34 +00003397+ R e a d B l o b M S B S h o r t %
3398% %
3399% %
3400% %
3401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3402%
3403% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3404% most-significant byte first order.
3405%
3406% The format of the ReadBlobMSBShort method is:
3407%
3408% unsigned short ReadBlobMSBShort(Image *image)
3409%
3410% A description of each parameter follows.
3411%
3412% o image: the image.
3413%
3414*/
3415MagickExport unsigned short ReadBlobMSBShort(Image *image)
3416{
3417 register const unsigned char
3418 *p;
3419
3420 register unsigned int
3421 value;
3422
3423 ssize_t
3424 count;
3425
3426 unsigned char
3427 buffer[2];
3428
3429 assert(image != (Image *) NULL);
3430 assert(image->signature == MagickSignature);
3431 *buffer='\0';
3432 p=ReadBlobStream(image,2,buffer,&count);
3433 if (count != 2)
3434 return((unsigned short) 0U);
3435 value=(unsigned int) ((*p++) << 8);
3436 value|=(unsigned int) (*p++);
3437 return((unsigned short) (value & 0xffff));
3438}
3439
3440/*
3441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3442% %
3443% %
3444% %
3445+ R e a d B l o b S t r i n g %
3446% %
3447% %
3448% %
3449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3450%
3451% ReadBlobString() reads characters from a blob or file until a newline
3452% character is read or an end-of-file condition is encountered.
3453%
3454% The format of the ReadBlobString method is:
3455%
3456% char *ReadBlobString(Image *image,char *string)
3457%
3458% A description of each parameter follows:
3459%
3460% o image: the image.
3461%
3462% o string: the address of a character buffer.
3463%
3464*/
3465MagickExport char *ReadBlobString(Image *image,char *string)
3466{
3467 register const unsigned char
3468 *p;
3469
cristybb503372010-05-27 20:51:26 +00003470 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003471 i;
3472
3473 ssize_t
3474 count;
3475
3476 unsigned char
3477 buffer[1];
3478
3479 assert(image != (Image *) NULL);
3480 assert(image->signature == MagickSignature);
3481 for (i=0; i < (MaxTextExtent-1L); i++)
3482 {
3483 p=ReadBlobStream(image,1,buffer,&count);
3484 if (count != 1)
3485 {
3486 if (i == 0)
3487 return((char *) NULL);
3488 break;
3489 }
3490 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003491 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003492 break;
3493 }
cristy2b5db102010-06-09 01:07:28 +00003494 if (string[i] == '\r')
3495 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003496 string[i]='\0';
3497 return(string);
3498}
3499
3500/*
3501%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3502% %
3503% %
3504% %
3505+ R e f e r e n c e B l o b %
3506% %
3507% %
3508% %
3509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3510%
3511% ReferenceBlob() increments the reference count associated with the pixel
3512% blob returning a pointer to the blob.
3513%
3514% The format of the ReferenceBlob method is:
3515%
3516% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3517%
3518% A description of each parameter follows:
3519%
3520% o blob_info: the blob_info.
3521%
3522*/
3523MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3524{
3525 assert(blob != (BlobInfo *) NULL);
3526 assert(blob->signature == MagickSignature);
3527 if (blob->debug != MagickFalse)
3528 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003529 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003530 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003531 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003532 return(blob);
3533}
3534
3535/*
3536%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3537% %
3538% %
3539% %
3540+ S e e k B l o b %
3541% %
3542% %
3543% %
3544%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3545%
3546% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3547% and returns the resulting offset.
3548%
3549% The format of the SeekBlob method is:
3550%
3551% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3552% const int whence)
3553%
3554% A description of each parameter follows:
3555%
3556% o image: the image.
3557%
3558% o offset: Specifies an integer representing the offset in bytes.
3559%
3560% o whence: Specifies an integer representing how the offset is
3561% treated relative to the beginning of the blob as follows:
3562%
3563% SEEK_SET Set position equal to offset bytes.
3564% SEEK_CUR Set position to current location plus offset.
3565% SEEK_END Set position to EOF plus offset.
3566%
3567*/
3568MagickExport MagickOffsetType SeekBlob(Image *image,
3569 const MagickOffsetType offset,const int whence)
3570{
3571 assert(image != (Image *) NULL);
3572 assert(image->signature == MagickSignature);
3573 if (image->debug != MagickFalse)
3574 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3575 assert(image->blob != (BlobInfo *) NULL);
3576 assert(image->blob->type != UndefinedStream);
3577 switch (image->blob->type)
3578 {
3579 case UndefinedStream:
3580 break;
cristybc20d112012-07-29 20:27:00 +00003581 case StandardStream:
3582 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003583 case FileStream:
3584 {
cristye7b28372012-06-17 13:59:06 +00003585 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003586 return(-1);
3587 image->blob->offset=TellBlob(image);
3588 break;
3589 }
cristy3ed852e2009-09-05 21:47:34 +00003590 case PipeStream:
3591 case ZipStream:
3592 {
3593#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003594 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003595 return(-1);
3596#endif
3597 image->blob->offset=TellBlob(image);
3598 break;
3599 }
3600 case BZipStream:
3601 return(-1);
3602 case FifoStream:
3603 return(-1);
3604 case BlobStream:
3605 {
3606 switch (whence)
3607 {
3608 case SEEK_SET:
3609 default:
3610 {
3611 if (offset < 0)
3612 return(-1);
3613 image->blob->offset=offset;
3614 break;
3615 }
3616 case SEEK_CUR:
3617 {
3618 if ((image->blob->offset+offset) < 0)
3619 return(-1);
3620 image->blob->offset+=offset;
3621 break;
3622 }
3623 case SEEK_END:
3624 {
3625 if (((MagickOffsetType) image->blob->length+offset) < 0)
3626 return(-1);
3627 image->blob->offset=image->blob->length+offset;
3628 break;
3629 }
3630 }
3631 if (image->blob->offset <= (MagickOffsetType)
3632 ((off_t) image->blob->length))
3633 image->blob->eof=MagickFalse;
3634 else
3635 if (image->blob->mapped != MagickFalse)
3636 return(-1);
3637 else
3638 {
3639 image->blob->extent=(size_t) (image->blob->offset+
3640 image->blob->quantum);
3641 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3642 image->blob->data,image->blob->extent+1,
3643 sizeof(*image->blob->data));
3644 (void) SyncBlob(image);
3645 if (image->blob->data == (unsigned char *) NULL)
3646 {
3647 (void) DetachBlob(image->blob);
3648 return(-1);
3649 }
3650 }
3651 break;
3652 }
3653 }
3654 return(image->blob->offset);
3655}
3656
3657/*
3658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3659% %
3660% %
3661% %
3662+ S e t B l o b E x e m p t %
3663% %
3664% %
3665% %
3666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3667%
3668% SetBlobExempt() sets the blob exempt status.
3669%
3670% The format of the SetBlobExempt method is:
3671%
3672% MagickBooleanType SetBlobExempt(const Image *image,
3673% const MagickBooleanType exempt)
3674%
3675% A description of each parameter follows:
3676%
3677% o image: the image.
3678%
3679% o exempt: Set to true if this blob is exempt from being closed.
3680%
3681*/
cristy7832dc22011-09-05 01:21:53 +00003682MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003683{
3684 assert(image != (const Image *) NULL);
3685 assert(image->signature == MagickSignature);
3686 if (image->debug != MagickFalse)
3687 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3688 image->blob->exempt=exempt;
3689}
3690
3691/*
3692%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3693% %
3694% %
3695% %
3696+ S e t B l o b E x t e n t %
3697% %
3698% %
3699% %
3700%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3701%
3702% SetBlobExtent() ensures enough space is allocated for the blob. If the
3703% method is successful, subsequent writes to bytes in the specified range are
3704% guaranteed not to fail.
3705%
3706% The format of the SetBlobExtent method is:
3707%
3708% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3709%
3710% A description of each parameter follows:
3711%
3712% o image: the image.
3713%
3714% o extent: the blob maximum extent.
3715%
3716*/
cristy7832dc22011-09-05 01:21:53 +00003717MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003718 const MagickSizeType extent)
3719{
3720 assert(image != (Image *) NULL);
3721 assert(image->signature == MagickSignature);
3722 if (image->debug != MagickFalse)
3723 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3724 assert(image->blob != (BlobInfo *) NULL);
3725 assert(image->blob->type != UndefinedStream);
3726 switch (image->blob->type)
3727 {
3728 case UndefinedStream:
3729 break;
cristybc20d112012-07-29 20:27:00 +00003730 case StandardStream:
3731 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003732 case FileStream:
3733 {
3734 if (extent != (MagickSizeType) ((off_t) extent))
3735 return(MagickFalse);
cristycf4ac942012-10-18 14:32:28 +00003736#if !defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
cristy3ed852e2009-09-05 21:47:34 +00003737 return(MagickFalse);
3738#else
3739 {
3740 int
3741 status;
3742
3743 MagickOffsetType
3744 offset;
3745
3746 offset=TellBlob(image);
cristy96c8d5b2012-10-18 23:40:47 +00003747 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
cristy19e17f92012-10-18 14:51:50 +00003748 extent-offset);
cristy3ed852e2009-09-05 21:47:34 +00003749 if (status != 0)
3750 return(MagickFalse);
3751 }
3752#endif
3753 break;
3754 }
cristy3ed852e2009-09-05 21:47:34 +00003755 case PipeStream:
3756 case ZipStream:
3757 return(MagickFalse);
3758 case BZipStream:
3759 return(MagickFalse);
3760 case FifoStream:
3761 return(MagickFalse);
3762 case BlobStream:
3763 {
3764 if (image->blob->mapped != MagickFalse)
3765 {
cristye7b28372012-06-17 13:59:06 +00003766 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003767 return(MagickFalse);
3768 (void) UnmapBlob(image->blob->data,image->blob->length);
cristycf4ac942012-10-18 14:32:28 +00003769#if !defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
cristy3ed852e2009-09-05 21:47:34 +00003770 return(MagickFalse);
3771#else
3772 {
3773 int
3774 status;
3775
3776 MagickOffsetType
3777 offset;
3778
3779 offset=TellBlob(image);
cristy96c8d5b2012-10-18 23:40:47 +00003780 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
cristy3b5a2cf2012-10-18 14:50:08 +00003781 extent-offset);
cristy3ed852e2009-09-05 21:47:34 +00003782 if (status != 0)
3783 return(MagickFalse);
3784 }
cristy95888612012-04-04 21:56:52 +00003785 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003786 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003787 image->blob->extent=(size_t) extent;
3788 image->blob->length=(size_t) extent;
3789 (void) SyncBlob(image);
3790 break;
3791#endif
3792 }
3793 if (extent != (MagickSizeType) ((size_t) extent))
3794 return(MagickFalse);
3795 image->blob->extent=(size_t) extent;
3796 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3797 image->blob->extent+1,sizeof(*image->blob->data));
3798 (void) SyncBlob(image);
3799 if (image->blob->data == (unsigned char *) NULL)
3800 {
3801 (void) DetachBlob(image->blob);
3802 return(MagickFalse);
3803 }
3804 break;
3805 }
3806 }
3807 return(MagickTrue);
3808}
3809
3810/*
3811%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3812% %
3813% %
3814% %
3815+ S y n c B l o b %
3816% %
3817% %
3818% %
3819%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3820%
3821% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3822% attributes if it is an blob.
3823%
3824% The format of the SyncBlob method is:
3825%
3826% int SyncBlob(Image *image)
3827%
3828% A description of each parameter follows:
3829%
3830% o image: the image.
3831%
3832*/
3833static int SyncBlob(Image *image)
3834{
3835 int
3836 status;
3837
3838 assert(image != (Image *) NULL);
3839 assert(image->signature == MagickSignature);
3840 if (image->debug != MagickFalse)
3841 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3842 assert(image->blob != (BlobInfo *) NULL);
3843 assert(image->blob->type != UndefinedStream);
3844 status=0;
3845 switch (image->blob->type)
3846 {
3847 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003848 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003849 break;
3850 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003851 case PipeStream:
3852 {
cristye7b28372012-06-17 13:59:06 +00003853 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003854 break;
3855 }
3856 case ZipStream:
3857 {
3858#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003859 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003860#endif
3861 break;
3862 }
3863 case BZipStream:
3864 {
3865#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003866 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003867#endif
3868 break;
3869 }
3870 case FifoStream:
3871 break;
3872 case BlobStream:
3873 {
3874#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3875 if (image->blob->mapped != MagickFalse)
3876 status=msync(image->blob->data,image->blob->length,MS_SYNC);
3877#endif
3878 break;
3879 }
3880 }
3881 return(status);
3882}
3883
3884/*
3885%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3886% %
3887% %
3888% %
3889+ T e l l B l o b %
3890% %
3891% %
3892% %
3893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3894%
3895% TellBlob() obtains the current value of the blob or file position.
3896%
3897% The format of the TellBlob method is:
3898%
3899% MagickOffsetType TellBlob(const Image *image)
3900%
3901% A description of each parameter follows:
3902%
3903% o image: the image.
3904%
3905*/
3906MagickExport MagickOffsetType TellBlob(const Image *image)
3907{
3908 MagickOffsetType
3909 offset;
3910
3911 assert(image != (Image *) NULL);
3912 assert(image->signature == MagickSignature);
3913 if (image->debug != MagickFalse)
3914 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3915 assert(image->blob != (BlobInfo *) NULL);
3916 assert(image->blob->type != UndefinedStream);
3917 offset=(-1);
3918 switch (image->blob->type)
3919 {
3920 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003921 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003922 break;
3923 case FileStream:
3924 {
cristye7b28372012-06-17 13:59:06 +00003925 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003926 break;
3927 }
cristy3ed852e2009-09-05 21:47:34 +00003928 case PipeStream:
3929 break;
3930 case ZipStream:
3931 {
3932#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003933 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003934#endif
3935 break;
3936 }
3937 case BZipStream:
3938 break;
3939 case FifoStream:
3940 break;
3941 case BlobStream:
3942 {
3943 offset=image->blob->offset;
3944 break;
3945 }
3946 }
3947 return(offset);
3948}
3949
3950/*
3951%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3952% %
3953% %
3954% %
3955+ U n m a p B l o b %
3956% %
3957% %
3958% %
3959%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3960%
3961% UnmapBlob() deallocates the binary large object previously allocated with
3962% the MapBlob method.
3963%
3964% The format of the UnmapBlob method is:
3965%
3966% MagickBooleanType UnmapBlob(void *map,const size_t length)
3967%
3968% A description of each parameter follows:
3969%
3970% o map: the address of the binary large object.
3971%
3972% o length: the length of the binary large object.
3973%
3974*/
3975MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3976{
3977#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3978 int
3979 status;
3980
3981 status=munmap(map,length);
3982 return(status == -1 ? MagickFalse : MagickTrue);
3983#else
3984 (void) map;
3985 (void) length;
3986 return(MagickFalse);
3987#endif
3988}
3989
3990/*
3991%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3992% %
3993% %
3994% %
3995+ W r i t e B l o b %
3996% %
3997% %
3998% %
3999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4000%
4001% WriteBlob() writes data to a blob or image file. It returns the number of
4002% bytes written.
4003%
4004% The format of the WriteBlob method is:
4005%
4006% ssize_t WriteBlob(Image *image,const size_t length,
4007% const unsigned char *data)
4008%
4009% A description of each parameter follows:
4010%
4011% o image: the image.
4012%
4013% o length: Specifies an integer representing the number of bytes to
4014% write to the file.
4015%
4016% o data: The address of the data to write to the blob or file.
4017%
4018*/
4019MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4020 const unsigned char *data)
4021{
4022 int
4023 c;
4024
4025 register const unsigned char
4026 *p;
4027
4028 ssize_t
4029 count;
4030
4031 assert(image != (Image *) NULL);
4032 assert(image->signature == MagickSignature);
4033 assert(data != (const unsigned char *) NULL);
4034 assert(image->blob != (BlobInfo *) NULL);
4035 assert(image->blob->type != UndefinedStream);
4036 if (length == 0)
4037 return(0);
4038 count=0;
4039 p=data;
4040 switch (image->blob->type)
4041 {
4042 case UndefinedStream:
4043 break;
cristy3ed852e2009-09-05 21:47:34 +00004044 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004045 {
cristye4085b12012-10-20 22:52:08 +00004046 register ssize_t
4047 i;
4048
4049 count=0;
4050 for (i=0; i < (MagickOffsetType) length; i+=count)
4051 {
4052 count=write(fileno(image->blob->file_info.file),data+i,(size_t)
cristy8e3de442012-10-20 22:57:32 +00004053 MagickMin(length-i,SSIZE_MAX));
cristya2538e12012-10-21 00:41:31 +00004054 if (count <= 0)
cristye4085b12012-10-20 22:52:08 +00004055 {
cristya2538e12012-10-21 00:41:31 +00004056 count=0;
4057 if (errno != EINTR)
4058 break;
cristye4085b12012-10-20 22:52:08 +00004059 }
4060 }
4061 count=i;
cristybc20d112012-07-29 20:27:00 +00004062 break;
4063 }
4064 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004065 case PipeStream:
4066 {
4067 switch (length)
4068 {
4069 default:
4070 {
4071 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004072 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004073 break;
4074 }
4075 case 2:
4076 {
cristye7b28372012-06-17 13:59:06 +00004077 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004078 if (c == EOF)
4079 break;
4080 count++;
4081 }
4082 case 1:
4083 {
cristye7b28372012-06-17 13:59:06 +00004084 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004085 if (c == EOF)
4086 break;
4087 count++;
4088 }
4089 case 0:
4090 break;
4091 }
4092 break;
4093 }
4094 case ZipStream:
4095 {
4096#if defined(MAGICKCORE_ZLIB_DELEGATE)
4097 switch (length)
4098 {
4099 default:
4100 {
cristye7b28372012-06-17 13:59:06 +00004101 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004102 (unsigned int) length);
4103 break;
4104 }
4105 case 2:
4106 {
cristye7b28372012-06-17 13:59:06 +00004107 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004108 if (c == EOF)
4109 break;
4110 count++;
4111 }
4112 case 1:
4113 {
cristye7b28372012-06-17 13:59:06 +00004114 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004115 if (c == EOF)
4116 break;
4117 count++;
4118 }
4119 case 0:
4120 break;
4121 }
4122#endif
4123 break;
4124 }
4125 case BZipStream:
4126 {
4127#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004128 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004129 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004130#endif
4131 break;
4132 }
4133 case FifoStream:
4134 {
4135 count=(ssize_t) image->blob->stream(image,data,length);
4136 break;
4137 }
4138 case BlobStream:
4139 {
4140 register unsigned char
4141 *q;
4142
4143 if ((image->blob->offset+(MagickOffsetType) length) >=
4144 (MagickOffsetType) image->blob->extent)
4145 {
4146 if (image->blob->mapped != MagickFalse)
4147 return(0);
4148 image->blob->quantum<<=1;
4149 image->blob->extent+=length+image->blob->quantum;
4150 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4151 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4152 (void) SyncBlob(image);
4153 if (image->blob->data == (unsigned char *) NULL)
4154 {
4155 (void) DetachBlob(image->blob);
4156 return(0);
4157 }
4158 }
4159 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004160 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004161 image->blob->offset+=length;
4162 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4163 image->blob->length=(size_t) image->blob->offset;
4164 count=(ssize_t) length;
4165 }
4166 }
4167 return(count);
4168}
4169
4170/*
4171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4172% %
4173% %
4174% %
4175+ W r i t e B l o b B y t e %
4176% %
4177% %
4178% %
4179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4180%
4181% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4182% written (either 0 or 1);
4183%
4184% The format of the WriteBlobByte method is:
4185%
4186% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4187%
4188% A description of each parameter follows.
4189%
4190% o image: the image.
4191%
4192% o value: Specifies the value to write.
4193%
4194*/
4195MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4196{
4197 assert(image != (Image *) NULL);
4198 assert(image->signature == MagickSignature);
4199 return(WriteBlobStream(image,1,&value));
4200}
4201
4202/*
4203%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4204% %
4205% %
4206% %
4207+ W r i t e B l o b F l o a t %
4208% %
4209% %
4210% %
4211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4212%
4213% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4214% specified by the endian member of the image structure.
4215%
4216% The format of the WriteBlobFloat method is:
4217%
4218% ssize_t WriteBlobFloat(Image *image,const float value)
4219%
4220% A description of each parameter follows.
4221%
4222% o image: the image.
4223%
4224% o value: Specifies the value to write.
4225%
4226*/
4227MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4228{
4229 union
4230 {
4231 unsigned int
4232 unsigned_value;
4233
4234 float
4235 float_value;
4236 } quantum;
4237
4238 quantum.unsigned_value=0U;
4239 quantum.float_value=value;
4240 return(WriteBlobLong(image,quantum.unsigned_value));
4241}
4242
4243/*
4244%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4245% %
4246% %
4247% %
4248+ W r i t e B l o b L o n g %
4249% %
4250% %
4251% %
4252%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4253%
cristybb503372010-05-27 20:51:26 +00004254% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004255% specified by the endian member of the image structure.
4256%
4257% The format of the WriteBlobLong method is:
4258%
4259% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4260%
4261% A description of each parameter follows.
4262%
4263% o image: the image.
4264%
4265% o value: Specifies the value to write.
4266%
4267*/
4268MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4269{
4270 unsigned char
4271 buffer[4];
4272
4273 assert(image != (Image *) NULL);
4274 assert(image->signature == MagickSignature);
4275 if (image->endian == LSBEndian)
4276 {
4277 buffer[0]=(unsigned char) value;
4278 buffer[1]=(unsigned char) (value >> 8);
4279 buffer[2]=(unsigned char) (value >> 16);
4280 buffer[3]=(unsigned char) (value >> 24);
4281 return(WriteBlobStream(image,4,buffer));
4282 }
4283 buffer[0]=(unsigned char) (value >> 24);
4284 buffer[1]=(unsigned char) (value >> 16);
4285 buffer[2]=(unsigned char) (value >> 8);
4286 buffer[3]=(unsigned char) value;
4287 return(WriteBlobStream(image,4,buffer));
4288}
4289
4290/*
4291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4292% %
4293% %
4294% %
4295+ W r i t e B l o b S h o r t %
4296% %
4297% %
4298% %
4299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4300%
4301% WriteBlobShort() writes a short value as a 16-bit quantity in the
4302% byte-order specified by the endian member of the image structure.
4303%
4304% The format of the WriteBlobShort method is:
4305%
4306% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4307%
4308% A description of each parameter follows.
4309%
4310% o image: the image.
4311%
4312% o value: Specifies the value to write.
4313%
4314*/
4315MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4316{
4317 unsigned char
4318 buffer[2];
4319
4320 assert(image != (Image *) NULL);
4321 assert(image->signature == MagickSignature);
4322 if (image->endian == LSBEndian)
4323 {
4324 buffer[0]=(unsigned char) value;
4325 buffer[1]=(unsigned char) (value >> 8);
4326 return(WriteBlobStream(image,2,buffer));
4327 }
4328 buffer[0]=(unsigned char) (value >> 8);
4329 buffer[1]=(unsigned char) value;
4330 return(WriteBlobStream(image,2,buffer));
4331}
4332
4333/*
4334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4335% %
4336% %
4337% %
4338+ W r i t e B l o b L S B L o n g %
4339% %
4340% %
4341% %
4342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4343%
cristybb503372010-05-27 20:51:26 +00004344% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004345% least-significant byte first order.
4346%
4347% The format of the WriteBlobLSBLong method is:
4348%
4349% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4350%
4351% A description of each parameter follows.
4352%
4353% o image: the image.
4354%
4355% o value: Specifies the value to write.
4356%
4357*/
4358MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4359{
4360 unsigned char
4361 buffer[4];
4362
4363 assert(image != (Image *) NULL);
4364 assert(image->signature == MagickSignature);
4365 buffer[0]=(unsigned char) value;
4366 buffer[1]=(unsigned char) (value >> 8);
4367 buffer[2]=(unsigned char) (value >> 16);
4368 buffer[3]=(unsigned char) (value >> 24);
4369 return(WriteBlobStream(image,4,buffer));
4370}
4371
4372/*
4373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4374% %
4375% %
4376% %
4377+ W r i t e B l o b L S B S h o r t %
4378% %
4379% %
4380% %
4381%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4382%
cristybb503372010-05-27 20:51:26 +00004383% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004384% least-significant byte first order.
4385%
4386% The format of the WriteBlobLSBShort method is:
4387%
4388% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4389%
4390% A description of each parameter follows.
4391%
4392% o image: the image.
4393%
4394% o value: Specifies the value to write.
4395%
4396*/
4397MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4398{
4399 unsigned char
4400 buffer[2];
4401
4402 assert(image != (Image *) NULL);
4403 assert(image->signature == MagickSignature);
4404 buffer[0]=(unsigned char) value;
4405 buffer[1]=(unsigned char) (value >> 8);
4406 return(WriteBlobStream(image,2,buffer));
4407}
4408
4409/*
4410%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4411% %
4412% %
4413% %
4414+ W r i t e B l o b M S B L o n g %
4415% %
4416% %
4417% %
4418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4419%
cristybb503372010-05-27 20:51:26 +00004420% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004421% most-significant byte first order.
4422%
4423% The format of the WriteBlobMSBLong method is:
4424%
4425% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4426%
4427% A description of each parameter follows.
4428%
4429% o value: Specifies the value to write.
4430%
4431% o image: the image.
4432%
4433*/
4434MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4435{
4436 unsigned char
4437 buffer[4];
4438
4439 assert(image != (Image *) NULL);
4440 assert(image->signature == MagickSignature);
4441 buffer[0]=(unsigned char) (value >> 24);
4442 buffer[1]=(unsigned char) (value >> 16);
4443 buffer[2]=(unsigned char) (value >> 8);
4444 buffer[3]=(unsigned char) value;
4445 return(WriteBlobStream(image,4,buffer));
4446}
4447
4448/*
4449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4450% %
4451% %
4452% %
cristy2ca49922010-03-06 02:54:01 +00004453+ W r i t e B l o b M S B L o n g L o n g %
4454% %
4455% %
4456% %
4457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4458%
4459% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4460% most-significant byte first order.
4461%
4462% The format of the WriteBlobMSBLongLong method is:
4463%
4464% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4465%
4466% A description of each parameter follows.
4467%
4468% o value: Specifies the value to write.
4469%
4470% o image: the image.
4471%
4472*/
4473MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4474 const MagickSizeType value)
4475{
4476 unsigned char
4477 buffer[8];
4478
4479 assert(image != (Image *) NULL);
4480 assert(image->signature == MagickSignature);
4481 buffer[0]=(unsigned char) (value >> 56);
4482 buffer[1]=(unsigned char) (value >> 48);
4483 buffer[2]=(unsigned char) (value >> 40);
4484 buffer[3]=(unsigned char) (value >> 32);
4485 buffer[4]=(unsigned char) (value >> 24);
4486 buffer[5]=(unsigned char) (value >> 16);
4487 buffer[6]=(unsigned char) (value >> 8);
4488 buffer[7]=(unsigned char) value;
4489 return(WriteBlobStream(image,8,buffer));
4490}
4491
4492/*
4493%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4494% %
4495% %
4496% %
cristy3ed852e2009-09-05 21:47:34 +00004497+ W r i t e B l o b M S B S h o r t %
4498% %
4499% %
4500% %
4501%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4502%
cristybb503372010-05-27 20:51:26 +00004503% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004504% most-significant byte first order.
4505%
4506% The format of the WriteBlobMSBShort method is:
4507%
4508% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4509%
4510% A description of each parameter follows.
4511%
4512% o value: Specifies the value to write.
4513%
4514% o file: Specifies the file to write the data to.
4515%
4516*/
4517MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4518{
4519 unsigned char
4520 buffer[2];
4521
4522 assert(image != (Image *) NULL);
4523 assert(image->signature == MagickSignature);
4524 buffer[0]=(unsigned char) (value >> 8);
4525 buffer[1]=(unsigned char) value;
4526 return(WriteBlobStream(image,2,buffer));
4527}
4528
4529/*
4530%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4531% %
4532% %
4533% %
4534+ W r i t e B l o b S t r i n g %
4535% %
4536% %
4537% %
4538%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4539%
4540% WriteBlobString() write a string to a blob. It returns the number of
4541% characters written.
4542%
4543% The format of the WriteBlobString method is:
4544%
4545% ssize_t WriteBlobString(Image *image,const char *string)
4546%
4547% A description of each parameter follows.
4548%
4549% o image: the image.
4550%
4551% o string: Specifies the string to write.
4552%
4553*/
4554MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4555{
4556 assert(image != (Image *) NULL);
4557 assert(image->signature == MagickSignature);
4558 assert(string != (const char *) NULL);
4559 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4560}