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