blob: 13f668afb362295eb37debcaf4671f97a71b63f1 [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;
2157#else
2158 return((unsigned char *) NULL);
2159#endif
2160 switch (mode)
2161 {
2162 case ReadMode:
2163 default:
2164 {
2165 protection=PROT_READ;
2166 flags|=MAP_PRIVATE;
2167 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2168 (off_t) offset);
2169 break;
2170 }
2171 case WriteMode:
2172 {
2173 protection=PROT_WRITE;
2174 flags|=MAP_SHARED;
2175 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2176 (off_t) offset);
cristy2a9e7cb2010-03-05 02:15:05 +00002177#if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
2178 (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
2179 POSIX_MADV_WILLNEED);
2180#endif
cristy3ed852e2009-09-05 21:47:34 +00002181 break;
2182 }
2183 case IOMode:
2184 {
2185 protection=PROT_READ | PROT_WRITE;
2186 flags|=MAP_SHARED;
2187 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2188 (off_t) offset);
2189 break;
2190 }
2191 }
2192 if (map == (unsigned char *) MAP_FAILED)
2193 return((unsigned char *) NULL);
2194 return(map);
2195#else
2196 (void) file;
2197 (void) mode;
2198 (void) offset;
2199 (void) length;
2200 return((unsigned char *) NULL);
2201#endif
2202}
2203
2204/*
2205%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2206% %
2207% %
2208% %
2209+ M S B O r d e r L o n g %
2210% %
2211% %
2212% %
2213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2214%
2215% MSBOrderLong() converts a least-significant byte first buffer of integers to
2216% most-significant byte first.
2217%
2218% The format of the MSBOrderLong method is:
2219%
2220% void MSBOrderLong(unsigned char *buffer,const size_t length)
2221%
2222% A description of each parameter follows.
2223%
2224% o buffer: Specifies a pointer to a buffer of integers.
2225%
2226% o length: Specifies the length of the buffer.
2227%
2228*/
2229MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2230{
2231 int
2232 c;
2233
2234 register unsigned char
2235 *p,
2236 *q;
2237
2238 assert(buffer != (unsigned char *) NULL);
2239 q=buffer+length;
2240 while (buffer < q)
2241 {
2242 p=buffer+3;
2243 c=(int) (*p);
2244 *p=(*buffer);
2245 *buffer++=(unsigned char) c;
2246 p=buffer+1;
2247 c=(int) (*p);
2248 *p=(*buffer);
2249 *buffer++=(unsigned char) c;
2250 buffer+=2;
2251 }
2252}
2253
2254/*
2255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2256% %
2257% %
2258% %
2259+ M S B O r d e r S h o r t %
2260% %
2261% %
2262% %
2263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2264%
2265% MSBOrderShort() converts a least-significant byte first buffer of integers
2266% to most-significant byte first.
2267%
2268% The format of the MSBOrderShort method is:
2269%
2270% void MSBOrderShort(unsigned char *p,const size_t length)
2271%
2272% A description of each parameter follows.
2273%
2274% o p: Specifies a pointer to a buffer of integers.
2275%
2276% o length: Specifies the length of the buffer.
2277%
2278*/
2279MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2280{
2281 int
2282 c;
2283
2284 register unsigned char
2285 *q;
2286
2287 assert(p != (unsigned char *) NULL);
2288 q=p+length;
2289 while (p < q)
2290 {
2291 c=(int) (*p);
2292 *p=(*(p+1));
2293 p++;
2294 *p++=(unsigned char) c;
2295 }
2296}
2297
2298/*
2299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2300% %
2301% %
2302% %
2303+ O p e n B l o b %
2304% %
2305% %
2306% %
2307%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2308%
2309% OpenBlob() opens a file associated with the image. A file name of '-' sets
2310% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2311% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2312% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2313% from a system command.
2314%
2315% The format of the OpenBlob method is:
2316%
2317% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2318% const BlobMode mode,ExceptionInfo *exception)
2319%
2320% A description of each parameter follows:
2321%
2322% o image_info: the image info.
2323%
2324% o image: the image.
2325%
2326% o mode: the mode for opening the file.
2327%
2328*/
2329MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2330 Image *image,const BlobMode mode,ExceptionInfo *exception)
2331{
2332 char
cristybf6a7092010-06-11 02:12:15 +00002333 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002334 filename[MaxTextExtent];
2335
2336 const char
2337 *type;
2338
2339 MagickBooleanType
2340 status;
2341
2342 PolicyRights
2343 rights;
2344
2345 assert(image_info != (ImageInfo *) NULL);
2346 assert(image_info->signature == MagickSignature);
2347 if (image_info->debug != MagickFalse)
2348 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2349 image_info->filename);
2350 assert(image != (Image *) NULL);
2351 assert(image->signature == MagickSignature);
2352 if (image_info->blob != (void *) NULL)
2353 {
2354 if (image_info->stream != (StreamHandler) NULL)
2355 image->blob->stream=(StreamHandler) image_info->stream;
2356 AttachBlob(image->blob,image_info->blob,image_info->length);
2357 return(MagickTrue);
2358 }
2359 (void) DetachBlob(image->blob);
2360 switch (mode)
2361 {
2362 default: type="r"; break;
2363 case ReadBlobMode: type="r"; break;
2364 case ReadBinaryBlobMode: type="rb"; break;
2365 case WriteBlobMode: type="w"; break;
2366 case WriteBinaryBlobMode: type="w+b"; break;
2367 case AppendBlobMode: type="a"; break;
2368 case AppendBinaryBlobMode: type="a+b"; break;
2369 }
2370 if (*type != 'r')
2371 image->blob->synchronize=image_info->synchronize;
2372 if (image_info->stream != (StreamHandler) NULL)
2373 {
2374 image->blob->stream=(StreamHandler) image_info->stream;
2375 if (*type == 'w')
2376 {
2377 image->blob->type=FifoStream;
2378 return(MagickTrue);
2379 }
2380 }
2381 /*
2382 Open image file.
2383 */
2384 *filename='\0';
2385 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2386 rights=ReadPolicyRights;
2387 if (*type == 'w')
2388 rights=WritePolicyRights;
2389 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2390 {
cristya9197f62010-01-12 02:23:34 +00002391 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002392 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
cristyefe601c2013-01-05 17:51:12 +00002393 "NotAuthorized","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00002394 return(MagickFalse);
2395 }
2396 if ((LocaleCompare(filename,"-") == 0) ||
2397 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2398 {
cristye7b28372012-06-17 13:59:06 +00002399 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002400#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002401 if (strchr(type,'b') != (char *) NULL)
cristye7b28372012-06-17 13:59:06 +00002402 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002403#endif
2404 image->blob->type=StandardStream;
2405 image->blob->exempt=MagickTrue;
2406 return(MagickTrue);
2407 }
cristybc20d112012-07-29 20:27:00 +00002408 if (LocaleNCompare(filename,"fd:",3) == 0)
2409 {
2410 char
2411 mode[MaxTextExtent];
2412
2413 *mode=(*type);
2414 mode[1]='\0';
2415 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2416#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2417 if (strchr(type,'b') != (char *) NULL)
2418 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2419#endif
2420 image->blob->type=StandardStream;
2421 image->blob->exempt=MagickTrue;
2422 return(MagickTrue);
2423 }
cristy3ed852e2009-09-05 21:47:34 +00002424#if defined(MAGICKCORE_HAVE_POPEN)
2425 if (*filename == '|')
2426 {
2427 char
2428 mode[MaxTextExtent];
2429
2430 /*
2431 Pipe image to or from a system command.
2432 */
2433#if defined(SIGPIPE)
2434 if (*type == 'w')
2435 (void) signal(SIGPIPE,SIG_IGN);
2436#endif
2437 *mode=(*type);
2438 mode[1]='\0';
cristye7b28372012-06-17 13:59:06 +00002439 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2440 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002441 {
2442 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2443 return(MagickFalse);
2444 }
2445 image->blob->type=PipeStream;
2446 image->blob->exempt=MagickTrue;
2447 return(MagickTrue);
2448 }
2449#endif
2450 status=GetPathAttributes(filename,&image->blob->properties);
2451#if defined(S_ISFIFO)
2452 if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2453 {
cristye7b28372012-06-17 13:59:06 +00002454 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2455 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002456 {
2457 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2458 return(MagickFalse);
2459 }
2460 image->blob->type=FileStream;
2461 image->blob->exempt=MagickTrue;
2462 return(MagickTrue);
2463 }
2464#endif
cristybf6a7092010-06-11 02:12:15 +00002465 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002466 if (*type == 'w')
2467 {
cristye8939e72010-02-03 17:05:25 +00002468 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002469 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002470 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002471 {
2472 /*
2473 Form filename for multi-part images.
2474 */
2475 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002476 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002477 if ((LocaleCompare(filename,image->filename) == 0) &&
2478 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2479 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002480 {
cristybf7fa0d2010-02-04 00:51:10 +00002481 char
cristybf7fa0d2010-02-04 00:51:10 +00002482 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002483
cristybf7fa0d2010-02-04 00:51:10 +00002484 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002485 if (*extension == '\0')
cristyb51dff52011-05-19 16:55:47 +00002486 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002487 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002488 else
cristyb51dff52011-05-19 16:55:47 +00002489 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002490 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002491 }
2492 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002493#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002494 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002495#endif
cristye8939e72010-02-03 17:05:25 +00002496 }
cristy3ed852e2009-09-05 21:47:34 +00002497 }
cristybf6a7092010-06-11 02:12:15 +00002498 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002499 {
cristye7b28372012-06-17 13:59:06 +00002500 image->blob->file_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002501 image->blob->type=FileStream;
2502 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002503 }
2504 else
cristybf6a7092010-06-11 02:12:15 +00002505 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002506 {
cristye7b28372012-06-17 13:59:06 +00002507 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2508 if (image->blob->file_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002509 {
2510 size_t
cristybf6a7092010-06-11 02:12:15 +00002511 count;
cristy3ed852e2009-09-05 21:47:34 +00002512
cristybf6a7092010-06-11 02:12:15 +00002513 unsigned char
2514 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002515
cristybf6a7092010-06-11 02:12:15 +00002516 image->blob->type=FileStream;
2517#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002518 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2519 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002520#endif
2521 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristye7b28372012-06-17 13:59:06 +00002522 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
cristyae958042013-01-05 15:48:19 +00002523 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
cristy79fe6932012-12-25 00:31:30 +00002524 (void) fflush(image->blob->file_info.file);
cristybf6a7092010-06-11 02:12:15 +00002525 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2526 " read %.20g magic header bytes",(double) count);
2527#if defined(MAGICKCORE_ZLIB_DELEGATE)
2528 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2529 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002530 {
cristye7b28372012-06-17 13:59:06 +00002531 (void) fclose(image->blob->file_info.file);
2532 image->blob->file_info.gzfile=gzopen(filename,type);
2533 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002534 image->blob->type=ZipStream;
2535 }
2536#endif
2537#if defined(MAGICKCORE_BZLIB_DELEGATE)
2538 if (strncmp((char *) magick,"BZh",3) == 0)
2539 {
cristye7b28372012-06-17 13:59:06 +00002540 (void) fclose(image->blob->file_info.file);
2541 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2542 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002543 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002544 }
cristybf6a7092010-06-11 02:12:15 +00002545#endif
cristyc6c589d2010-07-06 01:34:57 +00002546 if (image->blob->type == FileStream)
2547 {
2548 const MagickInfo
2549 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002550
cristyc6c589d2010-07-06 01:34:57 +00002551 ExceptionInfo
2552 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002553
cristyc6c589d2010-07-06 01:34:57 +00002554 struct stat
2555 *properties;
cristybf6a7092010-06-11 02:12:15 +00002556
cristyc6c589d2010-07-06 01:34:57 +00002557 sans_exception=AcquireExceptionInfo();
2558 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2559 sans_exception=DestroyExceptionInfo(sans_exception);
2560 properties=(&image->blob->properties);
2561 if ((magick_info != (const MagickInfo *) NULL) &&
2562 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2563 (properties->st_size <= MagickMaxBufferExtent))
2564 {
2565 size_t
2566 length;
cristybf6a7092010-06-11 02:12:15 +00002567
cristyc6c589d2010-07-06 01:34:57 +00002568 void
2569 *blob;
cristybf6a7092010-06-11 02:12:15 +00002570
cristyc6c589d2010-07-06 01:34:57 +00002571 length=(size_t) properties->st_size;
cristye7b28372012-06-17 13:59:06 +00002572 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,
cristy95888612012-04-04 21:56:52 +00002573 0,length);
cristyc6c589d2010-07-06 01:34:57 +00002574 if (blob != (void *) NULL)
2575 {
2576 /*
2577 Format supports blobs-- use memory-mapped I/O.
2578 */
2579 if (image_info->file != (FILE *) NULL)
2580 image->blob->exempt=MagickFalse;
2581 else
2582 {
cristye7b28372012-06-17 13:59:06 +00002583 (void) fclose(image->blob->file_info.file);
2584 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002585 }
2586 AttachBlob(image->blob,blob,length);
2587 image->blob->mapped=MagickTrue;
2588 }
2589 }
2590 }
cristy3ed852e2009-09-05 21:47:34 +00002591 }
cristybf6a7092010-06-11 02:12:15 +00002592 }
2593 else
2594#if defined(MAGICKCORE_ZLIB_DELEGATE)
2595 if ((LocaleCompare(extension,"Z") == 0) ||
2596 (LocaleCompare(extension,"gz") == 0) ||
2597 (LocaleCompare(extension,"wmz") == 0) ||
2598 (LocaleCompare(extension,"svgz") == 0))
2599 {
2600 if (mode == WriteBinaryBlobMode)
2601 type="wb";
cristye7b28372012-06-17 13:59:06 +00002602 image->blob->file_info.gzfile=gzopen(filename,type);
2603 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002604 image->blob->type=ZipStream;
2605 }
2606 else
2607#endif
2608#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002609 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002610 {
cristye7b28372012-06-17 13:59:06 +00002611 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2612 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002613 image->blob->type=BZipStream;
2614 }
2615 else
2616#endif
2617 {
cristye7b28372012-06-17 13:59:06 +00002618 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2619 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002620 {
2621 image->blob->type=FileStream;
2622#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002623 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2624 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002625#endif
2626 }
2627 }
cristy3ed852e2009-09-05 21:47:34 +00002628 image->blob->status=MagickFalse;
2629 if (image->blob->type != UndefinedStream)
2630 image->blob->size=GetBlobSize(image);
2631 else
2632 {
2633 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2634 return(MagickFalse);
2635 }
2636 return(MagickTrue);
2637}
2638
2639/*
2640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2641% %
2642% %
2643% %
2644+ P i n g B l o b %
2645% %
2646% %
2647% %
2648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2649%
2650% PingBlob() returns all the attributes of an image or image sequence except
2651% for the pixels. It is much faster and consumes far less memory than
2652% BlobToImage(). On failure, a NULL image is returned and exception
2653% describes the reason for the failure.
2654%
2655% The format of the PingBlob method is:
2656%
2657% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2658% const size_t length,ExceptionInfo *exception)
2659%
2660% A description of each parameter follows:
2661%
2662% o image_info: the image info.
2663%
2664% o blob: the address of a character stream in one of the image formats
2665% understood by ImageMagick.
2666%
2667% o length: This size_t integer reflects the length in bytes of the blob.
2668%
2669% o exception: return any errors or warnings in this structure.
2670%
2671*/
2672
2673#if defined(__cplusplus) || defined(c_plusplus)
2674extern "C" {
2675#endif
2676
2677static size_t PingStream(const Image *magick_unused(image),
2678 const void *magick_unused(pixels),const size_t columns)
2679{
2680 return(columns);
2681}
2682
2683#if defined(__cplusplus) || defined(c_plusplus)
2684}
2685#endif
2686
2687MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2688 const size_t length,ExceptionInfo *exception)
2689{
2690 Image
2691 *image;
2692
2693 ImageInfo
2694 *ping_info;
2695
2696 assert(image_info != (ImageInfo *) NULL);
2697 assert(image_info->signature == MagickSignature);
2698 if (image_info->debug != MagickFalse)
2699 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2700 image_info->filename);
2701 assert(exception != (ExceptionInfo *) NULL);
2702 if ((blob == (const void *) NULL) || (length == 0))
2703 {
2704 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +00002705 "UnrecognizedImageFormat","`%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002706 return((Image *) NULL);
2707 }
2708 ping_info=CloneImageInfo(image_info);
2709 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2710 if (ping_info->blob == (const void *) NULL)
2711 {
2712 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00002713 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002714 return((Image *) NULL);
2715 }
cristy54aad5e2010-09-03 16:02:04 +00002716 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002717 ping_info->length=length;
2718 ping_info->ping=MagickTrue;
2719 image=ReadStream(ping_info,&PingStream,exception);
2720 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2721 ping_info=DestroyImageInfo(ping_info);
2722 return(image);
2723}
2724
2725/*
2726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2727% %
2728% %
2729% %
2730+ R e a d B l o b %
2731% %
2732% %
2733% %
2734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2735%
2736% ReadBlob() reads data from the blob or image file and returns it. It
cristy5f3d2752013-01-05 18:53:38 +00002737% returns the number of bytes read. If length is zero, ReadBlob() returns
2738% zero and has no other results. If length is greater than SSIZE_MAX, the
2739% result is unspecified.
cristy3ed852e2009-09-05 21:47:34 +00002740%
2741% The format of the ReadBlob method is:
2742%
2743% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2744%
2745% A description of each parameter follows:
2746%
2747% o image: the image.
2748%
2749% o length: Specifies an integer representing the number of bytes to read
2750% from the file.
2751%
2752% o data: Specifies an area to place the information requested from the
2753% file.
2754%
2755*/
2756MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2757 unsigned char *data)
2758{
2759 int
2760 c;
2761
2762 register unsigned char
2763 *q;
2764
2765 ssize_t
2766 count;
2767
2768 assert(image != (Image *) NULL);
2769 assert(image->signature == MagickSignature);
2770 assert(image->blob != (BlobInfo *) NULL);
2771 assert(image->blob->type != UndefinedStream);
2772 if (length == 0)
2773 return(0);
2774 assert(data != (void *) NULL);
2775 count=0;
2776 q=data;
2777 switch (image->blob->type)
2778 {
2779 case UndefinedStream:
2780 break;
cristy3ed852e2009-09-05 21:47:34 +00002781 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002782 {
cristy5f3d2752013-01-05 18:53:38 +00002783 count=read(fileno(image->blob->file_info.file),q,length);
cristybc20d112012-07-29 20:27:00 +00002784 break;
2785 }
2786 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002787 case PipeStream:
2788 {
2789 switch (length)
2790 {
2791 default:
2792 {
cristye7b28372012-06-17 13:59:06 +00002793 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002794 break;
2795 }
2796 case 2:
2797 {
cristye7b28372012-06-17 13:59:06 +00002798 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002799 if (c == EOF)
2800 break;
2801 *q++=(unsigned char) c;
2802 count++;
2803 }
2804 case 1:
2805 {
cristye7b28372012-06-17 13:59:06 +00002806 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002807 if (c == EOF)
2808 break;
2809 *q++=(unsigned char) c;
2810 count++;
2811 }
2812 case 0:
2813 break;
2814 }
2815 break;
2816 }
2817 case ZipStream:
2818 {
2819#if defined(MAGICKCORE_ZLIB_DELEGATE)
2820 switch (length)
2821 {
2822 default:
2823 {
cristye7b28372012-06-17 13:59:06 +00002824 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002825 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002826 break;
2827 }
2828 case 2:
2829 {
cristye7b28372012-06-17 13:59:06 +00002830 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002831 if (c == EOF)
2832 break;
2833 *q++=(unsigned char) c;
2834 count++;
2835 }
2836 case 1:
2837 {
cristye7b28372012-06-17 13:59:06 +00002838 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002839 if (c == EOF)
2840 break;
2841 *q++=(unsigned char) c;
2842 count++;
2843 }
2844 case 0:
2845 break;
2846 }
2847#endif
2848 break;
2849 }
2850 case BZipStream:
2851 {
2852#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy5f3d2752013-01-05 18:53:38 +00002853 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
cristy3ed852e2009-09-05 21:47:34 +00002854#endif
2855 break;
2856 }
2857 case FifoStream:
2858 break;
2859 case BlobStream:
2860 {
2861 register const unsigned char
2862 *p;
2863
2864 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2865 {
2866 image->blob->eof=MagickTrue;
2867 break;
2868 }
2869 p=image->blob->data+image->blob->offset;
cristye7b28372012-06-17 13:59:06 +00002870 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2871 image->blob->offset));
cristy3ed852e2009-09-05 21:47:34 +00002872 image->blob->offset+=count;
2873 if (count != (ssize_t) length)
2874 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002875 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002876 break;
2877 }
2878 }
2879 return(count);
2880}
2881
2882/*
2883%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2884% %
2885% %
2886% %
2887+ R e a d B l o b B y t e %
2888% %
2889% %
2890% %
2891%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2892%
2893% ReadBlobByte() reads a single byte from the image file and returns it.
2894%
2895% The format of the ReadBlobByte method is:
2896%
2897% int ReadBlobByte(Image *image)
2898%
2899% A description of each parameter follows.
2900%
2901% o image: the image.
2902%
2903*/
2904MagickExport int ReadBlobByte(Image *image)
2905{
2906 register const unsigned char
2907 *p;
2908
2909 ssize_t
2910 count;
2911
2912 unsigned char
2913 buffer[1];
2914
2915 assert(image != (Image *) NULL);
2916 assert(image->signature == MagickSignature);
2917 p=ReadBlobStream(image,1,buffer,&count);
2918 if (count != 1)
2919 return(EOF);
2920 return((int) (*p));
2921}
2922
2923/*
2924%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2925% %
2926% %
2927% %
2928+ R e a d B l o b D o u b l e %
2929% %
2930% %
2931% %
2932%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2933%
2934% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2935% specified by the endian member of the image structure.
2936%
2937% The format of the ReadBlobDouble method is:
2938%
2939% double ReadBlobDouble(Image *image)
2940%
2941% A description of each parameter follows.
2942%
2943% o image: the image.
2944%
2945*/
2946MagickExport double ReadBlobDouble(Image *image)
2947{
2948 union
2949 {
2950 MagickSizeType
2951 unsigned_value;
2952
2953 double
2954 double_value;
2955 } quantum;
2956
2957 quantum.double_value=0.0;
2958 quantum.unsigned_value=ReadBlobLongLong(image);
2959 return(quantum.double_value);
2960}
2961
2962/*
2963%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2964% %
2965% %
2966% %
2967+ R e a d B l o b F l o a t %
2968% %
2969% %
2970% %
2971%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2972%
2973% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2974% specified by the endian member of the image structure.
2975%
2976% The format of the ReadBlobFloat method is:
2977%
2978% float ReadBlobFloat(Image *image)
2979%
2980% A description of each parameter follows.
2981%
2982% o image: the image.
2983%
2984*/
2985MagickExport float ReadBlobFloat(Image *image)
2986{
2987 union
2988 {
2989 unsigned int
2990 unsigned_value;
2991
2992 float
2993 float_value;
2994 } quantum;
2995
2996 quantum.float_value=0.0;
2997 quantum.unsigned_value=ReadBlobLong(image);
2998 return(quantum.float_value);
2999}
3000
3001/*
3002%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3003% %
3004% %
3005% %
3006+ R e a d B l o b L o n g %
3007% %
3008% %
3009% %
3010%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3011%
cristybb503372010-05-27 20:51:26 +00003012% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003013% specified by the endian member of the image structure.
3014%
3015% The format of the ReadBlobLong method is:
3016%
3017% unsigned int ReadBlobLong(Image *image)
3018%
3019% A description of each parameter follows.
3020%
3021% o image: the image.
3022%
3023*/
3024MagickExport unsigned int ReadBlobLong(Image *image)
3025{
3026 register const unsigned char
3027 *p;
3028
3029 ssize_t
3030 count;
3031
3032 unsigned char
3033 buffer[4];
3034
3035 unsigned int
3036 value;
3037
3038 assert(image != (Image *) NULL);
3039 assert(image->signature == MagickSignature);
3040 *buffer='\0';
3041 p=ReadBlobStream(image,4,buffer,&count);
3042 if (count != 4)
3043 return(0UL);
3044 if (image->endian == LSBEndian)
3045 {
3046 value=(unsigned int) (*p++);
3047 value|=((unsigned int) (*p++)) << 8;
3048 value|=((unsigned int) (*p++)) << 16;
3049 value|=((unsigned int) (*p++)) << 24;
3050 return(value);
3051 }
3052 value=((unsigned int) (*p++)) << 24;
3053 value|=((unsigned int) (*p++)) << 16;
3054 value|=((unsigned int) (*p++)) << 8;
3055 value|=((unsigned int) (*p++));
3056 return(value);
3057}
3058
3059/*
3060%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3061% %
3062% %
3063% %
3064+ R e a d B l o b L o n g L o n g %
3065% %
3066% %
3067% %
3068%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3069%
cristy4cb162a2010-05-30 03:04:47 +00003070% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3071% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003072%
cristy4cb162a2010-05-30 03:04:47 +00003073% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003074%
cristy4cb162a2010-05-30 03:04:47 +00003075% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003076%
3077% A description of each parameter follows.
3078%
3079% o image: the image.
3080%
3081*/
3082MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3083{
cristy0286d852010-10-12 18:38:07 +00003084 MagickSizeType
3085 value;
3086
cristy3ed852e2009-09-05 21:47:34 +00003087 register const unsigned char
3088 *p;
3089
3090 ssize_t
3091 count;
3092
3093 unsigned char
3094 buffer[8];
3095
cristy3ed852e2009-09-05 21:47:34 +00003096 assert(image != (Image *) NULL);
3097 assert(image->signature == MagickSignature);
3098 *buffer='\0';
3099 p=ReadBlobStream(image,8,buffer,&count);
3100 if (count != 8)
3101 return(MagickULLConstant(0));
3102 if (image->endian == LSBEndian)
3103 {
3104 value=(MagickSizeType) (*p++);
3105 value|=((MagickSizeType) (*p++)) << 8;
3106 value|=((MagickSizeType) (*p++)) << 16;
3107 value|=((MagickSizeType) (*p++)) << 24;
3108 value|=((MagickSizeType) (*p++)) << 32;
3109 value|=((MagickSizeType) (*p++)) << 40;
3110 value|=((MagickSizeType) (*p++)) << 48;
3111 value|=((MagickSizeType) (*p++)) << 56;
3112 return(value & MagickULLConstant(0xffffffffffffffff));
3113 }
3114 value=((MagickSizeType) (*p++)) << 56;
3115 value|=((MagickSizeType) (*p++)) << 48;
3116 value|=((MagickSizeType) (*p++)) << 40;
3117 value|=((MagickSizeType) (*p++)) << 32;
3118 value|=((MagickSizeType) (*p++)) << 24;
3119 value|=((MagickSizeType) (*p++)) << 16;
3120 value|=((MagickSizeType) (*p++)) << 8;
3121 value|=((MagickSizeType) (*p++));
3122 return(value & MagickULLConstant(0xffffffffffffffff));
3123}
3124
3125/*
3126%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3127% %
3128% %
3129% %
3130+ R e a d B l o b S h o r t %
3131% %
3132% %
3133% %
3134%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3135%
3136% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3137% specified by the endian member of the image structure.
3138%
3139% The format of the ReadBlobShort method is:
3140%
3141% unsigned short ReadBlobShort(Image *image)
3142%
3143% A description of each parameter follows.
3144%
3145% o image: the image.
3146%
3147*/
3148MagickExport unsigned short ReadBlobShort(Image *image)
3149{
3150 register const unsigned char
3151 *p;
3152
3153 register unsigned int
3154 value;
3155
3156 ssize_t
3157 count;
3158
3159 unsigned char
3160 buffer[2];
3161
3162 assert(image != (Image *) NULL);
3163 assert(image->signature == MagickSignature);
3164 *buffer='\0';
3165 p=ReadBlobStream(image,2,buffer,&count);
3166 if (count != 2)
3167 return((unsigned short) 0U);
3168 if (image->endian == LSBEndian)
3169 {
3170 value=(unsigned int) (*p++);
3171 value|=((unsigned int) (*p++)) << 8;
3172 return((unsigned short) (value & 0xffff));
3173 }
3174 value=(unsigned int) ((*p++) << 8);
3175 value|=(unsigned int) (*p++);
3176 return((unsigned short) (value & 0xffff));
3177}
3178
3179/*
3180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3181% %
3182% %
3183% %
3184+ R e a d B l o b L S B L o n g %
3185% %
3186% %
3187% %
3188%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3189%
cristybb503372010-05-27 20:51:26 +00003190% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003191% least-significant byte first order.
3192%
3193% The format of the ReadBlobLSBLong method is:
3194%
3195% unsigned int ReadBlobLSBLong(Image *image)
3196%
3197% A description of each parameter follows.
3198%
3199% o image: the image.
3200%
3201*/
3202MagickExport unsigned int ReadBlobLSBLong(Image *image)
3203{
3204 register const unsigned char
3205 *p;
3206
3207 register unsigned int
3208 value;
3209
3210 ssize_t
3211 count;
3212
3213 unsigned char
3214 buffer[4];
3215
3216 assert(image != (Image *) NULL);
3217 assert(image->signature == MagickSignature);
3218 *buffer='\0';
3219 p=ReadBlobStream(image,4,buffer,&count);
3220 if (count != 4)
3221 return(0U);
3222 value=(unsigned int) (*p++);
3223 value|=((unsigned int) (*p++)) << 8;
3224 value|=((unsigned int) (*p++)) << 16;
3225 value|=((unsigned int) (*p++)) << 24;
3226 return(value);
3227}
3228
3229/*
3230%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3231% %
3232% %
3233% %
3234+ R e a d B l o b L S B S h o r t %
3235% %
3236% %
3237% %
3238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3239%
3240% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3241% least-significant byte first order.
3242%
3243% The format of the ReadBlobLSBShort method is:
3244%
3245% unsigned short ReadBlobLSBShort(Image *image)
3246%
3247% A description of each parameter follows.
3248%
3249% o image: the image.
3250%
3251*/
3252MagickExport unsigned short ReadBlobLSBShort(Image *image)
3253{
3254 register const unsigned char
3255 *p;
3256
3257 register unsigned int
3258 value;
3259
3260 ssize_t
3261 count;
3262
3263 unsigned char
3264 buffer[2];
3265
3266 assert(image != (Image *) NULL);
3267 assert(image->signature == MagickSignature);
3268 *buffer='\0';
3269 p=ReadBlobStream(image,2,buffer,&count);
3270 if (count != 2)
3271 return((unsigned short) 0U);
3272 value=(unsigned int) (*p++);
3273 value|=((unsigned int) ((*p++)) << 8);
3274 return((unsigned short) (value & 0xffff));
3275}
3276
3277/*
3278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3279% %
3280% %
3281% %
3282+ R e a d B l o b M S B L o n g %
3283% %
3284% %
3285% %
3286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3287%
cristybb503372010-05-27 20:51:26 +00003288% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003289% most-significant byte first order.
3290%
3291% The format of the ReadBlobMSBLong method is:
3292%
3293% unsigned int ReadBlobMSBLong(Image *image)
3294%
3295% A description of each parameter follows.
3296%
3297% o image: the image.
3298%
3299*/
3300MagickExport unsigned int ReadBlobMSBLong(Image *image)
3301{
3302 register const unsigned char
3303 *p;
3304
3305 register unsigned int
3306 value;
3307
3308 ssize_t
3309 count;
3310
3311 unsigned char
3312 buffer[4];
3313
3314 assert(image != (Image *) NULL);
3315 assert(image->signature == MagickSignature);
3316 *buffer='\0';
3317 p=ReadBlobStream(image,4,buffer,&count);
3318 if (count != 4)
3319 return(0UL);
3320 value=((unsigned int) (*p++) << 24);
3321 value|=((unsigned int) (*p++) << 16);
3322 value|=((unsigned int) (*p++) << 8);
3323 value|=(unsigned int) (*p++);
3324 return(value);
3325}
3326
3327/*
3328%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3329% %
3330% %
3331% %
cristy2d3d87f2010-03-01 00:23:08 +00003332+ R e a d B l o b M S B L o n g L o n g %
3333% %
3334% %
3335% %
3336%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3337%
cristybb503372010-05-27 20:51:26 +00003338% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003339% most-significant byte first order.
3340%
3341% The format of the ReadBlobMSBLongLong method is:
3342%
3343% unsigned int ReadBlobMSBLongLong(Image *image)
3344%
3345% A description of each parameter follows.
3346%
3347% o image: the image.
3348%
3349*/
3350MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3351{
3352 register const unsigned char
3353 *p;
3354
3355 register MagickSizeType
3356 value;
3357
3358 ssize_t
3359 count;
3360
3361 unsigned char
cristy0286d852010-10-12 18:38:07 +00003362 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003363
3364 assert(image != (Image *) NULL);
3365 assert(image->signature == MagickSignature);
3366 *buffer='\0';
3367 p=ReadBlobStream(image,8,buffer,&count);
3368 if (count != 8)
3369 return(MagickULLConstant(0));
3370 value=((MagickSizeType) (*p++)) << 56;
3371 value|=((MagickSizeType) (*p++)) << 48;
3372 value|=((MagickSizeType) (*p++)) << 40;
3373 value|=((MagickSizeType) (*p++)) << 32;
3374 value|=((MagickSizeType) (*p++)) << 24;
3375 value|=((MagickSizeType) (*p++)) << 16;
3376 value|=((MagickSizeType) (*p++)) << 8;
3377 value|=((MagickSizeType) (*p++));
3378 return(value & MagickULLConstant(0xffffffffffffffff));
3379}
3380
3381/*
3382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3383% %
3384% %
3385% %
cristy3ed852e2009-09-05 21:47:34 +00003386+ R e a d B l o b M S B S h o r t %
3387% %
3388% %
3389% %
3390%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3391%
3392% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3393% most-significant byte first order.
3394%
3395% The format of the ReadBlobMSBShort method is:
3396%
3397% unsigned short ReadBlobMSBShort(Image *image)
3398%
3399% A description of each parameter follows.
3400%
3401% o image: the image.
3402%
3403*/
3404MagickExport unsigned short ReadBlobMSBShort(Image *image)
3405{
3406 register const unsigned char
3407 *p;
3408
3409 register unsigned int
3410 value;
3411
3412 ssize_t
3413 count;
3414
3415 unsigned char
3416 buffer[2];
3417
3418 assert(image != (Image *) NULL);
3419 assert(image->signature == MagickSignature);
3420 *buffer='\0';
3421 p=ReadBlobStream(image,2,buffer,&count);
3422 if (count != 2)
3423 return((unsigned short) 0U);
3424 value=(unsigned int) ((*p++) << 8);
3425 value|=(unsigned int) (*p++);
3426 return((unsigned short) (value & 0xffff));
3427}
3428
3429/*
3430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3431% %
3432% %
3433% %
3434+ R e a d B l o b S t r i n g %
3435% %
3436% %
3437% %
3438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3439%
3440% ReadBlobString() reads characters from a blob or file until a newline
3441% character is read or an end-of-file condition is encountered.
3442%
3443% The format of the ReadBlobString method is:
3444%
3445% char *ReadBlobString(Image *image,char *string)
3446%
3447% A description of each parameter follows:
3448%
3449% o image: the image.
3450%
3451% o string: the address of a character buffer.
3452%
3453*/
3454MagickExport char *ReadBlobString(Image *image,char *string)
3455{
3456 register const unsigned char
3457 *p;
3458
cristybb503372010-05-27 20:51:26 +00003459 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003460 i;
3461
3462 ssize_t
3463 count;
3464
3465 unsigned char
3466 buffer[1];
3467
3468 assert(image != (Image *) NULL);
3469 assert(image->signature == MagickSignature);
3470 for (i=0; i < (MaxTextExtent-1L); i++)
3471 {
3472 p=ReadBlobStream(image,1,buffer,&count);
3473 if (count != 1)
3474 {
3475 if (i == 0)
3476 return((char *) NULL);
3477 break;
3478 }
3479 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003480 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003481 break;
3482 }
cristy2b5db102010-06-09 01:07:28 +00003483 if (string[i] == '\r')
3484 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003485 string[i]='\0';
3486 return(string);
3487}
3488
3489/*
3490%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3491% %
3492% %
3493% %
3494+ R e f e r e n c e B l o b %
3495% %
3496% %
3497% %
3498%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3499%
3500% ReferenceBlob() increments the reference count associated with the pixel
3501% blob returning a pointer to the blob.
3502%
3503% The format of the ReferenceBlob method is:
3504%
3505% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3506%
3507% A description of each parameter follows:
3508%
3509% o blob_info: the blob_info.
3510%
3511*/
3512MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3513{
3514 assert(blob != (BlobInfo *) NULL);
3515 assert(blob->signature == MagickSignature);
3516 if (blob->debug != MagickFalse)
3517 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003518 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003519 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003520 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003521 return(blob);
3522}
3523
3524/*
3525%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3526% %
3527% %
3528% %
3529+ S e e k B l o b %
3530% %
3531% %
3532% %
3533%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3534%
3535% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3536% and returns the resulting offset.
3537%
3538% The format of the SeekBlob method is:
3539%
3540% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3541% const int whence)
3542%
3543% A description of each parameter follows:
3544%
3545% o image: the image.
3546%
3547% o offset: Specifies an integer representing the offset in bytes.
3548%
3549% o whence: Specifies an integer representing how the offset is
3550% treated relative to the beginning of the blob as follows:
3551%
3552% SEEK_SET Set position equal to offset bytes.
3553% SEEK_CUR Set position to current location plus offset.
3554% SEEK_END Set position to EOF plus offset.
3555%
3556*/
3557MagickExport MagickOffsetType SeekBlob(Image *image,
3558 const MagickOffsetType offset,const int whence)
3559{
3560 assert(image != (Image *) NULL);
3561 assert(image->signature == MagickSignature);
3562 if (image->debug != MagickFalse)
3563 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3564 assert(image->blob != (BlobInfo *) NULL);
3565 assert(image->blob->type != UndefinedStream);
3566 switch (image->blob->type)
3567 {
3568 case UndefinedStream:
3569 break;
cristybc20d112012-07-29 20:27:00 +00003570 case StandardStream:
3571 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003572 case FileStream:
3573 {
cristye7b28372012-06-17 13:59:06 +00003574 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003575 return(-1);
3576 image->blob->offset=TellBlob(image);
3577 break;
3578 }
cristy3ed852e2009-09-05 21:47:34 +00003579 case PipeStream:
3580 case ZipStream:
3581 {
3582#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003583 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003584 return(-1);
3585#endif
3586 image->blob->offset=TellBlob(image);
3587 break;
3588 }
3589 case BZipStream:
3590 return(-1);
3591 case FifoStream:
3592 return(-1);
3593 case BlobStream:
3594 {
3595 switch (whence)
3596 {
3597 case SEEK_SET:
3598 default:
3599 {
3600 if (offset < 0)
3601 return(-1);
3602 image->blob->offset=offset;
3603 break;
3604 }
3605 case SEEK_CUR:
3606 {
3607 if ((image->blob->offset+offset) < 0)
3608 return(-1);
3609 image->blob->offset+=offset;
3610 break;
3611 }
3612 case SEEK_END:
3613 {
3614 if (((MagickOffsetType) image->blob->length+offset) < 0)
3615 return(-1);
3616 image->blob->offset=image->blob->length+offset;
3617 break;
3618 }
3619 }
3620 if (image->blob->offset <= (MagickOffsetType)
3621 ((off_t) image->blob->length))
3622 image->blob->eof=MagickFalse;
3623 else
3624 if (image->blob->mapped != MagickFalse)
3625 return(-1);
3626 else
3627 {
3628 image->blob->extent=(size_t) (image->blob->offset+
3629 image->blob->quantum);
3630 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3631 image->blob->data,image->blob->extent+1,
3632 sizeof(*image->blob->data));
3633 (void) SyncBlob(image);
3634 if (image->blob->data == (unsigned char *) NULL)
3635 {
3636 (void) DetachBlob(image->blob);
3637 return(-1);
3638 }
3639 }
3640 break;
3641 }
3642 }
3643 return(image->blob->offset);
3644}
3645
3646/*
3647%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3648% %
3649% %
3650% %
3651+ S e t B l o b E x e m p t %
3652% %
3653% %
3654% %
3655%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3656%
3657% SetBlobExempt() sets the blob exempt status.
3658%
3659% The format of the SetBlobExempt method is:
3660%
3661% MagickBooleanType SetBlobExempt(const Image *image,
3662% const MagickBooleanType exempt)
3663%
3664% A description of each parameter follows:
3665%
3666% o image: the image.
3667%
3668% o exempt: Set to true if this blob is exempt from being closed.
3669%
3670*/
cristy7832dc22011-09-05 01:21:53 +00003671MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003672{
3673 assert(image != (const Image *) NULL);
3674 assert(image->signature == MagickSignature);
3675 if (image->debug != MagickFalse)
3676 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3677 image->blob->exempt=exempt;
3678}
3679
3680/*
3681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3682% %
3683% %
3684% %
3685+ S e t B l o b E x t e n t %
3686% %
3687% %
3688% %
3689%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3690%
3691% SetBlobExtent() ensures enough space is allocated for the blob. If the
3692% method is successful, subsequent writes to bytes in the specified range are
3693% guaranteed not to fail.
3694%
3695% The format of the SetBlobExtent method is:
3696%
3697% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3698%
3699% A description of each parameter follows:
3700%
3701% o image: the image.
3702%
3703% o extent: the blob maximum extent.
3704%
3705*/
cristy7832dc22011-09-05 01:21:53 +00003706MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003707 const MagickSizeType extent)
3708{
3709 assert(image != (Image *) NULL);
3710 assert(image->signature == MagickSignature);
3711 if (image->debug != MagickFalse)
3712 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3713 assert(image->blob != (BlobInfo *) NULL);
3714 assert(image->blob->type != UndefinedStream);
3715 switch (image->blob->type)
3716 {
3717 case UndefinedStream:
3718 break;
cristybc20d112012-07-29 20:27:00 +00003719 case StandardStream:
3720 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003721 case FileStream:
3722 {
cristy38e35f42012-12-18 21:12:17 +00003723 MagickOffsetType
3724 offset;
3725
3726 ssize_t
3727 count;
3728
cristy3ed852e2009-09-05 21:47:34 +00003729 if (extent != (MagickSizeType) ((off_t) extent))
3730 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003731 offset=SeekBlob(image,0,SEEK_END);
3732 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003733 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003734 if ((MagickSizeType) offset >= extent)
3735 break;
3736 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003737 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3738 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003739#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3740 if (image->blob->synchronize != MagickFalse)
3741 {
3742 int
3743 status;
3744
3745 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3746 extent-offset);
3747 if (status != 0)
3748 return(MagickFalse);
3749 }
3750#endif
cristy38e35f42012-12-18 21:12:17 +00003751 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003752 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003753 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003754 break;
3755 }
cristy3ed852e2009-09-05 21:47:34 +00003756 case PipeStream:
3757 case ZipStream:
3758 return(MagickFalse);
3759 case BZipStream:
3760 return(MagickFalse);
3761 case FifoStream:
3762 return(MagickFalse);
3763 case BlobStream:
3764 {
cristy38e35f42012-12-18 21:12:17 +00003765 if (extent != (MagickSizeType) ((size_t) extent))
3766 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003767 if (image->blob->mapped != MagickFalse)
3768 {
cristy38e35f42012-12-18 21:12:17 +00003769 MagickOffsetType
3770 offset;
3771
3772 ssize_t
3773 count;
3774
cristy3ed852e2009-09-05 21:47:34 +00003775 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003776 if (extent != (MagickSizeType) ((off_t) extent))
3777 return(MagickFalse);
3778 offset=SeekBlob(image,0,SEEK_END);
3779 if (offset < 0)
3780 return(MagickFalse);
3781 if ((MagickSizeType) offset >= extent)
3782 break;
3783 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003784 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003785 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003786#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3787 if (image->blob->synchronize != MagickFalse)
3788 {
3789 int
3790 status;
3791
3792 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3793 extent-offset);
3794 if (status != 0)
3795 return(MagickFalse);
3796 }
3797#endif
cristy38e35f42012-12-18 21:12:17 +00003798 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003799 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003800 return(MagickFalse);
cristy95888612012-04-04 21:56:52 +00003801 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003802 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003803 image->blob->extent=(size_t) extent;
3804 image->blob->length=(size_t) extent;
3805 (void) SyncBlob(image);
3806 break;
cristy3ed852e2009-09-05 21:47:34 +00003807 }
cristy3ed852e2009-09-05 21:47:34 +00003808 image->blob->extent=(size_t) extent;
3809 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3810 image->blob->extent+1,sizeof(*image->blob->data));
3811 (void) SyncBlob(image);
3812 if (image->blob->data == (unsigned char *) NULL)
3813 {
3814 (void) DetachBlob(image->blob);
3815 return(MagickFalse);
3816 }
3817 break;
3818 }
3819 }
3820 return(MagickTrue);
3821}
3822
3823/*
3824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3825% %
3826% %
3827% %
3828+ S y n c B l o b %
3829% %
3830% %
3831% %
3832%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3833%
3834% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3835% attributes if it is an blob.
3836%
3837% The format of the SyncBlob method is:
3838%
3839% int SyncBlob(Image *image)
3840%
3841% A description of each parameter follows:
3842%
3843% o image: the image.
3844%
3845*/
3846static int SyncBlob(Image *image)
3847{
3848 int
3849 status;
3850
3851 assert(image != (Image *) NULL);
3852 assert(image->signature == MagickSignature);
3853 if (image->debug != MagickFalse)
3854 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3855 assert(image->blob != (BlobInfo *) NULL);
3856 assert(image->blob->type != UndefinedStream);
3857 status=0;
3858 switch (image->blob->type)
3859 {
3860 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003861 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003862 break;
3863 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003864 case PipeStream:
3865 {
cristye7b28372012-06-17 13:59:06 +00003866 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003867 break;
3868 }
3869 case ZipStream:
3870 {
3871#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003872 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003873#endif
3874 break;
3875 }
3876 case BZipStream:
3877 {
3878#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003879 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003880#endif
3881 break;
3882 }
3883 case FifoStream:
3884 break;
3885 case BlobStream:
3886 {
3887#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3888 if (image->blob->mapped != MagickFalse)
3889 status=msync(image->blob->data,image->blob->length,MS_SYNC);
3890#endif
3891 break;
3892 }
3893 }
3894 return(status);
3895}
3896
3897/*
3898%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3899% %
3900% %
3901% %
3902+ T e l l B l o b %
3903% %
3904% %
3905% %
3906%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3907%
3908% TellBlob() obtains the current value of the blob or file position.
3909%
3910% The format of the TellBlob method is:
3911%
3912% MagickOffsetType TellBlob(const Image *image)
3913%
3914% A description of each parameter follows:
3915%
3916% o image: the image.
3917%
3918*/
3919MagickExport MagickOffsetType TellBlob(const Image *image)
3920{
3921 MagickOffsetType
3922 offset;
3923
3924 assert(image != (Image *) NULL);
3925 assert(image->signature == MagickSignature);
3926 if (image->debug != MagickFalse)
3927 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3928 assert(image->blob != (BlobInfo *) NULL);
3929 assert(image->blob->type != UndefinedStream);
3930 offset=(-1);
3931 switch (image->blob->type)
3932 {
3933 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003934 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003935 break;
3936 case FileStream:
3937 {
cristye7b28372012-06-17 13:59:06 +00003938 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003939 break;
3940 }
cristy3ed852e2009-09-05 21:47:34 +00003941 case PipeStream:
3942 break;
3943 case ZipStream:
3944 {
3945#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003946 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003947#endif
3948 break;
3949 }
3950 case BZipStream:
3951 break;
3952 case FifoStream:
3953 break;
3954 case BlobStream:
3955 {
3956 offset=image->blob->offset;
3957 break;
3958 }
3959 }
3960 return(offset);
3961}
3962
3963/*
3964%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3965% %
3966% %
3967% %
3968+ U n m a p B l o b %
3969% %
3970% %
3971% %
3972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3973%
3974% UnmapBlob() deallocates the binary large object previously allocated with
3975% the MapBlob method.
3976%
3977% The format of the UnmapBlob method is:
3978%
3979% MagickBooleanType UnmapBlob(void *map,const size_t length)
3980%
3981% A description of each parameter follows:
3982%
3983% o map: the address of the binary large object.
3984%
3985% o length: the length of the binary large object.
3986%
3987*/
3988MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3989{
3990#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3991 int
3992 status;
3993
3994 status=munmap(map,length);
3995 return(status == -1 ? MagickFalse : MagickTrue);
3996#else
3997 (void) map;
3998 (void) length;
3999 return(MagickFalse);
4000#endif
4001}
4002
4003/*
4004%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4005% %
4006% %
4007% %
4008+ W r i t e B l o b %
4009% %
4010% %
4011% %
4012%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4013%
4014% WriteBlob() writes data to a blob or image file. It returns the number of
4015% bytes written.
4016%
4017% The format of the WriteBlob method is:
4018%
4019% ssize_t WriteBlob(Image *image,const size_t length,
4020% const unsigned char *data)
4021%
4022% A description of each parameter follows:
4023%
4024% o image: the image.
4025%
4026% o length: Specifies an integer representing the number of bytes to
4027% write to the file.
4028%
4029% o data: The address of the data to write to the blob or file.
4030%
4031*/
4032MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4033 const unsigned char *data)
4034{
4035 int
4036 c;
4037
4038 register const unsigned char
4039 *p;
4040
4041 ssize_t
4042 count;
4043
4044 assert(image != (Image *) NULL);
4045 assert(image->signature == MagickSignature);
4046 assert(data != (const unsigned char *) NULL);
4047 assert(image->blob != (BlobInfo *) NULL);
4048 assert(image->blob->type != UndefinedStream);
4049 if (length == 0)
4050 return(0);
4051 count=0;
4052 p=data;
4053 switch (image->blob->type)
4054 {
4055 case UndefinedStream:
4056 break;
cristy3ed852e2009-09-05 21:47:34 +00004057 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004058 {
cristy5f3d2752013-01-05 18:53:38 +00004059 count=write(fileno(image->blob->file_info.file),data,length);
cristybc20d112012-07-29 20:27:00 +00004060 break;
4061 }
4062 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004063 case PipeStream:
4064 {
4065 switch (length)
4066 {
4067 default:
4068 {
4069 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004070 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004071 break;
4072 }
4073 case 2:
4074 {
cristye7b28372012-06-17 13:59:06 +00004075 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004076 if (c == EOF)
4077 break;
4078 count++;
4079 }
4080 case 1:
4081 {
cristye7b28372012-06-17 13:59:06 +00004082 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004083 if (c == EOF)
4084 break;
4085 count++;
4086 }
4087 case 0:
4088 break;
4089 }
4090 break;
4091 }
4092 case ZipStream:
4093 {
4094#if defined(MAGICKCORE_ZLIB_DELEGATE)
4095 switch (length)
4096 {
4097 default:
4098 {
cristye7b28372012-06-17 13:59:06 +00004099 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004100 (unsigned int) length);
4101 break;
4102 }
4103 case 2:
4104 {
cristye7b28372012-06-17 13:59:06 +00004105 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004106 if (c == EOF)
4107 break;
4108 count++;
4109 }
4110 case 1:
4111 {
cristye7b28372012-06-17 13:59:06 +00004112 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004113 if (c == EOF)
4114 break;
4115 count++;
4116 }
4117 case 0:
4118 break;
4119 }
4120#endif
4121 break;
4122 }
4123 case BZipStream:
4124 {
4125#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004126 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004127 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004128#endif
4129 break;
4130 }
4131 case FifoStream:
4132 {
4133 count=(ssize_t) image->blob->stream(image,data,length);
4134 break;
4135 }
4136 case BlobStream:
4137 {
4138 register unsigned char
4139 *q;
4140
4141 if ((image->blob->offset+(MagickOffsetType) length) >=
4142 (MagickOffsetType) image->blob->extent)
4143 {
4144 if (image->blob->mapped != MagickFalse)
4145 return(0);
4146 image->blob->quantum<<=1;
4147 image->blob->extent+=length+image->blob->quantum;
4148 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4149 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4150 (void) SyncBlob(image);
4151 if (image->blob->data == (unsigned char *) NULL)
4152 {
4153 (void) DetachBlob(image->blob);
4154 return(0);
4155 }
4156 }
4157 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004158 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004159 image->blob->offset+=length;
4160 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4161 image->blob->length=(size_t) image->blob->offset;
4162 count=(ssize_t) length;
4163 }
4164 }
4165 return(count);
4166}
4167
4168/*
4169%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4170% %
4171% %
4172% %
4173+ W r i t e B l o b B y t e %
4174% %
4175% %
4176% %
4177%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4178%
4179% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4180% written (either 0 or 1);
4181%
4182% The format of the WriteBlobByte method is:
4183%
4184% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4185%
4186% A description of each parameter follows.
4187%
4188% o image: the image.
4189%
4190% o value: Specifies the value to write.
4191%
4192*/
4193MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4194{
4195 assert(image != (Image *) NULL);
4196 assert(image->signature == MagickSignature);
4197 return(WriteBlobStream(image,1,&value));
4198}
4199
4200/*
4201%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4202% %
4203% %
4204% %
4205+ W r i t e B l o b F l o a t %
4206% %
4207% %
4208% %
4209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4210%
4211% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4212% specified by the endian member of the image structure.
4213%
4214% The format of the WriteBlobFloat method is:
4215%
4216% ssize_t WriteBlobFloat(Image *image,const float value)
4217%
4218% A description of each parameter follows.
4219%
4220% o image: the image.
4221%
4222% o value: Specifies the value to write.
4223%
4224*/
4225MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4226{
4227 union
4228 {
4229 unsigned int
4230 unsigned_value;
4231
4232 float
4233 float_value;
4234 } quantum;
4235
4236 quantum.unsigned_value=0U;
4237 quantum.float_value=value;
4238 return(WriteBlobLong(image,quantum.unsigned_value));
4239}
4240
4241/*
4242%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4243% %
4244% %
4245% %
4246+ W r i t e B l o b L o n g %
4247% %
4248% %
4249% %
4250%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4251%
cristybb503372010-05-27 20:51:26 +00004252% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004253% specified by the endian member of the image structure.
4254%
4255% The format of the WriteBlobLong method is:
4256%
4257% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4258%
4259% A description of each parameter follows.
4260%
4261% o image: the image.
4262%
4263% o value: Specifies the value to write.
4264%
4265*/
4266MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4267{
4268 unsigned char
4269 buffer[4];
4270
4271 assert(image != (Image *) NULL);
4272 assert(image->signature == MagickSignature);
4273 if (image->endian == LSBEndian)
4274 {
4275 buffer[0]=(unsigned char) value;
4276 buffer[1]=(unsigned char) (value >> 8);
4277 buffer[2]=(unsigned char) (value >> 16);
4278 buffer[3]=(unsigned char) (value >> 24);
4279 return(WriteBlobStream(image,4,buffer));
4280 }
4281 buffer[0]=(unsigned char) (value >> 24);
4282 buffer[1]=(unsigned char) (value >> 16);
4283 buffer[2]=(unsigned char) (value >> 8);
4284 buffer[3]=(unsigned char) value;
4285 return(WriteBlobStream(image,4,buffer));
4286}
4287
4288/*
4289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4290% %
4291% %
4292% %
4293+ W r i t e B l o b S h o r t %
4294% %
4295% %
4296% %
4297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4298%
4299% WriteBlobShort() writes a short value as a 16-bit quantity in the
4300% byte-order specified by the endian member of the image structure.
4301%
4302% The format of the WriteBlobShort method is:
4303%
4304% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4305%
4306% A description of each parameter follows.
4307%
4308% o image: the image.
4309%
4310% o value: Specifies the value to write.
4311%
4312*/
4313MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4314{
4315 unsigned char
4316 buffer[2];
4317
4318 assert(image != (Image *) NULL);
4319 assert(image->signature == MagickSignature);
4320 if (image->endian == LSBEndian)
4321 {
4322 buffer[0]=(unsigned char) value;
4323 buffer[1]=(unsigned char) (value >> 8);
4324 return(WriteBlobStream(image,2,buffer));
4325 }
4326 buffer[0]=(unsigned char) (value >> 8);
4327 buffer[1]=(unsigned char) value;
4328 return(WriteBlobStream(image,2,buffer));
4329}
4330
4331/*
4332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4333% %
4334% %
4335% %
4336+ W r i t e B l o b L S B L o n g %
4337% %
4338% %
4339% %
4340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4341%
cristybb503372010-05-27 20:51:26 +00004342% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004343% least-significant byte first order.
4344%
4345% The format of the WriteBlobLSBLong method is:
4346%
4347% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4348%
4349% A description of each parameter follows.
4350%
4351% o image: the image.
4352%
4353% o value: Specifies the value to write.
4354%
4355*/
4356MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4357{
4358 unsigned char
4359 buffer[4];
4360
4361 assert(image != (Image *) NULL);
4362 assert(image->signature == MagickSignature);
4363 buffer[0]=(unsigned char) value;
4364 buffer[1]=(unsigned char) (value >> 8);
4365 buffer[2]=(unsigned char) (value >> 16);
4366 buffer[3]=(unsigned char) (value >> 24);
4367 return(WriteBlobStream(image,4,buffer));
4368}
4369
4370/*
4371%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4372% %
4373% %
4374% %
4375+ W r i t e B l o b L S B S h o r t %
4376% %
4377% %
4378% %
4379%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4380%
cristybb503372010-05-27 20:51:26 +00004381% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004382% least-significant byte first order.
4383%
4384% The format of the WriteBlobLSBShort method is:
4385%
4386% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4387%
4388% A description of each parameter follows.
4389%
4390% o image: the image.
4391%
4392% o value: Specifies the value to write.
4393%
4394*/
4395MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4396{
4397 unsigned char
4398 buffer[2];
4399
4400 assert(image != (Image *) NULL);
4401 assert(image->signature == MagickSignature);
4402 buffer[0]=(unsigned char) value;
4403 buffer[1]=(unsigned char) (value >> 8);
4404 return(WriteBlobStream(image,2,buffer));
4405}
4406
4407/*
4408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4409% %
4410% %
4411% %
4412+ W r i t e B l o b M S B L o n g %
4413% %
4414% %
4415% %
4416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4417%
cristybb503372010-05-27 20:51:26 +00004418% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004419% most-significant byte first order.
4420%
4421% The format of the WriteBlobMSBLong method is:
4422%
4423% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4424%
4425% A description of each parameter follows.
4426%
4427% o value: Specifies the value to write.
4428%
4429% o image: the image.
4430%
4431*/
4432MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4433{
4434 unsigned char
4435 buffer[4];
4436
4437 assert(image != (Image *) NULL);
4438 assert(image->signature == MagickSignature);
4439 buffer[0]=(unsigned char) (value >> 24);
4440 buffer[1]=(unsigned char) (value >> 16);
4441 buffer[2]=(unsigned char) (value >> 8);
4442 buffer[3]=(unsigned char) value;
4443 return(WriteBlobStream(image,4,buffer));
4444}
4445
4446/*
4447%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4448% %
4449% %
4450% %
cristy2ca49922010-03-06 02:54:01 +00004451+ W r i t e B l o b M S B L o n g L o n g %
4452% %
4453% %
4454% %
4455%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4456%
4457% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4458% most-significant byte first order.
4459%
4460% The format of the WriteBlobMSBLongLong method is:
4461%
4462% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4463%
4464% A description of each parameter follows.
4465%
4466% o value: Specifies the value to write.
4467%
4468% o image: the image.
4469%
4470*/
4471MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4472 const MagickSizeType value)
4473{
4474 unsigned char
4475 buffer[8];
4476
4477 assert(image != (Image *) NULL);
4478 assert(image->signature == MagickSignature);
4479 buffer[0]=(unsigned char) (value >> 56);
4480 buffer[1]=(unsigned char) (value >> 48);
4481 buffer[2]=(unsigned char) (value >> 40);
4482 buffer[3]=(unsigned char) (value >> 32);
4483 buffer[4]=(unsigned char) (value >> 24);
4484 buffer[5]=(unsigned char) (value >> 16);
4485 buffer[6]=(unsigned char) (value >> 8);
4486 buffer[7]=(unsigned char) value;
4487 return(WriteBlobStream(image,8,buffer));
4488}
4489
4490/*
4491%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4492% %
4493% %
4494% %
cristy3ed852e2009-09-05 21:47:34 +00004495+ W r i t e B l o b M S B S h o r t %
4496% %
4497% %
4498% %
4499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4500%
cristybb503372010-05-27 20:51:26 +00004501% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004502% most-significant byte first order.
4503%
4504% The format of the WriteBlobMSBShort method is:
4505%
4506% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4507%
4508% A description of each parameter follows.
4509%
4510% o value: Specifies the value to write.
4511%
4512% o file: Specifies the file to write the data to.
4513%
4514*/
4515MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4516{
4517 unsigned char
4518 buffer[2];
4519
4520 assert(image != (Image *) NULL);
4521 assert(image->signature == MagickSignature);
4522 buffer[0]=(unsigned char) (value >> 8);
4523 buffer[1]=(unsigned char) value;
4524 return(WriteBlobStream(image,2,buffer));
4525}
4526
4527/*
4528%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4529% %
4530% %
4531% %
4532+ W r i t e B l o b S t r i n g %
4533% %
4534% %
4535% %
4536%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4537%
4538% WriteBlobString() write a string to a blob. It returns the number of
4539% characters written.
4540%
4541% The format of the WriteBlobString method is:
4542%
4543% ssize_t WriteBlobString(Image *image,const char *string)
4544%
4545% A description of each parameter follows.
4546%
4547% o image: the image.
4548%
4549% o string: Specifies the string to write.
4550%
4551*/
4552MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4553{
4554 assert(image != (Image *) NULL);
4555 assert(image->signature == MagickSignature);
4556 assert(string != (const char *) NULL);
4557 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4558}