blob: 70577427fc9581f36362cfd82fe5157bdf892950 [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,
cristyefe601c2013-01-05 17:51:12 +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(),
cristyefe601c2013-01-05 17:51:12 +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);
cristy7e2a7c72012-12-27 00:56:47 +0000514 status=SyncBlob(image);
cristy3ed852e2009-09-05 21:47:34 +0000515 switch (image->blob->type)
516 {
517 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000518 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000519 break;
520 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000521 case PipeStream:
522 {
cristy02ce8cc2012-12-27 00:35:49 +0000523 if (image->blob->synchronize != MagickFalse)
524 status=fsync(fileno(image->blob->file_info.file));
cristye7b28372012-06-17 13:59:06 +0000525 status=ferror(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000526 break;
527 }
528 case ZipStream:
529 {
530#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000531 (void) gzerror(image->blob->file_info.gzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000532#endif
533 break;
534 }
535 case BZipStream:
536 {
537#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000538 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000539#endif
540 break;
541 }
542 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000543 break;
cristy02ce8cc2012-12-27 00:35:49 +0000544 case BlobStream:
545 {
546 if ((image->blob->file_info.file != (FILE *) NULL) &&
547 (image->blob->synchronize != MagickFalse))
cristy5678acd2012-12-27 00:41:55 +0000548 {
549 (void) fsync(fileno(image->blob->file_info.file));
550 status=ferror(image->blob->file_info.file);
551 }
cristy02ce8cc2012-12-27 00:35:49 +0000552 break;
553 }
cristy3ed852e2009-09-05 21:47:34 +0000554 }
555 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
cristycd9e6322012-12-27 00:29:00 +0000556 image->blob->size=GetBlobSize(image);
557 image->extent=image->blob->size;
558 image->blob->eof=MagickFalse;
cristybae22e42012-12-27 00:25:59 +0000559 if (image->blob->exempt != MagickFalse)
560 {
561 image->blob->type=UndefinedStream;
562 return(image->blob->status);
563 }
cristy3ed852e2009-09-05 21:47:34 +0000564 switch (image->blob->type)
565 {
566 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000567 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000568 break;
569 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000570 {
cristye7b28372012-06-17 13:59:06 +0000571 status=fclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000572 break;
573 }
574 case PipeStream:
575 {
576#if defined(MAGICKCORE_HAVE_PCLOSE)
cristye7b28372012-06-17 13:59:06 +0000577 status=pclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000578#endif
579 break;
580 }
581 case ZipStream:
582 {
583#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000584 status=gzclose(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +0000585#endif
586 break;
587 }
588 case BZipStream:
589 {
590#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000591 BZ2_bzclose(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +0000592#endif
593 break;
594 }
595 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000596 break;
cristyff483372010-10-16 17:00:58 +0000597 case BlobStream:
598 {
cristye7b28372012-06-17 13:59:06 +0000599 if (image->blob->file_info.file != (FILE *) NULL)
cristy02ce8cc2012-12-27 00:35:49 +0000600 status=fclose(image->blob->file_info.file);
cristyff483372010-10-16 17:00:58 +0000601 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(),
cristyefe601c2013-01-05 17:51:12 +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(),
cristyefe601c2013-01-05 17:51:12 +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);
cristyd45808f2012-12-14 21:30:35 +00001146 file=fileno(stdin);
1147 if (LocaleCompare(filename,"-") != 0)
1148 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001149 if (file == -1)
1150 {
cristyc82a27b2011-10-21 01:07:16 +00001151 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001152 return(MagickFalse);
1153 }
1154 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001155 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1156 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001157 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1158 if (blob == (unsigned char *) NULL)
1159 {
cristyc82a27b2011-10-21 01:07:16 +00001160 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1161 filename);
cristy3ed852e2009-09-05 21:47:34 +00001162 return(MagickFalse);
1163 }
1164 for ( ; ; )
1165 {
1166 count=(ssize_t) read(file,blob,quantum);
1167 if (count <= 0)
1168 {
1169 count=0;
1170 if (errno != EINTR)
1171 break;
1172 }
1173 length=(size_t) count;
1174 count=WriteBlobStream(image,length,blob);
1175 if (count != (ssize_t) length)
1176 {
cristyc82a27b2011-10-21 01:07:16 +00001177 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001178 break;
1179 }
1180 }
cristya7cb4312010-06-26 00:47:03 +00001181 file=close(file);
1182 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001183 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001184 blob=(unsigned char *) RelinquishMagickMemory(blob);
1185 return(MagickTrue);
1186}
1187
1188/*
1189%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1190% %
1191% %
1192% %
1193+ G e t B l o b E r r o r %
1194% %
1195% %
1196% %
1197%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1198%
1199% GetBlobError() returns MagickTrue if the blob associated with the specified
1200% image encountered an error.
1201%
1202% The format of the GetBlobError method is:
1203%
1204% MagickBooleanType GetBlobError(const Image *image)
1205%
1206% A description of each parameter follows:
1207%
1208% o image: the image.
1209%
1210*/
cristy7832dc22011-09-05 01:21:53 +00001211MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001212{
1213 assert(image != (const Image *) NULL);
1214 assert(image->signature == MagickSignature);
1215 if (image->debug != MagickFalse)
1216 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1217 return(image->blob->status);
1218}
1219
1220/*
1221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1222% %
1223% %
1224% %
1225+ G e t B l o b F i l e H a n d l e %
1226% %
1227% %
1228% %
1229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1230%
1231% GetBlobFileHandle() returns the file handle associated with the image blob.
1232%
1233% The format of the GetBlobFile method is:
1234%
1235% FILE *GetBlobFileHandle(const Image *image)
1236%
1237% A description of each parameter follows:
1238%
1239% o image: the image.
1240%
1241*/
1242MagickExport FILE *GetBlobFileHandle(const Image *image)
1243{
1244 assert(image != (const Image *) NULL);
1245 assert(image->signature == MagickSignature);
cristye7b28372012-06-17 13:59:06 +00001246 return(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001247}
1248
1249/*
1250%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1251% %
1252% %
1253% %
1254+ G e t B l o b I n f o %
1255% %
1256% %
1257% %
1258%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1259%
1260% GetBlobInfo() initializes the BlobInfo structure.
1261%
1262% The format of the GetBlobInfo method is:
1263%
1264% void GetBlobInfo(BlobInfo *blob_info)
1265%
1266% A description of each parameter follows:
1267%
1268% o blob_info: Specifies a pointer to a BlobInfo structure.
1269%
1270*/
cristy7832dc22011-09-05 01:21:53 +00001271MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001272{
1273 assert(blob_info != (BlobInfo *) NULL);
1274 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1275 blob_info->type=UndefinedStream;
1276 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1277 blob_info->properties.st_mtime=time((time_t *) NULL);
1278 blob_info->properties.st_ctime=time((time_t *) NULL);
1279 blob_info->debug=IsEventLogging();
1280 blob_info->reference_count=1;
1281 blob_info->semaphore=AllocateSemaphoreInfo();
1282 blob_info->signature=MagickSignature;
1283}
1284
1285/*
1286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1287% %
1288% %
1289% %
1290% G e t B l o b P r o p e r t i e s %
1291% %
1292% %
1293% %
1294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1295%
1296% GetBlobProperties() returns information about an image blob.
1297%
1298% The format of the GetBlobProperties method is:
1299%
1300% const struct stat *GetBlobProperties(const Image *image)
1301%
1302% A description of each parameter follows:
1303%
1304% o image: the image.
1305%
1306*/
cristy7832dc22011-09-05 01:21:53 +00001307MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001308{
1309 assert(image != (Image *) NULL);
1310 assert(image->signature == MagickSignature);
1311 if (image->debug != MagickFalse)
1312 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1313 return(&image->blob->properties);
1314}
1315
1316/*
1317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1318% %
1319% %
1320% %
1321+ G e t B l o b S i z e %
1322% %
1323% %
1324% %
1325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1326%
1327% GetBlobSize() returns the current length of the image file or blob; zero is
1328% returned if the size cannot be determined.
1329%
1330% The format of the GetBlobSize method is:
1331%
1332% MagickSizeType GetBlobSize(const Image *image)
1333%
1334% A description of each parameter follows:
1335%
1336% o image: the image.
1337%
1338*/
1339MagickExport MagickSizeType GetBlobSize(const Image *image)
1340{
1341 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001342 extent;
cristy3ed852e2009-09-05 21:47:34 +00001343
1344 assert(image != (Image *) NULL);
1345 assert(image->signature == MagickSignature);
1346 if (image->debug != MagickFalse)
1347 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1348 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001349 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001350 switch (image->blob->type)
1351 {
1352 case UndefinedStream:
1353 {
cristy81b8ce52010-02-05 01:53:17 +00001354 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001355 break;
1356 }
cristybc20d112012-07-29 20:27:00 +00001357 case StandardStream:
1358 {
1359 extent=image->blob->size;
1360 break;
1361 }
cristy3ed852e2009-09-05 21:47:34 +00001362 case FileStream:
1363 {
cristye7b28372012-06-17 13:59:06 +00001364 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001365 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001366 break;
1367 }
cristy3ed852e2009-09-05 21:47:34 +00001368 case PipeStream:
1369 {
cristy81b8ce52010-02-05 01:53:17 +00001370 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001371 break;
1372 }
1373 case ZipStream:
1374 case BZipStream:
1375 {
1376 MagickBooleanType
1377 status;
1378
1379 status=GetPathAttributes(image->filename,&image->blob->properties);
1380 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001381 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001382 break;
1383 }
1384 case FifoStream:
1385 break;
1386 case BlobStream:
1387 {
cristy891dc792010-03-04 01:47:16 +00001388 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001389 break;
1390 }
1391 }
cristy81b8ce52010-02-05 01:53:17 +00001392 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001393}
1394
1395/*
1396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1397% %
1398% %
1399% %
1400+ G e t B l o b S t r e a m D a t a %
1401% %
1402% %
1403% %
1404%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1405%
1406% GetBlobStreamData() returns the stream data for the image.
1407%
1408% The format of the GetBlobStreamData method is:
1409%
1410% unsigned char *GetBlobStreamData(const Image *image)
1411%
1412% A description of each parameter follows:
1413%
1414% o image: the image.
1415%
1416*/
1417MagickExport unsigned char *GetBlobStreamData(const Image *image)
1418{
1419 assert(image != (const Image *) NULL);
1420 assert(image->signature == MagickSignature);
1421 return(image->blob->data);
1422}
1423
1424/*
1425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1426% %
1427% %
1428% %
1429+ G e t B l o b S t r e a m H a n d l e r %
1430% %
1431% %
1432% %
1433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1434%
1435% GetBlobStreamHandler() returns the stream handler for the image.
1436%
1437% The format of the GetBlobStreamHandler method is:
1438%
1439% StreamHandler GetBlobStreamHandler(const Image *image)
1440%
1441% A description of each parameter follows:
1442%
1443% o image: the image.
1444%
1445*/
cristy7832dc22011-09-05 01:21:53 +00001446MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001447{
1448 assert(image != (const Image *) NULL);
1449 assert(image->signature == MagickSignature);
1450 if (image->debug != MagickFalse)
1451 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1452 return(image->blob->stream);
1453}
1454
1455/*
1456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1457% %
1458% %
1459% %
1460% I m a g e T o B l o b %
1461% %
1462% %
1463% %
1464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1465%
1466% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001467% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001468% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001469% etc.). This method is the equivalent of WriteImage(), but writes the
1470% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001471%
1472% The format of the ImageToBlob method is:
1473%
1474% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1475% size_t *length,ExceptionInfo *exception)
1476%
1477% A description of each parameter follows:
1478%
1479% o image_info: the image info.
1480%
1481% o image: the image.
1482%
1483% o length: This pointer to a size_t integer sets the initial length of the
1484% blob. On return, it reflects the actual length of the blob.
1485%
1486% o exception: return any errors or warnings in this structure.
1487%
1488*/
1489MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1490 Image *image,size_t *length,ExceptionInfo *exception)
1491{
1492 const MagickInfo
1493 *magick_info;
1494
1495 ImageInfo
1496 *blob_info;
1497
1498 MagickBooleanType
1499 status;
1500
1501 unsigned char
1502 *blob;
1503
1504 assert(image_info != (const ImageInfo *) NULL);
1505 assert(image_info->signature == MagickSignature);
1506 if (image_info->debug != MagickFalse)
1507 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1508 image_info->filename);
1509 assert(image != (Image *) NULL);
1510 assert(image->signature == MagickSignature);
1511 assert(exception != (ExceptionInfo *) NULL);
1512 *length=0;
1513 blob=(unsigned char *) NULL;
1514 blob_info=CloneImageInfo(image_info);
1515 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001516 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001517 if (*blob_info->magick != '\0')
1518 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1519 magick_info=GetMagickInfo(image->magick,exception);
1520 if (magick_info == (const MagickInfo *) NULL)
1521 {
1522 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001523 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001524 image->filename);
1525 return(blob);
1526 }
1527 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1528 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1529 {
1530 /*
1531 Native blob support for this image format.
1532 */
1533 blob_info->length=0;
1534 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1535 sizeof(unsigned char));
1536 if (blob_info->blob == (void *) NULL)
1537 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001538 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001539 else
1540 {
1541 (void) CloseBlob(image);
1542 image->blob->exempt=MagickTrue;
1543 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001544 status=WriteImage(blob_info,image,exception);
cristyc42554f2012-08-22 12:00:43 +00001545 *length=image->blob->length;
1546 blob=DetachBlob(image->blob);
cristy6e50f9e2012-08-22 16:30:29 +00001547 if (status == MagickFalse)
1548 blob=(unsigned char *) RelinquishMagickMemory(blob);
1549 else
1550 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1551 sizeof(*blob));
cristy3ed852e2009-09-05 21:47:34 +00001552 }
1553 }
1554 else
1555 {
1556 char
1557 unique[MaxTextExtent];
1558
1559 int
1560 file;
1561
1562 /*
1563 Write file to disk in blob image format.
1564 */
1565 file=AcquireUniqueFileResource(unique);
1566 if (file == -1)
1567 {
1568 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1569 image_info->filename);
1570 }
1571 else
1572 {
1573 blob_info->file=fdopen(file,"wb");
1574 if (blob_info->file != (FILE *) NULL)
1575 {
cristyb51dff52011-05-19 16:55:47 +00001576 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001577 image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001578 status=WriteImage(blob_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001579 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001580 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001581 blob=FileToBlob(image->filename,~0UL,length,exception);
1582 }
1583 (void) RelinquishUniqueFileResource(unique);
1584 }
1585 }
1586 blob_info=DestroyImageInfo(blob_info);
1587 return(blob);
1588}
1589
1590/*
1591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1592% %
1593% %
1594% %
1595% I m a g e T o F i l e %
1596% %
1597% %
1598% %
1599%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1600%
1601% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1602% occurs otherwise MagickTrue.
1603%
1604% The format of the ImageToFile method is:
1605%
1606% MagickBooleanType ImageToFile(Image *image,char *filename,
1607% ExceptionInfo *exception)
1608%
1609% A description of each parameter follows:
1610%
1611% o image: the image.
1612%
1613% o filename: Write the image to this file.
1614%
1615% o exception: return any errors or warnings in this structure.
1616%
1617*/
cristy3ed852e2009-09-05 21:47:34 +00001618MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1619 ExceptionInfo *exception)
1620{
1621 int
1622 file;
1623
1624 register const unsigned char
1625 *p;
1626
1627 register size_t
1628 i;
1629
1630 size_t
1631 length,
1632 quantum;
1633
1634 ssize_t
1635 count;
1636
1637 struct stat
cristye7b28372012-06-17 13:59:06 +00001638 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001639
1640 unsigned char
1641 *buffer;
1642
1643 assert(image != (Image *) NULL);
1644 assert(image->signature == MagickSignature);
1645 assert(image->blob != (BlobInfo *) NULL);
1646 assert(image->blob->type != UndefinedStream);
1647 if (image->debug != MagickFalse)
1648 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1649 assert(filename != (const char *) NULL);
1650 if (*filename == '\0')
1651 file=AcquireUniqueFileResource(filename);
1652 else
1653 if (LocaleCompare(filename,"-") == 0)
1654 file=fileno(stdout);
1655 else
cristyb70aab92012-01-31 15:04:04 +00001656 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001657 if (file == -1)
1658 {
1659 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1660 return(MagickFalse);
1661 }
1662 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001663 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1664 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001665 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001666 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1667 if (buffer == (unsigned char *) NULL)
1668 {
1669 file=close(file)-1;
1670 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001671 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001672 return(MagickFalse);
1673 }
1674 length=0;
1675 p=ReadBlobStream(image,quantum,buffer,&count);
1676 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1677 {
1678 length=(size_t) count;
1679 for (i=0; i < length; i+=count)
1680 {
1681 count=write(file,p+i,(size_t) (length-i));
1682 if (count <= 0)
1683 {
1684 count=0;
1685 if (errno != EINTR)
1686 break;
1687 }
1688 }
1689 if (i < length)
1690 break;
1691 }
cristy54439632010-07-15 00:43:34 +00001692 if (LocaleCompare(filename,"-") != 0)
1693 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001694 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001695 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001696 {
1697 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1698 return(MagickFalse);
1699 }
1700 return(MagickTrue);
1701}
1702
1703/*
1704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1705% %
1706% %
1707% %
1708% I m a g e s T o B l o b %
1709% %
1710% %
1711% %
1712%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1713%
1714% ImagesToBlob() implements direct to memory image formats. It returns the
1715% image sequence as a blob and its length. The magick member of the ImageInfo
1716% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1717%
1718% Note, some image formats do not permit multiple images to the same image
1719% stream (e.g. JPEG). in this instance, just the first image of the
1720% sequence is returned as a blob.
1721%
1722% The format of the ImagesToBlob method is:
1723%
1724% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1725% size_t *length,ExceptionInfo *exception)
1726%
1727% A description of each parameter follows:
1728%
1729% o image_info: the image info.
1730%
1731% o images: the image list.
1732%
1733% o length: This pointer to a size_t integer sets the initial length of the
1734% blob. On return, it reflects the actual length of the blob.
1735%
1736% o exception: return any errors or warnings in this structure.
1737%
1738*/
1739MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1740 Image *images,size_t *length,ExceptionInfo *exception)
1741{
1742 const MagickInfo
1743 *magick_info;
1744
1745 ImageInfo
1746 *blob_info;
1747
1748 MagickBooleanType
1749 status;
1750
1751 unsigned char
1752 *blob;
1753
1754 assert(image_info != (const ImageInfo *) NULL);
1755 assert(image_info->signature == MagickSignature);
1756 if (image_info->debug != MagickFalse)
1757 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1758 image_info->filename);
1759 assert(images != (Image *) NULL);
1760 assert(images->signature == MagickSignature);
1761 assert(exception != (ExceptionInfo *) NULL);
1762 *length=0;
1763 blob=(unsigned char *) NULL;
1764 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001765 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1766 exception);
cristy3ed852e2009-09-05 21:47:34 +00001767 if (*blob_info->magick != '\0')
1768 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1769 if (blob_info->adjoin == MagickFalse)
1770 {
1771 blob_info=DestroyImageInfo(blob_info);
1772 return(ImageToBlob(image_info,images,length,exception));
1773 }
1774 magick_info=GetMagickInfo(images->magick,exception);
1775 if (magick_info == (const MagickInfo *) NULL)
1776 {
1777 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001778 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001779 images->filename);
1780 return(blob);
1781 }
1782 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1783 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1784 {
1785 /*
1786 Native blob support for this images format.
1787 */
1788 blob_info->length=0;
1789 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1790 sizeof(unsigned char));
1791 if (blob_info->blob == (void *) NULL)
1792 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001793 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
cristy3ed852e2009-09-05 21:47:34 +00001794 else
1795 {
1796 images->blob->exempt=MagickTrue;
1797 *images->filename='\0';
1798 status=WriteImages(blob_info,images,images->filename,exception);
cristyb24e2402011-10-07 00:48:39 +00001799 if ((status != MagickFalse) && (images->blob->length != 0))
cristy3ed852e2009-09-05 21:47:34 +00001800 {
1801 *length=images->blob->length;
1802 blob=DetachBlob(images->blob);
1803 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1804 sizeof(*blob));
1805 }
1806 }
1807 }
1808 else
1809 {
1810 char
1811 filename[MaxTextExtent],
1812 unique[MaxTextExtent];
1813
1814 int
1815 file;
1816
1817 /*
1818 Write file to disk in blob images format.
1819 */
1820 file=AcquireUniqueFileResource(unique);
1821 if (file == -1)
1822 {
1823 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1824 image_info->filename);
1825 }
1826 else
1827 {
1828 blob_info->file=fdopen(file,"wb");
1829 if (blob_info->file != (FILE *) NULL)
1830 {
cristyb51dff52011-05-19 16:55:47 +00001831 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001832 images->magick,unique);
1833 status=WriteImages(blob_info,images,filename,exception);
1834 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001835 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001836 blob=FileToBlob(images->filename,~0UL,length,exception);
1837 }
1838 (void) RelinquishUniqueFileResource(unique);
1839 }
1840 }
1841 blob_info=DestroyImageInfo(blob_info);
1842 return(blob);
1843}
1844/*
1845%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1846% %
1847% %
1848% %
1849% I n j e c t I m a g e B l o b %
1850% %
1851% %
1852% %
1853%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1854%
1855% InjectImageBlob() injects the image with a copy of itself in the specified
1856% format (e.g. inject JPEG into a PDF image).
1857%
1858% The format of the InjectImageBlob method is:
1859%
1860% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1861% Image *image,Image *inject_image,const char *format,
1862% ExceptionInfo *exception)
1863%
1864% A description of each parameter follows:
1865%
1866% o image_info: the image info..
1867%
1868% o image: the image.
1869%
1870% o inject_image: inject into the image stream.
1871%
1872% o format: the image format.
1873%
1874% o exception: return any errors or warnings in this structure.
1875%
1876*/
1877MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1878 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1879{
1880 char
1881 filename[MaxTextExtent];
1882
1883 FILE
1884 *unique_file;
1885
1886 Image
1887 *byte_image;
1888
1889 ImageInfo
1890 *write_info;
1891
1892 int
1893 file;
1894
1895 MagickBooleanType
1896 status;
1897
cristybb503372010-05-27 20:51:26 +00001898 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001899 i;
1900
1901 size_t
1902 quantum;
1903
1904 ssize_t
1905 count;
1906
1907 struct stat
cristye7b28372012-06-17 13:59:06 +00001908 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001909
1910 unsigned char
1911 *buffer;
1912
1913 /*
1914 Write inject image to a temporary file.
1915 */
1916 assert(image_info != (ImageInfo *) NULL);
1917 assert(image_info->signature == MagickSignature);
1918 assert(image != (Image *) NULL);
1919 assert(image->signature == MagickSignature);
1920 if (image->debug != MagickFalse)
1921 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1922 assert(inject_image != (Image *) NULL);
1923 assert(inject_image->signature == MagickSignature);
1924 assert(exception != (ExceptionInfo *) NULL);
1925 unique_file=(FILE *) NULL;
1926 file=AcquireUniqueFileResource(filename);
1927 if (file != -1)
1928 unique_file=fdopen(file,"wb");
1929 if ((file == -1) || (unique_file == (FILE *) NULL))
1930 {
1931 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1932 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1933 image->filename);
1934 return(MagickFalse);
1935 }
1936 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1937 if (byte_image == (Image *) NULL)
1938 {
1939 (void) fclose(unique_file);
1940 (void) RelinquishUniqueFileResource(filename);
1941 return(MagickFalse);
1942 }
cristyb51dff52011-05-19 16:55:47 +00001943 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001944 filename);
1945 DestroyBlob(byte_image);
1946 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1947 write_info=CloneImageInfo(image_info);
1948 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001949 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001950 write_info=DestroyImageInfo(write_info);
1951 byte_image=DestroyImage(byte_image);
1952 (void) fclose(unique_file);
1953 if (status == MagickFalse)
1954 {
1955 (void) RelinquishUniqueFileResource(filename);
1956 return(MagickFalse);
1957 }
1958 /*
1959 Inject into image stream.
1960 */
cristy18c6c272011-09-23 14:40:37 +00001961 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001962 if (file == -1)
1963 {
1964 (void) RelinquishUniqueFileResource(filename);
1965 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1966 image_info->filename);
1967 return(MagickFalse);
1968 }
1969 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001970 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1971 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001972 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1973 if (buffer == (unsigned char *) NULL)
1974 {
1975 (void) RelinquishUniqueFileResource(filename);
1976 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1977 image->filename);
1978 }
1979 for (i=0; ; i+=count)
1980 {
1981 count=(ssize_t) read(file,buffer,quantum);
1982 if (count <= 0)
1983 {
1984 count=0;
1985 if (errno != EINTR)
1986 break;
1987 }
1988 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1989 MagickFalse;
1990 }
cristya7cb4312010-06-26 00:47:03 +00001991 file=close(file);
1992 if (file == -1)
1993 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001994 (void) RelinquishUniqueFileResource(filename);
1995 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1996 return(status);
1997}
1998
1999/*
2000%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2001% %
2002% %
2003% %
2004+ I s B l o b E x e m p t %
2005% %
2006% %
2007% %
2008%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2009%
2010% IsBlobExempt() returns true if the blob is exempt.
2011%
2012% The format of the IsBlobExempt method is:
2013%
2014% MagickBooleanType IsBlobExempt(const Image *image)
2015%
2016% A description of each parameter follows:
2017%
2018% o image: the image.
2019%
2020*/
cristy7832dc22011-09-05 01:21:53 +00002021MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002022{
2023 assert(image != (const Image *) NULL);
2024 assert(image->signature == MagickSignature);
2025 if (image->debug != MagickFalse)
2026 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2027 return(image->blob->exempt);
2028}
2029
2030/*
2031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2032% %
2033% %
2034% %
2035+ I s B l o b S e e k a b l e %
2036% %
2037% %
2038% %
2039%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2040%
2041% IsBlobSeekable() returns true if the blob is seekable.
2042%
2043% The format of the IsBlobSeekable method is:
2044%
2045% MagickBooleanType IsBlobSeekable(const Image *image)
2046%
2047% A description of each parameter follows:
2048%
2049% o image: the image.
2050%
2051*/
cristy7832dc22011-09-05 01:21:53 +00002052MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002053{
2054 MagickBooleanType
2055 seekable;
2056
2057 assert(image != (const Image *) NULL);
2058 assert(image->signature == MagickSignature);
2059 if (image->debug != MagickFalse)
2060 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002061 switch (image->blob->type)
2062 {
2063 case FileStream:
2064 case BlobStream:
2065 case ZipStream:
2066 {
2067 seekable=MagickTrue;
2068 break;
2069 }
2070 default:
2071 {
2072 seekable=MagickFalse;
2073 break;
2074 }
2075 }
cristy3ed852e2009-09-05 21:47:34 +00002076 return(seekable);
2077}
2078
2079/*
2080%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2081% %
2082% %
2083% %
2084+ I s B l o b T e m p o r a r y %
2085% %
2086% %
2087% %
2088%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2089%
2090% IsBlobTemporary() returns true if the blob is temporary.
2091%
2092% The format of the IsBlobTemporary method is:
2093%
2094% MagickBooleanType IsBlobTemporary(const Image *image)
2095%
2096% A description of each parameter follows:
2097%
2098% o image: the image.
2099%
2100*/
cristy7832dc22011-09-05 01:21:53 +00002101MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002102{
2103 assert(image != (const Image *) NULL);
2104 assert(image->signature == MagickSignature);
2105 if (image->debug != MagickFalse)
2106 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2107 return(image->blob->temporary);
2108}
2109
2110/*
2111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2112% %
2113% %
2114% %
2115+ M a p B l o b %
2116% %
2117% %
2118% %
2119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2120%
2121% MapBlob() creates a mapping from a file to a binary large object.
2122%
2123% The format of the MapBlob method is:
2124%
2125% unsigned char *MapBlob(int file,const MapMode mode,
2126% const MagickOffsetType offset,const size_t length)
2127%
2128% A description of each parameter follows:
2129%
2130% o file: map this file descriptor.
2131%
2132% o mode: ReadMode, WriteMode, or IOMode.
2133%
2134% o offset: starting at this offset within the file.
2135%
2136% o length: the length of the mapping is returned in this pointer.
2137%
2138*/
2139MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2140 const MagickOffsetType offset,const size_t length)
2141{
2142#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
2143 int
2144 flags,
2145 protection;
2146
2147 unsigned char
2148 *map;
2149
2150 /*
2151 Map file.
2152 */
2153 flags=0;
2154 if (file == -1)
2155#if defined(MAP_ANONYMOUS)
2156 flags|=MAP_ANONYMOUS;
cristy6dac2da2013-04-16 19:10:51 +00002157#if defined(MAGICKCORE_HAVE_HUGEPAGES) && defined(MAP_HUGETLB)
2158 flags|=MAP_HUGETLB;
2159#endif
cristy3ed852e2009-09-05 21:47:34 +00002160#else
2161 return((unsigned char *) NULL);
2162#endif
2163 switch (mode)
2164 {
2165 case ReadMode:
2166 default:
2167 {
2168 protection=PROT_READ;
2169 flags|=MAP_PRIVATE;
2170 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2171 (off_t) offset);
2172 break;
2173 }
2174 case WriteMode:
2175 {
2176 protection=PROT_WRITE;
2177 flags|=MAP_SHARED;
2178 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2179 (off_t) offset);
cristy2a9e7cb2010-03-05 02:15:05 +00002180#if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
2181 (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
2182 POSIX_MADV_WILLNEED);
2183#endif
cristy3ed852e2009-09-05 21:47:34 +00002184 break;
2185 }
2186 case IOMode:
2187 {
2188 protection=PROT_READ | PROT_WRITE;
2189 flags|=MAP_SHARED;
2190 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2191 (off_t) offset);
2192 break;
2193 }
2194 }
2195 if (map == (unsigned char *) MAP_FAILED)
2196 return((unsigned char *) NULL);
2197 return(map);
2198#else
2199 (void) file;
2200 (void) mode;
2201 (void) offset;
2202 (void) length;
2203 return((unsigned char *) NULL);
2204#endif
2205}
2206
2207/*
2208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2209% %
2210% %
2211% %
2212+ M S B O r d e r L o n g %
2213% %
2214% %
2215% %
2216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2217%
2218% MSBOrderLong() converts a least-significant byte first buffer of integers to
2219% most-significant byte first.
2220%
2221% The format of the MSBOrderLong method is:
2222%
2223% void MSBOrderLong(unsigned char *buffer,const size_t length)
2224%
2225% A description of each parameter follows.
2226%
2227% o buffer: Specifies a pointer to a buffer of integers.
2228%
2229% o length: Specifies the length of the buffer.
2230%
2231*/
2232MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2233{
2234 int
2235 c;
2236
2237 register unsigned char
2238 *p,
2239 *q;
2240
2241 assert(buffer != (unsigned char *) NULL);
2242 q=buffer+length;
2243 while (buffer < q)
2244 {
2245 p=buffer+3;
2246 c=(int) (*p);
2247 *p=(*buffer);
2248 *buffer++=(unsigned char) c;
2249 p=buffer+1;
2250 c=(int) (*p);
2251 *p=(*buffer);
2252 *buffer++=(unsigned char) c;
2253 buffer+=2;
2254 }
2255}
2256
2257/*
2258%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2259% %
2260% %
2261% %
2262+ M S B O r d e r S h o r t %
2263% %
2264% %
2265% %
2266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2267%
2268% MSBOrderShort() converts a least-significant byte first buffer of integers
2269% to most-significant byte first.
2270%
2271% The format of the MSBOrderShort method is:
2272%
2273% void MSBOrderShort(unsigned char *p,const size_t length)
2274%
2275% A description of each parameter follows.
2276%
2277% o p: Specifies a pointer to a buffer of integers.
2278%
2279% o length: Specifies the length of the buffer.
2280%
2281*/
2282MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2283{
2284 int
2285 c;
2286
2287 register unsigned char
2288 *q;
2289
2290 assert(p != (unsigned char *) NULL);
2291 q=p+length;
2292 while (p < q)
2293 {
2294 c=(int) (*p);
2295 *p=(*(p+1));
2296 p++;
2297 *p++=(unsigned char) c;
2298 }
2299}
2300
2301/*
2302%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2303% %
2304% %
2305% %
2306+ O p e n B l o b %
2307% %
2308% %
2309% %
2310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2311%
2312% OpenBlob() opens a file associated with the image. A file name of '-' sets
2313% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2314% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2315% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2316% from a system command.
2317%
2318% The format of the OpenBlob method is:
2319%
2320% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2321% const BlobMode mode,ExceptionInfo *exception)
2322%
2323% A description of each parameter follows:
2324%
2325% o image_info: the image info.
2326%
2327% o image: the image.
2328%
2329% o mode: the mode for opening the file.
2330%
2331*/
2332MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2333 Image *image,const BlobMode mode,ExceptionInfo *exception)
2334{
2335 char
cristybf6a7092010-06-11 02:12:15 +00002336 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002337 filename[MaxTextExtent];
2338
2339 const char
2340 *type;
2341
2342 MagickBooleanType
2343 status;
2344
2345 PolicyRights
2346 rights;
2347
2348 assert(image_info != (ImageInfo *) NULL);
2349 assert(image_info->signature == MagickSignature);
2350 if (image_info->debug != MagickFalse)
2351 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2352 image_info->filename);
2353 assert(image != (Image *) NULL);
2354 assert(image->signature == MagickSignature);
2355 if (image_info->blob != (void *) NULL)
2356 {
2357 if (image_info->stream != (StreamHandler) NULL)
2358 image->blob->stream=(StreamHandler) image_info->stream;
2359 AttachBlob(image->blob,image_info->blob,image_info->length);
2360 return(MagickTrue);
2361 }
2362 (void) DetachBlob(image->blob);
2363 switch (mode)
2364 {
2365 default: type="r"; break;
2366 case ReadBlobMode: type="r"; break;
2367 case ReadBinaryBlobMode: type="rb"; break;
2368 case WriteBlobMode: type="w"; break;
2369 case WriteBinaryBlobMode: type="w+b"; break;
2370 case AppendBlobMode: type="a"; break;
2371 case AppendBinaryBlobMode: type="a+b"; break;
2372 }
2373 if (*type != 'r')
2374 image->blob->synchronize=image_info->synchronize;
2375 if (image_info->stream != (StreamHandler) NULL)
2376 {
2377 image->blob->stream=(StreamHandler) image_info->stream;
2378 if (*type == 'w')
2379 {
2380 image->blob->type=FifoStream;
2381 return(MagickTrue);
2382 }
2383 }
2384 /*
2385 Open image file.
2386 */
2387 *filename='\0';
2388 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2389 rights=ReadPolicyRights;
2390 if (*type == 'w')
2391 rights=WritePolicyRights;
2392 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2393 {
cristya9197f62010-01-12 02:23:34 +00002394 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002395 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
cristyefe601c2013-01-05 17:51:12 +00002396 "NotAuthorized","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00002397 return(MagickFalse);
2398 }
2399 if ((LocaleCompare(filename,"-") == 0) ||
2400 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2401 {
cristye7b28372012-06-17 13:59:06 +00002402 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002403#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002404 if (strchr(type,'b') != (char *) NULL)
cristye7b28372012-06-17 13:59:06 +00002405 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002406#endif
2407 image->blob->type=StandardStream;
2408 image->blob->exempt=MagickTrue;
2409 return(MagickTrue);
2410 }
cristybc20d112012-07-29 20:27:00 +00002411 if (LocaleNCompare(filename,"fd:",3) == 0)
2412 {
2413 char
2414 mode[MaxTextExtent];
2415
2416 *mode=(*type);
2417 mode[1]='\0';
2418 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2419#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2420 if (strchr(type,'b') != (char *) NULL)
2421 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2422#endif
2423 image->blob->type=StandardStream;
2424 image->blob->exempt=MagickTrue;
2425 return(MagickTrue);
2426 }
cristy3ed852e2009-09-05 21:47:34 +00002427#if defined(MAGICKCORE_HAVE_POPEN)
2428 if (*filename == '|')
2429 {
2430 char
2431 mode[MaxTextExtent];
2432
2433 /*
2434 Pipe image to or from a system command.
2435 */
2436#if defined(SIGPIPE)
2437 if (*type == 'w')
2438 (void) signal(SIGPIPE,SIG_IGN);
2439#endif
2440 *mode=(*type);
2441 mode[1]='\0';
cristye7b28372012-06-17 13:59:06 +00002442 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2443 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002444 {
2445 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2446 return(MagickFalse);
2447 }
2448 image->blob->type=PipeStream;
2449 image->blob->exempt=MagickTrue;
2450 return(MagickTrue);
2451 }
2452#endif
2453 status=GetPathAttributes(filename,&image->blob->properties);
2454#if defined(S_ISFIFO)
2455 if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2456 {
cristye7b28372012-06-17 13:59:06 +00002457 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2458 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002459 {
2460 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2461 return(MagickFalse);
2462 }
2463 image->blob->type=FileStream;
2464 image->blob->exempt=MagickTrue;
2465 return(MagickTrue);
2466 }
2467#endif
cristybf6a7092010-06-11 02:12:15 +00002468 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002469 if (*type == 'w')
2470 {
cristye8939e72010-02-03 17:05:25 +00002471 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002472 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002473 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002474 {
2475 /*
2476 Form filename for multi-part images.
2477 */
2478 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002479 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002480 if ((LocaleCompare(filename,image->filename) == 0) &&
2481 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2482 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002483 {
cristybf7fa0d2010-02-04 00:51:10 +00002484 char
cristybf7fa0d2010-02-04 00:51:10 +00002485 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002486
cristybf7fa0d2010-02-04 00:51:10 +00002487 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002488 if (*extension == '\0')
cristyb51dff52011-05-19 16:55:47 +00002489 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002490 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002491 else
cristyb51dff52011-05-19 16:55:47 +00002492 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002493 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002494 }
2495 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002496#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002497 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002498#endif
cristye8939e72010-02-03 17:05:25 +00002499 }
cristy3ed852e2009-09-05 21:47:34 +00002500 }
cristybf6a7092010-06-11 02:12:15 +00002501 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002502 {
cristye7b28372012-06-17 13:59:06 +00002503 image->blob->file_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002504 image->blob->type=FileStream;
2505 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002506 }
2507 else
cristybf6a7092010-06-11 02:12:15 +00002508 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002509 {
cristye7b28372012-06-17 13:59:06 +00002510 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2511 if (image->blob->file_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002512 {
2513 size_t
cristybf6a7092010-06-11 02:12:15 +00002514 count;
cristy3ed852e2009-09-05 21:47:34 +00002515
cristybf6a7092010-06-11 02:12:15 +00002516 unsigned char
2517 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002518
cristybf6a7092010-06-11 02:12:15 +00002519 image->blob->type=FileStream;
2520#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002521 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2522 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002523#endif
2524 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristye7b28372012-06-17 13:59:06 +00002525 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
cristyae958042013-01-05 15:48:19 +00002526 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
cristy79fe6932012-12-25 00:31:30 +00002527 (void) fflush(image->blob->file_info.file);
cristybf6a7092010-06-11 02:12:15 +00002528 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2529 " read %.20g magic header bytes",(double) count);
2530#if defined(MAGICKCORE_ZLIB_DELEGATE)
2531 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2532 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002533 {
cristye7b28372012-06-17 13:59:06 +00002534 (void) fclose(image->blob->file_info.file);
2535 image->blob->file_info.gzfile=gzopen(filename,type);
2536 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002537 image->blob->type=ZipStream;
2538 }
2539#endif
2540#if defined(MAGICKCORE_BZLIB_DELEGATE)
2541 if (strncmp((char *) magick,"BZh",3) == 0)
2542 {
cristye7b28372012-06-17 13:59:06 +00002543 (void) fclose(image->blob->file_info.file);
2544 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2545 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002546 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002547 }
cristybf6a7092010-06-11 02:12:15 +00002548#endif
cristyc6c589d2010-07-06 01:34:57 +00002549 if (image->blob->type == FileStream)
2550 {
2551 const MagickInfo
2552 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002553
cristyc6c589d2010-07-06 01:34:57 +00002554 ExceptionInfo
2555 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002556
cristyc6c589d2010-07-06 01:34:57 +00002557 struct stat
2558 *properties;
cristybf6a7092010-06-11 02:12:15 +00002559
cristyc6c589d2010-07-06 01:34:57 +00002560 sans_exception=AcquireExceptionInfo();
2561 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2562 sans_exception=DestroyExceptionInfo(sans_exception);
2563 properties=(&image->blob->properties);
2564 if ((magick_info != (const MagickInfo *) NULL) &&
2565 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2566 (properties->st_size <= MagickMaxBufferExtent))
2567 {
2568 size_t
2569 length;
cristybf6a7092010-06-11 02:12:15 +00002570
cristyc6c589d2010-07-06 01:34:57 +00002571 void
2572 *blob;
cristybf6a7092010-06-11 02:12:15 +00002573
cristyc6c589d2010-07-06 01:34:57 +00002574 length=(size_t) properties->st_size;
cristye7b28372012-06-17 13:59:06 +00002575 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,
cristy95888612012-04-04 21:56:52 +00002576 0,length);
cristyc6c589d2010-07-06 01:34:57 +00002577 if (blob != (void *) NULL)
2578 {
2579 /*
2580 Format supports blobs-- use memory-mapped I/O.
2581 */
2582 if (image_info->file != (FILE *) NULL)
2583 image->blob->exempt=MagickFalse;
2584 else
2585 {
cristye7b28372012-06-17 13:59:06 +00002586 (void) fclose(image->blob->file_info.file);
2587 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002588 }
2589 AttachBlob(image->blob,blob,length);
2590 image->blob->mapped=MagickTrue;
2591 }
2592 }
2593 }
cristy3ed852e2009-09-05 21:47:34 +00002594 }
cristybf6a7092010-06-11 02:12:15 +00002595 }
2596 else
2597#if defined(MAGICKCORE_ZLIB_DELEGATE)
2598 if ((LocaleCompare(extension,"Z") == 0) ||
2599 (LocaleCompare(extension,"gz") == 0) ||
2600 (LocaleCompare(extension,"wmz") == 0) ||
2601 (LocaleCompare(extension,"svgz") == 0))
2602 {
2603 if (mode == WriteBinaryBlobMode)
2604 type="wb";
cristye7b28372012-06-17 13:59:06 +00002605 image->blob->file_info.gzfile=gzopen(filename,type);
2606 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002607 image->blob->type=ZipStream;
2608 }
2609 else
2610#endif
2611#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002612 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002613 {
cristye7b28372012-06-17 13:59:06 +00002614 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2615 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002616 image->blob->type=BZipStream;
2617 }
2618 else
2619#endif
2620 {
cristye7b28372012-06-17 13:59:06 +00002621 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2622 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002623 {
2624 image->blob->type=FileStream;
2625#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002626 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2627 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002628#endif
2629 }
2630 }
cristy3ed852e2009-09-05 21:47:34 +00002631 image->blob->status=MagickFalse;
2632 if (image->blob->type != UndefinedStream)
2633 image->blob->size=GetBlobSize(image);
2634 else
2635 {
2636 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2637 return(MagickFalse);
2638 }
2639 return(MagickTrue);
2640}
2641
2642/*
2643%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2644% %
2645% %
2646% %
2647+ P i n g B l o b %
2648% %
2649% %
2650% %
2651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2652%
2653% PingBlob() returns all the attributes of an image or image sequence except
2654% for the pixels. It is much faster and consumes far less memory than
2655% BlobToImage(). On failure, a NULL image is returned and exception
2656% describes the reason for the failure.
2657%
2658% The format of the PingBlob method is:
2659%
2660% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2661% const size_t length,ExceptionInfo *exception)
2662%
2663% A description of each parameter follows:
2664%
2665% o image_info: the image info.
2666%
2667% o blob: the address of a character stream in one of the image formats
2668% understood by ImageMagick.
2669%
2670% o length: This size_t integer reflects the length in bytes of the blob.
2671%
2672% o exception: return any errors or warnings in this structure.
2673%
2674*/
2675
2676#if defined(__cplusplus) || defined(c_plusplus)
2677extern "C" {
2678#endif
2679
2680static size_t PingStream(const Image *magick_unused(image),
2681 const void *magick_unused(pixels),const size_t columns)
2682{
2683 return(columns);
2684}
2685
2686#if defined(__cplusplus) || defined(c_plusplus)
2687}
2688#endif
2689
2690MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2691 const size_t length,ExceptionInfo *exception)
2692{
2693 Image
2694 *image;
2695
2696 ImageInfo
2697 *ping_info;
2698
2699 assert(image_info != (ImageInfo *) NULL);
2700 assert(image_info->signature == MagickSignature);
2701 if (image_info->debug != MagickFalse)
2702 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2703 image_info->filename);
2704 assert(exception != (ExceptionInfo *) NULL);
2705 if ((blob == (const void *) NULL) || (length == 0))
2706 {
2707 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +00002708 "UnrecognizedImageFormat","`%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002709 return((Image *) NULL);
2710 }
2711 ping_info=CloneImageInfo(image_info);
2712 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2713 if (ping_info->blob == (const void *) NULL)
2714 {
2715 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00002716 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002717 return((Image *) NULL);
2718 }
cristy54aad5e2010-09-03 16:02:04 +00002719 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002720 ping_info->length=length;
2721 ping_info->ping=MagickTrue;
2722 image=ReadStream(ping_info,&PingStream,exception);
2723 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2724 ping_info=DestroyImageInfo(ping_info);
2725 return(image);
2726}
2727
2728/*
2729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2730% %
2731% %
2732% %
2733+ R e a d B l o b %
2734% %
2735% %
2736% %
2737%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2738%
2739% ReadBlob() reads data from the blob or image file and returns it. It
cristy5f3d2752013-01-05 18:53:38 +00002740% returns the number of bytes read. If length is zero, ReadBlob() returns
2741% zero and has no other results. If length is greater than SSIZE_MAX, the
2742% result is unspecified.
cristy3ed852e2009-09-05 21:47:34 +00002743%
2744% The format of the ReadBlob method is:
2745%
2746% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2747%
2748% A description of each parameter follows:
2749%
2750% o image: the image.
2751%
2752% o length: Specifies an integer representing the number of bytes to read
2753% from the file.
2754%
2755% o data: Specifies an area to place the information requested from the
2756% file.
2757%
2758*/
2759MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2760 unsigned char *data)
2761{
2762 int
2763 c;
2764
2765 register unsigned char
2766 *q;
2767
2768 ssize_t
2769 count;
2770
2771 assert(image != (Image *) NULL);
2772 assert(image->signature == MagickSignature);
2773 assert(image->blob != (BlobInfo *) NULL);
2774 assert(image->blob->type != UndefinedStream);
2775 if (length == 0)
2776 return(0);
2777 assert(data != (void *) NULL);
2778 count=0;
2779 q=data;
2780 switch (image->blob->type)
2781 {
2782 case UndefinedStream:
2783 break;
cristy3ed852e2009-09-05 21:47:34 +00002784 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002785 {
cristy5f3d2752013-01-05 18:53:38 +00002786 count=read(fileno(image->blob->file_info.file),q,length);
cristybc20d112012-07-29 20:27:00 +00002787 break;
2788 }
2789 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002790 case PipeStream:
2791 {
2792 switch (length)
2793 {
2794 default:
2795 {
cristye7b28372012-06-17 13:59:06 +00002796 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002797 break;
2798 }
2799 case 2:
2800 {
cristye7b28372012-06-17 13:59:06 +00002801 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002802 if (c == EOF)
2803 break;
2804 *q++=(unsigned char) c;
2805 count++;
2806 }
2807 case 1:
2808 {
cristye7b28372012-06-17 13:59:06 +00002809 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002810 if (c == EOF)
2811 break;
2812 *q++=(unsigned char) c;
2813 count++;
2814 }
2815 case 0:
2816 break;
2817 }
2818 break;
2819 }
2820 case ZipStream:
2821 {
2822#if defined(MAGICKCORE_ZLIB_DELEGATE)
2823 switch (length)
2824 {
2825 default:
2826 {
cristye7b28372012-06-17 13:59:06 +00002827 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002828 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002829 break;
2830 }
2831 case 2:
2832 {
cristye7b28372012-06-17 13:59:06 +00002833 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002834 if (c == EOF)
2835 break;
2836 *q++=(unsigned char) c;
2837 count++;
2838 }
2839 case 1:
2840 {
cristye7b28372012-06-17 13:59:06 +00002841 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002842 if (c == EOF)
2843 break;
2844 *q++=(unsigned char) c;
2845 count++;
2846 }
2847 case 0:
2848 break;
2849 }
2850#endif
2851 break;
2852 }
2853 case BZipStream:
2854 {
2855#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy5f3d2752013-01-05 18:53:38 +00002856 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
cristy3ed852e2009-09-05 21:47:34 +00002857#endif
2858 break;
2859 }
2860 case FifoStream:
2861 break;
2862 case BlobStream:
2863 {
2864 register const unsigned char
2865 *p;
2866
2867 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2868 {
2869 image->blob->eof=MagickTrue;
2870 break;
2871 }
2872 p=image->blob->data+image->blob->offset;
cristye7b28372012-06-17 13:59:06 +00002873 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2874 image->blob->offset));
cristy3ed852e2009-09-05 21:47:34 +00002875 image->blob->offset+=count;
2876 if (count != (ssize_t) length)
2877 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002878 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002879 break;
2880 }
2881 }
2882 return(count);
2883}
2884
2885/*
2886%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2887% %
2888% %
2889% %
2890+ R e a d B l o b B y t e %
2891% %
2892% %
2893% %
2894%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2895%
2896% ReadBlobByte() reads a single byte from the image file and returns it.
2897%
2898% The format of the ReadBlobByte method is:
2899%
2900% int ReadBlobByte(Image *image)
2901%
2902% A description of each parameter follows.
2903%
2904% o image: the image.
2905%
2906*/
2907MagickExport int ReadBlobByte(Image *image)
2908{
2909 register const unsigned char
2910 *p;
2911
2912 ssize_t
2913 count;
2914
2915 unsigned char
2916 buffer[1];
2917
2918 assert(image != (Image *) NULL);
2919 assert(image->signature == MagickSignature);
2920 p=ReadBlobStream(image,1,buffer,&count);
2921 if (count != 1)
2922 return(EOF);
2923 return((int) (*p));
2924}
2925
2926/*
2927%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2928% %
2929% %
2930% %
2931+ R e a d B l o b D o u b l e %
2932% %
2933% %
2934% %
2935%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2936%
2937% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2938% specified by the endian member of the image structure.
2939%
2940% The format of the ReadBlobDouble method is:
2941%
2942% double ReadBlobDouble(Image *image)
2943%
2944% A description of each parameter follows.
2945%
2946% o image: the image.
2947%
2948*/
2949MagickExport double ReadBlobDouble(Image *image)
2950{
2951 union
2952 {
2953 MagickSizeType
2954 unsigned_value;
2955
2956 double
2957 double_value;
2958 } quantum;
2959
2960 quantum.double_value=0.0;
2961 quantum.unsigned_value=ReadBlobLongLong(image);
2962 return(quantum.double_value);
2963}
2964
2965/*
2966%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2967% %
2968% %
2969% %
2970+ R e a d B l o b F l o a t %
2971% %
2972% %
2973% %
2974%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2975%
2976% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2977% specified by the endian member of the image structure.
2978%
2979% The format of the ReadBlobFloat method is:
2980%
2981% float ReadBlobFloat(Image *image)
2982%
2983% A description of each parameter follows.
2984%
2985% o image: the image.
2986%
2987*/
2988MagickExport float ReadBlobFloat(Image *image)
2989{
2990 union
2991 {
2992 unsigned int
2993 unsigned_value;
2994
2995 float
2996 float_value;
2997 } quantum;
2998
2999 quantum.float_value=0.0;
3000 quantum.unsigned_value=ReadBlobLong(image);
3001 return(quantum.float_value);
3002}
3003
3004/*
3005%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3006% %
3007% %
3008% %
3009+ R e a d B l o b L o n g %
3010% %
3011% %
3012% %
3013%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3014%
cristybb503372010-05-27 20:51:26 +00003015% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003016% specified by the endian member of the image structure.
3017%
3018% The format of the ReadBlobLong method is:
3019%
3020% unsigned int ReadBlobLong(Image *image)
3021%
3022% A description of each parameter follows.
3023%
3024% o image: the image.
3025%
3026*/
3027MagickExport unsigned int ReadBlobLong(Image *image)
3028{
3029 register const unsigned char
3030 *p;
3031
3032 ssize_t
3033 count;
3034
3035 unsigned char
3036 buffer[4];
3037
3038 unsigned int
3039 value;
3040
3041 assert(image != (Image *) NULL);
3042 assert(image->signature == MagickSignature);
3043 *buffer='\0';
3044 p=ReadBlobStream(image,4,buffer,&count);
3045 if (count != 4)
3046 return(0UL);
3047 if (image->endian == LSBEndian)
3048 {
3049 value=(unsigned int) (*p++);
3050 value|=((unsigned int) (*p++)) << 8;
3051 value|=((unsigned int) (*p++)) << 16;
3052 value|=((unsigned int) (*p++)) << 24;
3053 return(value);
3054 }
3055 value=((unsigned int) (*p++)) << 24;
3056 value|=((unsigned int) (*p++)) << 16;
3057 value|=((unsigned int) (*p++)) << 8;
3058 value|=((unsigned int) (*p++));
3059 return(value);
3060}
3061
3062/*
3063%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3064% %
3065% %
3066% %
3067+ R e a d B l o b L o n g L o n g %
3068% %
3069% %
3070% %
3071%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3072%
cristy4cb162a2010-05-30 03:04:47 +00003073% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3074% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003075%
cristy4cb162a2010-05-30 03:04:47 +00003076% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003077%
cristy4cb162a2010-05-30 03:04:47 +00003078% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003079%
3080% A description of each parameter follows.
3081%
3082% o image: the image.
3083%
3084*/
3085MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3086{
cristy0286d852010-10-12 18:38:07 +00003087 MagickSizeType
3088 value;
3089
cristy3ed852e2009-09-05 21:47:34 +00003090 register const unsigned char
3091 *p;
3092
3093 ssize_t
3094 count;
3095
3096 unsigned char
3097 buffer[8];
3098
cristy3ed852e2009-09-05 21:47:34 +00003099 assert(image != (Image *) NULL);
3100 assert(image->signature == MagickSignature);
3101 *buffer='\0';
3102 p=ReadBlobStream(image,8,buffer,&count);
3103 if (count != 8)
3104 return(MagickULLConstant(0));
3105 if (image->endian == LSBEndian)
3106 {
3107 value=(MagickSizeType) (*p++);
3108 value|=((MagickSizeType) (*p++)) << 8;
3109 value|=((MagickSizeType) (*p++)) << 16;
3110 value|=((MagickSizeType) (*p++)) << 24;
3111 value|=((MagickSizeType) (*p++)) << 32;
3112 value|=((MagickSizeType) (*p++)) << 40;
3113 value|=((MagickSizeType) (*p++)) << 48;
3114 value|=((MagickSizeType) (*p++)) << 56;
3115 return(value & MagickULLConstant(0xffffffffffffffff));
3116 }
3117 value=((MagickSizeType) (*p++)) << 56;
3118 value|=((MagickSizeType) (*p++)) << 48;
3119 value|=((MagickSizeType) (*p++)) << 40;
3120 value|=((MagickSizeType) (*p++)) << 32;
3121 value|=((MagickSizeType) (*p++)) << 24;
3122 value|=((MagickSizeType) (*p++)) << 16;
3123 value|=((MagickSizeType) (*p++)) << 8;
3124 value|=((MagickSizeType) (*p++));
3125 return(value & MagickULLConstant(0xffffffffffffffff));
3126}
3127
3128/*
3129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3130% %
3131% %
3132% %
3133+ R e a d B l o b S h o r t %
3134% %
3135% %
3136% %
3137%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3138%
3139% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3140% specified by the endian member of the image structure.
3141%
3142% The format of the ReadBlobShort method is:
3143%
3144% unsigned short ReadBlobShort(Image *image)
3145%
3146% A description of each parameter follows.
3147%
3148% o image: the image.
3149%
3150*/
3151MagickExport unsigned short ReadBlobShort(Image *image)
3152{
3153 register const unsigned char
3154 *p;
3155
3156 register unsigned int
3157 value;
3158
3159 ssize_t
3160 count;
3161
3162 unsigned char
3163 buffer[2];
3164
3165 assert(image != (Image *) NULL);
3166 assert(image->signature == MagickSignature);
3167 *buffer='\0';
3168 p=ReadBlobStream(image,2,buffer,&count);
3169 if (count != 2)
3170 return((unsigned short) 0U);
3171 if (image->endian == LSBEndian)
3172 {
3173 value=(unsigned int) (*p++);
3174 value|=((unsigned int) (*p++)) << 8;
3175 return((unsigned short) (value & 0xffff));
3176 }
3177 value=(unsigned int) ((*p++) << 8);
3178 value|=(unsigned int) (*p++);
3179 return((unsigned short) (value & 0xffff));
3180}
3181
3182/*
3183%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3184% %
3185% %
3186% %
3187+ R e a d B l o b L S B L o n g %
3188% %
3189% %
3190% %
3191%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3192%
cristybb503372010-05-27 20:51:26 +00003193% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003194% least-significant byte first order.
3195%
3196% The format of the ReadBlobLSBLong method is:
3197%
3198% unsigned int ReadBlobLSBLong(Image *image)
3199%
3200% A description of each parameter follows.
3201%
3202% o image: the image.
3203%
3204*/
3205MagickExport unsigned int ReadBlobLSBLong(Image *image)
3206{
3207 register const unsigned char
3208 *p;
3209
3210 register unsigned int
3211 value;
3212
3213 ssize_t
3214 count;
3215
3216 unsigned char
3217 buffer[4];
3218
3219 assert(image != (Image *) NULL);
3220 assert(image->signature == MagickSignature);
3221 *buffer='\0';
3222 p=ReadBlobStream(image,4,buffer,&count);
3223 if (count != 4)
3224 return(0U);
3225 value=(unsigned int) (*p++);
3226 value|=((unsigned int) (*p++)) << 8;
3227 value|=((unsigned int) (*p++)) << 16;
3228 value|=((unsigned int) (*p++)) << 24;
3229 return(value);
3230}
3231
3232/*
3233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3234% %
3235% %
3236% %
3237+ R e a d B l o b L S B S h o r t %
3238% %
3239% %
3240% %
3241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3242%
3243% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3244% least-significant byte first order.
3245%
3246% The format of the ReadBlobLSBShort method is:
3247%
3248% unsigned short ReadBlobLSBShort(Image *image)
3249%
3250% A description of each parameter follows.
3251%
3252% o image: the image.
3253%
3254*/
3255MagickExport unsigned short ReadBlobLSBShort(Image *image)
3256{
3257 register const unsigned char
3258 *p;
3259
3260 register unsigned int
3261 value;
3262
3263 ssize_t
3264 count;
3265
3266 unsigned char
3267 buffer[2];
3268
3269 assert(image != (Image *) NULL);
3270 assert(image->signature == MagickSignature);
3271 *buffer='\0';
3272 p=ReadBlobStream(image,2,buffer,&count);
3273 if (count != 2)
3274 return((unsigned short) 0U);
3275 value=(unsigned int) (*p++);
3276 value|=((unsigned int) ((*p++)) << 8);
3277 return((unsigned short) (value & 0xffff));
3278}
3279
3280/*
3281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3282% %
3283% %
3284% %
3285+ R e a d B l o b M S B L o n g %
3286% %
3287% %
3288% %
3289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3290%
cristybb503372010-05-27 20:51:26 +00003291% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003292% most-significant byte first order.
3293%
3294% The format of the ReadBlobMSBLong method is:
3295%
3296% unsigned int ReadBlobMSBLong(Image *image)
3297%
3298% A description of each parameter follows.
3299%
3300% o image: the image.
3301%
3302*/
3303MagickExport unsigned int ReadBlobMSBLong(Image *image)
3304{
3305 register const unsigned char
3306 *p;
3307
3308 register unsigned int
3309 value;
3310
3311 ssize_t
3312 count;
3313
3314 unsigned char
3315 buffer[4];
3316
3317 assert(image != (Image *) NULL);
3318 assert(image->signature == MagickSignature);
3319 *buffer='\0';
3320 p=ReadBlobStream(image,4,buffer,&count);
3321 if (count != 4)
3322 return(0UL);
3323 value=((unsigned int) (*p++) << 24);
3324 value|=((unsigned int) (*p++) << 16);
3325 value|=((unsigned int) (*p++) << 8);
3326 value|=(unsigned int) (*p++);
3327 return(value);
3328}
3329
3330/*
3331%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3332% %
3333% %
3334% %
cristy2d3d87f2010-03-01 00:23:08 +00003335+ R e a d B l o b M S B L o n g L o n g %
3336% %
3337% %
3338% %
3339%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3340%
cristybb503372010-05-27 20:51:26 +00003341% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003342% most-significant byte first order.
3343%
3344% The format of the ReadBlobMSBLongLong method is:
3345%
3346% unsigned int ReadBlobMSBLongLong(Image *image)
3347%
3348% A description of each parameter follows.
3349%
3350% o image: the image.
3351%
3352*/
3353MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3354{
3355 register const unsigned char
3356 *p;
3357
3358 register MagickSizeType
3359 value;
3360
3361 ssize_t
3362 count;
3363
3364 unsigned char
cristy0286d852010-10-12 18:38:07 +00003365 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003366
3367 assert(image != (Image *) NULL);
3368 assert(image->signature == MagickSignature);
3369 *buffer='\0';
3370 p=ReadBlobStream(image,8,buffer,&count);
3371 if (count != 8)
3372 return(MagickULLConstant(0));
3373 value=((MagickSizeType) (*p++)) << 56;
3374 value|=((MagickSizeType) (*p++)) << 48;
3375 value|=((MagickSizeType) (*p++)) << 40;
3376 value|=((MagickSizeType) (*p++)) << 32;
3377 value|=((MagickSizeType) (*p++)) << 24;
3378 value|=((MagickSizeType) (*p++)) << 16;
3379 value|=((MagickSizeType) (*p++)) << 8;
3380 value|=((MagickSizeType) (*p++));
3381 return(value & MagickULLConstant(0xffffffffffffffff));
3382}
3383
3384/*
3385%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3386% %
3387% %
3388% %
cristy3ed852e2009-09-05 21:47:34 +00003389+ R e a d B l o b M S B S h o r t %
3390% %
3391% %
3392% %
3393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3394%
3395% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3396% most-significant byte first order.
3397%
3398% The format of the ReadBlobMSBShort method is:
3399%
3400% unsigned short ReadBlobMSBShort(Image *image)
3401%
3402% A description of each parameter follows.
3403%
3404% o image: the image.
3405%
3406*/
3407MagickExport unsigned short ReadBlobMSBShort(Image *image)
3408{
3409 register const unsigned char
3410 *p;
3411
3412 register unsigned int
3413 value;
3414
3415 ssize_t
3416 count;
3417
3418 unsigned char
3419 buffer[2];
3420
3421 assert(image != (Image *) NULL);
3422 assert(image->signature == MagickSignature);
3423 *buffer='\0';
3424 p=ReadBlobStream(image,2,buffer,&count);
3425 if (count != 2)
3426 return((unsigned short) 0U);
3427 value=(unsigned int) ((*p++) << 8);
3428 value|=(unsigned int) (*p++);
3429 return((unsigned short) (value & 0xffff));
3430}
3431
3432/*
3433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3434% %
3435% %
3436% %
3437+ R e a d B l o b S t r i n g %
3438% %
3439% %
3440% %
3441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3442%
3443% ReadBlobString() reads characters from a blob or file until a newline
3444% character is read or an end-of-file condition is encountered.
3445%
3446% The format of the ReadBlobString method is:
3447%
3448% char *ReadBlobString(Image *image,char *string)
3449%
3450% A description of each parameter follows:
3451%
3452% o image: the image.
3453%
3454% o string: the address of a character buffer.
3455%
3456*/
3457MagickExport char *ReadBlobString(Image *image,char *string)
3458{
3459 register const unsigned char
3460 *p;
3461
cristybb503372010-05-27 20:51:26 +00003462 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003463 i;
3464
3465 ssize_t
3466 count;
3467
3468 unsigned char
3469 buffer[1];
3470
3471 assert(image != (Image *) NULL);
3472 assert(image->signature == MagickSignature);
3473 for (i=0; i < (MaxTextExtent-1L); i++)
3474 {
3475 p=ReadBlobStream(image,1,buffer,&count);
3476 if (count != 1)
3477 {
3478 if (i == 0)
3479 return((char *) NULL);
3480 break;
3481 }
3482 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003483 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003484 break;
3485 }
cristy2b5db102010-06-09 01:07:28 +00003486 if (string[i] == '\r')
3487 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003488 string[i]='\0';
3489 return(string);
3490}
3491
3492/*
3493%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3494% %
3495% %
3496% %
3497+ R e f e r e n c e B l o b %
3498% %
3499% %
3500% %
3501%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3502%
3503% ReferenceBlob() increments the reference count associated with the pixel
3504% blob returning a pointer to the blob.
3505%
3506% The format of the ReferenceBlob method is:
3507%
3508% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3509%
3510% A description of each parameter follows:
3511%
3512% o blob_info: the blob_info.
3513%
3514*/
3515MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3516{
3517 assert(blob != (BlobInfo *) NULL);
3518 assert(blob->signature == MagickSignature);
3519 if (blob->debug != MagickFalse)
3520 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003521 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003522 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003523 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003524 return(blob);
3525}
3526
3527/*
3528%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3529% %
3530% %
3531% %
3532+ S e e k B l o b %
3533% %
3534% %
3535% %
3536%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3537%
3538% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3539% and returns the resulting offset.
3540%
3541% The format of the SeekBlob method is:
3542%
3543% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3544% const int whence)
3545%
3546% A description of each parameter follows:
3547%
3548% o image: the image.
3549%
3550% o offset: Specifies an integer representing the offset in bytes.
3551%
3552% o whence: Specifies an integer representing how the offset is
3553% treated relative to the beginning of the blob as follows:
3554%
3555% SEEK_SET Set position equal to offset bytes.
3556% SEEK_CUR Set position to current location plus offset.
3557% SEEK_END Set position to EOF plus offset.
3558%
3559*/
3560MagickExport MagickOffsetType SeekBlob(Image *image,
3561 const MagickOffsetType offset,const int whence)
3562{
3563 assert(image != (Image *) NULL);
3564 assert(image->signature == MagickSignature);
3565 if (image->debug != MagickFalse)
3566 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3567 assert(image->blob != (BlobInfo *) NULL);
3568 assert(image->blob->type != UndefinedStream);
3569 switch (image->blob->type)
3570 {
3571 case UndefinedStream:
3572 break;
cristybc20d112012-07-29 20:27:00 +00003573 case StandardStream:
3574 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003575 case FileStream:
3576 {
cristye7b28372012-06-17 13:59:06 +00003577 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003578 return(-1);
3579 image->blob->offset=TellBlob(image);
3580 break;
3581 }
cristy3ed852e2009-09-05 21:47:34 +00003582 case PipeStream:
3583 case ZipStream:
3584 {
3585#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003586 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003587 return(-1);
3588#endif
3589 image->blob->offset=TellBlob(image);
3590 break;
3591 }
3592 case BZipStream:
3593 return(-1);
3594 case FifoStream:
3595 return(-1);
3596 case BlobStream:
3597 {
3598 switch (whence)
3599 {
3600 case SEEK_SET:
3601 default:
3602 {
3603 if (offset < 0)
3604 return(-1);
3605 image->blob->offset=offset;
3606 break;
3607 }
3608 case SEEK_CUR:
3609 {
3610 if ((image->blob->offset+offset) < 0)
3611 return(-1);
3612 image->blob->offset+=offset;
3613 break;
3614 }
3615 case SEEK_END:
3616 {
3617 if (((MagickOffsetType) image->blob->length+offset) < 0)
3618 return(-1);
3619 image->blob->offset=image->blob->length+offset;
3620 break;
3621 }
3622 }
3623 if (image->blob->offset <= (MagickOffsetType)
3624 ((off_t) image->blob->length))
3625 image->blob->eof=MagickFalse;
3626 else
3627 if (image->blob->mapped != MagickFalse)
3628 return(-1);
3629 else
3630 {
3631 image->blob->extent=(size_t) (image->blob->offset+
3632 image->blob->quantum);
3633 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3634 image->blob->data,image->blob->extent+1,
3635 sizeof(*image->blob->data));
3636 (void) SyncBlob(image);
3637 if (image->blob->data == (unsigned char *) NULL)
3638 {
3639 (void) DetachBlob(image->blob);
3640 return(-1);
3641 }
3642 }
3643 break;
3644 }
3645 }
3646 return(image->blob->offset);
3647}
3648
3649/*
3650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3651% %
3652% %
3653% %
3654+ S e t B l o b E x e m p t %
3655% %
3656% %
3657% %
3658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3659%
3660% SetBlobExempt() sets the blob exempt status.
3661%
3662% The format of the SetBlobExempt method is:
3663%
3664% MagickBooleanType SetBlobExempt(const Image *image,
3665% const MagickBooleanType exempt)
3666%
3667% A description of each parameter follows:
3668%
3669% o image: the image.
3670%
3671% o exempt: Set to true if this blob is exempt from being closed.
3672%
3673*/
cristy7832dc22011-09-05 01:21:53 +00003674MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003675{
3676 assert(image != (const Image *) NULL);
3677 assert(image->signature == MagickSignature);
3678 if (image->debug != MagickFalse)
3679 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3680 image->blob->exempt=exempt;
3681}
3682
3683/*
3684%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3685% %
3686% %
3687% %
3688+ S e t B l o b E x t e n t %
3689% %
3690% %
3691% %
3692%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3693%
3694% SetBlobExtent() ensures enough space is allocated for the blob. If the
3695% method is successful, subsequent writes to bytes in the specified range are
3696% guaranteed not to fail.
3697%
3698% The format of the SetBlobExtent method is:
3699%
3700% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3701%
3702% A description of each parameter follows:
3703%
3704% o image: the image.
3705%
3706% o extent: the blob maximum extent.
3707%
3708*/
cristy7832dc22011-09-05 01:21:53 +00003709MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003710 const MagickSizeType extent)
3711{
3712 assert(image != (Image *) NULL);
3713 assert(image->signature == MagickSignature);
3714 if (image->debug != MagickFalse)
3715 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3716 assert(image->blob != (BlobInfo *) NULL);
3717 assert(image->blob->type != UndefinedStream);
3718 switch (image->blob->type)
3719 {
3720 case UndefinedStream:
3721 break;
cristybc20d112012-07-29 20:27:00 +00003722 case StandardStream:
3723 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003724 case FileStream:
3725 {
cristy38e35f42012-12-18 21:12:17 +00003726 MagickOffsetType
3727 offset;
3728
3729 ssize_t
3730 count;
3731
cristy3ed852e2009-09-05 21:47:34 +00003732 if (extent != (MagickSizeType) ((off_t) extent))
3733 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003734 offset=SeekBlob(image,0,SEEK_END);
3735 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003736 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003737 if ((MagickSizeType) offset >= extent)
3738 break;
3739 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003740 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3741 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003742#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3743 if (image->blob->synchronize != MagickFalse)
3744 {
3745 int
3746 status;
3747
3748 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3749 extent-offset);
3750 if (status != 0)
3751 return(MagickFalse);
3752 }
3753#endif
cristy38e35f42012-12-18 21:12:17 +00003754 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003755 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003756 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003757 break;
3758 }
cristy3ed852e2009-09-05 21:47:34 +00003759 case PipeStream:
3760 case ZipStream:
3761 return(MagickFalse);
3762 case BZipStream:
3763 return(MagickFalse);
3764 case FifoStream:
3765 return(MagickFalse);
3766 case BlobStream:
3767 {
cristy38e35f42012-12-18 21:12:17 +00003768 if (extent != (MagickSizeType) ((size_t) extent))
3769 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003770 if (image->blob->mapped != MagickFalse)
3771 {
cristy38e35f42012-12-18 21:12:17 +00003772 MagickOffsetType
3773 offset;
3774
3775 ssize_t
3776 count;
3777
cristy3ed852e2009-09-05 21:47:34 +00003778 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003779 if (extent != (MagickSizeType) ((off_t) extent))
3780 return(MagickFalse);
3781 offset=SeekBlob(image,0,SEEK_END);
3782 if (offset < 0)
3783 return(MagickFalse);
3784 if ((MagickSizeType) offset >= extent)
3785 break;
3786 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003787 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003788 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003789#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3790 if (image->blob->synchronize != MagickFalse)
3791 {
3792 int
3793 status;
3794
3795 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3796 extent-offset);
3797 if (status != 0)
3798 return(MagickFalse);
3799 }
3800#endif
cristy38e35f42012-12-18 21:12:17 +00003801 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003802 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003803 return(MagickFalse);
cristy95888612012-04-04 21:56:52 +00003804 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003805 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003806 image->blob->extent=(size_t) extent;
3807 image->blob->length=(size_t) extent;
3808 (void) SyncBlob(image);
3809 break;
cristy3ed852e2009-09-05 21:47:34 +00003810 }
cristy3ed852e2009-09-05 21:47:34 +00003811 image->blob->extent=(size_t) extent;
3812 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3813 image->blob->extent+1,sizeof(*image->blob->data));
3814 (void) SyncBlob(image);
3815 if (image->blob->data == (unsigned char *) NULL)
3816 {
3817 (void) DetachBlob(image->blob);
3818 return(MagickFalse);
3819 }
3820 break;
3821 }
3822 }
3823 return(MagickTrue);
3824}
3825
3826/*
3827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3828% %
3829% %
3830% %
3831+ S y n c B l o b %
3832% %
3833% %
3834% %
3835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3836%
3837% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3838% attributes if it is an blob.
3839%
3840% The format of the SyncBlob method is:
3841%
3842% int SyncBlob(Image *image)
3843%
3844% A description of each parameter follows:
3845%
3846% o image: the image.
3847%
3848*/
3849static int SyncBlob(Image *image)
3850{
3851 int
3852 status;
3853
3854 assert(image != (Image *) NULL);
3855 assert(image->signature == MagickSignature);
3856 if (image->debug != MagickFalse)
3857 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3858 assert(image->blob != (BlobInfo *) NULL);
3859 assert(image->blob->type != UndefinedStream);
3860 status=0;
3861 switch (image->blob->type)
3862 {
3863 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003864 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003865 break;
3866 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003867 case PipeStream:
3868 {
cristye7b28372012-06-17 13:59:06 +00003869 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003870 break;
3871 }
3872 case ZipStream:
3873 {
3874#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003875 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003876#endif
3877 break;
3878 }
3879 case BZipStream:
3880 {
3881#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003882 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003883#endif
3884 break;
3885 }
3886 case FifoStream:
3887 break;
3888 case BlobStream:
3889 {
3890#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3891 if (image->blob->mapped != MagickFalse)
3892 status=msync(image->blob->data,image->blob->length,MS_SYNC);
3893#endif
3894 break;
3895 }
3896 }
3897 return(status);
3898}
3899
3900/*
3901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3902% %
3903% %
3904% %
3905+ T e l l B l o b %
3906% %
3907% %
3908% %
3909%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3910%
3911% TellBlob() obtains the current value of the blob or file position.
3912%
3913% The format of the TellBlob method is:
3914%
3915% MagickOffsetType TellBlob(const Image *image)
3916%
3917% A description of each parameter follows:
3918%
3919% o image: the image.
3920%
3921*/
3922MagickExport MagickOffsetType TellBlob(const Image *image)
3923{
3924 MagickOffsetType
3925 offset;
3926
3927 assert(image != (Image *) NULL);
3928 assert(image->signature == MagickSignature);
3929 if (image->debug != MagickFalse)
3930 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3931 assert(image->blob != (BlobInfo *) NULL);
3932 assert(image->blob->type != UndefinedStream);
3933 offset=(-1);
3934 switch (image->blob->type)
3935 {
3936 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003937 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003938 break;
3939 case FileStream:
3940 {
cristye7b28372012-06-17 13:59:06 +00003941 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003942 break;
3943 }
cristy3ed852e2009-09-05 21:47:34 +00003944 case PipeStream:
3945 break;
3946 case ZipStream:
3947 {
3948#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003949 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003950#endif
3951 break;
3952 }
3953 case BZipStream:
3954 break;
3955 case FifoStream:
3956 break;
3957 case BlobStream:
3958 {
3959 offset=image->blob->offset;
3960 break;
3961 }
3962 }
3963 return(offset);
3964}
3965
3966/*
3967%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3968% %
3969% %
3970% %
3971+ U n m a p B l o b %
3972% %
3973% %
3974% %
3975%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3976%
3977% UnmapBlob() deallocates the binary large object previously allocated with
3978% the MapBlob method.
3979%
3980% The format of the UnmapBlob method is:
3981%
3982% MagickBooleanType UnmapBlob(void *map,const size_t length)
3983%
3984% A description of each parameter follows:
3985%
3986% o map: the address of the binary large object.
3987%
3988% o length: the length of the binary large object.
3989%
3990*/
3991MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3992{
3993#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3994 int
3995 status;
3996
3997 status=munmap(map,length);
3998 return(status == -1 ? MagickFalse : MagickTrue);
3999#else
4000 (void) map;
4001 (void) length;
4002 return(MagickFalse);
4003#endif
4004}
4005
4006/*
4007%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4008% %
4009% %
4010% %
4011+ W r i t e B l o b %
4012% %
4013% %
4014% %
4015%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4016%
4017% WriteBlob() writes data to a blob or image file. It returns the number of
4018% bytes written.
4019%
4020% The format of the WriteBlob method is:
4021%
4022% ssize_t WriteBlob(Image *image,const size_t length,
4023% const unsigned char *data)
4024%
4025% A description of each parameter follows:
4026%
4027% o image: the image.
4028%
4029% o length: Specifies an integer representing the number of bytes to
4030% write to the file.
4031%
4032% o data: The address of the data to write to the blob or file.
4033%
4034*/
4035MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4036 const unsigned char *data)
4037{
4038 int
4039 c;
4040
4041 register const unsigned char
4042 *p;
4043
4044 ssize_t
4045 count;
4046
4047 assert(image != (Image *) NULL);
4048 assert(image->signature == MagickSignature);
4049 assert(data != (const unsigned char *) NULL);
4050 assert(image->blob != (BlobInfo *) NULL);
4051 assert(image->blob->type != UndefinedStream);
4052 if (length == 0)
4053 return(0);
4054 count=0;
4055 p=data;
4056 switch (image->blob->type)
4057 {
4058 case UndefinedStream:
4059 break;
cristy3ed852e2009-09-05 21:47:34 +00004060 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004061 {
cristy5f3d2752013-01-05 18:53:38 +00004062 count=write(fileno(image->blob->file_info.file),data,length);
cristybc20d112012-07-29 20:27:00 +00004063 break;
4064 }
4065 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004066 case PipeStream:
4067 {
4068 switch (length)
4069 {
4070 default:
4071 {
4072 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004073 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004074 break;
4075 }
4076 case 2:
4077 {
cristye7b28372012-06-17 13:59:06 +00004078 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004079 if (c == EOF)
4080 break;
4081 count++;
4082 }
4083 case 1:
4084 {
cristye7b28372012-06-17 13:59:06 +00004085 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004086 if (c == EOF)
4087 break;
4088 count++;
4089 }
4090 case 0:
4091 break;
4092 }
4093 break;
4094 }
4095 case ZipStream:
4096 {
4097#if defined(MAGICKCORE_ZLIB_DELEGATE)
4098 switch (length)
4099 {
4100 default:
4101 {
cristye7b28372012-06-17 13:59:06 +00004102 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004103 (unsigned int) length);
4104 break;
4105 }
4106 case 2:
4107 {
cristye7b28372012-06-17 13:59:06 +00004108 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004109 if (c == EOF)
4110 break;
4111 count++;
4112 }
4113 case 1:
4114 {
cristye7b28372012-06-17 13:59:06 +00004115 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004116 if (c == EOF)
4117 break;
4118 count++;
4119 }
4120 case 0:
4121 break;
4122 }
4123#endif
4124 break;
4125 }
4126 case BZipStream:
4127 {
4128#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004129 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004130 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004131#endif
4132 break;
4133 }
4134 case FifoStream:
4135 {
4136 count=(ssize_t) image->blob->stream(image,data,length);
4137 break;
4138 }
4139 case BlobStream:
4140 {
4141 register unsigned char
4142 *q;
4143
4144 if ((image->blob->offset+(MagickOffsetType) length) >=
4145 (MagickOffsetType) image->blob->extent)
4146 {
4147 if (image->blob->mapped != MagickFalse)
4148 return(0);
4149 image->blob->quantum<<=1;
4150 image->blob->extent+=length+image->blob->quantum;
4151 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4152 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4153 (void) SyncBlob(image);
4154 if (image->blob->data == (unsigned char *) NULL)
4155 {
4156 (void) DetachBlob(image->blob);
4157 return(0);
4158 }
4159 }
4160 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004161 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004162 image->blob->offset+=length;
4163 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4164 image->blob->length=(size_t) image->blob->offset;
4165 count=(ssize_t) length;
4166 }
4167 }
4168 return(count);
4169}
4170
4171/*
4172%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4173% %
4174% %
4175% %
4176+ W r i t e B l o b B y t e %
4177% %
4178% %
4179% %
4180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4181%
4182% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4183% written (either 0 or 1);
4184%
4185% The format of the WriteBlobByte method is:
4186%
4187% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4188%
4189% A description of each parameter follows.
4190%
4191% o image: the image.
4192%
4193% o value: Specifies the value to write.
4194%
4195*/
4196MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4197{
4198 assert(image != (Image *) NULL);
4199 assert(image->signature == MagickSignature);
4200 return(WriteBlobStream(image,1,&value));
4201}
4202
4203/*
4204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4205% %
4206% %
4207% %
4208+ W r i t e B l o b F l o a t %
4209% %
4210% %
4211% %
4212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4213%
4214% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4215% specified by the endian member of the image structure.
4216%
4217% The format of the WriteBlobFloat method is:
4218%
4219% ssize_t WriteBlobFloat(Image *image,const float value)
4220%
4221% A description of each parameter follows.
4222%
4223% o image: the image.
4224%
4225% o value: Specifies the value to write.
4226%
4227*/
4228MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4229{
4230 union
4231 {
4232 unsigned int
4233 unsigned_value;
4234
4235 float
4236 float_value;
4237 } quantum;
4238
4239 quantum.unsigned_value=0U;
4240 quantum.float_value=value;
4241 return(WriteBlobLong(image,quantum.unsigned_value));
4242}
4243
4244/*
4245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4246% %
4247% %
4248% %
4249+ W r i t e B l o b L o n g %
4250% %
4251% %
4252% %
4253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4254%
cristybb503372010-05-27 20:51:26 +00004255% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004256% specified by the endian member of the image structure.
4257%
4258% The format of the WriteBlobLong method is:
4259%
4260% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4261%
4262% A description of each parameter follows.
4263%
4264% o image: the image.
4265%
4266% o value: Specifies the value to write.
4267%
4268*/
4269MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4270{
4271 unsigned char
4272 buffer[4];
4273
4274 assert(image != (Image *) NULL);
4275 assert(image->signature == MagickSignature);
4276 if (image->endian == LSBEndian)
4277 {
4278 buffer[0]=(unsigned char) value;
4279 buffer[1]=(unsigned char) (value >> 8);
4280 buffer[2]=(unsigned char) (value >> 16);
4281 buffer[3]=(unsigned char) (value >> 24);
4282 return(WriteBlobStream(image,4,buffer));
4283 }
4284 buffer[0]=(unsigned char) (value >> 24);
4285 buffer[1]=(unsigned char) (value >> 16);
4286 buffer[2]=(unsigned char) (value >> 8);
4287 buffer[3]=(unsigned char) value;
4288 return(WriteBlobStream(image,4,buffer));
4289}
4290
4291/*
4292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4293% %
4294% %
4295% %
4296+ W r i t e B l o b S h o r t %
4297% %
4298% %
4299% %
4300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4301%
4302% WriteBlobShort() writes a short value as a 16-bit quantity in the
4303% byte-order specified by the endian member of the image structure.
4304%
4305% The format of the WriteBlobShort method is:
4306%
4307% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4308%
4309% A description of each parameter follows.
4310%
4311% o image: the image.
4312%
4313% o value: Specifies the value to write.
4314%
4315*/
4316MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4317{
4318 unsigned char
4319 buffer[2];
4320
4321 assert(image != (Image *) NULL);
4322 assert(image->signature == MagickSignature);
4323 if (image->endian == LSBEndian)
4324 {
4325 buffer[0]=(unsigned char) value;
4326 buffer[1]=(unsigned char) (value >> 8);
4327 return(WriteBlobStream(image,2,buffer));
4328 }
4329 buffer[0]=(unsigned char) (value >> 8);
4330 buffer[1]=(unsigned char) value;
4331 return(WriteBlobStream(image,2,buffer));
4332}
4333
4334/*
4335%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4336% %
4337% %
4338% %
4339+ W r i t e B l o b L S B L o n g %
4340% %
4341% %
4342% %
4343%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4344%
cristybb503372010-05-27 20:51:26 +00004345% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004346% least-significant byte first order.
4347%
4348% The format of the WriteBlobLSBLong method is:
4349%
4350% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4351%
4352% A description of each parameter follows.
4353%
4354% o image: the image.
4355%
4356% o value: Specifies the value to write.
4357%
4358*/
4359MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4360{
4361 unsigned char
4362 buffer[4];
4363
4364 assert(image != (Image *) NULL);
4365 assert(image->signature == MagickSignature);
4366 buffer[0]=(unsigned char) value;
4367 buffer[1]=(unsigned char) (value >> 8);
4368 buffer[2]=(unsigned char) (value >> 16);
4369 buffer[3]=(unsigned char) (value >> 24);
4370 return(WriteBlobStream(image,4,buffer));
4371}
4372
4373/*
4374%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4375% %
4376% %
4377% %
4378+ W r i t e B l o b L S B S h o r t %
4379% %
4380% %
4381% %
4382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4383%
cristybb503372010-05-27 20:51:26 +00004384% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004385% least-significant byte first order.
4386%
4387% The format of the WriteBlobLSBShort method is:
4388%
4389% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4390%
4391% A description of each parameter follows.
4392%
4393% o image: the image.
4394%
4395% o value: Specifies the value to write.
4396%
4397*/
4398MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4399{
4400 unsigned char
4401 buffer[2];
4402
4403 assert(image != (Image *) NULL);
4404 assert(image->signature == MagickSignature);
4405 buffer[0]=(unsigned char) value;
4406 buffer[1]=(unsigned char) (value >> 8);
4407 return(WriteBlobStream(image,2,buffer));
4408}
4409
4410/*
4411%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4412% %
4413% %
4414% %
4415+ W r i t e B l o b M S B L o n g %
4416% %
4417% %
4418% %
4419%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4420%
cristybb503372010-05-27 20:51:26 +00004421% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004422% most-significant byte first order.
4423%
4424% The format of the WriteBlobMSBLong method is:
4425%
4426% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4427%
4428% A description of each parameter follows.
4429%
4430% o value: Specifies the value to write.
4431%
4432% o image: the image.
4433%
4434*/
4435MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4436{
4437 unsigned char
4438 buffer[4];
4439
4440 assert(image != (Image *) NULL);
4441 assert(image->signature == MagickSignature);
4442 buffer[0]=(unsigned char) (value >> 24);
4443 buffer[1]=(unsigned char) (value >> 16);
4444 buffer[2]=(unsigned char) (value >> 8);
4445 buffer[3]=(unsigned char) value;
4446 return(WriteBlobStream(image,4,buffer));
4447}
4448
4449/*
4450%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4451% %
4452% %
4453% %
cristy2ca49922010-03-06 02:54:01 +00004454+ W r i t e B l o b M S B L o n g L o n g %
4455% %
4456% %
4457% %
4458%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4459%
4460% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4461% most-significant byte first order.
4462%
4463% The format of the WriteBlobMSBLongLong method is:
4464%
4465% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4466%
4467% A description of each parameter follows.
4468%
4469% o value: Specifies the value to write.
4470%
4471% o image: the image.
4472%
4473*/
4474MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4475 const MagickSizeType value)
4476{
4477 unsigned char
4478 buffer[8];
4479
4480 assert(image != (Image *) NULL);
4481 assert(image->signature == MagickSignature);
4482 buffer[0]=(unsigned char) (value >> 56);
4483 buffer[1]=(unsigned char) (value >> 48);
4484 buffer[2]=(unsigned char) (value >> 40);
4485 buffer[3]=(unsigned char) (value >> 32);
4486 buffer[4]=(unsigned char) (value >> 24);
4487 buffer[5]=(unsigned char) (value >> 16);
4488 buffer[6]=(unsigned char) (value >> 8);
4489 buffer[7]=(unsigned char) value;
4490 return(WriteBlobStream(image,8,buffer));
4491}
4492
4493/*
4494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4495% %
4496% %
4497% %
cristy3ed852e2009-09-05 21:47:34 +00004498+ W r i t e B l o b M S B S h o r t %
4499% %
4500% %
4501% %
4502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4503%
cristybb503372010-05-27 20:51:26 +00004504% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004505% most-significant byte first order.
4506%
4507% The format of the WriteBlobMSBShort method is:
4508%
4509% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4510%
4511% A description of each parameter follows.
4512%
4513% o value: Specifies the value to write.
4514%
4515% o file: Specifies the file to write the data to.
4516%
4517*/
4518MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4519{
4520 unsigned char
4521 buffer[2];
4522
4523 assert(image != (Image *) NULL);
4524 assert(image->signature == MagickSignature);
4525 buffer[0]=(unsigned char) (value >> 8);
4526 buffer[1]=(unsigned char) value;
4527 return(WriteBlobStream(image,2,buffer));
4528}
4529
4530/*
4531%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4532% %
4533% %
4534% %
4535+ W r i t e B l o b S t r i n g %
4536% %
4537% %
4538% %
4539%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4540%
4541% WriteBlobString() write a string to a blob. It returns the number of
4542% characters written.
4543%
4544% The format of the WriteBlobString method is:
4545%
4546% ssize_t WriteBlobString(Image *image,const char *string)
4547%
4548% A description of each parameter follows.
4549%
4550% o image: the image.
4551%
4552% o string: Specifies the string to write.
4553%
4554*/
4555MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4556{
4557 assert(image != (Image *) NULL);
4558 assert(image->signature == MagickSignature);
4559 assert(string != (const char *) NULL);
4560 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4561}