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