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