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