blob: b0534fc1cef56d8e705c5d4e6e7e683748283c7e [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% %
cristy7e41fe82010-12-04 23:12:08 +000020% Copyright 1999-2011 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"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/client.h"
48#include "MagickCore/constitute.h"
49#include "MagickCore/delegate.h"
50#include "MagickCore/exception.h"
51#include "MagickCore/exception-private.h"
52#include "MagickCore/image-private.h"
53#include "MagickCore/list.h"
54#include "MagickCore/locale_.h"
55#include "MagickCore/log.h"
56#include "MagickCore/magick.h"
57#include "MagickCore/memory_.h"
58#include "MagickCore/policy.h"
59#include "MagickCore/resource_.h"
60#include "MagickCore/semaphore.h"
61#include "MagickCore/string_.h"
62#include "MagickCore/string-private.h"
63#include "MagickCore/token.h"
64#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000065#include "MagickCore/utility-private.h"
cristy0157aea2010-04-24 21:12:18 +000066#if defined(MAGICKCORE_HAVE_MMAP_FILEIO) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +000067# include <sys/mman.h>
68#endif
69#if defined(MAGICKCORE_ZLIB_DELEGATE)
70#include "zlib.h"
71#endif
72#if defined(MAGICKCORE_BZLIB_DELEGATE)
73#include "bzlib.h"
74#endif
75
76/*
77 Define declarations.
78*/
79#define MagickMaxBlobExtent 65541
cristy3ed852e2009-09-05 21:47:34 +000080#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
81# define MAP_ANONYMOUS MAP_ANON
82#endif
83#if !defined(MAP_FAILED)
84#define MAP_FAILED ((void *) -1)
85#endif
86#if !defined(MS_SYNC)
87#define MS_SYNC 0x04
88#endif
89#if defined(__OS2__)
90#include <io.h>
91#define _O_BINARY O_BINARY
92#endif
93
94/*
95 Typedef declarations.
96*/
97struct _BlobInfo
98{
99 size_t
100 length,
101 extent,
102 quantum;
103
104 MagickBooleanType
105 mapped,
106 eof;
107
108 MagickOffsetType
109 offset;
110
111 MagickSizeType
112 size;
113
114 MagickBooleanType
115 exempt,
116 synchronize,
117 status,
118 temporary;
119
120 StreamType
121 type;
122
123 FILE
124 *file;
125
126 struct stat
127 properties;
128
129 StreamHandler
130 stream;
131
132 unsigned char
133 *data;
134
135 MagickBooleanType
136 debug;
137
138 SemaphoreInfo
139 *semaphore;
140
cristybb503372010-05-27 20:51:26 +0000141 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000142 reference_count;
143
cristybb503372010-05-27 20:51:26 +0000144 size_t
cristy3ed852e2009-09-05 21:47:34 +0000145 signature;
146};
147
148/*
149 Forward declarations.
150*/
151static int
152 SyncBlob(Image *);
153
154/*
155%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156% %
157% %
158% %
159+ A t t a c h B l o b %
160% %
161% %
162% %
163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164%
165% AttachBlob() attaches a blob to the BlobInfo structure.
166%
167% The format of the AttachBlob method is:
168%
169% void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
170%
171% A description of each parameter follows:
172%
173% o blob_info: Specifies a pointer to a BlobInfo structure.
174%
175% o blob: the address of a character stream in one of the image formats
176% understood by ImageMagick.
177%
178% o length: This size_t integer reflects the length in bytes of the blob.
179%
180*/
181MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
182 const size_t length)
183{
184 assert(blob_info != (BlobInfo *) NULL);
185 if (blob_info->debug != MagickFalse)
186 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
187 blob_info->length=length;
188 blob_info->extent=length;
189 blob_info->quantum=(size_t) MagickMaxBlobExtent;
190 blob_info->offset=0;
191 blob_info->type=BlobStream;
192 blob_info->file=(FILE *) NULL;
193 blob_info->data=(unsigned char *) blob;
194 blob_info->mapped=MagickFalse;
195}
196
197/*
198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199% %
200% %
201% %
202+ B l o b T o F i l e %
203% %
204% %
205% %
206%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207%
208% BlobToFile() writes a blob to a file. It returns MagickFalse if an error
209% occurs otherwise MagickTrue.
210%
211% The format of the BlobToFile method is:
212%
213% MagickBooleanType BlobToFile(char *filename,const void *blob,
214% const size_t length,ExceptionInfo *exception)
215%
216% A description of each parameter follows:
217%
218% o filename: Write the blob to this file.
219%
220% o blob: the address of a blob.
221%
222% o length: This length in bytes of the blob.
223%
224% o exception: return any errors or warnings in this structure.
225%
226*/
227
cristy7753b2a2011-02-19 18:36:52 +0000228static inline MagickSizeType MagickMin(const MagickSizeType x,
229 const MagickSizeType y)
cristy3ed852e2009-09-05 21:47:34 +0000230{
231 if (x < y)
232 return(x);
233 return(y);
234}
235
236MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
237 const size_t length,ExceptionInfo *exception)
238{
239 int
240 file;
241
242 register size_t
243 i;
244
245 ssize_t
246 count;
247
248 assert(filename != (const char *) NULL);
249 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
250 assert(blob != (const void *) NULL);
251 if (*filename == '\0')
252 file=AcquireUniqueFileResource(filename);
253 else
cristy18c6c272011-09-23 14:40:37 +0000254 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +0000255 if (file == -1)
256 {
257 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
258 return(MagickFalse);
259 }
260 for (i=0; i < length; i+=count)
261 {
cristy7753b2a2011-02-19 18:36:52 +0000262 count=(ssize_t) write(file,(const char *) blob+i,(size_t) MagickMin(length-
263 i,(MagickSizeType) SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +0000264 if (count <= 0)
265 {
266 count=0;
267 if (errno != EINTR)
268 break;
269 }
270 }
cristya7cb4312010-06-26 00:47:03 +0000271 file=close(file);
272 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +0000273 {
274 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
275 return(MagickFalse);
276 }
277 return(MagickTrue);
278}
279
280/*
281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282% %
283% %
284% %
285% B l o b T o I m a g e %
286% %
287% %
288% %
289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290%
291% BlobToImage() implements direct to memory image formats. It returns the
292% blob as an image.
293%
294% The format of the BlobToImage method is:
295%
296% Image *BlobToImage(const ImageInfo *image_info,const void *blob,
297% const size_t length,ExceptionInfo *exception)
298%
299% A description of each parameter follows:
300%
301% o image_info: the image info.
302%
303% o blob: the address of a character stream in one of the image formats
304% understood by ImageMagick.
305%
306% o length: This size_t integer reflects the length in bytes of the blob.
307%
308% o exception: return any errors or warnings in this structure.
309%
310*/
311MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
312 const size_t length,ExceptionInfo *exception)
313{
314 const MagickInfo
315 *magick_info;
316
317 Image
318 *image;
319
320 ImageInfo
321 *blob_info,
322 *clone_info;
323
324 MagickBooleanType
325 status;
326
327 assert(image_info != (ImageInfo *) NULL);
328 assert(image_info->signature == MagickSignature);
329 if (image_info->debug != MagickFalse)
330 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
331 image_info->filename);
332 assert(exception != (ExceptionInfo *) NULL);
333 if ((blob == (const void *) NULL) || (length == 0))
334 {
335 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
336 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
337 return((Image *) NULL);
338 }
339 blob_info=CloneImageInfo(image_info);
340 blob_info->blob=(void *) blob;
341 blob_info->length=length;
342 if (*blob_info->magick == '\0')
cristyd965a422010-03-03 17:47:35 +0000343 (void) SetImageInfo(blob_info,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000344 magick_info=GetMagickInfo(blob_info->magick,exception);
345 if (magick_info == (const MagickInfo *) NULL)
346 {
347 blob_info=DestroyImageInfo(blob_info);
348 (void) ThrowMagickException(exception,GetMagickModule(),
349 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
350 image_info->filename);
351 return((Image *) NULL);
352 }
353 if (GetMagickBlobSupport(magick_info) != MagickFalse)
354 {
355 /*
356 Native blob support for this image format.
357 */
358 (void) CopyMagickString(blob_info->filename,image_info->filename,
359 MaxTextExtent);
360 (void) CopyMagickString(blob_info->magick,image_info->magick,
361 MaxTextExtent);
362 image=ReadImage(blob_info,exception);
363 if (image != (Image *) NULL)
364 (void) DetachBlob(image->blob);
365 blob_info=DestroyImageInfo(blob_info);
366 return(image);
367 }
368 /*
369 Write blob to a temporary file on disk.
370 */
371 blob_info->blob=(void *) NULL;
372 blob_info->length=0;
373 *blob_info->filename='\0';
374 status=BlobToFile(blob_info->filename,blob,length,exception);
375 if (status == MagickFalse)
376 {
377 (void) RelinquishUniqueFileResource(blob_info->filename);
378 blob_info=DestroyImageInfo(blob_info);
379 return((Image *) NULL);
380 }
381 clone_info=CloneImageInfo(blob_info);
cristyb51dff52011-05-19 16:55:47 +0000382 (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +0000383 blob_info->magick,blob_info->filename);
384 image=ReadImage(clone_info,exception);
385 clone_info=DestroyImageInfo(clone_info);
386 (void) RelinquishUniqueFileResource(blob_info->filename);
387 blob_info=DestroyImageInfo(blob_info);
388 return(image);
389}
390
391/*
392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393% %
394% %
395% %
396+ C l o n e B l o b I n f o %
397% %
398% %
399% %
400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401%
402% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
403% blob info is NULL, a new one.
404%
405% The format of the CloneBlobInfo method is:
406%
407% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
408%
409% A description of each parameter follows:
410%
411% o blob_info: the blob info.
412%
413*/
414MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
415{
416 BlobInfo
417 *clone_info;
418
cristy73bd4a52010-10-05 11:24:23 +0000419 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
cristy3ed852e2009-09-05 21:47:34 +0000420 if (clone_info == (BlobInfo *) NULL)
421 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
422 GetBlobInfo(clone_info);
423 if (blob_info == (BlobInfo *) NULL)
424 return(clone_info);
425 clone_info->length=blob_info->length;
426 clone_info->extent=blob_info->extent;
427 clone_info->synchronize=blob_info->synchronize;
428 clone_info->quantum=blob_info->quantum;
429 clone_info->mapped=blob_info->mapped;
430 clone_info->eof=blob_info->eof;
431 clone_info->offset=blob_info->offset;
432 clone_info->size=blob_info->size;
433 clone_info->exempt=blob_info->exempt;
434 clone_info->status=blob_info->status;
435 clone_info->temporary=blob_info->temporary;
436 clone_info->type=blob_info->type;
437 clone_info->file=blob_info->file;
438 clone_info->properties=blob_info->properties;
439 clone_info->stream=blob_info->stream;
440 clone_info->data=blob_info->data;
441 clone_info->debug=IsEventLogging();
442 clone_info->reference_count=1;
443 return(clone_info);
444}
445
446/*
447%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448% %
449% %
450% %
451+ C l o s e B l o b %
452% %
453% %
454% %
455%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
456%
457% CloseBlob() closes a stream associated with the image.
458%
459% The format of the CloseBlob method is:
460%
461% MagickBooleanType CloseBlob(Image *image)
462%
463% A description of each parameter follows:
464%
465% o image: the image.
466%
467*/
468MagickExport MagickBooleanType CloseBlob(Image *image)
469{
470 int
471 status;
472
473 /*
474 Close image file.
475 */
476 assert(image != (Image *) NULL);
477 assert(image->signature == MagickSignature);
478 if (image->debug != MagickFalse)
479 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
480 assert(image->blob != (BlobInfo *) NULL);
481 if (image->blob->type == UndefinedStream)
482 return(MagickTrue);
483 if (image->blob->synchronize != MagickFalse)
484 SyncBlob(image);
485 image->blob->size=GetBlobSize(image);
cristy81b8ce52010-02-05 01:53:17 +0000486 image->extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +0000487 image->blob->eof=MagickFalse;
488 if (image->blob->exempt != MagickFalse)
489 {
490 image->blob->type=UndefinedStream;
491 return(MagickTrue);
492 }
493 status=0;
494 switch (image->blob->type)
495 {
496 case UndefinedStream:
497 break;
498 case FileStream:
499 case StandardStream:
500 case PipeStream:
501 {
502 status=ferror(image->blob->file);
503 break;
504 }
505 case ZipStream:
506 {
507#if defined(MAGICKCORE_ZLIB_DELEGATE)
508 (void) gzerror(image->blob->file,&status);
509#endif
510 break;
511 }
512 case BZipStream:
513 {
514#if defined(MAGICKCORE_BZLIB_DELEGATE)
515 (void) BZ2_bzerror((BZFILE *) image->blob->file,&status);
516#endif
517 break;
518 }
519 case FifoStream:
520 case BlobStream:
521 break;
522 }
523 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
524 switch (image->blob->type)
525 {
526 case UndefinedStream:
527 break;
528 case FileStream:
529 case StandardStream:
530 {
531 if (image->blob->synchronize != MagickFalse)
cristyff483372010-10-16 17:00:58 +0000532 {
533 status=fflush(image->blob->file);
534 status=fsync(fileno(image->blob->file));
535 }
cristy3ed852e2009-09-05 21:47:34 +0000536 status=fclose(image->blob->file);
537 break;
538 }
539 case PipeStream:
540 {
541#if defined(MAGICKCORE_HAVE_PCLOSE)
542 status=pclose(image->blob->file);
543#endif
544 break;
545 }
546 case ZipStream:
547 {
548#if defined(MAGICKCORE_ZLIB_DELEGATE)
549 status=gzclose(image->blob->file);
550#endif
551 break;
552 }
553 case BZipStream:
554 {
555#if defined(MAGICKCORE_BZLIB_DELEGATE)
556 BZ2_bzclose((BZFILE *) image->blob->file);
557#endif
558 break;
559 }
560 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000561 break;
cristyff483372010-10-16 17:00:58 +0000562 case BlobStream:
563 {
564 if (image->blob->file != (FILE *) NULL)
565 {
566 if (image->blob->synchronize != MagickFalse)
567 (void) fsync(fileno(image->blob->file));
568 status=fclose(image->blob->file);
569 }
570 break;
571 }
cristy3ed852e2009-09-05 21:47:34 +0000572 }
573 (void) DetachBlob(image->blob);
574 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
575 return(image->blob->status);
576}
577
578/*
579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580% %
581% %
582% %
583+ D e s t r o y B l o b %
584% %
585% %
586% %
587%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
588%
589% DestroyBlob() deallocates memory associated with a blob.
590%
591% The format of the DestroyBlob method is:
592%
593% void DestroyBlob(Image *image)
594%
595% A description of each parameter follows:
596%
597% o image: the image.
598%
599*/
600MagickExport void DestroyBlob(Image *image)
601{
602 MagickBooleanType
603 destroy;
604
605 assert(image != (Image *) NULL);
606 assert(image->signature == MagickSignature);
607 if (image->debug != MagickFalse)
608 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
609 assert(image->blob != (BlobInfo *) NULL);
610 assert(image->blob->signature == MagickSignature);
611 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000612 LockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000613 image->blob->reference_count--;
614 assert(image->blob->reference_count >= 0);
615 if (image->blob->reference_count == 0)
616 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000617 UnlockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000618 if (destroy == MagickFalse)
619 return;
620 (void) CloseBlob(image);
621 if (image->blob->mapped != MagickFalse)
622 (void) UnmapBlob(image->blob->data,image->blob->length);
623 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
624 DestroySemaphoreInfo(&image->blob->semaphore);
625 image->blob->signature=(~MagickSignature);
626 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
627}
628
629/*
630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
631% %
632% %
633% %
634+ D e t a c h B l o b %
635% %
636% %
637% %
638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639%
640% DetachBlob() detaches a blob from the BlobInfo structure.
641%
642% The format of the DetachBlob method is:
643%
644% unsigned char *DetachBlob(BlobInfo *blob_info)
645%
646% A description of each parameter follows:
647%
648% o blob_info: Specifies a pointer to a BlobInfo structure.
649%
650*/
651MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
652{
653 unsigned char
654 *data;
655
656 assert(blob_info != (BlobInfo *) NULL);
657 if (blob_info->debug != MagickFalse)
658 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
659 if (blob_info->mapped != MagickFalse)
660 (void) UnmapBlob(blob_info->data,blob_info->length);
661 blob_info->mapped=MagickFalse;
662 blob_info->length=0;
663 blob_info->offset=0;
664 blob_info->eof=MagickFalse;
665 blob_info->exempt=MagickFalse;
666 blob_info->type=UndefinedStream;
667 blob_info->file=(FILE *) NULL;
668 data=blob_info->data;
669 blob_info->data=(unsigned char *) NULL;
670 blob_info->stream=(StreamHandler) NULL;
671 return(data);
672}
673
674/*
675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
676% %
677% %
678% %
cristyc1af14f2010-09-16 20:01:21 +0000679+ D i s c a r d B l o b B y t e s %
680% %
681% %
682% %
683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684%
685% DiscardBlobBytes() discards bytes in a blob.
686%
687% The format of the DiscardBlobBytes method is:
688%
689% MagickBooleanType DiscardBlobBytes(Image *image,const size_t length)
690%
691% A description of each parameter follows.
692%
693% o image: the image.
694%
695% o length: the number of bytes to skip.
696%
697*/
698
699static inline const unsigned char *ReadBlobStream(Image *image,
700 const size_t length,unsigned char *data,ssize_t *count)
701{
702 assert(count != (ssize_t *) NULL);
703 assert(image->blob != (BlobInfo *) NULL);
704 if (image->blob->type != BlobStream)
705 {
706 *count=ReadBlob(image,length,data);
707 return(data);
708 }
709 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
710 {
711 *count=0;
712 image->blob->eof=MagickTrue;
713 return(data);
714 }
715 data=image->blob->data+image->blob->offset;
cristy7753b2a2011-02-19 18:36:52 +0000716 *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
cristyc1af14f2010-09-16 20:01:21 +0000717 image->blob->offset));
718 image->blob->offset+=(*count);
719 if (*count != (ssize_t) length)
720 image->blob->eof=MagickTrue;
721 return(data);
722}
723
724MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
cristy7753b2a2011-02-19 18:36:52 +0000725 const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000726{
cristy7753b2a2011-02-19 18:36:52 +0000727 register MagickOffsetType
cristyc1af14f2010-09-16 20:01:21 +0000728 i;
729
730 size_t
731 quantum;
732
733 ssize_t
734 count;
735
736 unsigned char
cristyf55846d2010-09-17 19:01:10 +0000737 buffer[16384];
cristyc1af14f2010-09-16 20:01:21 +0000738
739 assert(image != (Image *) NULL);
740 assert(image->signature == MagickSignature);
741 count=0;
cristy7753b2a2011-02-19 18:36:52 +0000742 for (i=0; i < (MagickOffsetType) length; i+=count)
cristyc1af14f2010-09-16 20:01:21 +0000743 {
cristy7753b2a2011-02-19 18:36:52 +0000744 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
cristyc1af14f2010-09-16 20:01:21 +0000745 (void) ReadBlobStream(image,quantum,buffer,&count);
746 if (count <= 0)
747 {
748 count=0;
749 if (errno != EINTR)
750 break;
751 }
752 }
cristy7753b2a2011-02-19 18:36:52 +0000753 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
cristyc1af14f2010-09-16 20:01:21 +0000754}
755
756/*
757%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
758% %
759% %
760% %
cristy3ed852e2009-09-05 21:47:34 +0000761+ D u p l i c a t e s B l o b %
762% %
763% %
764% %
765%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
766%
767% DuplicateBlob() duplicates a blob descriptor.
768%
769% The format of the DuplicateBlob method is:
770%
771% void DuplicateBlob(Image *image,const Image *duplicate)
772%
773% A description of each parameter follows:
774%
775% o image: the image.
776%
777% o duplicate: the duplicate image.
778%
779*/
780MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
781{
782 assert(image != (Image *) NULL);
783 assert(image->signature == MagickSignature);
784 if (image->debug != MagickFalse)
785 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
786 assert(duplicate != (Image *) NULL);
787 assert(duplicate->signature == MagickSignature);
788 DestroyBlob(image);
789 image->blob=ReferenceBlob(duplicate->blob);
790}
791
792/*
793%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
794% %
795% %
796% %
797+ E O F B l o b %
798% %
799% %
800% %
801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
802%
803% EOFBlob() returns a non-zero value when EOF has been detected reading from
804% a blob or file.
805%
806% The format of the EOFBlob method is:
807%
808% int EOFBlob(const Image *image)
809%
810% A description of each parameter follows:
811%
812% o image: the image.
813%
814*/
815MagickExport int EOFBlob(const Image *image)
816{
817 assert(image != (Image *) NULL);
818 assert(image->signature == MagickSignature);
819 if (image->debug != MagickFalse)
820 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
821 assert(image->blob != (BlobInfo *) NULL);
822 assert(image->blob->type != UndefinedStream);
823 switch (image->blob->type)
824 {
825 case UndefinedStream:
826 break;
827 case FileStream:
828 case StandardStream:
829 case PipeStream:
830 {
831 image->blob->eof=feof(image->blob->file) != 0 ? MagickTrue : MagickFalse;
832 break;
833 }
834 case ZipStream:
835 {
836 image->blob->eof=MagickFalse;
837 break;
838 }
839 case BZipStream:
840 {
841#if defined(MAGICKCORE_BZLIB_DELEGATE)
842 int
843 status;
844
845 status=0;
846 (void) BZ2_bzerror((BZFILE *) image->blob->file,&status);
847 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
848#endif
849 break;
850 }
851 case FifoStream:
852 {
853 image->blob->eof=MagickFalse;
854 break;
855 }
856 case BlobStream:
857 break;
858 }
859 return((int) image->blob->eof);
860}
861
862/*
863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
864% %
865% %
866% %
867+ F i l e T o B l o b %
868% %
869% %
870% %
871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
872%
cristy178edaf2011-01-23 03:42:39 +0000873% FileToBlob() returns the contents of a file as a buffer terminated with
874% the '\0' character. The length of the buffer (not including the extra
875% terminating '\0' character) is returned via the 'length' parameter. Free
876% the buffer with RelinquishMagickMemory().
cristy3ed852e2009-09-05 21:47:34 +0000877%
878% The format of the FileToBlob method is:
879%
880% unsigned char *FileToBlob(const char *filename,const size_t extent,
881% size_t *length,ExceptionInfo *exception)
882%
883% A description of each parameter follows:
884%
885% o blob: FileToBlob() returns the contents of a file as a blob. If
886% an error occurs NULL is returned.
887%
888% o filename: the filename.
889%
890% o extent: The maximum length of the blob.
891%
892% o length: On return, this reflects the actual length of the blob.
893%
894% o exception: return any errors or warnings in this structure.
895%
896*/
897MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
898 size_t *length,ExceptionInfo *exception)
899{
900 int
901 file;
902
903 MagickOffsetType
904 offset;
905
906 register size_t
907 i;
908
909 ssize_t
910 count;
911
912 unsigned char
913 *blob;
914
915 void
916 *map;
917
918 assert(filename != (const char *) NULL);
919 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
920 assert(exception != (ExceptionInfo *) NULL);
921 *length=0;
922 file=fileno(stdin);
923 if (LocaleCompare(filename,"-") != 0)
cristy18c6c272011-09-23 14:40:37 +0000924 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +0000925 if (file == -1)
926 {
927 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
928 return((unsigned char *) NULL);
929 }
cristy7f317702011-02-18 20:40:28 +0000930 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
cristy3ed852e2009-09-05 21:47:34 +0000931 count=0;
932 if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset)))
933 {
934 size_t
935 quantum;
936
937 struct stat
938 file_info;
939
940 /*
941 Stream is not seekable.
942 */
943 quantum=(size_t) MagickMaxBufferExtent;
944 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
cristy7753b2a2011-02-19 18:36:52 +0000945 quantum=(size_t) MagickMin((MagickSizeType) file_info.st_size,
946 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +0000947 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
948 for (i=0; blob != (unsigned char *) NULL; i+=count)
949 {
950 count=(ssize_t) read(file,blob+i,quantum);
951 if (count <= 0)
952 {
953 count=0;
954 if (errno != EINTR)
955 break;
956 }
957 if (~(1UL*i) < (quantum+1))
958 {
959 blob=(unsigned char *) RelinquishMagickMemory(blob);
960 break;
961 }
962 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
963 sizeof(*blob));
964 if ((size_t) (i+count) >= extent)
965 break;
966 }
cristy54439632010-07-15 00:43:34 +0000967 if (LocaleCompare(filename,"-") != 0)
968 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +0000969 if (blob == (unsigned char *) NULL)
970 {
971 (void) ThrowMagickException(exception,GetMagickModule(),
972 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
973 return((unsigned char *) NULL);
974 }
cristya7cb4312010-06-26 00:47:03 +0000975 if (file == -1)
976 {
977 blob=(unsigned char *) RelinquishMagickMemory(blob);
978 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
979 return((unsigned char *) NULL);
980 }
cristy7753b2a2011-02-19 18:36:52 +0000981 *length=(size_t) MagickMin(i+count,extent);
cristy3ed852e2009-09-05 21:47:34 +0000982 blob[*length]='\0';
983 return(blob);
984 }
cristy7753b2a2011-02-19 18:36:52 +0000985 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
cristy3ed852e2009-09-05 21:47:34 +0000986 blob=(unsigned char *) NULL;
cristy37e0b382011-06-07 13:31:21 +0000987 if (~(*length) >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +0000988 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
989 sizeof(*blob));
990 if (blob == (unsigned char *) NULL)
991 {
cristy54439632010-07-15 00:43:34 +0000992 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +0000993 (void) ThrowMagickException(exception,GetMagickModule(),
994 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
995 return((unsigned char *) NULL);
996 }
997 map=MapBlob(file,ReadMode,0,*length);
998 if (map != (unsigned char *) NULL)
999 {
cristy54aad5e2010-09-03 16:02:04 +00001000 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +00001001 (void) UnmapBlob(map,*length);
1002 }
1003 else
1004 {
cristy7f317702011-02-18 20:40:28 +00001005 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001006 for (i=0; i < *length; i+=count)
1007 {
cristy7753b2a2011-02-19 18:36:52 +00001008 count=(ssize_t) read(file,blob+i,(size_t) MagickMin(*length-i,
1009 (MagickSizeType) SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001010 if (count <= 0)
1011 {
1012 count=0;
1013 if (errno != EINTR)
1014 break;
1015 }
1016 }
1017 if (i < *length)
1018 {
1019 file=close(file)-1;
1020 blob=(unsigned char *) RelinquishMagickMemory(blob);
1021 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1022 return((unsigned char *) NULL);
1023 }
1024 }
cristy3ed852e2009-09-05 21:47:34 +00001025 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001026 if (LocaleCompare(filename,"-") != 0)
1027 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001028 if (file == -1)
1029 {
1030 blob=(unsigned char *) RelinquishMagickMemory(blob);
1031 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1032 }
cristy3ed852e2009-09-05 21:47:34 +00001033 return(blob);
1034}
1035
1036/*
1037%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1038% %
1039% %
1040% %
1041% F i l e T o I m a g e %
1042% %
1043% %
1044% %
1045%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1046%
1047% FileToImage() write the contents of a file to an image.
1048%
1049% The format of the FileToImage method is:
1050%
1051% MagickBooleanType FileToImage(Image *,const char *filename)
1052%
1053% A description of each parameter follows:
1054%
1055% o image: the image.
1056%
1057% o filename: the filename.
1058%
1059*/
1060
1061static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1062 const unsigned char *data)
1063{
1064 MagickSizeType
1065 extent;
1066
1067 register unsigned char
1068 *q;
1069
1070 assert(image->blob != (BlobInfo *) NULL);
1071 if (image->blob->type != BlobStream)
1072 return(WriteBlob(image,length,data));
1073 assert(image->blob->type != UndefinedStream);
1074 assert(data != (void *) NULL);
1075 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1076 if (extent >= image->blob->extent)
1077 {
1078 image->blob->quantum<<=1;
1079 extent=image->blob->extent+image->blob->quantum+length;
1080 if (SetBlobExtent(image,extent) == MagickFalse)
1081 return(0);
1082 }
1083 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001084 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001085 image->blob->offset+=length;
1086 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1087 image->blob->length=(size_t) image->blob->offset;
1088 return((ssize_t) length);
1089}
1090
cristyc82a27b2011-10-21 01:07:16 +00001091MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1092 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001093{
1094 int
1095 file;
1096
1097 size_t
1098 length,
1099 quantum;
1100
1101 ssize_t
1102 count;
1103
1104 struct stat
1105 file_info;
1106
1107 unsigned char
1108 *blob;
1109
1110 assert(image != (const Image *) NULL);
1111 assert(image->signature == MagickSignature);
1112 assert(filename != (const char *) NULL);
1113 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
cristy18c6c272011-09-23 14:40:37 +00001114 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001115 if (file == -1)
1116 {
cristyc82a27b2011-10-21 01:07:16 +00001117 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001118 return(MagickFalse);
1119 }
1120 quantum=(size_t) MagickMaxBufferExtent;
1121 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
cristy7753b2a2011-02-19 18:36:52 +00001122 quantum=(size_t) MagickMin(file_info.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001123 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1124 if (blob == (unsigned char *) NULL)
1125 {
cristyc82a27b2011-10-21 01:07:16 +00001126 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1127 filename);
cristy3ed852e2009-09-05 21:47:34 +00001128 return(MagickFalse);
1129 }
1130 for ( ; ; )
1131 {
1132 count=(ssize_t) read(file,blob,quantum);
1133 if (count <= 0)
1134 {
1135 count=0;
1136 if (errno != EINTR)
1137 break;
1138 }
1139 length=(size_t) count;
1140 count=WriteBlobStream(image,length,blob);
1141 if (count != (ssize_t) length)
1142 {
cristyc82a27b2011-10-21 01:07:16 +00001143 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001144 break;
1145 }
1146 }
cristya7cb4312010-06-26 00:47:03 +00001147 file=close(file);
1148 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001149 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001150 blob=(unsigned char *) RelinquishMagickMemory(blob);
1151 return(MagickTrue);
1152}
1153
1154/*
1155%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1156% %
1157% %
1158% %
1159+ G e t B l o b E r r o r %
1160% %
1161% %
1162% %
1163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164%
1165% GetBlobError() returns MagickTrue if the blob associated with the specified
1166% image encountered an error.
1167%
1168% The format of the GetBlobError method is:
1169%
1170% MagickBooleanType GetBlobError(const Image *image)
1171%
1172% A description of each parameter follows:
1173%
1174% o image: the image.
1175%
1176*/
cristy7832dc22011-09-05 01:21:53 +00001177MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001178{
1179 assert(image != (const Image *) NULL);
1180 assert(image->signature == MagickSignature);
1181 if (image->debug != MagickFalse)
1182 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1183 return(image->blob->status);
1184}
1185
1186/*
1187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1188% %
1189% %
1190% %
1191+ G e t B l o b F i l e H a n d l e %
1192% %
1193% %
1194% %
1195%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196%
1197% GetBlobFileHandle() returns the file handle associated with the image blob.
1198%
1199% The format of the GetBlobFile method is:
1200%
1201% FILE *GetBlobFileHandle(const Image *image)
1202%
1203% A description of each parameter follows:
1204%
1205% o image: the image.
1206%
1207*/
1208MagickExport FILE *GetBlobFileHandle(const Image *image)
1209{
1210 assert(image != (const Image *) NULL);
1211 assert(image->signature == MagickSignature);
1212 return(image->blob->file);
1213}
1214
1215/*
1216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1217% %
1218% %
1219% %
1220+ G e t B l o b I n f o %
1221% %
1222% %
1223% %
1224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1225%
1226% GetBlobInfo() initializes the BlobInfo structure.
1227%
1228% The format of the GetBlobInfo method is:
1229%
1230% void GetBlobInfo(BlobInfo *blob_info)
1231%
1232% A description of each parameter follows:
1233%
1234% o blob_info: Specifies a pointer to a BlobInfo structure.
1235%
1236*/
cristy7832dc22011-09-05 01:21:53 +00001237MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001238{
1239 assert(blob_info != (BlobInfo *) NULL);
1240 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1241 blob_info->type=UndefinedStream;
1242 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1243 blob_info->properties.st_mtime=time((time_t *) NULL);
1244 blob_info->properties.st_ctime=time((time_t *) NULL);
1245 blob_info->debug=IsEventLogging();
1246 blob_info->reference_count=1;
1247 blob_info->semaphore=AllocateSemaphoreInfo();
1248 blob_info->signature=MagickSignature;
1249}
1250
1251/*
1252%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1253% %
1254% %
1255% %
1256% G e t B l o b P r o p e r t i e s %
1257% %
1258% %
1259% %
1260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1261%
1262% GetBlobProperties() returns information about an image blob.
1263%
1264% The format of the GetBlobProperties method is:
1265%
1266% const struct stat *GetBlobProperties(const Image *image)
1267%
1268% A description of each parameter follows:
1269%
1270% o image: the image.
1271%
1272*/
cristy7832dc22011-09-05 01:21:53 +00001273MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001274{
1275 assert(image != (Image *) NULL);
1276 assert(image->signature == MagickSignature);
1277 if (image->debug != MagickFalse)
1278 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1279 return(&image->blob->properties);
1280}
1281
1282/*
1283%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1284% %
1285% %
1286% %
1287+ G e t B l o b S i z e %
1288% %
1289% %
1290% %
1291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1292%
1293% GetBlobSize() returns the current length of the image file or blob; zero is
1294% returned if the size cannot be determined.
1295%
1296% The format of the GetBlobSize method is:
1297%
1298% MagickSizeType GetBlobSize(const Image *image)
1299%
1300% A description of each parameter follows:
1301%
1302% o image: the image.
1303%
1304*/
1305MagickExport MagickSizeType GetBlobSize(const Image *image)
1306{
1307 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001308 extent;
cristy3ed852e2009-09-05 21:47:34 +00001309
1310 assert(image != (Image *) NULL);
1311 assert(image->signature == MagickSignature);
1312 if (image->debug != MagickFalse)
1313 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1314 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001315 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001316 switch (image->blob->type)
1317 {
1318 case UndefinedStream:
1319 {
cristy81b8ce52010-02-05 01:53:17 +00001320 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001321 break;
1322 }
1323 case FileStream:
1324 {
1325 if (fstat(fileno(image->blob->file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001326 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001327 break;
1328 }
1329 case StandardStream:
1330 case PipeStream:
1331 {
cristy81b8ce52010-02-05 01:53:17 +00001332 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001333 break;
1334 }
1335 case ZipStream:
1336 case BZipStream:
1337 {
1338 MagickBooleanType
1339 status;
1340
1341 status=GetPathAttributes(image->filename,&image->blob->properties);
1342 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001343 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001344 break;
1345 }
1346 case FifoStream:
1347 break;
1348 case BlobStream:
1349 {
cristy891dc792010-03-04 01:47:16 +00001350 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001351 break;
1352 }
1353 }
cristy81b8ce52010-02-05 01:53:17 +00001354 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001355}
1356
1357/*
1358%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1359% %
1360% %
1361% %
1362+ G e t B l o b S t r e a m D a t a %
1363% %
1364% %
1365% %
1366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1367%
1368% GetBlobStreamData() returns the stream data for the image.
1369%
1370% The format of the GetBlobStreamData method is:
1371%
1372% unsigned char *GetBlobStreamData(const Image *image)
1373%
1374% A description of each parameter follows:
1375%
1376% o image: the image.
1377%
1378*/
1379MagickExport unsigned char *GetBlobStreamData(const Image *image)
1380{
1381 assert(image != (const Image *) NULL);
1382 assert(image->signature == MagickSignature);
1383 return(image->blob->data);
1384}
1385
1386/*
1387%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1388% %
1389% %
1390% %
1391+ G e t B l o b S t r e a m H a n d l e r %
1392% %
1393% %
1394% %
1395%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1396%
1397% GetBlobStreamHandler() returns the stream handler for the image.
1398%
1399% The format of the GetBlobStreamHandler method is:
1400%
1401% StreamHandler GetBlobStreamHandler(const Image *image)
1402%
1403% A description of each parameter follows:
1404%
1405% o image: the image.
1406%
1407*/
cristy7832dc22011-09-05 01:21:53 +00001408MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001409{
1410 assert(image != (const Image *) NULL);
1411 assert(image->signature == MagickSignature);
1412 if (image->debug != MagickFalse)
1413 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1414 return(image->blob->stream);
1415}
1416
1417/*
1418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1419% %
1420% %
1421% %
1422% I m a g e T o B l o b %
1423% %
1424% %
1425% %
1426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1427%
1428% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001429% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001430% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001431% etc.). This method is the equivalent of WriteImage(), but writes the
1432% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001433%
1434% The format of the ImageToBlob method is:
1435%
1436% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1437% size_t *length,ExceptionInfo *exception)
1438%
1439% A description of each parameter follows:
1440%
1441% o image_info: the image info.
1442%
1443% o image: the image.
1444%
1445% o length: This pointer to a size_t integer sets the initial length of the
1446% blob. On return, it reflects the actual length of the blob.
1447%
1448% o exception: return any errors or warnings in this structure.
1449%
1450*/
1451MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1452 Image *image,size_t *length,ExceptionInfo *exception)
1453{
1454 const MagickInfo
1455 *magick_info;
1456
1457 ImageInfo
1458 *blob_info;
1459
1460 MagickBooleanType
1461 status;
1462
1463 unsigned char
1464 *blob;
1465
1466 assert(image_info != (const ImageInfo *) NULL);
1467 assert(image_info->signature == MagickSignature);
1468 if (image_info->debug != MagickFalse)
1469 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1470 image_info->filename);
1471 assert(image != (Image *) NULL);
1472 assert(image->signature == MagickSignature);
1473 assert(exception != (ExceptionInfo *) NULL);
1474 *length=0;
1475 blob=(unsigned char *) NULL;
1476 blob_info=CloneImageInfo(image_info);
1477 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001478 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001479 if (*blob_info->magick != '\0')
1480 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1481 magick_info=GetMagickInfo(image->magick,exception);
1482 if (magick_info == (const MagickInfo *) NULL)
1483 {
1484 (void) ThrowMagickException(exception,GetMagickModule(),
1485 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1486 image->filename);
1487 return(blob);
1488 }
1489 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1490 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1491 {
1492 /*
1493 Native blob support for this image format.
1494 */
1495 blob_info->length=0;
1496 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1497 sizeof(unsigned char));
1498 if (blob_info->blob == (void *) NULL)
1499 (void) ThrowMagickException(exception,GetMagickModule(),
1500 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1501 else
1502 {
1503 (void) CloseBlob(image);
1504 image->blob->exempt=MagickTrue;
1505 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001506 status=WriteImage(blob_info,image,exception);
1507 if ((status != MagickFalse) && (image->blob->length != 0))
cristy3ed852e2009-09-05 21:47:34 +00001508 {
1509 *length=image->blob->length;
1510 blob=DetachBlob(image->blob);
1511 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1512 sizeof(*blob));
1513 }
1514 }
1515 }
1516 else
1517 {
1518 char
1519 unique[MaxTextExtent];
1520
1521 int
1522 file;
1523
1524 /*
1525 Write file to disk in blob image format.
1526 */
1527 file=AcquireUniqueFileResource(unique);
1528 if (file == -1)
1529 {
1530 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1531 image_info->filename);
1532 }
1533 else
1534 {
1535 blob_info->file=fdopen(file,"wb");
1536 if (blob_info->file != (FILE *) NULL)
1537 {
cristyb51dff52011-05-19 16:55:47 +00001538 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001539 image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001540 status=WriteImage(blob_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001541 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001542 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001543 blob=FileToBlob(image->filename,~0UL,length,exception);
1544 }
1545 (void) RelinquishUniqueFileResource(unique);
1546 }
1547 }
1548 blob_info=DestroyImageInfo(blob_info);
1549 return(blob);
1550}
1551
1552/*
1553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1554% %
1555% %
1556% %
1557% I m a g e T o F i l e %
1558% %
1559% %
1560% %
1561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1562%
1563% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1564% occurs otherwise MagickTrue.
1565%
1566% The format of the ImageToFile method is:
1567%
1568% MagickBooleanType ImageToFile(Image *image,char *filename,
1569% ExceptionInfo *exception)
1570%
1571% A description of each parameter follows:
1572%
1573% o image: the image.
1574%
1575% o filename: Write the image to this file.
1576%
1577% o exception: return any errors or warnings in this structure.
1578%
1579*/
cristy3ed852e2009-09-05 21:47:34 +00001580MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1581 ExceptionInfo *exception)
1582{
1583 int
1584 file;
1585
1586 register const unsigned char
1587 *p;
1588
1589 register size_t
1590 i;
1591
1592 size_t
1593 length,
1594 quantum;
1595
1596 ssize_t
1597 count;
1598
1599 struct stat
1600 file_info;
1601
1602 unsigned char
1603 *buffer;
1604
1605 assert(image != (Image *) NULL);
1606 assert(image->signature == MagickSignature);
1607 assert(image->blob != (BlobInfo *) NULL);
1608 assert(image->blob->type != UndefinedStream);
1609 if (image->debug != MagickFalse)
1610 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1611 assert(filename != (const char *) NULL);
1612 if (*filename == '\0')
1613 file=AcquireUniqueFileResource(filename);
1614 else
1615 if (LocaleCompare(filename,"-") == 0)
1616 file=fileno(stdout);
1617 else
cristy18c6c272011-09-23 14:40:37 +00001618 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001619 if (file == -1)
1620 {
1621 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1622 return(MagickFalse);
1623 }
1624 quantum=(size_t) MagickMaxBufferExtent;
1625 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
cristy7753b2a2011-02-19 18:36:52 +00001626 quantum=(size_t) MagickMin((MagickSizeType) file_info.st_size,
1627 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001628 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1629 if (buffer == (unsigned char *) NULL)
1630 {
1631 file=close(file)-1;
1632 (void) ThrowMagickException(exception,GetMagickModule(),
1633 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1634 return(MagickFalse);
1635 }
1636 length=0;
1637 p=ReadBlobStream(image,quantum,buffer,&count);
1638 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1639 {
1640 length=(size_t) count;
1641 for (i=0; i < length; i+=count)
1642 {
1643 count=write(file,p+i,(size_t) (length-i));
1644 if (count <= 0)
1645 {
1646 count=0;
1647 if (errno != EINTR)
1648 break;
1649 }
1650 }
1651 if (i < length)
1652 break;
1653 }
cristy54439632010-07-15 00:43:34 +00001654 if (LocaleCompare(filename,"-") != 0)
1655 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001656 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001657 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001658 {
1659 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1660 return(MagickFalse);
1661 }
1662 return(MagickTrue);
1663}
1664
1665/*
1666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1667% %
1668% %
1669% %
1670% I m a g e s T o B l o b %
1671% %
1672% %
1673% %
1674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1675%
1676% ImagesToBlob() implements direct to memory image formats. It returns the
1677% image sequence as a blob and its length. The magick member of the ImageInfo
1678% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1679%
1680% Note, some image formats do not permit multiple images to the same image
1681% stream (e.g. JPEG). in this instance, just the first image of the
1682% sequence is returned as a blob.
1683%
1684% The format of the ImagesToBlob method is:
1685%
1686% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1687% size_t *length,ExceptionInfo *exception)
1688%
1689% A description of each parameter follows:
1690%
1691% o image_info: the image info.
1692%
1693% o images: the image list.
1694%
1695% o length: This pointer to a size_t integer sets the initial length of the
1696% blob. On return, it reflects the actual length of the blob.
1697%
1698% o exception: return any errors or warnings in this structure.
1699%
1700*/
1701MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1702 Image *images,size_t *length,ExceptionInfo *exception)
1703{
1704 const MagickInfo
1705 *magick_info;
1706
1707 ImageInfo
1708 *blob_info;
1709
1710 MagickBooleanType
1711 status;
1712
1713 unsigned char
1714 *blob;
1715
1716 assert(image_info != (const ImageInfo *) NULL);
1717 assert(image_info->signature == MagickSignature);
1718 if (image_info->debug != MagickFalse)
1719 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1720 image_info->filename);
1721 assert(images != (Image *) NULL);
1722 assert(images->signature == MagickSignature);
1723 assert(exception != (ExceptionInfo *) NULL);
1724 *length=0;
1725 blob=(unsigned char *) NULL;
1726 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001727 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1728 exception);
cristy3ed852e2009-09-05 21:47:34 +00001729 if (*blob_info->magick != '\0')
1730 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1731 if (blob_info->adjoin == MagickFalse)
1732 {
1733 blob_info=DestroyImageInfo(blob_info);
1734 return(ImageToBlob(image_info,images,length,exception));
1735 }
1736 magick_info=GetMagickInfo(images->magick,exception);
1737 if (magick_info == (const MagickInfo *) NULL)
1738 {
1739 (void) ThrowMagickException(exception,GetMagickModule(),
1740 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1741 images->filename);
1742 return(blob);
1743 }
1744 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1745 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1746 {
1747 /*
1748 Native blob support for this images format.
1749 */
1750 blob_info->length=0;
1751 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1752 sizeof(unsigned char));
1753 if (blob_info->blob == (void *) NULL)
1754 (void) ThrowMagickException(exception,GetMagickModule(),
1755 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
1756 else
1757 {
1758 images->blob->exempt=MagickTrue;
1759 *images->filename='\0';
1760 status=WriteImages(blob_info,images,images->filename,exception);
cristyb24e2402011-10-07 00:48:39 +00001761 if ((status != MagickFalse) && (images->blob->length != 0))
cristy3ed852e2009-09-05 21:47:34 +00001762 {
1763 *length=images->blob->length;
1764 blob=DetachBlob(images->blob);
1765 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1766 sizeof(*blob));
1767 }
1768 }
1769 }
1770 else
1771 {
1772 char
1773 filename[MaxTextExtent],
1774 unique[MaxTextExtent];
1775
1776 int
1777 file;
1778
1779 /*
1780 Write file to disk in blob images format.
1781 */
1782 file=AcquireUniqueFileResource(unique);
1783 if (file == -1)
1784 {
1785 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1786 image_info->filename);
1787 }
1788 else
1789 {
1790 blob_info->file=fdopen(file,"wb");
1791 if (blob_info->file != (FILE *) NULL)
1792 {
cristyb51dff52011-05-19 16:55:47 +00001793 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001794 images->magick,unique);
1795 status=WriteImages(blob_info,images,filename,exception);
1796 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001797 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001798 blob=FileToBlob(images->filename,~0UL,length,exception);
1799 }
1800 (void) RelinquishUniqueFileResource(unique);
1801 }
1802 }
1803 blob_info=DestroyImageInfo(blob_info);
1804 return(blob);
1805}
1806/*
1807%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1808% %
1809% %
1810% %
1811% I n j e c t I m a g e B l o b %
1812% %
1813% %
1814% %
1815%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1816%
1817% InjectImageBlob() injects the image with a copy of itself in the specified
1818% format (e.g. inject JPEG into a PDF image).
1819%
1820% The format of the InjectImageBlob method is:
1821%
1822% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1823% Image *image,Image *inject_image,const char *format,
1824% ExceptionInfo *exception)
1825%
1826% A description of each parameter follows:
1827%
1828% o image_info: the image info..
1829%
1830% o image: the image.
1831%
1832% o inject_image: inject into the image stream.
1833%
1834% o format: the image format.
1835%
1836% o exception: return any errors or warnings in this structure.
1837%
1838*/
1839MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1840 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1841{
1842 char
1843 filename[MaxTextExtent];
1844
1845 FILE
1846 *unique_file;
1847
1848 Image
1849 *byte_image;
1850
1851 ImageInfo
1852 *write_info;
1853
1854 int
1855 file;
1856
1857 MagickBooleanType
1858 status;
1859
cristybb503372010-05-27 20:51:26 +00001860 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001861 i;
1862
1863 size_t
1864 quantum;
1865
1866 ssize_t
1867 count;
1868
1869 struct stat
1870 file_info;
1871
1872 unsigned char
1873 *buffer;
1874
1875 /*
1876 Write inject image to a temporary file.
1877 */
1878 assert(image_info != (ImageInfo *) NULL);
1879 assert(image_info->signature == MagickSignature);
1880 assert(image != (Image *) NULL);
1881 assert(image->signature == MagickSignature);
1882 if (image->debug != MagickFalse)
1883 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1884 assert(inject_image != (Image *) NULL);
1885 assert(inject_image->signature == MagickSignature);
1886 assert(exception != (ExceptionInfo *) NULL);
1887 unique_file=(FILE *) NULL;
1888 file=AcquireUniqueFileResource(filename);
1889 if (file != -1)
1890 unique_file=fdopen(file,"wb");
1891 if ((file == -1) || (unique_file == (FILE *) NULL))
1892 {
1893 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1894 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1895 image->filename);
1896 return(MagickFalse);
1897 }
1898 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1899 if (byte_image == (Image *) NULL)
1900 {
1901 (void) fclose(unique_file);
1902 (void) RelinquishUniqueFileResource(filename);
1903 return(MagickFalse);
1904 }
cristyb51dff52011-05-19 16:55:47 +00001905 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001906 filename);
1907 DestroyBlob(byte_image);
1908 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1909 write_info=CloneImageInfo(image_info);
1910 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001911 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001912 write_info=DestroyImageInfo(write_info);
1913 byte_image=DestroyImage(byte_image);
1914 (void) fclose(unique_file);
1915 if (status == MagickFalse)
1916 {
1917 (void) RelinquishUniqueFileResource(filename);
1918 return(MagickFalse);
1919 }
1920 /*
1921 Inject into image stream.
1922 */
cristy18c6c272011-09-23 14:40:37 +00001923 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001924 if (file == -1)
1925 {
1926 (void) RelinquishUniqueFileResource(filename);
1927 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1928 image_info->filename);
1929 return(MagickFalse);
1930 }
1931 quantum=(size_t) MagickMaxBufferExtent;
1932 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
cristy7753b2a2011-02-19 18:36:52 +00001933 quantum=(size_t) MagickMin(file_info.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001934 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1935 if (buffer == (unsigned char *) NULL)
1936 {
1937 (void) RelinquishUniqueFileResource(filename);
1938 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1939 image->filename);
1940 }
1941 for (i=0; ; i+=count)
1942 {
1943 count=(ssize_t) read(file,buffer,quantum);
1944 if (count <= 0)
1945 {
1946 count=0;
1947 if (errno != EINTR)
1948 break;
1949 }
1950 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1951 MagickFalse;
1952 }
cristya7cb4312010-06-26 00:47:03 +00001953 file=close(file);
1954 if (file == -1)
1955 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001956 (void) RelinquishUniqueFileResource(filename);
1957 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1958 return(status);
1959}
1960
1961/*
1962%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1963% %
1964% %
1965% %
1966+ I s B l o b E x e m p t %
1967% %
1968% %
1969% %
1970%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1971%
1972% IsBlobExempt() returns true if the blob is exempt.
1973%
1974% The format of the IsBlobExempt method is:
1975%
1976% MagickBooleanType IsBlobExempt(const Image *image)
1977%
1978% A description of each parameter follows:
1979%
1980% o image: the image.
1981%
1982*/
cristy7832dc22011-09-05 01:21:53 +00001983MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001984{
1985 assert(image != (const Image *) NULL);
1986 assert(image->signature == MagickSignature);
1987 if (image->debug != MagickFalse)
1988 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1989 return(image->blob->exempt);
1990}
1991
1992/*
1993%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1994% %
1995% %
1996% %
1997+ I s B l o b S e e k a b l e %
1998% %
1999% %
2000% %
2001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2002%
2003% IsBlobSeekable() returns true if the blob is seekable.
2004%
2005% The format of the IsBlobSeekable method is:
2006%
2007% MagickBooleanType IsBlobSeekable(const Image *image)
2008%
2009% A description of each parameter follows:
2010%
2011% o image: the image.
2012%
2013*/
cristy7832dc22011-09-05 01:21:53 +00002014MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002015{
2016 MagickBooleanType
2017 seekable;
2018
2019 assert(image != (const Image *) NULL);
2020 assert(image->signature == MagickSignature);
2021 if (image->debug != MagickFalse)
2022 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2023 seekable=(image->blob->type == FileStream) ||
2024 (image->blob->type == BlobStream) ? MagickTrue : MagickFalse;
2025 return(seekable);
2026}
2027
2028/*
2029%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2030% %
2031% %
2032% %
2033+ I s B l o b T e m p o r a r y %
2034% %
2035% %
2036% %
2037%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2038%
2039% IsBlobTemporary() returns true if the blob is temporary.
2040%
2041% The format of the IsBlobTemporary method is:
2042%
2043% MagickBooleanType IsBlobTemporary(const Image *image)
2044%
2045% A description of each parameter follows:
2046%
2047% o image: the image.
2048%
2049*/
cristy7832dc22011-09-05 01:21:53 +00002050MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002051{
2052 assert(image != (const Image *) NULL);
2053 assert(image->signature == MagickSignature);
2054 if (image->debug != MagickFalse)
2055 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2056 return(image->blob->temporary);
2057}
2058
2059/*
2060%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2061% %
2062% %
2063% %
2064+ M a p B l o b %
2065% %
2066% %
2067% %
2068%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2069%
2070% MapBlob() creates a mapping from a file to a binary large object.
2071%
2072% The format of the MapBlob method is:
2073%
2074% unsigned char *MapBlob(int file,const MapMode mode,
2075% const MagickOffsetType offset,const size_t length)
2076%
2077% A description of each parameter follows:
2078%
2079% o file: map this file descriptor.
2080%
2081% o mode: ReadMode, WriteMode, or IOMode.
2082%
2083% o offset: starting at this offset within the file.
2084%
2085% o length: the length of the mapping is returned in this pointer.
2086%
2087*/
2088MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2089 const MagickOffsetType offset,const size_t length)
2090{
2091#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
2092 int
2093 flags,
2094 protection;
2095
2096 unsigned char
2097 *map;
2098
2099 /*
2100 Map file.
2101 */
2102 flags=0;
2103 if (file == -1)
2104#if defined(MAP_ANONYMOUS)
2105 flags|=MAP_ANONYMOUS;
2106#else
2107 return((unsigned char *) NULL);
2108#endif
2109 switch (mode)
2110 {
2111 case ReadMode:
2112 default:
2113 {
2114 protection=PROT_READ;
2115 flags|=MAP_PRIVATE;
2116 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2117 (off_t) offset);
2118 break;
2119 }
2120 case WriteMode:
2121 {
2122 protection=PROT_WRITE;
2123 flags|=MAP_SHARED;
2124 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2125 (off_t) offset);
cristy2a9e7cb2010-03-05 02:15:05 +00002126#if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
2127 (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
2128 POSIX_MADV_WILLNEED);
2129#endif
cristy3ed852e2009-09-05 21:47:34 +00002130 break;
2131 }
2132 case IOMode:
2133 {
2134 protection=PROT_READ | PROT_WRITE;
2135 flags|=MAP_SHARED;
2136 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2137 (off_t) offset);
2138 break;
2139 }
2140 }
2141 if (map == (unsigned char *) MAP_FAILED)
2142 return((unsigned char *) NULL);
2143 return(map);
2144#else
2145 (void) file;
2146 (void) mode;
2147 (void) offset;
2148 (void) length;
2149 return((unsigned char *) NULL);
2150#endif
2151}
2152
2153/*
2154%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2155% %
2156% %
2157% %
2158+ M S B O r d e r L o n g %
2159% %
2160% %
2161% %
2162%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2163%
2164% MSBOrderLong() converts a least-significant byte first buffer of integers to
2165% most-significant byte first.
2166%
2167% The format of the MSBOrderLong method is:
2168%
2169% void MSBOrderLong(unsigned char *buffer,const size_t length)
2170%
2171% A description of each parameter follows.
2172%
2173% o buffer: Specifies a pointer to a buffer of integers.
2174%
2175% o length: Specifies the length of the buffer.
2176%
2177*/
2178MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2179{
2180 int
2181 c;
2182
2183 register unsigned char
2184 *p,
2185 *q;
2186
2187 assert(buffer != (unsigned char *) NULL);
2188 q=buffer+length;
2189 while (buffer < q)
2190 {
2191 p=buffer+3;
2192 c=(int) (*p);
2193 *p=(*buffer);
2194 *buffer++=(unsigned char) c;
2195 p=buffer+1;
2196 c=(int) (*p);
2197 *p=(*buffer);
2198 *buffer++=(unsigned char) c;
2199 buffer+=2;
2200 }
2201}
2202
2203/*
2204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2205% %
2206% %
2207% %
2208+ M S B O r d e r S h o r t %
2209% %
2210% %
2211% %
2212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2213%
2214% MSBOrderShort() converts a least-significant byte first buffer of integers
2215% to most-significant byte first.
2216%
2217% The format of the MSBOrderShort method is:
2218%
2219% void MSBOrderShort(unsigned char *p,const size_t length)
2220%
2221% A description of each parameter follows.
2222%
2223% o p: Specifies a pointer to a buffer of integers.
2224%
2225% o length: Specifies the length of the buffer.
2226%
2227*/
2228MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2229{
2230 int
2231 c;
2232
2233 register unsigned char
2234 *q;
2235
2236 assert(p != (unsigned char *) NULL);
2237 q=p+length;
2238 while (p < q)
2239 {
2240 c=(int) (*p);
2241 *p=(*(p+1));
2242 p++;
2243 *p++=(unsigned char) c;
2244 }
2245}
2246
2247/*
2248%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2249% %
2250% %
2251% %
2252+ O p e n B l o b %
2253% %
2254% %
2255% %
2256%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2257%
2258% OpenBlob() opens a file associated with the image. A file name of '-' sets
2259% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2260% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2261% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2262% from a system command.
2263%
2264% The format of the OpenBlob method is:
2265%
2266% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2267% const BlobMode mode,ExceptionInfo *exception)
2268%
2269% A description of each parameter follows:
2270%
2271% o image_info: the image info.
2272%
2273% o image: the image.
2274%
2275% o mode: the mode for opening the file.
2276%
2277*/
2278MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2279 Image *image,const BlobMode mode,ExceptionInfo *exception)
2280{
2281 char
cristybf6a7092010-06-11 02:12:15 +00002282 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002283 filename[MaxTextExtent];
2284
2285 const char
2286 *type;
2287
2288 MagickBooleanType
2289 status;
2290
2291 PolicyRights
2292 rights;
2293
2294 assert(image_info != (ImageInfo *) NULL);
2295 assert(image_info->signature == MagickSignature);
2296 if (image_info->debug != MagickFalse)
2297 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2298 image_info->filename);
2299 assert(image != (Image *) NULL);
2300 assert(image->signature == MagickSignature);
2301 if (image_info->blob != (void *) NULL)
2302 {
2303 if (image_info->stream != (StreamHandler) NULL)
2304 image->blob->stream=(StreamHandler) image_info->stream;
2305 AttachBlob(image->blob,image_info->blob,image_info->length);
2306 return(MagickTrue);
2307 }
2308 (void) DetachBlob(image->blob);
2309 switch (mode)
2310 {
2311 default: type="r"; break;
2312 case ReadBlobMode: type="r"; break;
2313 case ReadBinaryBlobMode: type="rb"; break;
2314 case WriteBlobMode: type="w"; break;
2315 case WriteBinaryBlobMode: type="w+b"; break;
2316 case AppendBlobMode: type="a"; break;
2317 case AppendBinaryBlobMode: type="a+b"; break;
2318 }
2319 if (*type != 'r')
2320 image->blob->synchronize=image_info->synchronize;
2321 if (image_info->stream != (StreamHandler) NULL)
2322 {
2323 image->blob->stream=(StreamHandler) image_info->stream;
2324 if (*type == 'w')
2325 {
2326 image->blob->type=FifoStream;
2327 return(MagickTrue);
2328 }
2329 }
2330 /*
2331 Open image file.
2332 */
2333 *filename='\0';
2334 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2335 rights=ReadPolicyRights;
2336 if (*type == 'w')
2337 rights=WritePolicyRights;
2338 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2339 {
cristya9197f62010-01-12 02:23:34 +00002340 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002341 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2342 "NotAuthorized","`%s'",filename);
2343 return(MagickFalse);
2344 }
2345 if ((LocaleCompare(filename,"-") == 0) ||
2346 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2347 {
2348 image->blob->file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002349#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002350 if (strchr(type,'b') != (char *) NULL)
2351 setmode(_fileno(image->blob->file),_O_BINARY);
2352#endif
2353 image->blob->type=StandardStream;
2354 image->blob->exempt=MagickTrue;
2355 return(MagickTrue);
2356 }
2357 if (LocaleNCompare(filename,"fd:",3) == 0)
2358 {
2359 char
2360 mode[MaxTextExtent];
2361
2362 *mode=(*type);
2363 mode[1]='\0';
cristyf2f27272009-12-17 14:48:46 +00002364 image->blob->file=fdopen(StringToLong(filename+3),mode);
cristy0157aea2010-04-24 21:12:18 +00002365#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002366 if (strchr(type,'b') != (char *) NULL)
2367 setmode(_fileno(image->blob->file),_O_BINARY);
2368#endif
2369 image->blob->type=StandardStream;
2370 image->blob->exempt=MagickTrue;
2371 return(MagickTrue);
2372 }
2373#if defined(MAGICKCORE_HAVE_POPEN)
2374 if (*filename == '|')
2375 {
2376 char
2377 mode[MaxTextExtent];
2378
2379 /*
2380 Pipe image to or from a system command.
2381 */
2382#if defined(SIGPIPE)
2383 if (*type == 'w')
2384 (void) signal(SIGPIPE,SIG_IGN);
2385#endif
2386 *mode=(*type);
2387 mode[1]='\0';
cristy18c6c272011-09-23 14:40:37 +00002388 image->blob->file=(FILE *) popen_utf8(filename+1,mode);
cristy3ed852e2009-09-05 21:47:34 +00002389 if (image->blob->file == (FILE *) NULL)
2390 {
2391 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2392 return(MagickFalse);
2393 }
2394 image->blob->type=PipeStream;
2395 image->blob->exempt=MagickTrue;
2396 return(MagickTrue);
2397 }
2398#endif
2399 status=GetPathAttributes(filename,&image->blob->properties);
2400#if defined(S_ISFIFO)
2401 if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2402 {
cristy18c6c272011-09-23 14:40:37 +00002403 image->blob->file=(FILE *) fopen_utf8(filename,type);
cristy3ed852e2009-09-05 21:47:34 +00002404 if (image->blob->file == (FILE *) NULL)
2405 {
2406 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2407 return(MagickFalse);
2408 }
2409 image->blob->type=FileStream;
2410 image->blob->exempt=MagickTrue;
2411 return(MagickTrue);
2412 }
2413#endif
cristybf6a7092010-06-11 02:12:15 +00002414 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002415 if (*type == 'w')
2416 {
cristye8939e72010-02-03 17:05:25 +00002417 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002418 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002419 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002420 {
2421 /*
2422 Form filename for multi-part images.
2423 */
2424 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002425 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002426 if ((LocaleCompare(filename,image->filename) == 0) &&
2427 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2428 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002429 {
cristybf7fa0d2010-02-04 00:51:10 +00002430 char
cristybf7fa0d2010-02-04 00:51:10 +00002431 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002432
cristybf7fa0d2010-02-04 00:51:10 +00002433 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002434 if (*extension == '\0')
cristyb51dff52011-05-19 16:55:47 +00002435 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002436 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002437 else
cristyb51dff52011-05-19 16:55:47 +00002438 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002439 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002440 }
2441 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002442#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002443 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002444#endif
cristye8939e72010-02-03 17:05:25 +00002445 }
cristy3ed852e2009-09-05 21:47:34 +00002446 }
cristybf6a7092010-06-11 02:12:15 +00002447 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002448 {
cristybf6a7092010-06-11 02:12:15 +00002449 image->blob->file=image_info->file;
2450 image->blob->type=FileStream;
2451 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002452 }
2453 else
cristybf6a7092010-06-11 02:12:15 +00002454 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002455 {
cristy18c6c272011-09-23 14:40:37 +00002456 image->blob->file=(FILE *) fopen_utf8(filename,type);
cristy3ed852e2009-09-05 21:47:34 +00002457 if (image->blob->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002458 {
2459 size_t
cristybf6a7092010-06-11 02:12:15 +00002460 count;
cristy3ed852e2009-09-05 21:47:34 +00002461
cristybf6a7092010-06-11 02:12:15 +00002462 unsigned char
2463 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002464
cristybf6a7092010-06-11 02:12:15 +00002465 image->blob->type=FileStream;
2466#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyf55846d2010-09-17 19:01:10 +00002467 (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002468#endif
2469 (void) ResetMagickMemory(magick,0,sizeof(magick));
2470 count=fread(magick,1,sizeof(magick),image->blob->file);
2471 (void) rewind(image->blob->file);
2472 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2473 " read %.20g magic header bytes",(double) count);
2474#if defined(MAGICKCORE_ZLIB_DELEGATE)
2475 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2476 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002477 {
cristybf6a7092010-06-11 02:12:15 +00002478 (void) fclose(image->blob->file);
2479 image->blob->file=(FILE *) gzopen(filename,type);
2480 if (image->blob->file != (FILE *) NULL)
2481 image->blob->type=ZipStream;
2482 }
2483#endif
2484#if defined(MAGICKCORE_BZLIB_DELEGATE)
2485 if (strncmp((char *) magick,"BZh",3) == 0)
2486 {
2487 (void) fclose(image->blob->file);
2488 image->blob->file=(FILE *) BZ2_bzopen(filename,type);
2489 if (image->blob->file != (FILE *) NULL)
2490 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002491 }
cristybf6a7092010-06-11 02:12:15 +00002492#endif
cristyc6c589d2010-07-06 01:34:57 +00002493 if (image->blob->type == FileStream)
2494 {
2495 const MagickInfo
2496 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002497
cristyc6c589d2010-07-06 01:34:57 +00002498 ExceptionInfo
2499 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002500
cristyc6c589d2010-07-06 01:34:57 +00002501 struct stat
2502 *properties;
cristybf6a7092010-06-11 02:12:15 +00002503
cristyc6c589d2010-07-06 01:34:57 +00002504 sans_exception=AcquireExceptionInfo();
2505 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2506 sans_exception=DestroyExceptionInfo(sans_exception);
2507 properties=(&image->blob->properties);
2508 if ((magick_info != (const MagickInfo *) NULL) &&
2509 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2510 (properties->st_size <= MagickMaxBufferExtent))
2511 {
2512 size_t
2513 length;
cristybf6a7092010-06-11 02:12:15 +00002514
cristyc6c589d2010-07-06 01:34:57 +00002515 void
2516 *blob;
cristybf6a7092010-06-11 02:12:15 +00002517
cristyc6c589d2010-07-06 01:34:57 +00002518 length=(size_t) properties->st_size;
2519 blob=MapBlob(fileno(image->blob->file),ReadMode,0,length);
2520 if (blob != (void *) NULL)
2521 {
2522 /*
2523 Format supports blobs-- use memory-mapped I/O.
2524 */
2525 if (image_info->file != (FILE *) NULL)
2526 image->blob->exempt=MagickFalse;
2527 else
2528 {
2529 (void) fclose(image->blob->file);
2530 image->blob->file=(FILE *) NULL;
2531 }
2532 AttachBlob(image->blob,blob,length);
2533 image->blob->mapped=MagickTrue;
2534 }
2535 }
2536 }
cristy3ed852e2009-09-05 21:47:34 +00002537 }
cristybf6a7092010-06-11 02:12:15 +00002538 }
2539 else
2540#if defined(MAGICKCORE_ZLIB_DELEGATE)
2541 if ((LocaleCompare(extension,"Z") == 0) ||
2542 (LocaleCompare(extension,"gz") == 0) ||
2543 (LocaleCompare(extension,"wmz") == 0) ||
2544 (LocaleCompare(extension,"svgz") == 0))
2545 {
2546 if (mode == WriteBinaryBlobMode)
2547 type="wb";
2548 image->blob->file=(FILE *) gzopen(filename,type);
2549 if (image->blob->file != (FILE *) NULL)
2550 image->blob->type=ZipStream;
2551 }
2552 else
2553#endif
2554#if defined(MAGICKCORE_BZLIB_DELEGATE)
2555 if (LocaleCompare(extension,".bz2") == 0)
2556 {
2557 image->blob->file=(FILE *) BZ2_bzopen(filename,type);
2558 if (image->blob->file != (FILE *) NULL)
2559 image->blob->type=BZipStream;
2560 }
2561 else
2562#endif
2563 {
cristy18c6c272011-09-23 14:40:37 +00002564 image->blob->file=(FILE *) fopen_utf8(filename,type);
cristybf6a7092010-06-11 02:12:15 +00002565 if (image->blob->file != (FILE *) NULL)
2566 {
2567 image->blob->type=FileStream;
2568#if defined(MAGICKCORE_HAVE_SETVBUF)
2569 (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,
2570 16384);
2571#endif
2572 }
2573 }
cristy3ed852e2009-09-05 21:47:34 +00002574 image->blob->status=MagickFalse;
2575 if (image->blob->type != UndefinedStream)
2576 image->blob->size=GetBlobSize(image);
2577 else
2578 {
2579 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2580 return(MagickFalse);
2581 }
2582 return(MagickTrue);
2583}
2584
2585/*
2586%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2587% %
2588% %
2589% %
2590+ P i n g B l o b %
2591% %
2592% %
2593% %
2594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2595%
2596% PingBlob() returns all the attributes of an image or image sequence except
2597% for the pixels. It is much faster and consumes far less memory than
2598% BlobToImage(). On failure, a NULL image is returned and exception
2599% describes the reason for the failure.
2600%
2601% The format of the PingBlob method is:
2602%
2603% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2604% const size_t length,ExceptionInfo *exception)
2605%
2606% A description of each parameter follows:
2607%
2608% o image_info: the image info.
2609%
2610% o blob: the address of a character stream in one of the image formats
2611% understood by ImageMagick.
2612%
2613% o length: This size_t integer reflects the length in bytes of the blob.
2614%
2615% o exception: return any errors or warnings in this structure.
2616%
2617*/
2618
2619#if defined(__cplusplus) || defined(c_plusplus)
2620extern "C" {
2621#endif
2622
2623static size_t PingStream(const Image *magick_unused(image),
2624 const void *magick_unused(pixels),const size_t columns)
2625{
2626 return(columns);
2627}
2628
2629#if defined(__cplusplus) || defined(c_plusplus)
2630}
2631#endif
2632
2633MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2634 const size_t length,ExceptionInfo *exception)
2635{
2636 Image
2637 *image;
2638
2639 ImageInfo
2640 *ping_info;
2641
2642 assert(image_info != (ImageInfo *) NULL);
2643 assert(image_info->signature == MagickSignature);
2644 if (image_info->debug != MagickFalse)
2645 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2646 image_info->filename);
2647 assert(exception != (ExceptionInfo *) NULL);
2648 if ((blob == (const void *) NULL) || (length == 0))
2649 {
2650 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
2651 "UnrecognizedImageFormat","`%s'",image_info->magick);
2652 return((Image *) NULL);
2653 }
2654 ping_info=CloneImageInfo(image_info);
2655 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2656 if (ping_info->blob == (const void *) NULL)
2657 {
2658 (void) ThrowMagickException(exception,GetMagickModule(),
2659 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
2660 return((Image *) NULL);
2661 }
cristy54aad5e2010-09-03 16:02:04 +00002662 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002663 ping_info->length=length;
2664 ping_info->ping=MagickTrue;
2665 image=ReadStream(ping_info,&PingStream,exception);
2666 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2667 ping_info=DestroyImageInfo(ping_info);
2668 return(image);
2669}
2670
2671/*
2672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2673% %
2674% %
2675% %
2676+ R e a d B l o b %
2677% %
2678% %
2679% %
2680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2681%
2682% ReadBlob() reads data from the blob or image file and returns it. It
2683% returns the number of bytes read.
2684%
2685% The format of the ReadBlob method is:
2686%
2687% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2688%
2689% A description of each parameter follows:
2690%
2691% o image: the image.
2692%
2693% o length: Specifies an integer representing the number of bytes to read
2694% from the file.
2695%
2696% o data: Specifies an area to place the information requested from the
2697% file.
2698%
2699*/
2700MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2701 unsigned char *data)
2702{
2703 int
2704 c;
2705
2706 register unsigned char
2707 *q;
2708
2709 ssize_t
2710 count;
2711
2712 assert(image != (Image *) NULL);
2713 assert(image->signature == MagickSignature);
2714 assert(image->blob != (BlobInfo *) NULL);
2715 assert(image->blob->type != UndefinedStream);
2716 if (length == 0)
2717 return(0);
2718 assert(data != (void *) NULL);
2719 count=0;
2720 q=data;
2721 switch (image->blob->type)
2722 {
2723 case UndefinedStream:
2724 break;
2725 case FileStream:
2726 case StandardStream:
2727 case PipeStream:
2728 {
2729 switch (length)
2730 {
2731 default:
2732 {
2733 count=(ssize_t) fread(q,1,length,image->blob->file);
2734 break;
2735 }
2736 case 2:
2737 {
2738 c=getc(image->blob->file);
2739 if (c == EOF)
2740 break;
2741 *q++=(unsigned char) c;
2742 count++;
2743 }
2744 case 1:
2745 {
2746 c=getc(image->blob->file);
2747 if (c == EOF)
2748 break;
2749 *q++=(unsigned char) c;
2750 count++;
2751 }
2752 case 0:
2753 break;
2754 }
2755 break;
2756 }
2757 case ZipStream:
2758 {
2759#if defined(MAGICKCORE_ZLIB_DELEGATE)
2760 switch (length)
2761 {
2762 default:
2763 {
2764 count=(ssize_t) gzread(image->blob->file,q,(unsigned int) length);
2765 break;
2766 }
2767 case 2:
2768 {
2769 c=gzgetc(image->blob->file);
2770 if (c == EOF)
2771 break;
2772 *q++=(unsigned char) c;
2773 count++;
2774 }
2775 case 1:
2776 {
2777 c=gzgetc(image->blob->file);
2778 if (c == EOF)
2779 break;
2780 *q++=(unsigned char) c;
2781 count++;
2782 }
2783 case 0:
2784 break;
2785 }
2786#endif
2787 break;
2788 }
2789 case BZipStream:
2790 {
2791#if defined(MAGICKCORE_BZLIB_DELEGATE)
2792 count=(ssize_t) BZ2_bzread((BZFILE *) image->blob->file,q,(int) length);
2793#endif
2794 break;
2795 }
2796 case FifoStream:
2797 break;
2798 case BlobStream:
2799 {
2800 register const unsigned char
2801 *p;
2802
2803 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2804 {
2805 image->blob->eof=MagickTrue;
2806 break;
2807 }
2808 p=image->blob->data+image->blob->offset;
cristy7753b2a2011-02-19 18:36:52 +00002809 count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
cristy3ed852e2009-09-05 21:47:34 +00002810 image->blob->offset+=count;
2811 if (count != (ssize_t) length)
2812 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002813 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002814 break;
2815 }
2816 }
2817 return(count);
2818}
2819
2820/*
2821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2822% %
2823% %
2824% %
2825+ R e a d B l o b B y t e %
2826% %
2827% %
2828% %
2829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2830%
2831% ReadBlobByte() reads a single byte from the image file and returns it.
2832%
2833% The format of the ReadBlobByte method is:
2834%
2835% int ReadBlobByte(Image *image)
2836%
2837% A description of each parameter follows.
2838%
2839% o image: the image.
2840%
2841*/
2842MagickExport int ReadBlobByte(Image *image)
2843{
2844 register const unsigned char
2845 *p;
2846
2847 ssize_t
2848 count;
2849
2850 unsigned char
2851 buffer[1];
2852
2853 assert(image != (Image *) NULL);
2854 assert(image->signature == MagickSignature);
2855 p=ReadBlobStream(image,1,buffer,&count);
2856 if (count != 1)
2857 return(EOF);
2858 return((int) (*p));
2859}
2860
2861/*
2862%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2863% %
2864% %
2865% %
2866+ R e a d B l o b D o u b l e %
2867% %
2868% %
2869% %
2870%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2871%
2872% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2873% specified by the endian member of the image structure.
2874%
2875% The format of the ReadBlobDouble method is:
2876%
2877% double ReadBlobDouble(Image *image)
2878%
2879% A description of each parameter follows.
2880%
2881% o image: the image.
2882%
2883*/
2884MagickExport double ReadBlobDouble(Image *image)
2885{
2886 union
2887 {
2888 MagickSizeType
2889 unsigned_value;
2890
2891 double
2892 double_value;
2893 } quantum;
2894
2895 quantum.double_value=0.0;
2896 quantum.unsigned_value=ReadBlobLongLong(image);
2897 return(quantum.double_value);
2898}
2899
2900/*
2901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2902% %
2903% %
2904% %
2905+ R e a d B l o b F l o a t %
2906% %
2907% %
2908% %
2909%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2910%
2911% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2912% specified by the endian member of the image structure.
2913%
2914% The format of the ReadBlobFloat method is:
2915%
2916% float ReadBlobFloat(Image *image)
2917%
2918% A description of each parameter follows.
2919%
2920% o image: the image.
2921%
2922*/
2923MagickExport float ReadBlobFloat(Image *image)
2924{
2925 union
2926 {
2927 unsigned int
2928 unsigned_value;
2929
2930 float
2931 float_value;
2932 } quantum;
2933
2934 quantum.float_value=0.0;
2935 quantum.unsigned_value=ReadBlobLong(image);
2936 return(quantum.float_value);
2937}
2938
2939/*
2940%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2941% %
2942% %
2943% %
2944+ R e a d B l o b L o n g %
2945% %
2946% %
2947% %
2948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2949%
cristybb503372010-05-27 20:51:26 +00002950% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00002951% specified by the endian member of the image structure.
2952%
2953% The format of the ReadBlobLong method is:
2954%
2955% unsigned int ReadBlobLong(Image *image)
2956%
2957% A description of each parameter follows.
2958%
2959% o image: the image.
2960%
2961*/
2962MagickExport unsigned int ReadBlobLong(Image *image)
2963{
2964 register const unsigned char
2965 *p;
2966
2967 ssize_t
2968 count;
2969
2970 unsigned char
2971 buffer[4];
2972
2973 unsigned int
2974 value;
2975
2976 assert(image != (Image *) NULL);
2977 assert(image->signature == MagickSignature);
2978 *buffer='\0';
2979 p=ReadBlobStream(image,4,buffer,&count);
2980 if (count != 4)
2981 return(0UL);
2982 if (image->endian == LSBEndian)
2983 {
2984 value=(unsigned int) (*p++);
2985 value|=((unsigned int) (*p++)) << 8;
2986 value|=((unsigned int) (*p++)) << 16;
2987 value|=((unsigned int) (*p++)) << 24;
2988 return(value);
2989 }
2990 value=((unsigned int) (*p++)) << 24;
2991 value|=((unsigned int) (*p++)) << 16;
2992 value|=((unsigned int) (*p++)) << 8;
2993 value|=((unsigned int) (*p++));
2994 return(value);
2995}
2996
2997/*
2998%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2999% %
3000% %
3001% %
3002+ R e a d B l o b L o n g L o n g %
3003% %
3004% %
3005% %
3006%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3007%
cristy4cb162a2010-05-30 03:04:47 +00003008% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3009% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003010%
cristy4cb162a2010-05-30 03:04:47 +00003011% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003012%
cristy4cb162a2010-05-30 03:04:47 +00003013% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003014%
3015% A description of each parameter follows.
3016%
3017% o image: the image.
3018%
3019*/
3020MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3021{
cristy0286d852010-10-12 18:38:07 +00003022 MagickSizeType
3023 value;
3024
cristy3ed852e2009-09-05 21:47:34 +00003025 register const unsigned char
3026 *p;
3027
3028 ssize_t
3029 count;
3030
3031 unsigned char
3032 buffer[8];
3033
cristy3ed852e2009-09-05 21:47:34 +00003034 assert(image != (Image *) NULL);
3035 assert(image->signature == MagickSignature);
3036 *buffer='\0';
3037 p=ReadBlobStream(image,8,buffer,&count);
3038 if (count != 8)
3039 return(MagickULLConstant(0));
3040 if (image->endian == LSBEndian)
3041 {
3042 value=(MagickSizeType) (*p++);
3043 value|=((MagickSizeType) (*p++)) << 8;
3044 value|=((MagickSizeType) (*p++)) << 16;
3045 value|=((MagickSizeType) (*p++)) << 24;
3046 value|=((MagickSizeType) (*p++)) << 32;
3047 value|=((MagickSizeType) (*p++)) << 40;
3048 value|=((MagickSizeType) (*p++)) << 48;
3049 value|=((MagickSizeType) (*p++)) << 56;
3050 return(value & MagickULLConstant(0xffffffffffffffff));
3051 }
3052 value=((MagickSizeType) (*p++)) << 56;
3053 value|=((MagickSizeType) (*p++)) << 48;
3054 value|=((MagickSizeType) (*p++)) << 40;
3055 value|=((MagickSizeType) (*p++)) << 32;
3056 value|=((MagickSizeType) (*p++)) << 24;
3057 value|=((MagickSizeType) (*p++)) << 16;
3058 value|=((MagickSizeType) (*p++)) << 8;
3059 value|=((MagickSizeType) (*p++));
3060 return(value & MagickULLConstant(0xffffffffffffffff));
3061}
3062
3063/*
3064%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3065% %
3066% %
3067% %
3068+ R e a d B l o b S h o r t %
3069% %
3070% %
3071% %
3072%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3073%
3074% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3075% specified by the endian member of the image structure.
3076%
3077% The format of the ReadBlobShort method is:
3078%
3079% unsigned short ReadBlobShort(Image *image)
3080%
3081% A description of each parameter follows.
3082%
3083% o image: the image.
3084%
3085*/
3086MagickExport unsigned short ReadBlobShort(Image *image)
3087{
3088 register const unsigned char
3089 *p;
3090
3091 register unsigned int
3092 value;
3093
3094 ssize_t
3095 count;
3096
3097 unsigned char
3098 buffer[2];
3099
3100 assert(image != (Image *) NULL);
3101 assert(image->signature == MagickSignature);
3102 *buffer='\0';
3103 p=ReadBlobStream(image,2,buffer,&count);
3104 if (count != 2)
3105 return((unsigned short) 0U);
3106 if (image->endian == LSBEndian)
3107 {
3108 value=(unsigned int) (*p++);
3109 value|=((unsigned int) (*p++)) << 8;
3110 return((unsigned short) (value & 0xffff));
3111 }
3112 value=(unsigned int) ((*p++) << 8);
3113 value|=(unsigned int) (*p++);
3114 return((unsigned short) (value & 0xffff));
3115}
3116
3117/*
3118%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3119% %
3120% %
3121% %
3122+ R e a d B l o b L S B L o n g %
3123% %
3124% %
3125% %
3126%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3127%
cristybb503372010-05-27 20:51:26 +00003128% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003129% least-significant byte first order.
3130%
3131% The format of the ReadBlobLSBLong method is:
3132%
3133% unsigned int ReadBlobLSBLong(Image *image)
3134%
3135% A description of each parameter follows.
3136%
3137% o image: the image.
3138%
3139*/
3140MagickExport unsigned int ReadBlobLSBLong(Image *image)
3141{
3142 register const unsigned char
3143 *p;
3144
3145 register unsigned int
3146 value;
3147
3148 ssize_t
3149 count;
3150
3151 unsigned char
3152 buffer[4];
3153
3154 assert(image != (Image *) NULL);
3155 assert(image->signature == MagickSignature);
3156 *buffer='\0';
3157 p=ReadBlobStream(image,4,buffer,&count);
3158 if (count != 4)
3159 return(0U);
3160 value=(unsigned int) (*p++);
3161 value|=((unsigned int) (*p++)) << 8;
3162 value|=((unsigned int) (*p++)) << 16;
3163 value|=((unsigned int) (*p++)) << 24;
3164 return(value);
3165}
3166
3167/*
3168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3169% %
3170% %
3171% %
3172+ R e a d B l o b L S B S h o r t %
3173% %
3174% %
3175% %
3176%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3177%
3178% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3179% least-significant byte first order.
3180%
3181% The format of the ReadBlobLSBShort method is:
3182%
3183% unsigned short ReadBlobLSBShort(Image *image)
3184%
3185% A description of each parameter follows.
3186%
3187% o image: the image.
3188%
3189*/
3190MagickExport unsigned short ReadBlobLSBShort(Image *image)
3191{
3192 register const unsigned char
3193 *p;
3194
3195 register unsigned int
3196 value;
3197
3198 ssize_t
3199 count;
3200
3201 unsigned char
3202 buffer[2];
3203
3204 assert(image != (Image *) NULL);
3205 assert(image->signature == MagickSignature);
3206 *buffer='\0';
3207 p=ReadBlobStream(image,2,buffer,&count);
3208 if (count != 2)
3209 return((unsigned short) 0U);
3210 value=(unsigned int) (*p++);
3211 value|=((unsigned int) ((*p++)) << 8);
3212 return((unsigned short) (value & 0xffff));
3213}
3214
3215/*
3216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3217% %
3218% %
3219% %
3220+ R e a d B l o b M S B L o n g %
3221% %
3222% %
3223% %
3224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3225%
cristybb503372010-05-27 20:51:26 +00003226% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003227% most-significant byte first order.
3228%
3229% The format of the ReadBlobMSBLong method is:
3230%
3231% unsigned int ReadBlobMSBLong(Image *image)
3232%
3233% A description of each parameter follows.
3234%
3235% o image: the image.
3236%
3237*/
3238MagickExport unsigned int ReadBlobMSBLong(Image *image)
3239{
3240 register const unsigned char
3241 *p;
3242
3243 register unsigned int
3244 value;
3245
3246 ssize_t
3247 count;
3248
3249 unsigned char
3250 buffer[4];
3251
3252 assert(image != (Image *) NULL);
3253 assert(image->signature == MagickSignature);
3254 *buffer='\0';
3255 p=ReadBlobStream(image,4,buffer,&count);
3256 if (count != 4)
3257 return(0UL);
3258 value=((unsigned int) (*p++) << 24);
3259 value|=((unsigned int) (*p++) << 16);
3260 value|=((unsigned int) (*p++) << 8);
3261 value|=(unsigned int) (*p++);
3262 return(value);
3263}
3264
3265/*
3266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3267% %
3268% %
3269% %
cristy2d3d87f2010-03-01 00:23:08 +00003270+ R e a d B l o b M S B L o n g L o n g %
3271% %
3272% %
3273% %
3274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3275%
cristybb503372010-05-27 20:51:26 +00003276% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003277% most-significant byte first order.
3278%
3279% The format of the ReadBlobMSBLongLong method is:
3280%
3281% unsigned int ReadBlobMSBLongLong(Image *image)
3282%
3283% A description of each parameter follows.
3284%
3285% o image: the image.
3286%
3287*/
3288MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3289{
3290 register const unsigned char
3291 *p;
3292
3293 register MagickSizeType
3294 value;
3295
3296 ssize_t
3297 count;
3298
3299 unsigned char
cristy0286d852010-10-12 18:38:07 +00003300 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003301
3302 assert(image != (Image *) NULL);
3303 assert(image->signature == MagickSignature);
3304 *buffer='\0';
3305 p=ReadBlobStream(image,8,buffer,&count);
3306 if (count != 8)
3307 return(MagickULLConstant(0));
3308 value=((MagickSizeType) (*p++)) << 56;
3309 value|=((MagickSizeType) (*p++)) << 48;
3310 value|=((MagickSizeType) (*p++)) << 40;
3311 value|=((MagickSizeType) (*p++)) << 32;
3312 value|=((MagickSizeType) (*p++)) << 24;
3313 value|=((MagickSizeType) (*p++)) << 16;
3314 value|=((MagickSizeType) (*p++)) << 8;
3315 value|=((MagickSizeType) (*p++));
3316 return(value & MagickULLConstant(0xffffffffffffffff));
3317}
3318
3319/*
3320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3321% %
3322% %
3323% %
cristy3ed852e2009-09-05 21:47:34 +00003324+ R e a d B l o b M S B S h o r t %
3325% %
3326% %
3327% %
3328%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3329%
3330% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3331% most-significant byte first order.
3332%
3333% The format of the ReadBlobMSBShort method is:
3334%
3335% unsigned short ReadBlobMSBShort(Image *image)
3336%
3337% A description of each parameter follows.
3338%
3339% o image: the image.
3340%
3341*/
3342MagickExport unsigned short ReadBlobMSBShort(Image *image)
3343{
3344 register const unsigned char
3345 *p;
3346
3347 register unsigned int
3348 value;
3349
3350 ssize_t
3351 count;
3352
3353 unsigned char
3354 buffer[2];
3355
3356 assert(image != (Image *) NULL);
3357 assert(image->signature == MagickSignature);
3358 *buffer='\0';
3359 p=ReadBlobStream(image,2,buffer,&count);
3360 if (count != 2)
3361 return((unsigned short) 0U);
3362 value=(unsigned int) ((*p++) << 8);
3363 value|=(unsigned int) (*p++);
3364 return((unsigned short) (value & 0xffff));
3365}
3366
3367/*
3368%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3369% %
3370% %
3371% %
3372+ R e a d B l o b S t r i n g %
3373% %
3374% %
3375% %
3376%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3377%
3378% ReadBlobString() reads characters from a blob or file until a newline
3379% character is read or an end-of-file condition is encountered.
3380%
3381% The format of the ReadBlobString method is:
3382%
3383% char *ReadBlobString(Image *image,char *string)
3384%
3385% A description of each parameter follows:
3386%
3387% o image: the image.
3388%
3389% o string: the address of a character buffer.
3390%
3391*/
3392MagickExport char *ReadBlobString(Image *image,char *string)
3393{
3394 register const unsigned char
3395 *p;
3396
cristybb503372010-05-27 20:51:26 +00003397 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003398 i;
3399
3400 ssize_t
3401 count;
3402
3403 unsigned char
3404 buffer[1];
3405
3406 assert(image != (Image *) NULL);
3407 assert(image->signature == MagickSignature);
3408 for (i=0; i < (MaxTextExtent-1L); i++)
3409 {
3410 p=ReadBlobStream(image,1,buffer,&count);
3411 if (count != 1)
3412 {
3413 if (i == 0)
3414 return((char *) NULL);
3415 break;
3416 }
3417 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003418 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003419 break;
3420 }
cristy2b5db102010-06-09 01:07:28 +00003421 if (string[i] == '\r')
3422 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003423 string[i]='\0';
3424 return(string);
3425}
3426
3427/*
3428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3429% %
3430% %
3431% %
3432+ R e f e r e n c e B l o b %
3433% %
3434% %
3435% %
3436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3437%
3438% ReferenceBlob() increments the reference count associated with the pixel
3439% blob returning a pointer to the blob.
3440%
3441% The format of the ReferenceBlob method is:
3442%
3443% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3444%
3445% A description of each parameter follows:
3446%
3447% o blob_info: the blob_info.
3448%
3449*/
3450MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3451{
3452 assert(blob != (BlobInfo *) NULL);
3453 assert(blob->signature == MagickSignature);
3454 if (blob->debug != MagickFalse)
3455 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003456 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003457 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003458 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003459 return(blob);
3460}
3461
3462/*
3463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3464% %
3465% %
3466% %
3467+ S e e k B l o b %
3468% %
3469% %
3470% %
3471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3472%
3473% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3474% and returns the resulting offset.
3475%
3476% The format of the SeekBlob method is:
3477%
3478% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3479% const int whence)
3480%
3481% A description of each parameter follows:
3482%
3483% o image: the image.
3484%
3485% o offset: Specifies an integer representing the offset in bytes.
3486%
3487% o whence: Specifies an integer representing how the offset is
3488% treated relative to the beginning of the blob as follows:
3489%
3490% SEEK_SET Set position equal to offset bytes.
3491% SEEK_CUR Set position to current location plus offset.
3492% SEEK_END Set position to EOF plus offset.
3493%
3494*/
3495MagickExport MagickOffsetType SeekBlob(Image *image,
3496 const MagickOffsetType offset,const int whence)
3497{
3498 assert(image != (Image *) NULL);
3499 assert(image->signature == MagickSignature);
3500 if (image->debug != MagickFalse)
3501 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3502 assert(image->blob != (BlobInfo *) NULL);
3503 assert(image->blob->type != UndefinedStream);
3504 switch (image->blob->type)
3505 {
3506 case UndefinedStream:
3507 break;
3508 case FileStream:
3509 {
cristy53e0e4a2011-02-18 02:55:20 +00003510 if (fseek(image->blob->file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003511 return(-1);
3512 image->blob->offset=TellBlob(image);
3513 break;
3514 }
3515 case StandardStream:
3516 case PipeStream:
3517 case ZipStream:
3518 {
3519#if defined(MAGICKCORE_ZLIB_DELEGATE)
3520 if (gzseek(image->blob->file,(off_t) offset,whence) < 0)
3521 return(-1);
3522#endif
3523 image->blob->offset=TellBlob(image);
3524 break;
3525 }
3526 case BZipStream:
3527 return(-1);
3528 case FifoStream:
3529 return(-1);
3530 case BlobStream:
3531 {
3532 switch (whence)
3533 {
3534 case SEEK_SET:
3535 default:
3536 {
3537 if (offset < 0)
3538 return(-1);
3539 image->blob->offset=offset;
3540 break;
3541 }
3542 case SEEK_CUR:
3543 {
3544 if ((image->blob->offset+offset) < 0)
3545 return(-1);
3546 image->blob->offset+=offset;
3547 break;
3548 }
3549 case SEEK_END:
3550 {
3551 if (((MagickOffsetType) image->blob->length+offset) < 0)
3552 return(-1);
3553 image->blob->offset=image->blob->length+offset;
3554 break;
3555 }
3556 }
3557 if (image->blob->offset <= (MagickOffsetType)
3558 ((off_t) image->blob->length))
3559 image->blob->eof=MagickFalse;
3560 else
3561 if (image->blob->mapped != MagickFalse)
3562 return(-1);
3563 else
3564 {
3565 image->blob->extent=(size_t) (image->blob->offset+
3566 image->blob->quantum);
3567 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3568 image->blob->data,image->blob->extent+1,
3569 sizeof(*image->blob->data));
3570 (void) SyncBlob(image);
3571 if (image->blob->data == (unsigned char *) NULL)
3572 {
3573 (void) DetachBlob(image->blob);
3574 return(-1);
3575 }
3576 }
3577 break;
3578 }
3579 }
3580 return(image->blob->offset);
3581}
3582
3583/*
3584%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3585% %
3586% %
3587% %
3588+ S e t B l o b E x e m p t %
3589% %
3590% %
3591% %
3592%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3593%
3594% SetBlobExempt() sets the blob exempt status.
3595%
3596% The format of the SetBlobExempt method is:
3597%
3598% MagickBooleanType SetBlobExempt(const Image *image,
3599% const MagickBooleanType exempt)
3600%
3601% A description of each parameter follows:
3602%
3603% o image: the image.
3604%
3605% o exempt: Set to true if this blob is exempt from being closed.
3606%
3607*/
cristy7832dc22011-09-05 01:21:53 +00003608MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003609{
3610 assert(image != (const Image *) NULL);
3611 assert(image->signature == MagickSignature);
3612 if (image->debug != MagickFalse)
3613 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3614 image->blob->exempt=exempt;
3615}
3616
3617/*
3618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3619% %
3620% %
3621% %
3622+ S e t B l o b E x t e n t %
3623% %
3624% %
3625% %
3626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3627%
3628% SetBlobExtent() ensures enough space is allocated for the blob. If the
3629% method is successful, subsequent writes to bytes in the specified range are
3630% guaranteed not to fail.
3631%
3632% The format of the SetBlobExtent method is:
3633%
3634% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3635%
3636% A description of each parameter follows:
3637%
3638% o image: the image.
3639%
3640% o extent: the blob maximum extent.
3641%
3642*/
cristy7832dc22011-09-05 01:21:53 +00003643MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003644 const MagickSizeType extent)
3645{
3646 assert(image != (Image *) NULL);
3647 assert(image->signature == MagickSignature);
3648 if (image->debug != MagickFalse)
3649 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3650 assert(image->blob != (BlobInfo *) NULL);
3651 assert(image->blob->type != UndefinedStream);
3652 switch (image->blob->type)
3653 {
3654 case UndefinedStream:
3655 break;
3656 case FileStream:
3657 {
3658 if (extent != (MagickSizeType) ((off_t) extent))
3659 return(MagickFalse);
3660#if !defined(MAGICKCORE_POSIX_FALLOCATE)
3661 return(MagickFalse);
3662#else
3663 {
3664 int
3665 status;
3666
3667 MagickOffsetType
3668 offset;
3669
3670 offset=TellBlob(image);
3671 status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3672 (off_t) (extent-offset));
3673 if (status != 0)
3674 return(MagickFalse);
3675 }
3676#endif
3677 break;
3678 }
3679 case StandardStream:
3680 case PipeStream:
3681 case ZipStream:
3682 return(MagickFalse);
3683 case BZipStream:
3684 return(MagickFalse);
3685 case FifoStream:
3686 return(MagickFalse);
3687 case BlobStream:
3688 {
3689 if (image->blob->mapped != MagickFalse)
3690 {
3691 if (image->blob->file == (FILE *) NULL)
3692 return(MagickFalse);
3693 (void) UnmapBlob(image->blob->data,image->blob->length);
3694#if !defined(MAGICKCORE_POSIX_FALLOCATE)
3695 return(MagickFalse);
3696#else
3697 {
3698 int
3699 status;
3700
3701 MagickOffsetType
3702 offset;
3703
3704 offset=TellBlob(image);
3705 status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3706 (off_t) (extent-offset));
3707 if (status != 0)
3708 return(MagickFalse);
3709 }
3710 image->blob->data=(unsigned char*) MapBlob(fileno(image->blob->file),
3711 WriteMode,0,(size_t) extent);
3712 image->blob->extent=(size_t) extent;
3713 image->blob->length=(size_t) extent;
3714 (void) SyncBlob(image);
3715 break;
3716#endif
3717 }
3718 if (extent != (MagickSizeType) ((size_t) extent))
3719 return(MagickFalse);
3720 image->blob->extent=(size_t) extent;
3721 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3722 image->blob->extent+1,sizeof(*image->blob->data));
3723 (void) SyncBlob(image);
3724 if (image->blob->data == (unsigned char *) NULL)
3725 {
3726 (void) DetachBlob(image->blob);
3727 return(MagickFalse);
3728 }
3729 break;
3730 }
3731 }
3732 return(MagickTrue);
3733}
3734
3735/*
3736%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3737% %
3738% %
3739% %
3740+ S y n c B l o b %
3741% %
3742% %
3743% %
3744%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3745%
3746% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3747% attributes if it is an blob.
3748%
3749% The format of the SyncBlob method is:
3750%
3751% int SyncBlob(Image *image)
3752%
3753% A description of each parameter follows:
3754%
3755% o image: the image.
3756%
3757*/
3758static int SyncBlob(Image *image)
3759{
3760 int
3761 status;
3762
3763 assert(image != (Image *) NULL);
3764 assert(image->signature == MagickSignature);
3765 if (image->debug != MagickFalse)
3766 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3767 assert(image->blob != (BlobInfo *) NULL);
3768 assert(image->blob->type != UndefinedStream);
3769 status=0;
3770 switch (image->blob->type)
3771 {
3772 case UndefinedStream:
3773 break;
3774 case FileStream:
3775 case StandardStream:
3776 case PipeStream:
3777 {
3778 status=fflush(image->blob->file);
3779 break;
3780 }
3781 case ZipStream:
3782 {
3783#if defined(MAGICKCORE_ZLIB_DELEGATE)
3784 status=gzflush(image->blob->file,Z_SYNC_FLUSH);
3785#endif
3786 break;
3787 }
3788 case BZipStream:
3789 {
3790#if defined(MAGICKCORE_BZLIB_DELEGATE)
3791 status=BZ2_bzflush((BZFILE *) image->blob->file);
3792#endif
3793 break;
3794 }
3795 case FifoStream:
3796 break;
3797 case BlobStream:
3798 {
3799#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3800 if (image->blob->mapped != MagickFalse)
3801 status=msync(image->blob->data,image->blob->length,MS_SYNC);
3802#endif
3803 break;
3804 }
3805 }
3806 return(status);
3807}
3808
3809/*
3810%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3811% %
3812% %
3813% %
3814+ T e l l B l o b %
3815% %
3816% %
3817% %
3818%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3819%
3820% TellBlob() obtains the current value of the blob or file position.
3821%
3822% The format of the TellBlob method is:
3823%
3824% MagickOffsetType TellBlob(const Image *image)
3825%
3826% A description of each parameter follows:
3827%
3828% o image: the image.
3829%
3830*/
3831MagickExport MagickOffsetType TellBlob(const Image *image)
3832{
3833 MagickOffsetType
3834 offset;
3835
3836 assert(image != (Image *) NULL);
3837 assert(image->signature == MagickSignature);
3838 if (image->debug != MagickFalse)
3839 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3840 assert(image->blob != (BlobInfo *) NULL);
3841 assert(image->blob->type != UndefinedStream);
3842 offset=(-1);
3843 switch (image->blob->type)
3844 {
3845 case UndefinedStream:
3846 break;
3847 case FileStream:
3848 {
3849 offset=ftell(image->blob->file);
3850 break;
3851 }
3852 case StandardStream:
3853 case PipeStream:
3854 break;
3855 case ZipStream:
3856 {
3857#if defined(MAGICKCORE_ZLIB_DELEGATE)
3858 offset=(MagickOffsetType) gztell(image->blob->file);
3859#endif
3860 break;
3861 }
3862 case BZipStream:
3863 break;
3864 case FifoStream:
3865 break;
3866 case BlobStream:
3867 {
3868 offset=image->blob->offset;
3869 break;
3870 }
3871 }
3872 return(offset);
3873}
3874
3875/*
3876%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3877% %
3878% %
3879% %
3880+ U n m a p B l o b %
3881% %
3882% %
3883% %
3884%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3885%
3886% UnmapBlob() deallocates the binary large object previously allocated with
3887% the MapBlob method.
3888%
3889% The format of the UnmapBlob method is:
3890%
3891% MagickBooleanType UnmapBlob(void *map,const size_t length)
3892%
3893% A description of each parameter follows:
3894%
3895% o map: the address of the binary large object.
3896%
3897% o length: the length of the binary large object.
3898%
3899*/
3900MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3901{
3902#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3903 int
3904 status;
3905
3906 status=munmap(map,length);
3907 return(status == -1 ? MagickFalse : MagickTrue);
3908#else
3909 (void) map;
3910 (void) length;
3911 return(MagickFalse);
3912#endif
3913}
3914
3915/*
3916%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3917% %
3918% %
3919% %
3920+ W r i t e B l o b %
3921% %
3922% %
3923% %
3924%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3925%
3926% WriteBlob() writes data to a blob or image file. It returns the number of
3927% bytes written.
3928%
3929% The format of the WriteBlob method is:
3930%
3931% ssize_t WriteBlob(Image *image,const size_t length,
3932% const unsigned char *data)
3933%
3934% A description of each parameter follows:
3935%
3936% o image: the image.
3937%
3938% o length: Specifies an integer representing the number of bytes to
3939% write to the file.
3940%
3941% o data: The address of the data to write to the blob or file.
3942%
3943*/
3944MagickExport ssize_t WriteBlob(Image *image,const size_t length,
3945 const unsigned char *data)
3946{
3947 int
3948 c;
3949
3950 register const unsigned char
3951 *p;
3952
3953 ssize_t
3954 count;
3955
3956 assert(image != (Image *) NULL);
3957 assert(image->signature == MagickSignature);
3958 assert(data != (const unsigned char *) NULL);
3959 assert(image->blob != (BlobInfo *) NULL);
3960 assert(image->blob->type != UndefinedStream);
3961 if (length == 0)
3962 return(0);
3963 count=0;
3964 p=data;
3965 switch (image->blob->type)
3966 {
3967 case UndefinedStream:
3968 break;
3969 case FileStream:
3970 case StandardStream:
3971 case PipeStream:
3972 {
3973 switch (length)
3974 {
3975 default:
3976 {
3977 count=(ssize_t) fwrite((const char *) data,1,length,
3978 image->blob->file);
3979 break;
3980 }
3981 case 2:
3982 {
3983 c=putc((int) *p++,image->blob->file);
3984 if (c == EOF)
3985 break;
3986 count++;
3987 }
3988 case 1:
3989 {
3990 c=putc((int) *p++,image->blob->file);
3991 if (c == EOF)
3992 break;
3993 count++;
3994 }
3995 case 0:
3996 break;
3997 }
3998 break;
3999 }
4000 case ZipStream:
4001 {
4002#if defined(MAGICKCORE_ZLIB_DELEGATE)
4003 switch (length)
4004 {
4005 default:
4006 {
4007 count=(ssize_t) gzwrite(image->blob->file,(void *) data,
4008 (unsigned int) length);
4009 break;
4010 }
4011 case 2:
4012 {
4013 c=gzputc(image->blob->file,(int) *p++);
4014 if (c == EOF)
4015 break;
4016 count++;
4017 }
4018 case 1:
4019 {
4020 c=gzputc(image->blob->file,(int) *p++);
4021 if (c == EOF)
4022 break;
4023 count++;
4024 }
4025 case 0:
4026 break;
4027 }
4028#endif
4029 break;
4030 }
4031 case BZipStream:
4032 {
4033#if defined(MAGICKCORE_BZLIB_DELEGATE)
4034 count=(ssize_t) BZ2_bzwrite((BZFILE *) image->blob->file,(void *) data,
4035 (int) length);
4036#endif
4037 break;
4038 }
4039 case FifoStream:
4040 {
4041 count=(ssize_t) image->blob->stream(image,data,length);
4042 break;
4043 }
4044 case BlobStream:
4045 {
4046 register unsigned char
4047 *q;
4048
4049 if ((image->blob->offset+(MagickOffsetType) length) >=
4050 (MagickOffsetType) image->blob->extent)
4051 {
4052 if (image->blob->mapped != MagickFalse)
4053 return(0);
4054 image->blob->quantum<<=1;
4055 image->blob->extent+=length+image->blob->quantum;
4056 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4057 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4058 (void) SyncBlob(image);
4059 if (image->blob->data == (unsigned char *) NULL)
4060 {
4061 (void) DetachBlob(image->blob);
4062 return(0);
4063 }
4064 }
4065 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004066 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004067 image->blob->offset+=length;
4068 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4069 image->blob->length=(size_t) image->blob->offset;
4070 count=(ssize_t) length;
4071 }
4072 }
4073 return(count);
4074}
4075
4076/*
4077%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4078% %
4079% %
4080% %
4081+ W r i t e B l o b B y t e %
4082% %
4083% %
4084% %
4085%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4086%
4087% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4088% written (either 0 or 1);
4089%
4090% The format of the WriteBlobByte method is:
4091%
4092% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4093%
4094% A description of each parameter follows.
4095%
4096% o image: the image.
4097%
4098% o value: Specifies the value to write.
4099%
4100*/
4101MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4102{
4103 assert(image != (Image *) NULL);
4104 assert(image->signature == MagickSignature);
4105 return(WriteBlobStream(image,1,&value));
4106}
4107
4108/*
4109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4110% %
4111% %
4112% %
4113+ W r i t e B l o b F l o a t %
4114% %
4115% %
4116% %
4117%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4118%
4119% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4120% specified by the endian member of the image structure.
4121%
4122% The format of the WriteBlobFloat method is:
4123%
4124% ssize_t WriteBlobFloat(Image *image,const float value)
4125%
4126% A description of each parameter follows.
4127%
4128% o image: the image.
4129%
4130% o value: Specifies the value to write.
4131%
4132*/
4133MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4134{
4135 union
4136 {
4137 unsigned int
4138 unsigned_value;
4139
4140 float
4141 float_value;
4142 } quantum;
4143
4144 quantum.unsigned_value=0U;
4145 quantum.float_value=value;
4146 return(WriteBlobLong(image,quantum.unsigned_value));
4147}
4148
4149/*
4150%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4151% %
4152% %
4153% %
4154+ W r i t e B l o b L o n g %
4155% %
4156% %
4157% %
4158%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4159%
cristybb503372010-05-27 20:51:26 +00004160% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004161% specified by the endian member of the image structure.
4162%
4163% The format of the WriteBlobLong method is:
4164%
4165% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4166%
4167% A description of each parameter follows.
4168%
4169% o image: the image.
4170%
4171% o value: Specifies the value to write.
4172%
4173*/
4174MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4175{
4176 unsigned char
4177 buffer[4];
4178
4179 assert(image != (Image *) NULL);
4180 assert(image->signature == MagickSignature);
4181 if (image->endian == LSBEndian)
4182 {
4183 buffer[0]=(unsigned char) value;
4184 buffer[1]=(unsigned char) (value >> 8);
4185 buffer[2]=(unsigned char) (value >> 16);
4186 buffer[3]=(unsigned char) (value >> 24);
4187 return(WriteBlobStream(image,4,buffer));
4188 }
4189 buffer[0]=(unsigned char) (value >> 24);
4190 buffer[1]=(unsigned char) (value >> 16);
4191 buffer[2]=(unsigned char) (value >> 8);
4192 buffer[3]=(unsigned char) value;
4193 return(WriteBlobStream(image,4,buffer));
4194}
4195
4196/*
4197%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4198% %
4199% %
4200% %
4201+ W r i t e B l o b S h o r t %
4202% %
4203% %
4204% %
4205%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4206%
4207% WriteBlobShort() writes a short value as a 16-bit quantity in the
4208% byte-order specified by the endian member of the image structure.
4209%
4210% The format of the WriteBlobShort method is:
4211%
4212% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4213%
4214% A description of each parameter follows.
4215%
4216% o image: the image.
4217%
4218% o value: Specifies the value to write.
4219%
4220*/
4221MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4222{
4223 unsigned char
4224 buffer[2];
4225
4226 assert(image != (Image *) NULL);
4227 assert(image->signature == MagickSignature);
4228 if (image->endian == LSBEndian)
4229 {
4230 buffer[0]=(unsigned char) value;
4231 buffer[1]=(unsigned char) (value >> 8);
4232 return(WriteBlobStream(image,2,buffer));
4233 }
4234 buffer[0]=(unsigned char) (value >> 8);
4235 buffer[1]=(unsigned char) value;
4236 return(WriteBlobStream(image,2,buffer));
4237}
4238
4239/*
4240%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4241% %
4242% %
4243% %
4244+ W r i t e B l o b L S B L o n g %
4245% %
4246% %
4247% %
4248%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4249%
cristybb503372010-05-27 20:51:26 +00004250% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004251% least-significant byte first order.
4252%
4253% The format of the WriteBlobLSBLong method is:
4254%
4255% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4256%
4257% A description of each parameter follows.
4258%
4259% o image: the image.
4260%
4261% o value: Specifies the value to write.
4262%
4263*/
4264MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4265{
4266 unsigned char
4267 buffer[4];
4268
4269 assert(image != (Image *) NULL);
4270 assert(image->signature == MagickSignature);
4271 buffer[0]=(unsigned char) value;
4272 buffer[1]=(unsigned char) (value >> 8);
4273 buffer[2]=(unsigned char) (value >> 16);
4274 buffer[3]=(unsigned char) (value >> 24);
4275 return(WriteBlobStream(image,4,buffer));
4276}
4277
4278/*
4279%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4280% %
4281% %
4282% %
4283+ W r i t e B l o b L S B S h o r t %
4284% %
4285% %
4286% %
4287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4288%
cristybb503372010-05-27 20:51:26 +00004289% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004290% least-significant byte first order.
4291%
4292% The format of the WriteBlobLSBShort method is:
4293%
4294% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4295%
4296% A description of each parameter follows.
4297%
4298% o image: the image.
4299%
4300% o value: Specifies the value to write.
4301%
4302*/
4303MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4304{
4305 unsigned char
4306 buffer[2];
4307
4308 assert(image != (Image *) NULL);
4309 assert(image->signature == MagickSignature);
4310 buffer[0]=(unsigned char) value;
4311 buffer[1]=(unsigned char) (value >> 8);
4312 return(WriteBlobStream(image,2,buffer));
4313}
4314
4315/*
4316%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4317% %
4318% %
4319% %
4320+ W r i t e B l o b M S B L o n g %
4321% %
4322% %
4323% %
4324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4325%
cristybb503372010-05-27 20:51:26 +00004326% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004327% most-significant byte first order.
4328%
4329% The format of the WriteBlobMSBLong method is:
4330%
4331% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4332%
4333% A description of each parameter follows.
4334%
4335% o value: Specifies the value to write.
4336%
4337% o image: the image.
4338%
4339*/
4340MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4341{
4342 unsigned char
4343 buffer[4];
4344
4345 assert(image != (Image *) NULL);
4346 assert(image->signature == MagickSignature);
4347 buffer[0]=(unsigned char) (value >> 24);
4348 buffer[1]=(unsigned char) (value >> 16);
4349 buffer[2]=(unsigned char) (value >> 8);
4350 buffer[3]=(unsigned char) value;
4351 return(WriteBlobStream(image,4,buffer));
4352}
4353
4354/*
4355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4356% %
4357% %
4358% %
cristy2ca49922010-03-06 02:54:01 +00004359+ W r i t e B l o b M S B L o n g L o n g %
4360% %
4361% %
4362% %
4363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4364%
4365% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4366% most-significant byte first order.
4367%
4368% The format of the WriteBlobMSBLongLong method is:
4369%
4370% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4371%
4372% A description of each parameter follows.
4373%
4374% o value: Specifies the value to write.
4375%
4376% o image: the image.
4377%
4378*/
4379MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4380 const MagickSizeType value)
4381{
4382 unsigned char
4383 buffer[8];
4384
4385 assert(image != (Image *) NULL);
4386 assert(image->signature == MagickSignature);
4387 buffer[0]=(unsigned char) (value >> 56);
4388 buffer[1]=(unsigned char) (value >> 48);
4389 buffer[2]=(unsigned char) (value >> 40);
4390 buffer[3]=(unsigned char) (value >> 32);
4391 buffer[4]=(unsigned char) (value >> 24);
4392 buffer[5]=(unsigned char) (value >> 16);
4393 buffer[6]=(unsigned char) (value >> 8);
4394 buffer[7]=(unsigned char) value;
4395 return(WriteBlobStream(image,8,buffer));
4396}
4397
4398/*
4399%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4400% %
4401% %
4402% %
cristy3ed852e2009-09-05 21:47:34 +00004403+ W r i t e B l o b M S B S h o r t %
4404% %
4405% %
4406% %
4407%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4408%
cristybb503372010-05-27 20:51:26 +00004409% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004410% most-significant byte first order.
4411%
4412% The format of the WriteBlobMSBShort method is:
4413%
4414% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4415%
4416% A description of each parameter follows.
4417%
4418% o value: Specifies the value to write.
4419%
4420% o file: Specifies the file to write the data to.
4421%
4422*/
4423MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4424{
4425 unsigned char
4426 buffer[2];
4427
4428 assert(image != (Image *) NULL);
4429 assert(image->signature == MagickSignature);
4430 buffer[0]=(unsigned char) (value >> 8);
4431 buffer[1]=(unsigned char) value;
4432 return(WriteBlobStream(image,2,buffer));
4433}
4434
4435/*
4436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4437% %
4438% %
4439% %
4440+ W r i t e B l o b S t r i n g %
4441% %
4442% %
4443% %
4444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4445%
4446% WriteBlobString() write a string to a blob. It returns the number of
4447% characters written.
4448%
4449% The format of the WriteBlobString method is:
4450%
4451% ssize_t WriteBlobString(Image *image,const char *string)
4452%
4453% A description of each parameter follows.
4454%
4455% o image: the image.
4456%
4457% o string: Specifies the string to write.
4458%
4459*/
4460MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4461{
4462 assert(image != (Image *) NULL);
4463 assert(image->signature == MagickSignature);
4464 assert(string != (const char *) NULL);
4465 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4466}