blob: 8e973ba4592efdaf4c1b7367b7406d8e4d95cb8f [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 {
cristy8faec1e2013-04-25 19:41:22 +00002786 register ssize_t
2787 i;
2788
2789 for (i=0; i < (ssize_t) length; i+=count)
2790 {
2791 count=read(fileno(image->blob->file_info.file),q+i,(size_t)
2792 MagickMin(length-i,(MagickSizeType) SSIZE_MAX));
2793 if (count <= 0)
2794 {
2795 count=0;
2796 if (errno != EINTR)
2797 break;
2798 }
2799 }
2800 count=i;
cristybc20d112012-07-29 20:27:00 +00002801 break;
2802 }
2803 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002804 case PipeStream:
2805 {
2806 switch (length)
2807 {
2808 default:
2809 {
cristye7b28372012-06-17 13:59:06 +00002810 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002811 break;
2812 }
2813 case 2:
2814 {
cristye7b28372012-06-17 13:59:06 +00002815 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002816 if (c == EOF)
2817 break;
2818 *q++=(unsigned char) c;
2819 count++;
2820 }
2821 case 1:
2822 {
cristye7b28372012-06-17 13:59:06 +00002823 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002824 if (c == EOF)
2825 break;
2826 *q++=(unsigned char) c;
2827 count++;
2828 }
2829 case 0:
2830 break;
2831 }
2832 break;
2833 }
2834 case ZipStream:
2835 {
2836#if defined(MAGICKCORE_ZLIB_DELEGATE)
2837 switch (length)
2838 {
2839 default:
2840 {
cristye7b28372012-06-17 13:59:06 +00002841 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002842 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002843 break;
2844 }
2845 case 2:
2846 {
cristye7b28372012-06-17 13:59:06 +00002847 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002848 if (c == EOF)
2849 break;
2850 *q++=(unsigned char) c;
2851 count++;
2852 }
2853 case 1:
2854 {
cristye7b28372012-06-17 13:59:06 +00002855 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002856 if (c == EOF)
2857 break;
2858 *q++=(unsigned char) c;
2859 count++;
2860 }
2861 case 0:
2862 break;
2863 }
2864#endif
2865 break;
2866 }
2867 case BZipStream:
2868 {
2869#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy5f3d2752013-01-05 18:53:38 +00002870 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
cristy3ed852e2009-09-05 21:47:34 +00002871#endif
2872 break;
2873 }
2874 case FifoStream:
2875 break;
2876 case BlobStream:
2877 {
2878 register const unsigned char
2879 *p;
2880
2881 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2882 {
2883 image->blob->eof=MagickTrue;
2884 break;
2885 }
2886 p=image->blob->data+image->blob->offset;
cristye7b28372012-06-17 13:59:06 +00002887 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2888 image->blob->offset));
cristy3ed852e2009-09-05 21:47:34 +00002889 image->blob->offset+=count;
2890 if (count != (ssize_t) length)
2891 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002892 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002893 break;
2894 }
2895 }
2896 return(count);
2897}
2898
2899/*
2900%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2901% %
2902% %
2903% %
2904+ R e a d B l o b B y t e %
2905% %
2906% %
2907% %
2908%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2909%
2910% ReadBlobByte() reads a single byte from the image file and returns it.
2911%
2912% The format of the ReadBlobByte method is:
2913%
2914% int ReadBlobByte(Image *image)
2915%
2916% A description of each parameter follows.
2917%
2918% o image: the image.
2919%
2920*/
2921MagickExport int ReadBlobByte(Image *image)
2922{
2923 register const unsigned char
2924 *p;
2925
2926 ssize_t
2927 count;
2928
2929 unsigned char
2930 buffer[1];
2931
2932 assert(image != (Image *) NULL);
2933 assert(image->signature == MagickSignature);
2934 p=ReadBlobStream(image,1,buffer,&count);
2935 if (count != 1)
2936 return(EOF);
2937 return((int) (*p));
2938}
2939
2940/*
2941%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2942% %
2943% %
2944% %
2945+ R e a d B l o b D o u b l e %
2946% %
2947% %
2948% %
2949%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2950%
2951% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2952% specified by the endian member of the image structure.
2953%
2954% The format of the ReadBlobDouble method is:
2955%
2956% double ReadBlobDouble(Image *image)
2957%
2958% A description of each parameter follows.
2959%
2960% o image: the image.
2961%
2962*/
2963MagickExport double ReadBlobDouble(Image *image)
2964{
2965 union
2966 {
2967 MagickSizeType
2968 unsigned_value;
2969
2970 double
2971 double_value;
2972 } quantum;
2973
2974 quantum.double_value=0.0;
2975 quantum.unsigned_value=ReadBlobLongLong(image);
2976 return(quantum.double_value);
2977}
2978
2979/*
2980%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2981% %
2982% %
2983% %
2984+ R e a d B l o b F l o a t %
2985% %
2986% %
2987% %
2988%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2989%
2990% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2991% specified by the endian member of the image structure.
2992%
2993% The format of the ReadBlobFloat method is:
2994%
2995% float ReadBlobFloat(Image *image)
2996%
2997% A description of each parameter follows.
2998%
2999% o image: the image.
3000%
3001*/
3002MagickExport float ReadBlobFloat(Image *image)
3003{
3004 union
3005 {
3006 unsigned int
3007 unsigned_value;
3008
3009 float
3010 float_value;
3011 } quantum;
3012
3013 quantum.float_value=0.0;
3014 quantum.unsigned_value=ReadBlobLong(image);
3015 return(quantum.float_value);
3016}
3017
3018/*
3019%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3020% %
3021% %
3022% %
3023+ R e a d B l o b L o n g %
3024% %
3025% %
3026% %
3027%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3028%
cristybb503372010-05-27 20:51:26 +00003029% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003030% specified by the endian member of the image structure.
3031%
3032% The format of the ReadBlobLong method is:
3033%
3034% unsigned int ReadBlobLong(Image *image)
3035%
3036% A description of each parameter follows.
3037%
3038% o image: the image.
3039%
3040*/
3041MagickExport unsigned int ReadBlobLong(Image *image)
3042{
3043 register const unsigned char
3044 *p;
3045
3046 ssize_t
3047 count;
3048
3049 unsigned char
3050 buffer[4];
3051
3052 unsigned int
3053 value;
3054
3055 assert(image != (Image *) NULL);
3056 assert(image->signature == MagickSignature);
3057 *buffer='\0';
3058 p=ReadBlobStream(image,4,buffer,&count);
3059 if (count != 4)
3060 return(0UL);
3061 if (image->endian == LSBEndian)
3062 {
3063 value=(unsigned int) (*p++);
3064 value|=((unsigned int) (*p++)) << 8;
3065 value|=((unsigned int) (*p++)) << 16;
3066 value|=((unsigned int) (*p++)) << 24;
3067 return(value);
3068 }
3069 value=((unsigned int) (*p++)) << 24;
3070 value|=((unsigned int) (*p++)) << 16;
3071 value|=((unsigned int) (*p++)) << 8;
3072 value|=((unsigned int) (*p++));
3073 return(value);
3074}
3075
3076/*
3077%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3078% %
3079% %
3080% %
3081+ R e a d B l o b L o n g L o n g %
3082% %
3083% %
3084% %
3085%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3086%
cristy4cb162a2010-05-30 03:04:47 +00003087% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3088% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003089%
cristy4cb162a2010-05-30 03:04:47 +00003090% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003091%
cristy4cb162a2010-05-30 03:04:47 +00003092% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003093%
3094% A description of each parameter follows.
3095%
3096% o image: the image.
3097%
3098*/
3099MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3100{
cristy0286d852010-10-12 18:38:07 +00003101 MagickSizeType
3102 value;
3103
cristy3ed852e2009-09-05 21:47:34 +00003104 register const unsigned char
3105 *p;
3106
3107 ssize_t
3108 count;
3109
3110 unsigned char
3111 buffer[8];
3112
cristy3ed852e2009-09-05 21:47:34 +00003113 assert(image != (Image *) NULL);
3114 assert(image->signature == MagickSignature);
3115 *buffer='\0';
3116 p=ReadBlobStream(image,8,buffer,&count);
3117 if (count != 8)
3118 return(MagickULLConstant(0));
3119 if (image->endian == LSBEndian)
3120 {
3121 value=(MagickSizeType) (*p++);
3122 value|=((MagickSizeType) (*p++)) << 8;
3123 value|=((MagickSizeType) (*p++)) << 16;
3124 value|=((MagickSizeType) (*p++)) << 24;
3125 value|=((MagickSizeType) (*p++)) << 32;
3126 value|=((MagickSizeType) (*p++)) << 40;
3127 value|=((MagickSizeType) (*p++)) << 48;
3128 value|=((MagickSizeType) (*p++)) << 56;
3129 return(value & MagickULLConstant(0xffffffffffffffff));
3130 }
3131 value=((MagickSizeType) (*p++)) << 56;
3132 value|=((MagickSizeType) (*p++)) << 48;
3133 value|=((MagickSizeType) (*p++)) << 40;
3134 value|=((MagickSizeType) (*p++)) << 32;
3135 value|=((MagickSizeType) (*p++)) << 24;
3136 value|=((MagickSizeType) (*p++)) << 16;
3137 value|=((MagickSizeType) (*p++)) << 8;
3138 value|=((MagickSizeType) (*p++));
3139 return(value & MagickULLConstant(0xffffffffffffffff));
3140}
3141
3142/*
3143%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3144% %
3145% %
3146% %
3147+ R e a d B l o b S h o r t %
3148% %
3149% %
3150% %
3151%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3152%
3153% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3154% specified by the endian member of the image structure.
3155%
3156% The format of the ReadBlobShort method is:
3157%
3158% unsigned short ReadBlobShort(Image *image)
3159%
3160% A description of each parameter follows.
3161%
3162% o image: the image.
3163%
3164*/
3165MagickExport unsigned short ReadBlobShort(Image *image)
3166{
3167 register const unsigned char
3168 *p;
3169
3170 register unsigned int
3171 value;
3172
3173 ssize_t
3174 count;
3175
3176 unsigned char
3177 buffer[2];
3178
3179 assert(image != (Image *) NULL);
3180 assert(image->signature == MagickSignature);
3181 *buffer='\0';
3182 p=ReadBlobStream(image,2,buffer,&count);
3183 if (count != 2)
3184 return((unsigned short) 0U);
3185 if (image->endian == LSBEndian)
3186 {
3187 value=(unsigned int) (*p++);
3188 value|=((unsigned int) (*p++)) << 8;
3189 return((unsigned short) (value & 0xffff));
3190 }
3191 value=(unsigned int) ((*p++) << 8);
3192 value|=(unsigned int) (*p++);
3193 return((unsigned short) (value & 0xffff));
3194}
3195
3196/*
3197%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3198% %
3199% %
3200% %
3201+ R e a d B l o b L S B L o n g %
3202% %
3203% %
3204% %
3205%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3206%
cristybb503372010-05-27 20:51:26 +00003207% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003208% least-significant byte first order.
3209%
3210% The format of the ReadBlobLSBLong method is:
3211%
3212% unsigned int ReadBlobLSBLong(Image *image)
3213%
3214% A description of each parameter follows.
3215%
3216% o image: the image.
3217%
3218*/
3219MagickExport unsigned int ReadBlobLSBLong(Image *image)
3220{
3221 register const unsigned char
3222 *p;
3223
3224 register unsigned int
3225 value;
3226
3227 ssize_t
3228 count;
3229
3230 unsigned char
3231 buffer[4];
3232
3233 assert(image != (Image *) NULL);
3234 assert(image->signature == MagickSignature);
3235 *buffer='\0';
3236 p=ReadBlobStream(image,4,buffer,&count);
3237 if (count != 4)
3238 return(0U);
3239 value=(unsigned int) (*p++);
3240 value|=((unsigned int) (*p++)) << 8;
3241 value|=((unsigned int) (*p++)) << 16;
3242 value|=((unsigned int) (*p++)) << 24;
3243 return(value);
3244}
3245
3246/*
3247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3248% %
3249% %
3250% %
3251+ R e a d B l o b L S B S h o r t %
3252% %
3253% %
3254% %
3255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3256%
3257% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3258% least-significant byte first order.
3259%
3260% The format of the ReadBlobLSBShort method is:
3261%
3262% unsigned short ReadBlobLSBShort(Image *image)
3263%
3264% A description of each parameter follows.
3265%
3266% o image: the image.
3267%
3268*/
3269MagickExport unsigned short ReadBlobLSBShort(Image *image)
3270{
3271 register const unsigned char
3272 *p;
3273
3274 register unsigned int
3275 value;
3276
3277 ssize_t
3278 count;
3279
3280 unsigned char
3281 buffer[2];
3282
3283 assert(image != (Image *) NULL);
3284 assert(image->signature == MagickSignature);
3285 *buffer='\0';
3286 p=ReadBlobStream(image,2,buffer,&count);
3287 if (count != 2)
3288 return((unsigned short) 0U);
3289 value=(unsigned int) (*p++);
3290 value|=((unsigned int) ((*p++)) << 8);
3291 return((unsigned short) (value & 0xffff));
3292}
3293
3294/*
3295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3296% %
3297% %
3298% %
3299+ R e a d B l o b M S B L o n g %
3300% %
3301% %
3302% %
3303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3304%
cristybb503372010-05-27 20:51:26 +00003305% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003306% most-significant byte first order.
3307%
3308% The format of the ReadBlobMSBLong method is:
3309%
3310% unsigned int ReadBlobMSBLong(Image *image)
3311%
3312% A description of each parameter follows.
3313%
3314% o image: the image.
3315%
3316*/
3317MagickExport unsigned int ReadBlobMSBLong(Image *image)
3318{
3319 register const unsigned char
3320 *p;
3321
3322 register unsigned int
3323 value;
3324
3325 ssize_t
3326 count;
3327
3328 unsigned char
3329 buffer[4];
3330
3331 assert(image != (Image *) NULL);
3332 assert(image->signature == MagickSignature);
3333 *buffer='\0';
3334 p=ReadBlobStream(image,4,buffer,&count);
3335 if (count != 4)
3336 return(0UL);
3337 value=((unsigned int) (*p++) << 24);
3338 value|=((unsigned int) (*p++) << 16);
3339 value|=((unsigned int) (*p++) << 8);
3340 value|=(unsigned int) (*p++);
3341 return(value);
3342}
3343
3344/*
3345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3346% %
3347% %
3348% %
cristy2d3d87f2010-03-01 00:23:08 +00003349+ R e a d B l o b M S B L o n g L o n g %
3350% %
3351% %
3352% %
3353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3354%
cristybb503372010-05-27 20:51:26 +00003355% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003356% most-significant byte first order.
3357%
3358% The format of the ReadBlobMSBLongLong method is:
3359%
3360% unsigned int ReadBlobMSBLongLong(Image *image)
3361%
3362% A description of each parameter follows.
3363%
3364% o image: the image.
3365%
3366*/
3367MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3368{
3369 register const unsigned char
3370 *p;
3371
3372 register MagickSizeType
3373 value;
3374
3375 ssize_t
3376 count;
3377
3378 unsigned char
cristy0286d852010-10-12 18:38:07 +00003379 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003380
3381 assert(image != (Image *) NULL);
3382 assert(image->signature == MagickSignature);
3383 *buffer='\0';
3384 p=ReadBlobStream(image,8,buffer,&count);
3385 if (count != 8)
3386 return(MagickULLConstant(0));
3387 value=((MagickSizeType) (*p++)) << 56;
3388 value|=((MagickSizeType) (*p++)) << 48;
3389 value|=((MagickSizeType) (*p++)) << 40;
3390 value|=((MagickSizeType) (*p++)) << 32;
3391 value|=((MagickSizeType) (*p++)) << 24;
3392 value|=((MagickSizeType) (*p++)) << 16;
3393 value|=((MagickSizeType) (*p++)) << 8;
3394 value|=((MagickSizeType) (*p++));
3395 return(value & MagickULLConstant(0xffffffffffffffff));
3396}
3397
3398/*
3399%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3400% %
3401% %
3402% %
cristy3ed852e2009-09-05 21:47:34 +00003403+ R e a d B l o b M S B S h o r t %
3404% %
3405% %
3406% %
3407%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3408%
3409% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3410% most-significant byte first order.
3411%
3412% The format of the ReadBlobMSBShort method is:
3413%
3414% unsigned short ReadBlobMSBShort(Image *image)
3415%
3416% A description of each parameter follows.
3417%
3418% o image: the image.
3419%
3420*/
3421MagickExport unsigned short ReadBlobMSBShort(Image *image)
3422{
3423 register const unsigned char
3424 *p;
3425
3426 register unsigned int
3427 value;
3428
3429 ssize_t
3430 count;
3431
3432 unsigned char
3433 buffer[2];
3434
3435 assert(image != (Image *) NULL);
3436 assert(image->signature == MagickSignature);
3437 *buffer='\0';
3438 p=ReadBlobStream(image,2,buffer,&count);
3439 if (count != 2)
3440 return((unsigned short) 0U);
3441 value=(unsigned int) ((*p++) << 8);
3442 value|=(unsigned int) (*p++);
3443 return((unsigned short) (value & 0xffff));
3444}
3445
3446/*
3447%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3448% %
3449% %
3450% %
3451+ R e a d B l o b S t r i n g %
3452% %
3453% %
3454% %
3455%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3456%
3457% ReadBlobString() reads characters from a blob or file until a newline
3458% character is read or an end-of-file condition is encountered.
3459%
3460% The format of the ReadBlobString method is:
3461%
3462% char *ReadBlobString(Image *image,char *string)
3463%
3464% A description of each parameter follows:
3465%
3466% o image: the image.
3467%
3468% o string: the address of a character buffer.
3469%
3470*/
3471MagickExport char *ReadBlobString(Image *image,char *string)
3472{
3473 register const unsigned char
3474 *p;
3475
cristybb503372010-05-27 20:51:26 +00003476 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003477 i;
3478
3479 ssize_t
3480 count;
3481
3482 unsigned char
3483 buffer[1];
3484
3485 assert(image != (Image *) NULL);
3486 assert(image->signature == MagickSignature);
3487 for (i=0; i < (MaxTextExtent-1L); i++)
3488 {
3489 p=ReadBlobStream(image,1,buffer,&count);
3490 if (count != 1)
3491 {
3492 if (i == 0)
3493 return((char *) NULL);
3494 break;
3495 }
3496 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003497 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003498 break;
3499 }
cristy2b5db102010-06-09 01:07:28 +00003500 if (string[i] == '\r')
3501 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003502 string[i]='\0';
3503 return(string);
3504}
3505
3506/*
3507%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3508% %
3509% %
3510% %
3511+ R e f e r e n c e B l o b %
3512% %
3513% %
3514% %
3515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3516%
3517% ReferenceBlob() increments the reference count associated with the pixel
3518% blob returning a pointer to the blob.
3519%
3520% The format of the ReferenceBlob method is:
3521%
3522% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3523%
3524% A description of each parameter follows:
3525%
3526% o blob_info: the blob_info.
3527%
3528*/
3529MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3530{
3531 assert(blob != (BlobInfo *) NULL);
3532 assert(blob->signature == MagickSignature);
3533 if (blob->debug != MagickFalse)
3534 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003535 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003536 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003537 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003538 return(blob);
3539}
3540
3541/*
3542%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3543% %
3544% %
3545% %
3546+ S e e k B l o b %
3547% %
3548% %
3549% %
3550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3551%
3552% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3553% and returns the resulting offset.
3554%
3555% The format of the SeekBlob method is:
3556%
3557% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3558% const int whence)
3559%
3560% A description of each parameter follows:
3561%
3562% o image: the image.
3563%
3564% o offset: Specifies an integer representing the offset in bytes.
3565%
3566% o whence: Specifies an integer representing how the offset is
3567% treated relative to the beginning of the blob as follows:
3568%
3569% SEEK_SET Set position equal to offset bytes.
3570% SEEK_CUR Set position to current location plus offset.
3571% SEEK_END Set position to EOF plus offset.
3572%
3573*/
3574MagickExport MagickOffsetType SeekBlob(Image *image,
3575 const MagickOffsetType offset,const int whence)
3576{
3577 assert(image != (Image *) NULL);
3578 assert(image->signature == MagickSignature);
3579 if (image->debug != MagickFalse)
3580 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3581 assert(image->blob != (BlobInfo *) NULL);
3582 assert(image->blob->type != UndefinedStream);
3583 switch (image->blob->type)
3584 {
3585 case UndefinedStream:
3586 break;
cristybc20d112012-07-29 20:27:00 +00003587 case StandardStream:
3588 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003589 case FileStream:
3590 {
cristye7b28372012-06-17 13:59:06 +00003591 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003592 return(-1);
3593 image->blob->offset=TellBlob(image);
3594 break;
3595 }
cristy3ed852e2009-09-05 21:47:34 +00003596 case PipeStream:
3597 case ZipStream:
3598 {
3599#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003600 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003601 return(-1);
3602#endif
3603 image->blob->offset=TellBlob(image);
3604 break;
3605 }
3606 case BZipStream:
3607 return(-1);
3608 case FifoStream:
3609 return(-1);
3610 case BlobStream:
3611 {
3612 switch (whence)
3613 {
3614 case SEEK_SET:
3615 default:
3616 {
3617 if (offset < 0)
3618 return(-1);
3619 image->blob->offset=offset;
3620 break;
3621 }
3622 case SEEK_CUR:
3623 {
3624 if ((image->blob->offset+offset) < 0)
3625 return(-1);
3626 image->blob->offset+=offset;
3627 break;
3628 }
3629 case SEEK_END:
3630 {
3631 if (((MagickOffsetType) image->blob->length+offset) < 0)
3632 return(-1);
3633 image->blob->offset=image->blob->length+offset;
3634 break;
3635 }
3636 }
3637 if (image->blob->offset <= (MagickOffsetType)
3638 ((off_t) image->blob->length))
3639 image->blob->eof=MagickFalse;
3640 else
3641 if (image->blob->mapped != MagickFalse)
3642 return(-1);
3643 else
3644 {
3645 image->blob->extent=(size_t) (image->blob->offset+
3646 image->blob->quantum);
3647 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3648 image->blob->data,image->blob->extent+1,
3649 sizeof(*image->blob->data));
3650 (void) SyncBlob(image);
3651 if (image->blob->data == (unsigned char *) NULL)
3652 {
3653 (void) DetachBlob(image->blob);
3654 return(-1);
3655 }
3656 }
3657 break;
3658 }
3659 }
3660 return(image->blob->offset);
3661}
3662
3663/*
3664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3665% %
3666% %
3667% %
3668+ S e t B l o b E x e m p t %
3669% %
3670% %
3671% %
3672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3673%
3674% SetBlobExempt() sets the blob exempt status.
3675%
3676% The format of the SetBlobExempt method is:
3677%
3678% MagickBooleanType SetBlobExempt(const Image *image,
3679% const MagickBooleanType exempt)
3680%
3681% A description of each parameter follows:
3682%
3683% o image: the image.
3684%
3685% o exempt: Set to true if this blob is exempt from being closed.
3686%
3687*/
cristy7832dc22011-09-05 01:21:53 +00003688MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003689{
3690 assert(image != (const Image *) NULL);
3691 assert(image->signature == MagickSignature);
3692 if (image->debug != MagickFalse)
3693 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3694 image->blob->exempt=exempt;
3695}
3696
3697/*
3698%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3699% %
3700% %
3701% %
3702+ S e t B l o b E x t e n t %
3703% %
3704% %
3705% %
3706%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3707%
3708% SetBlobExtent() ensures enough space is allocated for the blob. If the
3709% method is successful, subsequent writes to bytes in the specified range are
3710% guaranteed not to fail.
3711%
3712% The format of the SetBlobExtent method is:
3713%
3714% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3715%
3716% A description of each parameter follows:
3717%
3718% o image: the image.
3719%
3720% o extent: the blob maximum extent.
3721%
3722*/
cristy7832dc22011-09-05 01:21:53 +00003723MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003724 const MagickSizeType extent)
3725{
3726 assert(image != (Image *) NULL);
3727 assert(image->signature == MagickSignature);
3728 if (image->debug != MagickFalse)
3729 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3730 assert(image->blob != (BlobInfo *) NULL);
3731 assert(image->blob->type != UndefinedStream);
3732 switch (image->blob->type)
3733 {
3734 case UndefinedStream:
3735 break;
cristybc20d112012-07-29 20:27:00 +00003736 case StandardStream:
3737 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003738 case FileStream:
3739 {
cristy38e35f42012-12-18 21:12:17 +00003740 MagickOffsetType
3741 offset;
3742
3743 ssize_t
3744 count;
3745
cristy3ed852e2009-09-05 21:47:34 +00003746 if (extent != (MagickSizeType) ((off_t) extent))
3747 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003748 offset=SeekBlob(image,0,SEEK_END);
3749 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003750 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003751 if ((MagickSizeType) offset >= extent)
3752 break;
3753 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003754 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3755 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003756#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3757 if (image->blob->synchronize != MagickFalse)
3758 {
3759 int
3760 status;
3761
3762 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3763 extent-offset);
3764 if (status != 0)
3765 return(MagickFalse);
3766 }
3767#endif
cristy38e35f42012-12-18 21:12:17 +00003768 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003769 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003770 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003771 break;
3772 }
cristy3ed852e2009-09-05 21:47:34 +00003773 case PipeStream:
3774 case ZipStream:
3775 return(MagickFalse);
3776 case BZipStream:
3777 return(MagickFalse);
3778 case FifoStream:
3779 return(MagickFalse);
3780 case BlobStream:
3781 {
cristy38e35f42012-12-18 21:12:17 +00003782 if (extent != (MagickSizeType) ((size_t) extent))
3783 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003784 if (image->blob->mapped != MagickFalse)
3785 {
cristy38e35f42012-12-18 21:12:17 +00003786 MagickOffsetType
3787 offset;
3788
3789 ssize_t
3790 count;
3791
cristy3ed852e2009-09-05 21:47:34 +00003792 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003793 if (extent != (MagickSizeType) ((off_t) extent))
3794 return(MagickFalse);
3795 offset=SeekBlob(image,0,SEEK_END);
3796 if (offset < 0)
3797 return(MagickFalse);
3798 if ((MagickSizeType) offset >= extent)
3799 break;
3800 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003801 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003802 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003803#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3804 if (image->blob->synchronize != MagickFalse)
3805 {
3806 int
3807 status;
3808
3809 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3810 extent-offset);
3811 if (status != 0)
3812 return(MagickFalse);
3813 }
3814#endif
cristy38e35f42012-12-18 21:12:17 +00003815 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003816 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003817 return(MagickFalse);
cristy95888612012-04-04 21:56:52 +00003818 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003819 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003820 image->blob->extent=(size_t) extent;
3821 image->blob->length=(size_t) extent;
3822 (void) SyncBlob(image);
3823 break;
cristy3ed852e2009-09-05 21:47:34 +00003824 }
cristy3ed852e2009-09-05 21:47:34 +00003825 image->blob->extent=(size_t) extent;
3826 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3827 image->blob->extent+1,sizeof(*image->blob->data));
3828 (void) SyncBlob(image);
3829 if (image->blob->data == (unsigned char *) NULL)
3830 {
3831 (void) DetachBlob(image->blob);
3832 return(MagickFalse);
3833 }
3834 break;
3835 }
3836 }
3837 return(MagickTrue);
3838}
3839
3840/*
3841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3842% %
3843% %
3844% %
3845+ S y n c B l o b %
3846% %
3847% %
3848% %
3849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3850%
3851% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3852% attributes if it is an blob.
3853%
3854% The format of the SyncBlob method is:
3855%
3856% int SyncBlob(Image *image)
3857%
3858% A description of each parameter follows:
3859%
3860% o image: the image.
3861%
3862*/
3863static int SyncBlob(Image *image)
3864{
3865 int
3866 status;
3867
3868 assert(image != (Image *) NULL);
3869 assert(image->signature == MagickSignature);
3870 if (image->debug != MagickFalse)
3871 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3872 assert(image->blob != (BlobInfo *) NULL);
3873 assert(image->blob->type != UndefinedStream);
3874 status=0;
3875 switch (image->blob->type)
3876 {
3877 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003878 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003879 break;
3880 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003881 case PipeStream:
3882 {
cristye7b28372012-06-17 13:59:06 +00003883 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003884 break;
3885 }
3886 case ZipStream:
3887 {
3888#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003889 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003890#endif
3891 break;
3892 }
3893 case BZipStream:
3894 {
3895#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003896 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003897#endif
3898 break;
3899 }
3900 case FifoStream:
3901 break;
3902 case BlobStream:
3903 {
3904#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3905 if (image->blob->mapped != MagickFalse)
3906 status=msync(image->blob->data,image->blob->length,MS_SYNC);
3907#endif
3908 break;
3909 }
3910 }
3911 return(status);
3912}
3913
3914/*
3915%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3916% %
3917% %
3918% %
3919+ T e l l B l o b %
3920% %
3921% %
3922% %
3923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3924%
3925% TellBlob() obtains the current value of the blob or file position.
3926%
3927% The format of the TellBlob method is:
3928%
3929% MagickOffsetType TellBlob(const Image *image)
3930%
3931% A description of each parameter follows:
3932%
3933% o image: the image.
3934%
3935*/
3936MagickExport MagickOffsetType TellBlob(const Image *image)
3937{
3938 MagickOffsetType
3939 offset;
3940
3941 assert(image != (Image *) NULL);
3942 assert(image->signature == MagickSignature);
3943 if (image->debug != MagickFalse)
3944 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3945 assert(image->blob != (BlobInfo *) NULL);
3946 assert(image->blob->type != UndefinedStream);
3947 offset=(-1);
3948 switch (image->blob->type)
3949 {
3950 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003951 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003952 break;
3953 case FileStream:
3954 {
cristye7b28372012-06-17 13:59:06 +00003955 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003956 break;
3957 }
cristy3ed852e2009-09-05 21:47:34 +00003958 case PipeStream:
3959 break;
3960 case ZipStream:
3961 {
3962#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003963 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003964#endif
3965 break;
3966 }
3967 case BZipStream:
3968 break;
3969 case FifoStream:
3970 break;
3971 case BlobStream:
3972 {
3973 offset=image->blob->offset;
3974 break;
3975 }
3976 }
3977 return(offset);
3978}
3979
3980/*
3981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3982% %
3983% %
3984% %
3985+ U n m a p B l o b %
3986% %
3987% %
3988% %
3989%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3990%
3991% UnmapBlob() deallocates the binary large object previously allocated with
3992% the MapBlob method.
3993%
3994% The format of the UnmapBlob method is:
3995%
3996% MagickBooleanType UnmapBlob(void *map,const size_t length)
3997%
3998% A description of each parameter follows:
3999%
4000% o map: the address of the binary large object.
4001%
4002% o length: the length of the binary large object.
4003%
4004*/
4005MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4006{
4007#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
4008 int
4009 status;
4010
4011 status=munmap(map,length);
4012 return(status == -1 ? MagickFalse : MagickTrue);
4013#else
4014 (void) map;
4015 (void) length;
4016 return(MagickFalse);
4017#endif
4018}
4019
4020/*
4021%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4022% %
4023% %
4024% %
4025+ W r i t e B l o b %
4026% %
4027% %
4028% %
4029%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4030%
4031% WriteBlob() writes data to a blob or image file. It returns the number of
4032% bytes written.
4033%
4034% The format of the WriteBlob method is:
4035%
4036% ssize_t WriteBlob(Image *image,const size_t length,
4037% const unsigned char *data)
4038%
4039% A description of each parameter follows:
4040%
4041% o image: the image.
4042%
4043% o length: Specifies an integer representing the number of bytes to
4044% write to the file.
4045%
4046% o data: The address of the data to write to the blob or file.
4047%
4048*/
4049MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4050 const unsigned char *data)
4051{
4052 int
4053 c;
4054
4055 register const unsigned char
4056 *p;
4057
4058 ssize_t
4059 count;
4060
4061 assert(image != (Image *) NULL);
4062 assert(image->signature == MagickSignature);
4063 assert(data != (const unsigned char *) NULL);
4064 assert(image->blob != (BlobInfo *) NULL);
4065 assert(image->blob->type != UndefinedStream);
4066 if (length == 0)
4067 return(0);
4068 count=0;
4069 p=data;
4070 switch (image->blob->type)
4071 {
4072 case UndefinedStream:
4073 break;
cristy3ed852e2009-09-05 21:47:34 +00004074 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004075 {
cristy5f3d2752013-01-05 18:53:38 +00004076 count=write(fileno(image->blob->file_info.file),data,length);
cristybc20d112012-07-29 20:27:00 +00004077 break;
4078 }
4079 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004080 case PipeStream:
4081 {
4082 switch (length)
4083 {
4084 default:
4085 {
4086 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004087 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004088 break;
4089 }
4090 case 2:
4091 {
cristye7b28372012-06-17 13:59:06 +00004092 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004093 if (c == EOF)
4094 break;
4095 count++;
4096 }
4097 case 1:
4098 {
cristye7b28372012-06-17 13:59:06 +00004099 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004100 if (c == EOF)
4101 break;
4102 count++;
4103 }
4104 case 0:
4105 break;
4106 }
4107 break;
4108 }
4109 case ZipStream:
4110 {
4111#if defined(MAGICKCORE_ZLIB_DELEGATE)
4112 switch (length)
4113 {
4114 default:
4115 {
cristye7b28372012-06-17 13:59:06 +00004116 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004117 (unsigned int) length);
4118 break;
4119 }
4120 case 2:
4121 {
cristye7b28372012-06-17 13:59:06 +00004122 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004123 if (c == EOF)
4124 break;
4125 count++;
4126 }
4127 case 1:
4128 {
cristye7b28372012-06-17 13:59:06 +00004129 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004130 if (c == EOF)
4131 break;
4132 count++;
4133 }
4134 case 0:
4135 break;
4136 }
4137#endif
4138 break;
4139 }
4140 case BZipStream:
4141 {
4142#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004143 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004144 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004145#endif
4146 break;
4147 }
4148 case FifoStream:
4149 {
4150 count=(ssize_t) image->blob->stream(image,data,length);
4151 break;
4152 }
4153 case BlobStream:
4154 {
4155 register unsigned char
4156 *q;
4157
4158 if ((image->blob->offset+(MagickOffsetType) length) >=
4159 (MagickOffsetType) image->blob->extent)
4160 {
4161 if (image->blob->mapped != MagickFalse)
4162 return(0);
4163 image->blob->quantum<<=1;
4164 image->blob->extent+=length+image->blob->quantum;
4165 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4166 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4167 (void) SyncBlob(image);
4168 if (image->blob->data == (unsigned char *) NULL)
4169 {
4170 (void) DetachBlob(image->blob);
4171 return(0);
4172 }
4173 }
4174 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004175 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004176 image->blob->offset+=length;
4177 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4178 image->blob->length=(size_t) image->blob->offset;
4179 count=(ssize_t) length;
4180 }
4181 }
4182 return(count);
4183}
4184
4185/*
4186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4187% %
4188% %
4189% %
4190+ W r i t e B l o b B y t e %
4191% %
4192% %
4193% %
4194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4195%
4196% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4197% written (either 0 or 1);
4198%
4199% The format of the WriteBlobByte method is:
4200%
4201% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4202%
4203% A description of each parameter follows.
4204%
4205% o image: the image.
4206%
4207% o value: Specifies the value to write.
4208%
4209*/
4210MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4211{
4212 assert(image != (Image *) NULL);
4213 assert(image->signature == MagickSignature);
4214 return(WriteBlobStream(image,1,&value));
4215}
4216
4217/*
4218%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4219% %
4220% %
4221% %
4222+ W r i t e B l o b F l o a t %
4223% %
4224% %
4225% %
4226%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4227%
4228% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4229% specified by the endian member of the image structure.
4230%
4231% The format of the WriteBlobFloat method is:
4232%
4233% ssize_t WriteBlobFloat(Image *image,const float value)
4234%
4235% A description of each parameter follows.
4236%
4237% o image: the image.
4238%
4239% o value: Specifies the value to write.
4240%
4241*/
4242MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4243{
4244 union
4245 {
4246 unsigned int
4247 unsigned_value;
4248
4249 float
4250 float_value;
4251 } quantum;
4252
4253 quantum.unsigned_value=0U;
4254 quantum.float_value=value;
4255 return(WriteBlobLong(image,quantum.unsigned_value));
4256}
4257
4258/*
4259%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4260% %
4261% %
4262% %
4263+ W r i t e B l o b L o n g %
4264% %
4265% %
4266% %
4267%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4268%
cristybb503372010-05-27 20:51:26 +00004269% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004270% specified by the endian member of the image structure.
4271%
4272% The format of the WriteBlobLong method is:
4273%
4274% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4275%
4276% A description of each parameter follows.
4277%
4278% o image: the image.
4279%
4280% o value: Specifies the value to write.
4281%
4282*/
4283MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4284{
4285 unsigned char
4286 buffer[4];
4287
4288 assert(image != (Image *) NULL);
4289 assert(image->signature == MagickSignature);
4290 if (image->endian == LSBEndian)
4291 {
4292 buffer[0]=(unsigned char) value;
4293 buffer[1]=(unsigned char) (value >> 8);
4294 buffer[2]=(unsigned char) (value >> 16);
4295 buffer[3]=(unsigned char) (value >> 24);
4296 return(WriteBlobStream(image,4,buffer));
4297 }
4298 buffer[0]=(unsigned char) (value >> 24);
4299 buffer[1]=(unsigned char) (value >> 16);
4300 buffer[2]=(unsigned char) (value >> 8);
4301 buffer[3]=(unsigned char) value;
4302 return(WriteBlobStream(image,4,buffer));
4303}
4304
4305/*
4306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4307% %
4308% %
4309% %
4310+ W r i t e B l o b S h o r t %
4311% %
4312% %
4313% %
4314%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4315%
4316% WriteBlobShort() writes a short value as a 16-bit quantity in the
4317% byte-order specified by the endian member of the image structure.
4318%
4319% The format of the WriteBlobShort method is:
4320%
4321% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4322%
4323% A description of each parameter follows.
4324%
4325% o image: the image.
4326%
4327% o value: Specifies the value to write.
4328%
4329*/
4330MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4331{
4332 unsigned char
4333 buffer[2];
4334
4335 assert(image != (Image *) NULL);
4336 assert(image->signature == MagickSignature);
4337 if (image->endian == LSBEndian)
4338 {
4339 buffer[0]=(unsigned char) value;
4340 buffer[1]=(unsigned char) (value >> 8);
4341 return(WriteBlobStream(image,2,buffer));
4342 }
4343 buffer[0]=(unsigned char) (value >> 8);
4344 buffer[1]=(unsigned char) value;
4345 return(WriteBlobStream(image,2,buffer));
4346}
4347
4348/*
4349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4350% %
4351% %
4352% %
4353+ W r i t e B l o b L S B L o n g %
4354% %
4355% %
4356% %
4357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4358%
cristybb503372010-05-27 20:51:26 +00004359% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004360% least-significant byte first order.
4361%
4362% The format of the WriteBlobLSBLong method is:
4363%
4364% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4365%
4366% A description of each parameter follows.
4367%
4368% o image: the image.
4369%
4370% o value: Specifies the value to write.
4371%
4372*/
4373MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4374{
4375 unsigned char
4376 buffer[4];
4377
4378 assert(image != (Image *) NULL);
4379 assert(image->signature == MagickSignature);
4380 buffer[0]=(unsigned char) value;
4381 buffer[1]=(unsigned char) (value >> 8);
4382 buffer[2]=(unsigned char) (value >> 16);
4383 buffer[3]=(unsigned char) (value >> 24);
4384 return(WriteBlobStream(image,4,buffer));
4385}
4386
4387/*
4388%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4389% %
4390% %
4391% %
4392+ W r i t e B l o b L S B S h o r t %
4393% %
4394% %
4395% %
4396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4397%
cristybb503372010-05-27 20:51:26 +00004398% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004399% least-significant byte first order.
4400%
4401% The format of the WriteBlobLSBShort method is:
4402%
4403% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4404%
4405% A description of each parameter follows.
4406%
4407% o image: the image.
4408%
4409% o value: Specifies the value to write.
4410%
4411*/
4412MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4413{
4414 unsigned char
4415 buffer[2];
4416
4417 assert(image != (Image *) NULL);
4418 assert(image->signature == MagickSignature);
4419 buffer[0]=(unsigned char) value;
4420 buffer[1]=(unsigned char) (value >> 8);
4421 return(WriteBlobStream(image,2,buffer));
4422}
4423
4424/*
4425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4426% %
4427% %
4428% %
4429+ W r i t e B l o b M S B L o n g %
4430% %
4431% %
4432% %
4433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4434%
cristybb503372010-05-27 20:51:26 +00004435% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004436% most-significant byte first order.
4437%
4438% The format of the WriteBlobMSBLong method is:
4439%
4440% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4441%
4442% A description of each parameter follows.
4443%
4444% o value: Specifies the value to write.
4445%
4446% o image: the image.
4447%
4448*/
4449MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4450{
4451 unsigned char
4452 buffer[4];
4453
4454 assert(image != (Image *) NULL);
4455 assert(image->signature == MagickSignature);
4456 buffer[0]=(unsigned char) (value >> 24);
4457 buffer[1]=(unsigned char) (value >> 16);
4458 buffer[2]=(unsigned char) (value >> 8);
4459 buffer[3]=(unsigned char) value;
4460 return(WriteBlobStream(image,4,buffer));
4461}
4462
4463/*
4464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4465% %
4466% %
4467% %
cristy2ca49922010-03-06 02:54:01 +00004468+ W r i t e B l o b M S B L o n g L o n g %
4469% %
4470% %
4471% %
4472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4473%
4474% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4475% most-significant byte first order.
4476%
4477% The format of the WriteBlobMSBLongLong method is:
4478%
4479% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4480%
4481% A description of each parameter follows.
4482%
4483% o value: Specifies the value to write.
4484%
4485% o image: the image.
4486%
4487*/
4488MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4489 const MagickSizeType value)
4490{
4491 unsigned char
4492 buffer[8];
4493
4494 assert(image != (Image *) NULL);
4495 assert(image->signature == MagickSignature);
4496 buffer[0]=(unsigned char) (value >> 56);
4497 buffer[1]=(unsigned char) (value >> 48);
4498 buffer[2]=(unsigned char) (value >> 40);
4499 buffer[3]=(unsigned char) (value >> 32);
4500 buffer[4]=(unsigned char) (value >> 24);
4501 buffer[5]=(unsigned char) (value >> 16);
4502 buffer[6]=(unsigned char) (value >> 8);
4503 buffer[7]=(unsigned char) value;
4504 return(WriteBlobStream(image,8,buffer));
4505}
4506
4507/*
4508%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4509% %
4510% %
4511% %
cristy3ed852e2009-09-05 21:47:34 +00004512+ W r i t e B l o b M S B S h o r t %
4513% %
4514% %
4515% %
4516%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4517%
cristybb503372010-05-27 20:51:26 +00004518% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004519% most-significant byte first order.
4520%
4521% The format of the WriteBlobMSBShort method is:
4522%
4523% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4524%
4525% A description of each parameter follows.
4526%
4527% o value: Specifies the value to write.
4528%
4529% o file: Specifies the file to write the data to.
4530%
4531*/
4532MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4533{
4534 unsigned char
4535 buffer[2];
4536
4537 assert(image != (Image *) NULL);
4538 assert(image->signature == MagickSignature);
4539 buffer[0]=(unsigned char) (value >> 8);
4540 buffer[1]=(unsigned char) value;
4541 return(WriteBlobStream(image,2,buffer));
4542}
4543
4544/*
4545%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4546% %
4547% %
4548% %
4549+ W r i t e B l o b S t r i n g %
4550% %
4551% %
4552% %
4553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4554%
4555% WriteBlobString() write a string to a blob. It returns the number of
4556% characters written.
4557%
4558% The format of the WriteBlobString method is:
4559%
4560% ssize_t WriteBlobString(Image *image,const char *string)
4561%
4562% A description of each parameter follows.
4563%
4564% o image: the image.
4565%
4566% o string: Specifies the string to write.
4567%
4568*/
4569MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4570{
4571 assert(image != (Image *) NULL);
4572 assert(image->signature == MagickSignature);
4573 assert(string != (const char *) NULL);
4574 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4575}