blob: 00f7204d2740c5db21baab68c2747c7296d1be4b [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);
2520 (void) rewind(image->blob->file_info.file);
cristybf6a7092010-06-11 02:12:15 +00002521 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2522 " read %.20g magic header bytes",(double) count);
2523#if defined(MAGICKCORE_ZLIB_DELEGATE)
2524 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2525 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002526 {
cristye7b28372012-06-17 13:59:06 +00002527 (void) fclose(image->blob->file_info.file);
2528 image->blob->file_info.gzfile=gzopen(filename,type);
2529 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002530 image->blob->type=ZipStream;
2531 }
2532#endif
2533#if defined(MAGICKCORE_BZLIB_DELEGATE)
2534 if (strncmp((char *) magick,"BZh",3) == 0)
2535 {
cristye7b28372012-06-17 13:59:06 +00002536 (void) fclose(image->blob->file_info.file);
2537 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2538 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002539 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002540 }
cristybf6a7092010-06-11 02:12:15 +00002541#endif
cristyc6c589d2010-07-06 01:34:57 +00002542 if (image->blob->type == FileStream)
2543 {
2544 const MagickInfo
2545 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002546
cristyc6c589d2010-07-06 01:34:57 +00002547 ExceptionInfo
2548 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002549
cristyc6c589d2010-07-06 01:34:57 +00002550 struct stat
2551 *properties;
cristybf6a7092010-06-11 02:12:15 +00002552
cristyc6c589d2010-07-06 01:34:57 +00002553 sans_exception=AcquireExceptionInfo();
2554 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2555 sans_exception=DestroyExceptionInfo(sans_exception);
2556 properties=(&image->blob->properties);
2557 if ((magick_info != (const MagickInfo *) NULL) &&
2558 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2559 (properties->st_size <= MagickMaxBufferExtent))
2560 {
2561 size_t
2562 length;
cristybf6a7092010-06-11 02:12:15 +00002563
cristyc6c589d2010-07-06 01:34:57 +00002564 void
2565 *blob;
cristybf6a7092010-06-11 02:12:15 +00002566
cristyc6c589d2010-07-06 01:34:57 +00002567 length=(size_t) properties->st_size;
cristye7b28372012-06-17 13:59:06 +00002568 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,
cristy95888612012-04-04 21:56:52 +00002569 0,length);
cristyc6c589d2010-07-06 01:34:57 +00002570 if (blob != (void *) NULL)
2571 {
2572 /*
2573 Format supports blobs-- use memory-mapped I/O.
2574 */
2575 if (image_info->file != (FILE *) NULL)
2576 image->blob->exempt=MagickFalse;
2577 else
2578 {
cristye7b28372012-06-17 13:59:06 +00002579 (void) fclose(image->blob->file_info.file);
2580 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002581 }
2582 AttachBlob(image->blob,blob,length);
2583 image->blob->mapped=MagickTrue;
2584 }
2585 }
2586 }
cristy3ed852e2009-09-05 21:47:34 +00002587 }
cristybf6a7092010-06-11 02:12:15 +00002588 }
2589 else
2590#if defined(MAGICKCORE_ZLIB_DELEGATE)
2591 if ((LocaleCompare(extension,"Z") == 0) ||
2592 (LocaleCompare(extension,"gz") == 0) ||
2593 (LocaleCompare(extension,"wmz") == 0) ||
2594 (LocaleCompare(extension,"svgz") == 0))
2595 {
2596 if (mode == WriteBinaryBlobMode)
2597 type="wb";
cristye7b28372012-06-17 13:59:06 +00002598 image->blob->file_info.gzfile=gzopen(filename,type);
2599 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002600 image->blob->type=ZipStream;
2601 }
2602 else
2603#endif
2604#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002605 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002606 {
cristye7b28372012-06-17 13:59:06 +00002607 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2608 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002609 image->blob->type=BZipStream;
2610 }
2611 else
2612#endif
2613 {
cristye7b28372012-06-17 13:59:06 +00002614 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2615 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002616 {
2617 image->blob->type=FileStream;
2618#if defined(MAGICKCORE_HAVE_SETVBUF)
cristye7b28372012-06-17 13:59:06 +00002619 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int) _IOFBF,
cristybf6a7092010-06-11 02:12:15 +00002620 16384);
2621#endif
2622 }
2623 }
cristy3ed852e2009-09-05 21:47:34 +00002624 image->blob->status=MagickFalse;
2625 if (image->blob->type != UndefinedStream)
2626 image->blob->size=GetBlobSize(image);
2627 else
2628 {
2629 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2630 return(MagickFalse);
2631 }
2632 return(MagickTrue);
2633}
2634
2635/*
2636%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2637% %
2638% %
2639% %
2640+ P i n g B l o b %
2641% %
2642% %
2643% %
2644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2645%
2646% PingBlob() returns all the attributes of an image or image sequence except
2647% for the pixels. It is much faster and consumes far less memory than
2648% BlobToImage(). On failure, a NULL image is returned and exception
2649% describes the reason for the failure.
2650%
2651% The format of the PingBlob method is:
2652%
2653% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2654% const size_t length,ExceptionInfo *exception)
2655%
2656% A description of each parameter follows:
2657%
2658% o image_info: the image info.
2659%
2660% o blob: the address of a character stream in one of the image formats
2661% understood by ImageMagick.
2662%
2663% o length: This size_t integer reflects the length in bytes of the blob.
2664%
2665% o exception: return any errors or warnings in this structure.
2666%
2667*/
2668
2669#if defined(__cplusplus) || defined(c_plusplus)
2670extern "C" {
2671#endif
2672
2673static size_t PingStream(const Image *magick_unused(image),
2674 const void *magick_unused(pixels),const size_t columns)
2675{
2676 return(columns);
2677}
2678
2679#if defined(__cplusplus) || defined(c_plusplus)
2680}
2681#endif
2682
2683MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2684 const size_t length,ExceptionInfo *exception)
2685{
2686 Image
2687 *image;
2688
2689 ImageInfo
2690 *ping_info;
2691
2692 assert(image_info != (ImageInfo *) NULL);
2693 assert(image_info->signature == MagickSignature);
2694 if (image_info->debug != MagickFalse)
2695 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2696 image_info->filename);
2697 assert(exception != (ExceptionInfo *) NULL);
2698 if ((blob == (const void *) NULL) || (length == 0))
2699 {
2700 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
anthonye5b39652012-04-21 05:37:29 +00002701 "UnrecognizedImageFormat","'%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002702 return((Image *) NULL);
2703 }
2704 ping_info=CloneImageInfo(image_info);
2705 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2706 if (ping_info->blob == (const void *) NULL)
2707 {
2708 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00002709 ResourceLimitFatalError,"MemoryAllocationFailed","'%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002710 return((Image *) NULL);
2711 }
cristy54aad5e2010-09-03 16:02:04 +00002712 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002713 ping_info->length=length;
2714 ping_info->ping=MagickTrue;
2715 image=ReadStream(ping_info,&PingStream,exception);
2716 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2717 ping_info=DestroyImageInfo(ping_info);
2718 return(image);
2719}
2720
2721/*
2722%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2723% %
2724% %
2725% %
2726+ R e a d B l o b %
2727% %
2728% %
2729% %
2730%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2731%
2732% ReadBlob() reads data from the blob or image file and returns it. It
2733% returns the number of bytes read.
2734%
2735% The format of the ReadBlob method is:
2736%
2737% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2738%
2739% A description of each parameter follows:
2740%
2741% o image: the image.
2742%
2743% o length: Specifies an integer representing the number of bytes to read
2744% from the file.
2745%
2746% o data: Specifies an area to place the information requested from the
2747% file.
2748%
2749*/
2750MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2751 unsigned char *data)
2752{
2753 int
2754 c;
2755
2756 register unsigned char
2757 *q;
2758
2759 ssize_t
2760 count;
2761
2762 assert(image != (Image *) NULL);
2763 assert(image->signature == MagickSignature);
2764 assert(image->blob != (BlobInfo *) NULL);
2765 assert(image->blob->type != UndefinedStream);
2766 if (length == 0)
2767 return(0);
2768 assert(data != (void *) NULL);
2769 count=0;
2770 q=data;
2771 switch (image->blob->type)
2772 {
2773 case UndefinedStream:
2774 break;
cristy3ed852e2009-09-05 21:47:34 +00002775 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002776 {
cristye4085b12012-10-20 22:52:08 +00002777 register ssize_t
2778 i;
2779
2780 count=0;
2781 for (i=0; i < (ssize_t) length; i+=count)
2782 {
cristy8e3de442012-10-20 22:57:32 +00002783 count=read(fileno(image->blob->file_info.file),q+i,(size_t) MagickMin(
2784 length-i,SSIZE_MAX));
cristya2538e12012-10-21 00:41:31 +00002785 if (count <= 0)
cristye4085b12012-10-20 22:52:08 +00002786 {
cristya2538e12012-10-21 00:41:31 +00002787 count=0;
2788 if (errno != EINTR)
2789 break;
cristye4085b12012-10-20 22:52:08 +00002790 }
2791 }
2792 count=i;
cristybc20d112012-07-29 20:27:00 +00002793 break;
2794 }
2795 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002796 case PipeStream:
2797 {
2798 switch (length)
2799 {
2800 default:
2801 {
cristye7b28372012-06-17 13:59:06 +00002802 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002803 break;
2804 }
2805 case 2:
2806 {
cristye7b28372012-06-17 13:59:06 +00002807 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002808 if (c == EOF)
2809 break;
2810 *q++=(unsigned char) c;
2811 count++;
2812 }
2813 case 1:
2814 {
cristye7b28372012-06-17 13:59:06 +00002815 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002816 if (c == EOF)
2817 break;
2818 *q++=(unsigned char) c;
2819 count++;
2820 }
2821 case 0:
2822 break;
2823 }
2824 break;
2825 }
2826 case ZipStream:
2827 {
2828#if defined(MAGICKCORE_ZLIB_DELEGATE)
2829 switch (length)
2830 {
2831 default:
2832 {
cristye7b28372012-06-17 13:59:06 +00002833 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002834 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002835 break;
2836 }
2837 case 2:
2838 {
cristye7b28372012-06-17 13:59:06 +00002839 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002840 if (c == EOF)
2841 break;
2842 *q++=(unsigned char) c;
2843 count++;
2844 }
2845 case 1:
2846 {
cristye7b28372012-06-17 13:59:06 +00002847 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002848 if (c == EOF)
2849 break;
2850 *q++=(unsigned char) c;
2851 count++;
2852 }
2853 case 0:
2854 break;
2855 }
2856#endif
2857 break;
2858 }
2859 case BZipStream:
2860 {
2861#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00002862 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,
cristy95888612012-04-04 21:56:52 +00002863 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00002864#endif
2865 break;
2866 }
2867 case FifoStream:
2868 break;
2869 case BlobStream:
2870 {
2871 register const unsigned char
2872 *p;
2873
2874 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2875 {
2876 image->blob->eof=MagickTrue;
2877 break;
2878 }
2879 p=image->blob->data+image->blob->offset;
cristye7b28372012-06-17 13:59:06 +00002880 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2881 image->blob->offset));
cristy3ed852e2009-09-05 21:47:34 +00002882 image->blob->offset+=count;
2883 if (count != (ssize_t) length)
2884 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002885 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002886 break;
2887 }
2888 }
2889 return(count);
2890}
2891
2892/*
2893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2894% %
2895% %
2896% %
2897+ R e a d B l o b B y t e %
2898% %
2899% %
2900% %
2901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2902%
2903% ReadBlobByte() reads a single byte from the image file and returns it.
2904%
2905% The format of the ReadBlobByte method is:
2906%
2907% int ReadBlobByte(Image *image)
2908%
2909% A description of each parameter follows.
2910%
2911% o image: the image.
2912%
2913*/
2914MagickExport int ReadBlobByte(Image *image)
2915{
2916 register const unsigned char
2917 *p;
2918
2919 ssize_t
2920 count;
2921
2922 unsigned char
2923 buffer[1];
2924
2925 assert(image != (Image *) NULL);
2926 assert(image->signature == MagickSignature);
2927 p=ReadBlobStream(image,1,buffer,&count);
2928 if (count != 1)
2929 return(EOF);
2930 return((int) (*p));
2931}
2932
2933/*
2934%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2935% %
2936% %
2937% %
2938+ R e a d B l o b D o u b l e %
2939% %
2940% %
2941% %
2942%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2943%
2944% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2945% specified by the endian member of the image structure.
2946%
2947% The format of the ReadBlobDouble method is:
2948%
2949% double ReadBlobDouble(Image *image)
2950%
2951% A description of each parameter follows.
2952%
2953% o image: the image.
2954%
2955*/
2956MagickExport double ReadBlobDouble(Image *image)
2957{
2958 union
2959 {
2960 MagickSizeType
2961 unsigned_value;
2962
2963 double
2964 double_value;
2965 } quantum;
2966
2967 quantum.double_value=0.0;
2968 quantum.unsigned_value=ReadBlobLongLong(image);
2969 return(quantum.double_value);
2970}
2971
2972/*
2973%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2974% %
2975% %
2976% %
2977+ R e a d B l o b F l o a t %
2978% %
2979% %
2980% %
2981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2982%
2983% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2984% specified by the endian member of the image structure.
2985%
2986% The format of the ReadBlobFloat method is:
2987%
2988% float ReadBlobFloat(Image *image)
2989%
2990% A description of each parameter follows.
2991%
2992% o image: the image.
2993%
2994*/
2995MagickExport float ReadBlobFloat(Image *image)
2996{
2997 union
2998 {
2999 unsigned int
3000 unsigned_value;
3001
3002 float
3003 float_value;
3004 } quantum;
3005
3006 quantum.float_value=0.0;
3007 quantum.unsigned_value=ReadBlobLong(image);
3008 return(quantum.float_value);
3009}
3010
3011/*
3012%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3013% %
3014% %
3015% %
3016+ R e a d B l o b L o n g %
3017% %
3018% %
3019% %
3020%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3021%
cristybb503372010-05-27 20:51:26 +00003022% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003023% specified by the endian member of the image structure.
3024%
3025% The format of the ReadBlobLong method is:
3026%
3027% unsigned int ReadBlobLong(Image *image)
3028%
3029% A description of each parameter follows.
3030%
3031% o image: the image.
3032%
3033*/
3034MagickExport unsigned int ReadBlobLong(Image *image)
3035{
3036 register const unsigned char
3037 *p;
3038
3039 ssize_t
3040 count;
3041
3042 unsigned char
3043 buffer[4];
3044
3045 unsigned int
3046 value;
3047
3048 assert(image != (Image *) NULL);
3049 assert(image->signature == MagickSignature);
3050 *buffer='\0';
3051 p=ReadBlobStream(image,4,buffer,&count);
3052 if (count != 4)
3053 return(0UL);
3054 if (image->endian == LSBEndian)
3055 {
3056 value=(unsigned int) (*p++);
3057 value|=((unsigned int) (*p++)) << 8;
3058 value|=((unsigned int) (*p++)) << 16;
3059 value|=((unsigned int) (*p++)) << 24;
3060 return(value);
3061 }
3062 value=((unsigned int) (*p++)) << 24;
3063 value|=((unsigned int) (*p++)) << 16;
3064 value|=((unsigned int) (*p++)) << 8;
3065 value|=((unsigned int) (*p++));
3066 return(value);
3067}
3068
3069/*
3070%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3071% %
3072% %
3073% %
3074+ R e a d B l o b L o n g L o n g %
3075% %
3076% %
3077% %
3078%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3079%
cristy4cb162a2010-05-30 03:04:47 +00003080% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3081% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003082%
cristy4cb162a2010-05-30 03:04:47 +00003083% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003084%
cristy4cb162a2010-05-30 03:04:47 +00003085% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003086%
3087% A description of each parameter follows.
3088%
3089% o image: the image.
3090%
3091*/
3092MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3093{
cristy0286d852010-10-12 18:38:07 +00003094 MagickSizeType
3095 value;
3096
cristy3ed852e2009-09-05 21:47:34 +00003097 register const unsigned char
3098 *p;
3099
3100 ssize_t
3101 count;
3102
3103 unsigned char
3104 buffer[8];
3105
cristy3ed852e2009-09-05 21:47:34 +00003106 assert(image != (Image *) NULL);
3107 assert(image->signature == MagickSignature);
3108 *buffer='\0';
3109 p=ReadBlobStream(image,8,buffer,&count);
3110 if (count != 8)
3111 return(MagickULLConstant(0));
3112 if (image->endian == LSBEndian)
3113 {
3114 value=(MagickSizeType) (*p++);
3115 value|=((MagickSizeType) (*p++)) << 8;
3116 value|=((MagickSizeType) (*p++)) << 16;
3117 value|=((MagickSizeType) (*p++)) << 24;
3118 value|=((MagickSizeType) (*p++)) << 32;
3119 value|=((MagickSizeType) (*p++)) << 40;
3120 value|=((MagickSizeType) (*p++)) << 48;
3121 value|=((MagickSizeType) (*p++)) << 56;
3122 return(value & MagickULLConstant(0xffffffffffffffff));
3123 }
3124 value=((MagickSizeType) (*p++)) << 56;
3125 value|=((MagickSizeType) (*p++)) << 48;
3126 value|=((MagickSizeType) (*p++)) << 40;
3127 value|=((MagickSizeType) (*p++)) << 32;
3128 value|=((MagickSizeType) (*p++)) << 24;
3129 value|=((MagickSizeType) (*p++)) << 16;
3130 value|=((MagickSizeType) (*p++)) << 8;
3131 value|=((MagickSizeType) (*p++));
3132 return(value & MagickULLConstant(0xffffffffffffffff));
3133}
3134
3135/*
3136%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3137% %
3138% %
3139% %
3140+ R e a d B l o b S h o r t %
3141% %
3142% %
3143% %
3144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3145%
3146% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3147% specified by the endian member of the image structure.
3148%
3149% The format of the ReadBlobShort method is:
3150%
3151% unsigned short ReadBlobShort(Image *image)
3152%
3153% A description of each parameter follows.
3154%
3155% o image: the image.
3156%
3157*/
3158MagickExport unsigned short ReadBlobShort(Image *image)
3159{
3160 register const unsigned char
3161 *p;
3162
3163 register unsigned int
3164 value;
3165
3166 ssize_t
3167 count;
3168
3169 unsigned char
3170 buffer[2];
3171
3172 assert(image != (Image *) NULL);
3173 assert(image->signature == MagickSignature);
3174 *buffer='\0';
3175 p=ReadBlobStream(image,2,buffer,&count);
3176 if (count != 2)
3177 return((unsigned short) 0U);
3178 if (image->endian == LSBEndian)
3179 {
3180 value=(unsigned int) (*p++);
3181 value|=((unsigned int) (*p++)) << 8;
3182 return((unsigned short) (value & 0xffff));
3183 }
3184 value=(unsigned int) ((*p++) << 8);
3185 value|=(unsigned int) (*p++);
3186 return((unsigned short) (value & 0xffff));
3187}
3188
3189/*
3190%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3191% %
3192% %
3193% %
3194+ R e a d B l o b L S B L o n g %
3195% %
3196% %
3197% %
3198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3199%
cristybb503372010-05-27 20:51:26 +00003200% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003201% least-significant byte first order.
3202%
3203% The format of the ReadBlobLSBLong method is:
3204%
3205% unsigned int ReadBlobLSBLong(Image *image)
3206%
3207% A description of each parameter follows.
3208%
3209% o image: the image.
3210%
3211*/
3212MagickExport unsigned int ReadBlobLSBLong(Image *image)
3213{
3214 register const unsigned char
3215 *p;
3216
3217 register unsigned int
3218 value;
3219
3220 ssize_t
3221 count;
3222
3223 unsigned char
3224 buffer[4];
3225
3226 assert(image != (Image *) NULL);
3227 assert(image->signature == MagickSignature);
3228 *buffer='\0';
3229 p=ReadBlobStream(image,4,buffer,&count);
3230 if (count != 4)
3231 return(0U);
3232 value=(unsigned int) (*p++);
3233 value|=((unsigned int) (*p++)) << 8;
3234 value|=((unsigned int) (*p++)) << 16;
3235 value|=((unsigned int) (*p++)) << 24;
3236 return(value);
3237}
3238
3239/*
3240%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3241% %
3242% %
3243% %
3244+ R e a d B l o b L S B S h o r t %
3245% %
3246% %
3247% %
3248%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3249%
3250% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3251% least-significant byte first order.
3252%
3253% The format of the ReadBlobLSBShort method is:
3254%
3255% unsigned short ReadBlobLSBShort(Image *image)
3256%
3257% A description of each parameter follows.
3258%
3259% o image: the image.
3260%
3261*/
3262MagickExport unsigned short ReadBlobLSBShort(Image *image)
3263{
3264 register const unsigned char
3265 *p;
3266
3267 register unsigned int
3268 value;
3269
3270 ssize_t
3271 count;
3272
3273 unsigned char
3274 buffer[2];
3275
3276 assert(image != (Image *) NULL);
3277 assert(image->signature == MagickSignature);
3278 *buffer='\0';
3279 p=ReadBlobStream(image,2,buffer,&count);
3280 if (count != 2)
3281 return((unsigned short) 0U);
3282 value=(unsigned int) (*p++);
3283 value|=((unsigned int) ((*p++)) << 8);
3284 return((unsigned short) (value & 0xffff));
3285}
3286
3287/*
3288%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3289% %
3290% %
3291% %
3292+ R e a d B l o b M S B L o n g %
3293% %
3294% %
3295% %
3296%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3297%
cristybb503372010-05-27 20:51:26 +00003298% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003299% most-significant byte first order.
3300%
3301% The format of the ReadBlobMSBLong method is:
3302%
3303% unsigned int ReadBlobMSBLong(Image *image)
3304%
3305% A description of each parameter follows.
3306%
3307% o image: the image.
3308%
3309*/
3310MagickExport unsigned int ReadBlobMSBLong(Image *image)
3311{
3312 register const unsigned char
3313 *p;
3314
3315 register unsigned int
3316 value;
3317
3318 ssize_t
3319 count;
3320
3321 unsigned char
3322 buffer[4];
3323
3324 assert(image != (Image *) NULL);
3325 assert(image->signature == MagickSignature);
3326 *buffer='\0';
3327 p=ReadBlobStream(image,4,buffer,&count);
3328 if (count != 4)
3329 return(0UL);
3330 value=((unsigned int) (*p++) << 24);
3331 value|=((unsigned int) (*p++) << 16);
3332 value|=((unsigned int) (*p++) << 8);
3333 value|=(unsigned int) (*p++);
3334 return(value);
3335}
3336
3337/*
3338%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3339% %
3340% %
3341% %
cristy2d3d87f2010-03-01 00:23:08 +00003342+ R e a d B l o b M S B L o n g L o n g %
3343% %
3344% %
3345% %
3346%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3347%
cristybb503372010-05-27 20:51:26 +00003348% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003349% most-significant byte first order.
3350%
3351% The format of the ReadBlobMSBLongLong method is:
3352%
3353% unsigned int ReadBlobMSBLongLong(Image *image)
3354%
3355% A description of each parameter follows.
3356%
3357% o image: the image.
3358%
3359*/
3360MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3361{
3362 register const unsigned char
3363 *p;
3364
3365 register MagickSizeType
3366 value;
3367
3368 ssize_t
3369 count;
3370
3371 unsigned char
cristy0286d852010-10-12 18:38:07 +00003372 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003373
3374 assert(image != (Image *) NULL);
3375 assert(image->signature == MagickSignature);
3376 *buffer='\0';
3377 p=ReadBlobStream(image,8,buffer,&count);
3378 if (count != 8)
3379 return(MagickULLConstant(0));
3380 value=((MagickSizeType) (*p++)) << 56;
3381 value|=((MagickSizeType) (*p++)) << 48;
3382 value|=((MagickSizeType) (*p++)) << 40;
3383 value|=((MagickSizeType) (*p++)) << 32;
3384 value|=((MagickSizeType) (*p++)) << 24;
3385 value|=((MagickSizeType) (*p++)) << 16;
3386 value|=((MagickSizeType) (*p++)) << 8;
3387 value|=((MagickSizeType) (*p++));
3388 return(value & MagickULLConstant(0xffffffffffffffff));
3389}
3390
3391/*
3392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3393% %
3394% %
3395% %
cristy3ed852e2009-09-05 21:47:34 +00003396+ R e a d B l o b M S B S h o r t %
3397% %
3398% %
3399% %
3400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3401%
3402% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3403% most-significant byte first order.
3404%
3405% The format of the ReadBlobMSBShort method is:
3406%
3407% unsigned short ReadBlobMSBShort(Image *image)
3408%
3409% A description of each parameter follows.
3410%
3411% o image: the image.
3412%
3413*/
3414MagickExport unsigned short ReadBlobMSBShort(Image *image)
3415{
3416 register const unsigned char
3417 *p;
3418
3419 register unsigned int
3420 value;
3421
3422 ssize_t
3423 count;
3424
3425 unsigned char
3426 buffer[2];
3427
3428 assert(image != (Image *) NULL);
3429 assert(image->signature == MagickSignature);
3430 *buffer='\0';
3431 p=ReadBlobStream(image,2,buffer,&count);
3432 if (count != 2)
3433 return((unsigned short) 0U);
3434 value=(unsigned int) ((*p++) << 8);
3435 value|=(unsigned int) (*p++);
3436 return((unsigned short) (value & 0xffff));
3437}
3438
3439/*
3440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3441% %
3442% %
3443% %
3444+ R e a d B l o b S t r i n g %
3445% %
3446% %
3447% %
3448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3449%
3450% ReadBlobString() reads characters from a blob or file until a newline
3451% character is read or an end-of-file condition is encountered.
3452%
3453% The format of the ReadBlobString method is:
3454%
3455% char *ReadBlobString(Image *image,char *string)
3456%
3457% A description of each parameter follows:
3458%
3459% o image: the image.
3460%
3461% o string: the address of a character buffer.
3462%
3463*/
3464MagickExport char *ReadBlobString(Image *image,char *string)
3465{
3466 register const unsigned char
3467 *p;
3468
cristybb503372010-05-27 20:51:26 +00003469 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003470 i;
3471
3472 ssize_t
3473 count;
3474
3475 unsigned char
3476 buffer[1];
3477
3478 assert(image != (Image *) NULL);
3479 assert(image->signature == MagickSignature);
3480 for (i=0; i < (MaxTextExtent-1L); i++)
3481 {
3482 p=ReadBlobStream(image,1,buffer,&count);
3483 if (count != 1)
3484 {
3485 if (i == 0)
3486 return((char *) NULL);
3487 break;
3488 }
3489 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003490 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003491 break;
3492 }
cristy2b5db102010-06-09 01:07:28 +00003493 if (string[i] == '\r')
3494 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003495 string[i]='\0';
3496 return(string);
3497}
3498
3499/*
3500%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3501% %
3502% %
3503% %
3504+ R e f e r e n c e B l o b %
3505% %
3506% %
3507% %
3508%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3509%
3510% ReferenceBlob() increments the reference count associated with the pixel
3511% blob returning a pointer to the blob.
3512%
3513% The format of the ReferenceBlob method is:
3514%
3515% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3516%
3517% A description of each parameter follows:
3518%
3519% o blob_info: the blob_info.
3520%
3521*/
3522MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3523{
3524 assert(blob != (BlobInfo *) NULL);
3525 assert(blob->signature == MagickSignature);
3526 if (blob->debug != MagickFalse)
3527 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003528 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003529 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003530 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003531 return(blob);
3532}
3533
3534/*
3535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3536% %
3537% %
3538% %
3539+ S e e k B l o b %
3540% %
3541% %
3542% %
3543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3544%
3545% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3546% and returns the resulting offset.
3547%
3548% The format of the SeekBlob method is:
3549%
3550% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3551% const int whence)
3552%
3553% A description of each parameter follows:
3554%
3555% o image: the image.
3556%
3557% o offset: Specifies an integer representing the offset in bytes.
3558%
3559% o whence: Specifies an integer representing how the offset is
3560% treated relative to the beginning of the blob as follows:
3561%
3562% SEEK_SET Set position equal to offset bytes.
3563% SEEK_CUR Set position to current location plus offset.
3564% SEEK_END Set position to EOF plus offset.
3565%
3566*/
3567MagickExport MagickOffsetType SeekBlob(Image *image,
3568 const MagickOffsetType offset,const int whence)
3569{
3570 assert(image != (Image *) NULL);
3571 assert(image->signature == MagickSignature);
3572 if (image->debug != MagickFalse)
3573 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3574 assert(image->blob != (BlobInfo *) NULL);
3575 assert(image->blob->type != UndefinedStream);
3576 switch (image->blob->type)
3577 {
3578 case UndefinedStream:
3579 break;
cristybc20d112012-07-29 20:27:00 +00003580 case StandardStream:
3581 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003582 case FileStream:
3583 {
cristye7b28372012-06-17 13:59:06 +00003584 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003585 return(-1);
3586 image->blob->offset=TellBlob(image);
3587 break;
3588 }
cristy3ed852e2009-09-05 21:47:34 +00003589 case PipeStream:
3590 case ZipStream:
3591 {
3592#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003593 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003594 return(-1);
3595#endif
3596 image->blob->offset=TellBlob(image);
3597 break;
3598 }
3599 case BZipStream:
3600 return(-1);
3601 case FifoStream:
3602 return(-1);
3603 case BlobStream:
3604 {
3605 switch (whence)
3606 {
3607 case SEEK_SET:
3608 default:
3609 {
3610 if (offset < 0)
3611 return(-1);
3612 image->blob->offset=offset;
3613 break;
3614 }
3615 case SEEK_CUR:
3616 {
3617 if ((image->blob->offset+offset) < 0)
3618 return(-1);
3619 image->blob->offset+=offset;
3620 break;
3621 }
3622 case SEEK_END:
3623 {
3624 if (((MagickOffsetType) image->blob->length+offset) < 0)
3625 return(-1);
3626 image->blob->offset=image->blob->length+offset;
3627 break;
3628 }
3629 }
3630 if (image->blob->offset <= (MagickOffsetType)
3631 ((off_t) image->blob->length))
3632 image->blob->eof=MagickFalse;
3633 else
3634 if (image->blob->mapped != MagickFalse)
3635 return(-1);
3636 else
3637 {
3638 image->blob->extent=(size_t) (image->blob->offset+
3639 image->blob->quantum);
3640 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3641 image->blob->data,image->blob->extent+1,
3642 sizeof(*image->blob->data));
3643 (void) SyncBlob(image);
3644 if (image->blob->data == (unsigned char *) NULL)
3645 {
3646 (void) DetachBlob(image->blob);
3647 return(-1);
3648 }
3649 }
3650 break;
3651 }
3652 }
3653 return(image->blob->offset);
3654}
3655
3656/*
3657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3658% %
3659% %
3660% %
3661+ S e t B l o b E x e m p t %
3662% %
3663% %
3664% %
3665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3666%
3667% SetBlobExempt() sets the blob exempt status.
3668%
3669% The format of the SetBlobExempt method is:
3670%
3671% MagickBooleanType SetBlobExempt(const Image *image,
3672% const MagickBooleanType exempt)
3673%
3674% A description of each parameter follows:
3675%
3676% o image: the image.
3677%
3678% o exempt: Set to true if this blob is exempt from being closed.
3679%
3680*/
cristy7832dc22011-09-05 01:21:53 +00003681MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003682{
3683 assert(image != (const Image *) NULL);
3684 assert(image->signature == MagickSignature);
3685 if (image->debug != MagickFalse)
3686 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3687 image->blob->exempt=exempt;
3688}
3689
3690/*
3691%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3692% %
3693% %
3694% %
3695+ S e t B l o b E x t e n t %
3696% %
3697% %
3698% %
3699%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3700%
3701% SetBlobExtent() ensures enough space is allocated for the blob. If the
3702% method is successful, subsequent writes to bytes in the specified range are
3703% guaranteed not to fail.
3704%
3705% The format of the SetBlobExtent method is:
3706%
3707% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3708%
3709% A description of each parameter follows:
3710%
3711% o image: the image.
3712%
3713% o extent: the blob maximum extent.
3714%
3715*/
cristy7832dc22011-09-05 01:21:53 +00003716MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003717 const MagickSizeType extent)
3718{
3719 assert(image != (Image *) NULL);
3720 assert(image->signature == MagickSignature);
3721 if (image->debug != MagickFalse)
3722 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3723 assert(image->blob != (BlobInfo *) NULL);
3724 assert(image->blob->type != UndefinedStream);
3725 switch (image->blob->type)
3726 {
3727 case UndefinedStream:
3728 break;
cristybc20d112012-07-29 20:27:00 +00003729 case StandardStream:
3730 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003731 case FileStream:
3732 {
cristy38e35f42012-12-18 21:12:17 +00003733 MagickOffsetType
3734 offset;
3735
3736 ssize_t
3737 count;
3738
cristy3ed852e2009-09-05 21:47:34 +00003739 if (extent != (MagickSizeType) ((off_t) extent))
3740 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003741 offset=SeekBlob(image,0,SEEK_END);
3742 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003743 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003744 if ((MagickSizeType) offset >= extent)
3745 break;
3746 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
3747 count=fwrite((const unsigned char *) "",1,1,image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003748#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3749 if (image->blob->synchronize != MagickFalse)
3750 {
3751 int
3752 status;
3753
3754 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3755 extent-offset);
3756 if (status != 0)
3757 return(MagickFalse);
3758 }
3759#endif
cristy38e35f42012-12-18 21:12:17 +00003760 offset=SeekBlob(image,offset,SEEK_SET);
3761 if (count != (MagickOffsetType) 1)
3762 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003763 break;
3764 }
cristy3ed852e2009-09-05 21:47:34 +00003765 case PipeStream:
3766 case ZipStream:
3767 return(MagickFalse);
3768 case BZipStream:
3769 return(MagickFalse);
3770 case FifoStream:
3771 return(MagickFalse);
3772 case BlobStream:
3773 {
cristy38e35f42012-12-18 21:12:17 +00003774 if (extent != (MagickSizeType) ((size_t) extent))
3775 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003776 if (image->blob->mapped != MagickFalse)
3777 {
cristy38e35f42012-12-18 21:12:17 +00003778 MagickOffsetType
3779 offset;
3780
3781 ssize_t
3782 count;
3783
cristy3ed852e2009-09-05 21:47:34 +00003784 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003785 if (extent != (MagickSizeType) ((off_t) extent))
3786 return(MagickFalse);
3787 offset=SeekBlob(image,0,SEEK_END);
3788 if (offset < 0)
3789 return(MagickFalse);
3790 if ((MagickSizeType) offset >= extent)
3791 break;
3792 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
3793 count=fwrite((const unsigned char *) "",1,1,
3794 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003795#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3796 if (image->blob->synchronize != MagickFalse)
3797 {
3798 int
3799 status;
3800
3801 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3802 extent-offset);
3803 if (status != 0)
3804 return(MagickFalse);
3805 }
3806#endif
cristy38e35f42012-12-18 21:12:17 +00003807 offset=SeekBlob(image,offset,SEEK_SET);
3808 if (count != (MagickOffsetType) 1)
3809 return(MagickTrue);
cristy95888612012-04-04 21:56:52 +00003810 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003811 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003812 image->blob->extent=(size_t) extent;
3813 image->blob->length=(size_t) extent;
3814 (void) SyncBlob(image);
3815 break;
cristy3ed852e2009-09-05 21:47:34 +00003816 }
cristy3ed852e2009-09-05 21:47:34 +00003817 image->blob->extent=(size_t) extent;
3818 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3819 image->blob->extent+1,sizeof(*image->blob->data));
3820 (void) SyncBlob(image);
3821 if (image->blob->data == (unsigned char *) NULL)
3822 {
3823 (void) DetachBlob(image->blob);
3824 return(MagickFalse);
3825 }
3826 break;
3827 }
3828 }
3829 return(MagickTrue);
3830}
3831
3832/*
3833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3834% %
3835% %
3836% %
3837+ S y n c B l o b %
3838% %
3839% %
3840% %
3841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3842%
3843% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3844% attributes if it is an blob.
3845%
3846% The format of the SyncBlob method is:
3847%
3848% int SyncBlob(Image *image)
3849%
3850% A description of each parameter follows:
3851%
3852% o image: the image.
3853%
3854*/
3855static int SyncBlob(Image *image)
3856{
3857 int
3858 status;
3859
3860 assert(image != (Image *) NULL);
3861 assert(image->signature == MagickSignature);
3862 if (image->debug != MagickFalse)
3863 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3864 assert(image->blob != (BlobInfo *) NULL);
3865 assert(image->blob->type != UndefinedStream);
3866 status=0;
3867 switch (image->blob->type)
3868 {
3869 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003870 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003871 break;
3872 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003873 case PipeStream:
3874 {
cristye7b28372012-06-17 13:59:06 +00003875 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003876 break;
3877 }
3878 case ZipStream:
3879 {
3880#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003881 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003882#endif
3883 break;
3884 }
3885 case BZipStream:
3886 {
3887#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003888 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003889#endif
3890 break;
3891 }
3892 case FifoStream:
3893 break;
3894 case BlobStream:
3895 {
3896#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3897 if (image->blob->mapped != MagickFalse)
3898 status=msync(image->blob->data,image->blob->length,MS_SYNC);
3899#endif
3900 break;
3901 }
3902 }
3903 return(status);
3904}
3905
3906/*
3907%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3908% %
3909% %
3910% %
3911+ T e l l B l o b %
3912% %
3913% %
3914% %
3915%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3916%
3917% TellBlob() obtains the current value of the blob or file position.
3918%
3919% The format of the TellBlob method is:
3920%
3921% MagickOffsetType TellBlob(const Image *image)
3922%
3923% A description of each parameter follows:
3924%
3925% o image: the image.
3926%
3927*/
3928MagickExport MagickOffsetType TellBlob(const Image *image)
3929{
3930 MagickOffsetType
3931 offset;
3932
3933 assert(image != (Image *) NULL);
3934 assert(image->signature == MagickSignature);
3935 if (image->debug != MagickFalse)
3936 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3937 assert(image->blob != (BlobInfo *) NULL);
3938 assert(image->blob->type != UndefinedStream);
3939 offset=(-1);
3940 switch (image->blob->type)
3941 {
3942 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003943 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003944 break;
3945 case FileStream:
3946 {
cristye7b28372012-06-17 13:59:06 +00003947 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003948 break;
3949 }
cristy3ed852e2009-09-05 21:47:34 +00003950 case PipeStream:
3951 break;
3952 case ZipStream:
3953 {
3954#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003955 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003956#endif
3957 break;
3958 }
3959 case BZipStream:
3960 break;
3961 case FifoStream:
3962 break;
3963 case BlobStream:
3964 {
3965 offset=image->blob->offset;
3966 break;
3967 }
3968 }
3969 return(offset);
3970}
3971
3972/*
3973%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3974% %
3975% %
3976% %
3977+ U n m a p B l o b %
3978% %
3979% %
3980% %
3981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3982%
3983% UnmapBlob() deallocates the binary large object previously allocated with
3984% the MapBlob method.
3985%
3986% The format of the UnmapBlob method is:
3987%
3988% MagickBooleanType UnmapBlob(void *map,const size_t length)
3989%
3990% A description of each parameter follows:
3991%
3992% o map: the address of the binary large object.
3993%
3994% o length: the length of the binary large object.
3995%
3996*/
3997MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3998{
3999#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
4000 int
4001 status;
4002
4003 status=munmap(map,length);
4004 return(status == -1 ? MagickFalse : MagickTrue);
4005#else
4006 (void) map;
4007 (void) length;
4008 return(MagickFalse);
4009#endif
4010}
4011
4012/*
4013%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4014% %
4015% %
4016% %
4017+ W r i t e B l o b %
4018% %
4019% %
4020% %
4021%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4022%
4023% WriteBlob() writes data to a blob or image file. It returns the number of
4024% bytes written.
4025%
4026% The format of the WriteBlob method is:
4027%
4028% ssize_t WriteBlob(Image *image,const size_t length,
4029% const unsigned char *data)
4030%
4031% A description of each parameter follows:
4032%
4033% o image: the image.
4034%
4035% o length: Specifies an integer representing the number of bytes to
4036% write to the file.
4037%
4038% o data: The address of the data to write to the blob or file.
4039%
4040*/
4041MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4042 const unsigned char *data)
4043{
4044 int
4045 c;
4046
4047 register const unsigned char
4048 *p;
4049
4050 ssize_t
4051 count;
4052
4053 assert(image != (Image *) NULL);
4054 assert(image->signature == MagickSignature);
4055 assert(data != (const unsigned char *) NULL);
4056 assert(image->blob != (BlobInfo *) NULL);
4057 assert(image->blob->type != UndefinedStream);
4058 if (length == 0)
4059 return(0);
4060 count=0;
4061 p=data;
4062 switch (image->blob->type)
4063 {
4064 case UndefinedStream:
4065 break;
cristy3ed852e2009-09-05 21:47:34 +00004066 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004067 {
cristye4085b12012-10-20 22:52:08 +00004068 register ssize_t
4069 i;
4070
4071 count=0;
4072 for (i=0; i < (MagickOffsetType) length; i+=count)
4073 {
4074 count=write(fileno(image->blob->file_info.file),data+i,(size_t)
cristy8e3de442012-10-20 22:57:32 +00004075 MagickMin(length-i,SSIZE_MAX));
cristya2538e12012-10-21 00:41:31 +00004076 if (count <= 0)
cristye4085b12012-10-20 22:52:08 +00004077 {
cristya2538e12012-10-21 00:41:31 +00004078 count=0;
4079 if (errno != EINTR)
4080 break;
cristye4085b12012-10-20 22:52:08 +00004081 }
4082 }
4083 count=i;
cristybc20d112012-07-29 20:27:00 +00004084 break;
4085 }
4086 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004087 case PipeStream:
4088 {
4089 switch (length)
4090 {
4091 default:
4092 {
4093 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004094 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004095 break;
4096 }
4097 case 2:
4098 {
cristye7b28372012-06-17 13:59:06 +00004099 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004100 if (c == EOF)
4101 break;
4102 count++;
4103 }
4104 case 1:
4105 {
cristye7b28372012-06-17 13:59:06 +00004106 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004107 if (c == EOF)
4108 break;
4109 count++;
4110 }
4111 case 0:
4112 break;
4113 }
4114 break;
4115 }
4116 case ZipStream:
4117 {
4118#if defined(MAGICKCORE_ZLIB_DELEGATE)
4119 switch (length)
4120 {
4121 default:
4122 {
cristye7b28372012-06-17 13:59:06 +00004123 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004124 (unsigned int) length);
4125 break;
4126 }
4127 case 2:
4128 {
cristye7b28372012-06-17 13:59:06 +00004129 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004130 if (c == EOF)
4131 break;
4132 count++;
4133 }
4134 case 1:
4135 {
cristye7b28372012-06-17 13:59:06 +00004136 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004137 if (c == EOF)
4138 break;
4139 count++;
4140 }
4141 case 0:
4142 break;
4143 }
4144#endif
4145 break;
4146 }
4147 case BZipStream:
4148 {
4149#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004150 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004151 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004152#endif
4153 break;
4154 }
4155 case FifoStream:
4156 {
4157 count=(ssize_t) image->blob->stream(image,data,length);
4158 break;
4159 }
4160 case BlobStream:
4161 {
4162 register unsigned char
4163 *q;
4164
4165 if ((image->blob->offset+(MagickOffsetType) length) >=
4166 (MagickOffsetType) image->blob->extent)
4167 {
4168 if (image->blob->mapped != MagickFalse)
4169 return(0);
4170 image->blob->quantum<<=1;
4171 image->blob->extent+=length+image->blob->quantum;
4172 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4173 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4174 (void) SyncBlob(image);
4175 if (image->blob->data == (unsigned char *) NULL)
4176 {
4177 (void) DetachBlob(image->blob);
4178 return(0);
4179 }
4180 }
4181 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004182 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004183 image->blob->offset+=length;
4184 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4185 image->blob->length=(size_t) image->blob->offset;
4186 count=(ssize_t) length;
4187 }
4188 }
4189 return(count);
4190}
4191
4192/*
4193%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4194% %
4195% %
4196% %
4197+ W r i t e B l o b B y t e %
4198% %
4199% %
4200% %
4201%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4202%
4203% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4204% written (either 0 or 1);
4205%
4206% The format of the WriteBlobByte method is:
4207%
4208% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4209%
4210% A description of each parameter follows.
4211%
4212% o image: the image.
4213%
4214% o value: Specifies the value to write.
4215%
4216*/
4217MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4218{
4219 assert(image != (Image *) NULL);
4220 assert(image->signature == MagickSignature);
4221 return(WriteBlobStream(image,1,&value));
4222}
4223
4224/*
4225%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4226% %
4227% %
4228% %
4229+ W r i t e B l o b F l o a t %
4230% %
4231% %
4232% %
4233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4234%
4235% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4236% specified by the endian member of the image structure.
4237%
4238% The format of the WriteBlobFloat method is:
4239%
4240% ssize_t WriteBlobFloat(Image *image,const float value)
4241%
4242% A description of each parameter follows.
4243%
4244% o image: the image.
4245%
4246% o value: Specifies the value to write.
4247%
4248*/
4249MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4250{
4251 union
4252 {
4253 unsigned int
4254 unsigned_value;
4255
4256 float
4257 float_value;
4258 } quantum;
4259
4260 quantum.unsigned_value=0U;
4261 quantum.float_value=value;
4262 return(WriteBlobLong(image,quantum.unsigned_value));
4263}
4264
4265/*
4266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4267% %
4268% %
4269% %
4270+ W r i t e B l o b L o n g %
4271% %
4272% %
4273% %
4274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4275%
cristybb503372010-05-27 20:51:26 +00004276% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004277% specified by the endian member of the image structure.
4278%
4279% The format of the WriteBlobLong method is:
4280%
4281% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4282%
4283% A description of each parameter follows.
4284%
4285% o image: the image.
4286%
4287% o value: Specifies the value to write.
4288%
4289*/
4290MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4291{
4292 unsigned char
4293 buffer[4];
4294
4295 assert(image != (Image *) NULL);
4296 assert(image->signature == MagickSignature);
4297 if (image->endian == LSBEndian)
4298 {
4299 buffer[0]=(unsigned char) value;
4300 buffer[1]=(unsigned char) (value >> 8);
4301 buffer[2]=(unsigned char) (value >> 16);
4302 buffer[3]=(unsigned char) (value >> 24);
4303 return(WriteBlobStream(image,4,buffer));
4304 }
4305 buffer[0]=(unsigned char) (value >> 24);
4306 buffer[1]=(unsigned char) (value >> 16);
4307 buffer[2]=(unsigned char) (value >> 8);
4308 buffer[3]=(unsigned char) value;
4309 return(WriteBlobStream(image,4,buffer));
4310}
4311
4312/*
4313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4314% %
4315% %
4316% %
4317+ W r i t e B l o b S h o r t %
4318% %
4319% %
4320% %
4321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4322%
4323% WriteBlobShort() writes a short value as a 16-bit quantity in the
4324% byte-order specified by the endian member of the image structure.
4325%
4326% The format of the WriteBlobShort method is:
4327%
4328% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4329%
4330% A description of each parameter follows.
4331%
4332% o image: the image.
4333%
4334% o value: Specifies the value to write.
4335%
4336*/
4337MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4338{
4339 unsigned char
4340 buffer[2];
4341
4342 assert(image != (Image *) NULL);
4343 assert(image->signature == MagickSignature);
4344 if (image->endian == LSBEndian)
4345 {
4346 buffer[0]=(unsigned char) value;
4347 buffer[1]=(unsigned char) (value >> 8);
4348 return(WriteBlobStream(image,2,buffer));
4349 }
4350 buffer[0]=(unsigned char) (value >> 8);
4351 buffer[1]=(unsigned char) value;
4352 return(WriteBlobStream(image,2,buffer));
4353}
4354
4355/*
4356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4357% %
4358% %
4359% %
4360+ W r i t e B l o b L S B L o n g %
4361% %
4362% %
4363% %
4364%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4365%
cristybb503372010-05-27 20:51:26 +00004366% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004367% least-significant byte first order.
4368%
4369% The format of the WriteBlobLSBLong method is:
4370%
4371% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4372%
4373% A description of each parameter follows.
4374%
4375% o image: the image.
4376%
4377% o value: Specifies the value to write.
4378%
4379*/
4380MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4381{
4382 unsigned char
4383 buffer[4];
4384
4385 assert(image != (Image *) NULL);
4386 assert(image->signature == MagickSignature);
4387 buffer[0]=(unsigned char) value;
4388 buffer[1]=(unsigned char) (value >> 8);
4389 buffer[2]=(unsigned char) (value >> 16);
4390 buffer[3]=(unsigned char) (value >> 24);
4391 return(WriteBlobStream(image,4,buffer));
4392}
4393
4394/*
4395%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4396% %
4397% %
4398% %
4399+ W r i t e B l o b L S B S h o r t %
4400% %
4401% %
4402% %
4403%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4404%
cristybb503372010-05-27 20:51:26 +00004405% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004406% least-significant byte first order.
4407%
4408% The format of the WriteBlobLSBShort method is:
4409%
4410% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4411%
4412% A description of each parameter follows.
4413%
4414% o image: the image.
4415%
4416% o value: Specifies the value to write.
4417%
4418*/
4419MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4420{
4421 unsigned char
4422 buffer[2];
4423
4424 assert(image != (Image *) NULL);
4425 assert(image->signature == MagickSignature);
4426 buffer[0]=(unsigned char) value;
4427 buffer[1]=(unsigned char) (value >> 8);
4428 return(WriteBlobStream(image,2,buffer));
4429}
4430
4431/*
4432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4433% %
4434% %
4435% %
4436+ W r i t e B l o b M S B L o n g %
4437% %
4438% %
4439% %
4440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4441%
cristybb503372010-05-27 20:51:26 +00004442% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004443% most-significant byte first order.
4444%
4445% The format of the WriteBlobMSBLong method is:
4446%
4447% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4448%
4449% A description of each parameter follows.
4450%
4451% o value: Specifies the value to write.
4452%
4453% o image: the image.
4454%
4455*/
4456MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4457{
4458 unsigned char
4459 buffer[4];
4460
4461 assert(image != (Image *) NULL);
4462 assert(image->signature == MagickSignature);
4463 buffer[0]=(unsigned char) (value >> 24);
4464 buffer[1]=(unsigned char) (value >> 16);
4465 buffer[2]=(unsigned char) (value >> 8);
4466 buffer[3]=(unsigned char) value;
4467 return(WriteBlobStream(image,4,buffer));
4468}
4469
4470/*
4471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4472% %
4473% %
4474% %
cristy2ca49922010-03-06 02:54:01 +00004475+ W r i t e B l o b M S B L o n g L o n g %
4476% %
4477% %
4478% %
4479%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4480%
4481% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4482% most-significant byte first order.
4483%
4484% The format of the WriteBlobMSBLongLong method is:
4485%
4486% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4487%
4488% A description of each parameter follows.
4489%
4490% o value: Specifies the value to write.
4491%
4492% o image: the image.
4493%
4494*/
4495MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4496 const MagickSizeType value)
4497{
4498 unsigned char
4499 buffer[8];
4500
4501 assert(image != (Image *) NULL);
4502 assert(image->signature == MagickSignature);
4503 buffer[0]=(unsigned char) (value >> 56);
4504 buffer[1]=(unsigned char) (value >> 48);
4505 buffer[2]=(unsigned char) (value >> 40);
4506 buffer[3]=(unsigned char) (value >> 32);
4507 buffer[4]=(unsigned char) (value >> 24);
4508 buffer[5]=(unsigned char) (value >> 16);
4509 buffer[6]=(unsigned char) (value >> 8);
4510 buffer[7]=(unsigned char) value;
4511 return(WriteBlobStream(image,8,buffer));
4512}
4513
4514/*
4515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4516% %
4517% %
4518% %
cristy3ed852e2009-09-05 21:47:34 +00004519+ W r i t e B l o b M S B S h o r t %
4520% %
4521% %
4522% %
4523%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4524%
cristybb503372010-05-27 20:51:26 +00004525% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004526% most-significant byte first order.
4527%
4528% The format of the WriteBlobMSBShort method is:
4529%
4530% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4531%
4532% A description of each parameter follows.
4533%
4534% o value: Specifies the value to write.
4535%
4536% o file: Specifies the file to write the data to.
4537%
4538*/
4539MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4540{
4541 unsigned char
4542 buffer[2];
4543
4544 assert(image != (Image *) NULL);
4545 assert(image->signature == MagickSignature);
4546 buffer[0]=(unsigned char) (value >> 8);
4547 buffer[1]=(unsigned char) value;
4548 return(WriteBlobStream(image,2,buffer));
4549}
4550
4551/*
4552%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4553% %
4554% %
4555% %
4556+ W r i t e B l o b S t r i n g %
4557% %
4558% %
4559% %
4560%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4561%
4562% WriteBlobString() write a string to a blob. It returns the number of
4563% characters written.
4564%
4565% The format of the WriteBlobString method is:
4566%
4567% ssize_t WriteBlobString(Image *image,const char *string)
4568%
4569% A description of each parameter follows.
4570%
4571% o image: the image.
4572%
4573% o string: Specifies the string to write.
4574%
4575*/
4576MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4577{
4578 assert(image != (Image *) NULL);
4579 assert(image->signature == MagickSignature);
4580 assert(string != (const char *) NULL);
4581 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4582}