MagickCore 6.9.12-98
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
blob.c
1/*
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% Cristy %
17% July 1999 %
18% %
19% %
20% Copyright 1999 ImageMagick Studio LLC, a non-profit organization %
21% 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% https://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#ifdef __VMS
44#include <types.h>
45#include <mman.h>
46#endif
47#include "magick/studio.h"
48#include "magick/blob.h"
49#include "magick/blob-private.h"
50#include "magick/cache.h"
51#include "magick/client.h"
52#include "magick/constitute.h"
53#include "magick/delegate.h"
54#include "magick/exception.h"
55#include "magick/exception-private.h"
56#include "magick/geometry.h"
57#include "magick/image-private.h"
58#include "magick/list.h"
59#include "magick/locale_.h"
60#include "magick/log.h"
61#include "magick/magick.h"
62#include "magick/memory_.h"
63#include "magick/nt-base-private.h"
64#include "magick/option.h"
65#include "magick/policy.h"
66#include "magick/resource_.h"
67#include "magick/semaphore.h"
68#include "magick/string_.h"
69#include "magick/string-private.h"
70#include "magick/timer-private.h"
71#include "magick/token.h"
72#include "magick/utility.h"
73#include "magick/utility-private.h"
74#if defined(MAGICKCORE_ZLIB_DELEGATE)
75#include "zlib.h"
76#endif
77#if defined(MAGICKCORE_BZLIB_DELEGATE)
78#include "bzlib.h"
79#endif
80
81/*
82 Define declarations.
83*/
84#define MagickMaxBlobExtent (8*8192)
85#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
86# define MAP_ANONYMOUS MAP_ANON
87#endif
88#if !defined(MAP_FAILED)
89#define MAP_FAILED ((void *) -1)
90#endif
91#if defined(__OS2__)
92#include <io.h>
93#define _O_BINARY O_BINARY
94#endif
95
96/*
97 Typedef declarations.
98*/
99typedef union FileInfo
100{
101 FILE
102 *file;
103
104#if defined(MAGICKCORE_ZLIB_DELEGATE)
105 gzFile
106 gzfile;
107#endif
108
109#if defined(MAGICKCORE_BZLIB_DELEGATE)
110 BZFILE
111 *bzfile;
112#endif
113} FileInfo;
114
116{
117 size_t
118 length,
119 extent,
120 quantum;
121
122 BlobMode
123 mode;
124
125 MagickBooleanType
126 mapped,
127 eof;
128
129 int
130 error,
131 error_number;
132
133 MagickOffsetType
134 offset;
135
136 MagickSizeType
137 size;
138
139 MagickBooleanType
140 exempt,
141 synchronize,
142 status,
143 temporary;
144
145 StreamType
146 type;
147
149 file_info;
150
151 struct stat
152 properties;
153
154 StreamHandler
155 stream;
156
157 unsigned char
158 *data;
159
160 MagickBooleanType
161 debug;
162
164 *semaphore;
165
166 ssize_t
167 reference_count;
168
169 size_t
170 signature;
171};
172
173/*
174 Forward declarations.
175*/
176static int
177 SyncBlob(Image *);
178
179/*
180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181% %
182% %
183% %
184+ A t t a c h B l o b %
185% %
186% %
187% %
188%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
189%
190% AttachBlob() attaches a blob to the BlobInfo structure.
191%
192% The format of the AttachBlob method is:
193%
194% void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
195%
196% A description of each parameter follows:
197%
198% o blob_info: Specifies a pointer to a BlobInfo structure.
199%
200% o blob: the address of a character stream in one of the image formats
201% understood by ImageMagick.
202%
203% o length: This size_t integer reflects the length in bytes of the blob.
204%
205*/
206MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
207 const size_t length)
208{
209 assert(blob_info != (BlobInfo *) NULL);
210 if (IsEventLogging() != MagickFalse)
211 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
212 blob_info->length=length;
213 blob_info->extent=length;
214 blob_info->quantum=(size_t) MagickMaxBlobExtent;
215 blob_info->offset=0;
216 blob_info->type=BlobStream;
217 blob_info->file_info.file=(FILE *) NULL;
218 blob_info->data=(unsigned char *) blob;
219 blob_info->mapped=MagickFalse;
220}
221
222/*
223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224% %
225% %
226% %
227+ B l o b T o F i l e %
228% %
229% %
230% %
231%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232%
233% BlobToFile() writes a blob to a file. It returns MagickFalse if an error
234% occurs otherwise MagickTrue.
235%
236% The format of the BlobToFile method is:
237%
238% MagickBooleanType BlobToFile(char *filename,const void *blob,
239% const size_t length,ExceptionInfo *exception)
240%
241% A description of each parameter follows:
242%
243% o filename: Write the blob to this file.
244%
245% o blob: the address of a blob.
246%
247% o length: This length in bytes of the blob.
248%
249% o exception: return any errors or warnings in this structure.
250%
251*/
252MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
253 const size_t length,ExceptionInfo *exception)
254{
255 int
256 file;
257
258 size_t
259 i;
260
261 ssize_t
262 count;
263
264 assert(filename != (const char *) NULL);
265 assert(blob != (const void *) NULL);
266 if (IsEventLogging() != MagickFalse)
267 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
268 if (*filename == '\0')
269 file=AcquireUniqueFileResource(filename);
270 else
271 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
272 if (file == -1)
273 {
274 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
275 return(MagickFalse);
276 }
277 for (i=0; i < length; i+=(size_t) count)
278 {
279 count=write(file,(const char *) blob+i,MagickMin(length-i,(size_t)
280 MAGICK_SSIZE_MAX));
281 if (count <= 0)
282 {
283 count=0;
284 if (errno != EINTR)
285 break;
286 }
287 }
288 file=close(file);
289 if ((file == -1) || (i < length))
290 {
291 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
292 return(MagickFalse);
293 }
294 return(MagickTrue);
295}
296
297/*
298%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299% %
300% %
301% %
302% B l o b T o I m a g e %
303% %
304% %
305% %
306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307%
308% BlobToImage() implements direct to memory image formats. It returns the
309% blob as an image.
310%
311% The format of the BlobToImage method is:
312%
313% Image *BlobToImage(const ImageInfo *image_info,const void *blob,
314% const size_t length,ExceptionInfo *exception)
315%
316% A description of each parameter follows:
317%
318% o image_info: the image info.
319%
320% o blob: the address of a character stream in one of the image formats
321% understood by ImageMagick.
322%
323% o length: This size_t integer reflects the length in bytes of the blob.
324%
325% o exception: return any errors or warnings in this structure.
326%
327*/
328MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
329 const size_t length,ExceptionInfo *exception)
330{
331 const MagickInfo
332 *magick_info;
333
334 Image
335 *image;
336
338 *blob_info,
339 *clone_info;
340
341 MagickBooleanType
342 status;
343
344 assert(image_info != (ImageInfo *) NULL);
345 assert(image_info->signature == MagickCoreSignature);
346 assert(exception != (ExceptionInfo *) NULL);
347 if (IsEventLogging() != MagickFalse)
348 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
349 image_info->filename);
350 if ((blob == (const void *) NULL) || (length == 0))
351 {
352 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
353 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
354 return((Image *) NULL);
355 }
356 blob_info=CloneImageInfo(image_info);
357 blob_info->blob=(void *) blob;
358 blob_info->length=length;
359 if (*blob_info->magick == '\0')
360 (void) SetImageInfo(blob_info,0,exception);
361 magick_info=GetMagickInfo(blob_info->magick,exception);
362 if (magick_info == (const MagickInfo *) NULL)
363 {
364 (void) ThrowMagickException(exception,GetMagickModule(),
365 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
366 blob_info->magick);
367 blob_info=DestroyImageInfo(blob_info);
368 return((Image *) NULL);
369 }
370 if (GetMagickBlobSupport(magick_info) != MagickFalse)
371 {
372 char
373 filename[MagickPathExtent];
374
375 /*
376 Native blob support for this image format.
377 */
378 (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
379 (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
380 blob_info->magick,filename);
381 image=ReadImage(blob_info,exception);
382 if (image != (Image *) NULL)
383 (void) DetachBlob(image->blob);
384 blob_info=DestroyImageInfo(blob_info);
385 return(image);
386 }
387 /*
388 Write blob to a temporary file on disk.
389 */
390 blob_info->blob=(void *) NULL;
391 blob_info->length=0;
392 *blob_info->filename='\0';
393 status=BlobToFile(blob_info->filename,blob,length,exception);
394 if (status == MagickFalse)
395 {
396 (void) RelinquishUniqueFileResource(blob_info->filename);
397 blob_info=DestroyImageInfo(blob_info);
398 return((Image *) NULL);
399 }
400 clone_info=CloneImageInfo(blob_info);
401 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
402 blob_info->magick,blob_info->filename);
403 image=ReadImage(clone_info,exception);
404 if (image != (Image *) NULL)
405 {
406 Image
407 *images;
408
409 /*
410 Restore original filenames and image format.
411 */
412 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
413 {
414 (void) CopyMagickString(images->filename,image_info->filename,
415 MagickPathExtent);
416 (void) CopyMagickString(images->magick_filename,image_info->filename,
417 MagickPathExtent);
418 (void) CopyMagickString(images->magick,magick_info->name,
419 MagickPathExtent);
420 images=GetNextImageInList(images);
421 }
422 }
423 clone_info=DestroyImageInfo(clone_info);
424 (void) RelinquishUniqueFileResource(blob_info->filename);
425 blob_info=DestroyImageInfo(blob_info);
426 return(image);
427}
428
429/*
430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431% %
432% %
433% %
434+ C l o n e B l o b I n f o %
435% %
436% %
437% %
438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439%
440% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
441% blob info is NULL, a new one.
442%
443% The format of the CloneBlobInfo method is:
444%
445% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
446%
447% A description of each parameter follows:
448%
449% o blob_info: the blob info.
450%
451*/
452MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
453{
455 *clone_info;
456
458 *semaphore;
459
460 clone_info=(BlobInfo *) AcquireCriticalMemory(sizeof(*clone_info));
461 GetBlobInfo(clone_info);
462 if (blob_info == (BlobInfo *) NULL)
463 return(clone_info);
464 semaphore=clone_info->semaphore;
465 (void) memcpy(clone_info,blob_info,sizeof(*clone_info));
466 if (blob_info->mapped != MagickFalse)
467 (void) AcquireMagickResource(MapResource,blob_info->length);
468 clone_info->semaphore=semaphore;
469 LockSemaphoreInfo(clone_info->semaphore);
470 clone_info->reference_count=1;
471 UnlockSemaphoreInfo(clone_info->semaphore);
472 return(clone_info);
473}
474
475/*
476%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477% %
478% %
479% %
480+ C l o s e B l o b %
481% %
482% %
483% %
484%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485%
486% CloseBlob() closes a stream associated with the image.
487%
488% The format of the CloseBlob method is:
489%
490% MagickBooleanType CloseBlob(Image *image)
491%
492% A description of each parameter follows:
493%
494% o image: the image.
495%
496*/
497
498static inline void ThrowBlobException(BlobInfo *blob_info)
499{
500 if ((blob_info->status == MagickFalse) && (errno != 0))
501 blob_info->error_number=errno;
502 blob_info->status=MagickTrue;
503}
504
505MagickExport MagickBooleanType CloseBlob(Image *image)
506{
508 *magick_restrict blob_info;
509
510 int
511 status;
512
513 /*
514 Close image file.
515 */
516 assert(image != (Image *) NULL);
517 assert(image->signature == MagickCoreSignature);
518 if (IsEventLogging() != MagickFalse)
519 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
520 blob_info=image->blob;
521 if ((blob_info == (BlobInfo *) NULL) || (blob_info->type == UndefinedStream))
522 return(MagickTrue);
523 status=SyncBlob(image);
524 switch (blob_info->type)
525 {
526 case UndefinedStream:
527 case StandardStream:
528 break;
529 case FileStream:
530 case PipeStream:
531 {
532 if (blob_info->synchronize != MagickFalse)
533 {
534 status=fflush(blob_info->file_info.file);
535 if (status != 0)
536 ThrowBlobException(blob_info);
537 status=fsync(fileno(blob_info->file_info.file));
538 if (status != 0)
539 ThrowBlobException(blob_info);
540 }
541 if ((status != 0) && (ferror(blob_info->file_info.file) != 0))
542 ThrowBlobException(blob_info);
543 break;
544 }
545 case ZipStream:
546 {
547#if defined(MAGICKCORE_ZLIB_DELEGATE)
548 status=Z_OK;
549 (void) gzerror(blob_info->file_info.gzfile,&status);
550 if (status != Z_OK)
551 ThrowBlobException(blob_info);
552#endif
553 break;
554 }
555 case BZipStream:
556 {
557#if defined(MAGICKCORE_BZLIB_DELEGATE)
558 status=BZ_OK;
559 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
560 if (status != BZ_OK)
561 ThrowBlobException(blob_info);
562#endif
563 break;
564 }
565 case FifoStream:
566 break;
567 case BlobStream:
568 {
569 if (blob_info->file_info.file != (FILE *) NULL)
570 {
571 if (blob_info->synchronize != MagickFalse)
572 {
573 status=fflush(blob_info->file_info.file);
574 if (status != 0)
575 ThrowBlobException(blob_info);
576 status=fsync(fileno(blob_info->file_info.file));
577 if (status != 0)
578 ThrowBlobException(blob_info);
579 }
580 if ((status != 0) && (ferror(blob_info->file_info.file) != 0))
581 ThrowBlobException(blob_info);
582 }
583 break;
584 }
585 }
586 blob_info->size=GetBlobSize(image);
587 image->extent=blob_info->size;
588 blob_info->eof=MagickFalse;
589 blob_info->error=0;
590 blob_info->mode=UndefinedBlobMode;
591 if (blob_info->exempt != MagickFalse)
592 {
593 blob_info->type=UndefinedStream;
594 return(blob_info->status);
595 }
596 switch (blob_info->type)
597 {
598 case UndefinedStream:
599 case StandardStream:
600 break;
601 case FileStream:
602 {
603 if (blob_info->file_info.file != (FILE *) NULL)
604 {
605 status=fclose(blob_info->file_info.file);
606 if (status != 0)
607 ThrowBlobException(blob_info);
608 }
609 break;
610 }
611 case PipeStream:
612 {
613#if defined(MAGICKCORE_HAVE_PCLOSE)
614 status=pclose(blob_info->file_info.file);
615 if (status != 0)
616 ThrowBlobException(blob_info);
617#endif
618 break;
619 }
620 case ZipStream:
621 {
622#if defined(MAGICKCORE_ZLIB_DELEGATE)
623 status=gzclose(blob_info->file_info.gzfile);
624 if (status != Z_OK)
625 ThrowBlobException(blob_info);
626#endif
627 break;
628 }
629 case BZipStream:
630 {
631#if defined(MAGICKCORE_BZLIB_DELEGATE)
632 BZ2_bzclose(blob_info->file_info.bzfile);
633#endif
634 break;
635 }
636 case FifoStream:
637 break;
638 case BlobStream:
639 {
640 if (blob_info->file_info.file != (FILE *) NULL)
641 {
642 status=fclose(blob_info->file_info.file);
643 if (status != 0)
644 ThrowBlobException(blob_info);
645 }
646 break;
647 }
648 }
649 (void) DetachBlob(blob_info);
650 return(blob_info->status);
651}
652
653/*
654%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655% %
656% %
657% %
658+ D e s t r o y B l o b %
659% %
660% %
661% %
662%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
663%
664% DestroyBlob() deallocates memory associated with a blob.
665%
666% The format of the DestroyBlob method is:
667%
668% void DestroyBlob(Image *image)
669%
670% A description of each parameter follows:
671%
672% o image: the image.
673%
674*/
675MagickExport void DestroyBlob(Image *image)
676{
678 *magick_restrict blob_info;
679
680 MagickBooleanType
681 destroy;
682
683 assert(image != (Image *) NULL);
684 assert(image->signature == MagickCoreSignature);
685 assert(image->blob != (BlobInfo *) NULL);
686 assert(image->blob->signature == MagickCoreSignature);
687 if (IsEventLogging() != MagickFalse)
688 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
689 blob_info=image->blob;
690 destroy=MagickFalse;
691 LockSemaphoreInfo(blob_info->semaphore);
692 blob_info->reference_count--;
693 assert(blob_info->reference_count >= 0);
694 if (blob_info->reference_count == 0)
695 destroy=MagickTrue;
696 UnlockSemaphoreInfo(blob_info->semaphore);
697 if (destroy == MagickFalse)
698 {
699 image->blob=(BlobInfo *) NULL;
700 return;
701 }
702 (void) CloseBlob(image);
703 if (blob_info->mapped != MagickFalse)
704 {
705 (void) UnmapBlob(blob_info->data,blob_info->length);
706 RelinquishMagickResource(MapResource,blob_info->length);
707 }
708 if (blob_info->semaphore != (SemaphoreInfo *) NULL)
709 DestroySemaphoreInfo(&blob_info->semaphore);
710 blob_info->signature=(~MagickCoreSignature);
711 image->blob=(BlobInfo *) RelinquishMagickMemory(blob_info);
712}
713
714/*
715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
716% %
717% %
718% %
719+ D e t a c h B l o b %
720% %
721% %
722% %
723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724%
725% DetachBlob() detaches a blob from the BlobInfo structure.
726%
727% The format of the DetachBlob method is:
728%
729% unsigned char *DetachBlob(BlobInfo *blob_info)
730%
731% A description of each parameter follows:
732%
733% o blob_info: Specifies a pointer to a BlobInfo structure.
734%
735*/
736MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
737{
738 unsigned char
739 *data;
740
741 assert(blob_info != (BlobInfo *) NULL);
742 if (IsEventLogging() != MagickFalse)
743 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
744 if (blob_info->mapped != MagickFalse)
745 {
746 (void) UnmapBlob(blob_info->data,blob_info->length);
747 blob_info->data=NULL;
748 RelinquishMagickResource(MapResource,blob_info->length);
749 }
750 blob_info->mapped=MagickFalse;
751 blob_info->length=0;
752 blob_info->offset=0;
753 blob_info->eof=MagickFalse;
754 blob_info->error=0;
755 blob_info->exempt=MagickFalse;
756 blob_info->type=UndefinedStream;
757 blob_info->file_info.file=(FILE *) NULL;
758 data=blob_info->data;
759 blob_info->data=(unsigned char *) NULL;
760 blob_info->stream=(StreamHandler) NULL;
761 return(data);
762}
763
764/*
765%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
766% %
767% %
768% %
769+ D i s a s s o c i a t e B l o b %
770% %
771% %
772% %
773%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
774%
775% DisassociateBlob() disassociates the image stream. It checks if the
776% blob of the specified image is referenced by other images. If the reference
777% count is higher then 1 a new blob is assigned to the specified image.
778%
779% The format of the DisassociateBlob method is:
780%
781% void DisassociateBlob(const Image *image)
782%
783% A description of each parameter follows:
784%
785% o image: the image.
786%
787*/
788MagickPrivate void DisassociateBlob(Image *image)
789{
791 *magick_restrict blob_info,
792 *clone_info;
793
794 MagickBooleanType
795 clone;
796
797 assert(image != (Image *) NULL);
798 assert(image->signature == MagickCoreSignature);
799 assert(image->blob != (BlobInfo *) NULL);
800 assert(image->blob->signature == MagickCoreSignature);
801 if (IsEventLogging() != MagickFalse)
802 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
803 blob_info=image->blob;
804 clone=MagickFalse;
805 LockSemaphoreInfo(blob_info->semaphore);
806 assert(blob_info->reference_count >= 0);
807 if (blob_info->reference_count > 1)
808 clone=MagickTrue;
809 UnlockSemaphoreInfo(blob_info->semaphore);
810 if (clone == MagickFalse)
811 return;
812 clone_info=CloneBlobInfo(blob_info);
813 DestroyBlob(image);
814 image->blob=clone_info;
815}
816
817/*
818%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
819% %
820% %
821% %
822+ D i s c a r d B l o b B y t e s %
823% %
824% %
825% %
826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827%
828% DiscardBlobBytes() discards bytes in a blob.
829%
830% The format of the DiscardBlobBytes method is:
831%
832% MagickBooleanType DiscardBlobBytes(Image *image,
833% const MagickSizeType length)
834%
835% A description of each parameter follows.
836%
837% o image: the image.
838%
839% o length: the number of bytes to skip.
840%
841*/
842MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
843 const MagickSizeType length)
844{
845 MagickSizeType
846 i;
847
848 size_t
849 quantum;
850
851 ssize_t
852 count;
853
854 unsigned char
855 buffer[MagickMinBufferExtent >> 1];
856
857 assert(image != (Image *) NULL);
858 assert(image->signature == MagickCoreSignature);
859 if (length != (MagickSizeType) ((MagickOffsetType) length))
860 return(MagickFalse);
861 count=0;
862 for (i=0; i < (MagickOffsetType) length; i+=count)
863 {
864 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
865 (void) ReadBlobStream(image,quantum,buffer,&count);
866 if (count <= 0)
867 {
868 count=0;
869 if (errno != EINTR)
870 break;
871 }
872 }
873 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
874}
875
876/*
877%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
878% %
879% %
880% %
881+ D u p l i c a t e s B l o b %
882% %
883% %
884% %
885%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
886%
887% DuplicateBlob() duplicates a blob descriptor.
888%
889% The format of the DuplicateBlob method is:
890%
891% void DuplicateBlob(Image *image,const Image *duplicate)
892%
893% A description of each parameter follows:
894%
895% o image: the image.
896%
897% o duplicate: the duplicate image.
898%
899*/
900MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
901{
902 assert(image != (Image *) NULL);
903 assert(image->signature == MagickCoreSignature);
904 assert(duplicate != (Image *) NULL);
905 assert(duplicate->signature == MagickCoreSignature);
906 if (IsEventLogging() != MagickFalse)
907 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
908 DestroyBlob(image);
909 image->blob=ReferenceBlob(duplicate->blob);
910}
911
912/*
913%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
914% %
915% %
916% %
917+ E O F B l o b %
918% %
919% %
920% %
921%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
922%
923% EOFBlob() returns a non-zero value when EOF has been detected reading from
924% a blob or file.
925%
926% The format of the EOFBlob method is:
927%
928% int EOFBlob(const Image *image)
929%
930% A description of each parameter follows:
931%
932% o image: the image.
933%
934*/
935MagickExport int EOFBlob(const Image *image)
936{
938 *magick_restrict blob_info;
939
940 assert(image != (Image *) NULL);
941 assert(image->signature == MagickCoreSignature);
942 assert(image->blob != (BlobInfo *) NULL);
943 assert(image->blob->type != UndefinedStream);
944 if (IsEventLogging() != MagickFalse)
945 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
946 blob_info=image->blob;
947 switch (blob_info->type)
948 {
949 case UndefinedStream:
950 case StandardStream:
951 break;
952 case FileStream:
953 case PipeStream:
954 {
955 blob_info->eof=feof(blob_info->file_info.file) != 0 ? MagickTrue :
956 MagickFalse;
957 break;
958 }
959 case ZipStream:
960 {
961#if defined(MAGICKCORE_ZLIB_DELEGATE)
962 blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
963 MagickFalse;
964#endif
965 break;
966 }
967 case BZipStream:
968 {
969#if defined(MAGICKCORE_BZLIB_DELEGATE)
970 int
971 status;
972
973 status=0;
974 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
975 blob_info->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
976#endif
977 break;
978 }
979 case FifoStream:
980 {
981 blob_info->eof=MagickFalse;
982 break;
983 }
984 case BlobStream:
985 break;
986 }
987 return((int) blob_info->eof);
988}
989
990/*
991%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992% %
993% %
994% %
995+ E r r o r B l o b %
996% %
997% %
998% %
999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000%
1001% ErrorBlob() returns a non-zero value when an error has been detected reading
1002% from a blob or file.
1003%
1004% The format of the ErrorBlob method is:
1005%
1006% int ErrorBlob(const Image *image)
1007%
1008% A description of each parameter follows:
1009%
1010% o image: the image.
1011%
1012*/
1013MagickExport int ErrorBlob(const Image *image)
1014{
1015 BlobInfo
1016 *magick_restrict blob_info;
1017
1018 assert(image != (Image *) NULL);
1019 assert(image->signature == MagickCoreSignature);
1020 assert(image->blob != (BlobInfo *) NULL);
1021 assert(image->blob->type != UndefinedStream);
1022 if (IsEventLogging() != MagickFalse)
1023 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1024 blob_info=image->blob;
1025 switch (blob_info->type)
1026 {
1027 case UndefinedStream:
1028 case StandardStream:
1029 break;
1030 case FileStream:
1031 case PipeStream:
1032 {
1033 blob_info->error=ferror(blob_info->file_info.file);
1034 break;
1035 }
1036 case ZipStream:
1037 {
1038#if defined(MAGICKCORE_ZLIB_DELEGATE)
1039 (void) gzerror(blob_info->file_info.gzfile,&blob_info->error);
1040#endif
1041 break;
1042 }
1043 case BZipStream:
1044 {
1045#if defined(MAGICKCORE_BZLIB_DELEGATE)
1046 (void) BZ2_bzerror(blob_info->file_info.bzfile,&blob_info->error);
1047#endif
1048 break;
1049 }
1050 case FifoStream:
1051 {
1052 blob_info->error=0;
1053 break;
1054 }
1055 case BlobStream:
1056 break;
1057 }
1058 return(blob_info->error);
1059}
1060
1061/*
1062%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1063% %
1064% %
1065% %
1066% F i l e T o B l o b %
1067% %
1068% %
1069% %
1070%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1071%
1072% FileToBlob() returns the contents of a file as a buffer terminated with
1073% the '\0' character. The length of the buffer (not including the extra
1074% terminating '\0' character) is returned via the 'length' parameter. Free
1075% the buffer with RelinquishMagickMemory().
1076%
1077% The format of the FileToBlob method is:
1078%
1079% unsigned char *FileToBlob(const char *filename,const size_t extent,
1080% size_t *length,ExceptionInfo *exception)
1081%
1082% A description of each parameter follows:
1083%
1084% o blob: FileToBlob() returns the contents of a file as a blob. If
1085% an error occurs NULL is returned.
1086%
1087% o filename: the filename.
1088%
1089% o extent: The maximum length of the blob.
1090%
1091% o length: On return, this reflects the actual length of the blob.
1092%
1093% o exception: return any errors or warnings in this structure.
1094%
1095*/
1096MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
1097 size_t *length,ExceptionInfo *exception)
1098{
1099 int
1100 file;
1101
1102 MagickBooleanType
1103 status;
1104
1105 MagickOffsetType
1106 offset;
1107
1108 size_t
1109 i;
1110
1111 ssize_t
1112 count;
1113
1114 struct stat
1115 attributes;
1116
1117 unsigned char
1118 *blob;
1119
1120 void
1121 *map;
1122
1123 assert(filename != (const char *) NULL);
1124 assert(exception != (ExceptionInfo *) NULL);
1125 assert(exception->signature == MagickCoreSignature);
1126 if (IsEventLogging() != MagickFalse)
1127 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1128 *length=0;
1129 status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
1130 if (status == MagickFalse)
1131 {
1132 errno=EPERM;
1133 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1134 "NotAuthorized","`%s'",filename);
1135 return(NULL);
1136 }
1137 file=fileno(stdin);
1138 if (LocaleCompare(filename,"-") != 0)
1139 {
1140 status=GetPathAttributes(filename,&attributes);
1141 if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
1142 {
1143 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1144 return(NULL);
1145 }
1146 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1147 }
1148 if (file == -1)
1149 {
1150 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1151 return((unsigned char *) NULL);
1152 }
1153 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
1154 count=0;
1155 if ((file == fileno(stdin)) || (offset < 0) ||
1156 (offset != (MagickOffsetType) ((ssize_t) offset)))
1157 {
1158 size_t
1159 quantum;
1160
1161 struct stat
1162 file_stats;
1163
1164 /*
1165 Stream is not seekable.
1166 */
1167 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1168 quantum=(size_t) MagickMaxBufferExtent;
1169 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1170 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1171 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1172 for (i=0; blob != (unsigned char *) NULL; i+=count)
1173 {
1174 count=read(file,blob+i,quantum);
1175 if (count <= 0)
1176 {
1177 count=0;
1178 if (errno != EINTR)
1179 break;
1180 }
1181 if (~((size_t) i) < (count+quantum+1))
1182 {
1183 blob=(unsigned char *) RelinquishMagickMemory(blob);
1184 break;
1185 }
1186 blob=(unsigned char *) ResizeQuantumMemory(blob,i+count+quantum+1,
1187 sizeof(*blob));
1188 if ((size_t) (i+count) >= extent)
1189 break;
1190 }
1191 if (LocaleCompare(filename,"-") != 0)
1192 file=close(file);
1193 if (blob == (unsigned char *) NULL)
1194 {
1195 (void) ThrowMagickException(exception,GetMagickModule(),
1196 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1197 return((unsigned char *) NULL);
1198 }
1199 if (file == -1)
1200 {
1201 blob=(unsigned char *) RelinquishMagickMemory(blob);
1202 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1203 return((unsigned char *) NULL);
1204 }
1205 *length=(size_t) MagickMin(i+count,extent);
1206 blob[*length]='\0';
1207 return(blob);
1208 }
1209 *length=(size_t) MagickMin(offset,(MagickOffsetType)
1210 MagickMin(extent,(size_t) MAGICK_SSIZE_MAX));
1211 blob=(unsigned char *) NULL;
1212 if (~(*length) >= (MagickPathExtent-1))
1213 blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
1214 sizeof(*blob));
1215 if (blob == (unsigned char *) NULL)
1216 {
1217 file=close(file);
1218 (void) ThrowMagickException(exception,GetMagickModule(),
1219 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1220 return((unsigned char *) NULL);
1221 }
1222 map=MapBlob(file,ReadMode,0,*length);
1223 if (map != (unsigned char *) NULL)
1224 {
1225 (void) memcpy(blob,map,*length);
1226 (void) UnmapBlob(map,*length);
1227 }
1228 else
1229 {
1230 (void) lseek(file,0,SEEK_SET);
1231 for (i=0; i < *length; i+=count)
1232 {
1233 count=read(file,blob+i,(size_t) MagickMin(*length-i,(size_t)
1234 MAGICK_SSIZE_MAX));
1235 if (count <= 0)
1236 {
1237 count=0;
1238 if (errno != EINTR)
1239 break;
1240 }
1241 }
1242 if (i < *length)
1243 {
1244 file=close(file)-1;
1245 blob=(unsigned char *) RelinquishMagickMemory(blob);
1246 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1247 return((unsigned char *) NULL);
1248 }
1249 }
1250 blob[*length]='\0';
1251 if (LocaleCompare(filename,"-") != 0)
1252 file=close(file);
1253 if (file == -1)
1254 {
1255 blob=(unsigned char *) RelinquishMagickMemory(blob);
1256 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1257 }
1258 return(blob);
1259}
1260
1261/*
1262%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1263% %
1264% %
1265% %
1266% F i l e T o I m a g e %
1267% %
1268% %
1269% %
1270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1271%
1272% FileToImage() write the contents of a file to an image.
1273%
1274% The format of the FileToImage method is:
1275%
1276% MagickBooleanType FileToImage(Image *,const char *filename)
1277%
1278% A description of each parameter follows:
1279%
1280% o image: the image.
1281%
1282% o filename: the filename.
1283%
1284*/
1285
1286static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1287 const unsigned char *magick_restrict data)
1288{
1289 BlobInfo
1290 *magick_restrict blob_info;
1291
1292 MagickSizeType
1293 extent;
1294
1295 unsigned char
1296 *magick_restrict q;
1297
1298 assert(image->blob != (BlobInfo *) NULL);
1299 assert(image->blob->type != UndefinedStream);
1300 assert(data != (void *) NULL);
1301 blob_info=image->blob;
1302 if (blob_info->type != BlobStream)
1303 return(WriteBlob(image,length,data));
1304 extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
1305 if (extent >= blob_info->extent)
1306 {
1307 extent=blob_info->extent+blob_info->quantum+length;
1308 blob_info->quantum<<=1;
1309 if (SetBlobExtent(image,extent) == MagickFalse)
1310 return(0);
1311 }
1312 q=blob_info->data+blob_info->offset;
1313 (void) memcpy(q,data,length);
1314 blob_info->offset+=length;
1315 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
1316 blob_info->length=(size_t) blob_info->offset;
1317 return((ssize_t) length);
1318}
1319
1320MagickExport MagickBooleanType FileToImage(Image *image,const char *filename)
1321{
1322 int
1323 file;
1324
1325 MagickBooleanType
1326 status;
1327
1328 size_t
1329 length,
1330 quantum;
1331
1332 ssize_t
1333 count;
1334
1335 struct stat
1336 file_stats;
1337
1338 unsigned char
1339 *blob;
1340
1341 assert(image != (const Image *) NULL);
1342 assert(image->signature == MagickCoreSignature);
1343 assert(filename != (const char *) NULL);
1344 if (IsEventLogging() != MagickFalse)
1345 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1346 status=IsRightsAuthorized(PathPolicyDomain,WritePolicyRights,filename);
1347 if (status == MagickFalse)
1348 {
1349 errno=EPERM;
1350 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1351 PolicyError,"NotAuthorized","`%s'",filename);
1352 return(MagickFalse);
1353 }
1354 file=fileno(stdin);
1355 if (LocaleCompare(filename,"-") != 0)
1356 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1357 if (file == -1)
1358 {
1359 ThrowFileException(&image->exception,BlobError,"UnableToOpenBlob",
1360 filename);
1361 return(MagickFalse);
1362 }
1363 quantum=(size_t) MagickMaxBufferExtent;
1364 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1365 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1366 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1367 if (blob == (unsigned char *) NULL)
1368 {
1369 file=close(file);
1370 ThrowFileException(&image->exception,ResourceLimitError,
1371 "MemoryAllocationFailed",filename);
1372 return(MagickFalse);
1373 }
1374 for ( ; ; )
1375 {
1376 count=read(file,blob,quantum);
1377 if (count <= 0)
1378 {
1379 count=0;
1380 if (errno != EINTR)
1381 break;
1382 }
1383 length=(size_t) count;
1384 count=WriteBlobStream(image,length,blob);
1385 if (count != (ssize_t) length)
1386 {
1387 ThrowFileException(&image->exception,BlobError,"UnableToWriteBlob",
1388 filename);
1389 break;
1390 }
1391 }
1392 file=close(file);
1393 if (file == -1)
1394 ThrowFileException(&image->exception,BlobError,"UnableToWriteBlob",
1395 filename);
1396 blob=(unsigned char *) RelinquishMagickMemory(blob);
1397 return(MagickTrue);
1398}
1399
1400/*
1401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1402% %
1403% %
1404% %
1405+ G e t B l o b E r r o r %
1406% %
1407% %
1408% %
1409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1410%
1411% GetBlobError() returns MagickTrue if the blob associated with the specified
1412% image encountered an error.
1413%
1414% The format of the GetBlobError method is:
1415%
1416% MagickBooleanType GetBlobError(const Image *image)
1417%
1418% A description of each parameter follows:
1419%
1420% o image: the image.
1421%
1422*/
1423MagickExport MagickBooleanType GetBlobError(const Image *image)
1424{
1425 assert(image != (const Image *) NULL);
1426 assert(image->signature == MagickCoreSignature);
1427 if (IsEventLogging() != MagickFalse)
1428 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1429 if ((image->blob->status != MagickFalse) && (image->blob->error_number != 0))
1430 errno=image->blob->error_number;
1431 return(image->blob->status);
1432}
1433
1434/*
1435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436% %
1437% %
1438% %
1439+ G e t B l o b F i l e H a n d l e %
1440% %
1441% %
1442% %
1443%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1444%
1445% GetBlobFileHandle() returns the file handle associated with the image blob.
1446%
1447% The format of the GetBlobFile method is:
1448%
1449% FILE *GetBlobFileHandle(const Image *image)
1450%
1451% A description of each parameter follows:
1452%
1453% o image: the image.
1454%
1455*/
1456MagickExport FILE *GetBlobFileHandle(const Image *image)
1457{
1458 assert(image != (const Image *) NULL);
1459 assert(image->signature == MagickCoreSignature);
1460 return(image->blob->file_info.file);
1461}
1462
1463/*
1464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1465% %
1466% %
1467% %
1468+ G e t B l o b I n f o %
1469% %
1470% %
1471% %
1472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1473%
1474% GetBlobInfo() initializes the BlobInfo structure.
1475%
1476% The format of the GetBlobInfo method is:
1477%
1478% void GetBlobInfo(BlobInfo *blob_info)
1479%
1480% A description of each parameter follows:
1481%
1482% o blob_info: Specifies a pointer to a BlobInfo structure.
1483%
1484*/
1485MagickExport void GetBlobInfo(BlobInfo *blob_info)
1486{
1487 assert(blob_info != (BlobInfo *) NULL);
1488 (void) memset(blob_info,0,sizeof(*blob_info));
1489 blob_info->type=UndefinedStream;
1490 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1491 blob_info->properties.st_mtime=GetMagickTime();
1492 blob_info->properties.st_ctime=blob_info->properties.st_mtime;
1493 blob_info->debug=GetLogEventMask() & BlobEvent ? MagickTrue : MagickFalse;
1494 blob_info->reference_count=1;
1495 blob_info->semaphore=AllocateSemaphoreInfo();
1496 blob_info->signature=MagickCoreSignature;
1497}
1498
1499/*
1500%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1501% %
1502% %
1503% %
1504% G e t B l o b P r o p e r t i e s %
1505% %
1506% %
1507% %
1508%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1509%
1510% GetBlobProperties() returns information about an image blob.
1511%
1512% The format of the GetBlobProperties method is:
1513%
1514% const struct stat *GetBlobProperties(const Image *image)
1515%
1516% A description of each parameter follows:
1517%
1518% o image: the image.
1519%
1520*/
1521MagickExport const struct stat *GetBlobProperties(const Image *image)
1522{
1523 assert(image != (Image *) NULL);
1524 assert(image->signature == MagickCoreSignature);
1525 if (IsEventLogging() != MagickFalse)
1526 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1527 return(&image->blob->properties);
1528}
1529
1530/*
1531%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1532% %
1533% %
1534% %
1535+ G e t B l o b S i z e %
1536% %
1537% %
1538% %
1539%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1540%
1541% GetBlobSize() returns the current length of the image file or blob; zero is
1542% returned if the size cannot be determined.
1543%
1544% The format of the GetBlobSize method is:
1545%
1546% MagickSizeType GetBlobSize(const Image *image)
1547%
1548% A description of each parameter follows:
1549%
1550% o image: the image.
1551%
1552*/
1553MagickExport MagickSizeType GetBlobSize(const Image *image)
1554{
1555 BlobInfo
1556 *magick_restrict blob_info;
1557
1558 MagickSizeType
1559 extent;
1560
1561 assert(image != (Image *) NULL);
1562 assert(image->signature == MagickCoreSignature);
1563 assert(image->blob != (BlobInfo *) NULL);
1564 if (IsEventLogging() != MagickFalse)
1565 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1566 blob_info=image->blob;
1567 extent=0;
1568 switch (blob_info->type)
1569 {
1570 case UndefinedStream:
1571 case StandardStream:
1572 {
1573 extent=blob_info->size;
1574 break;
1575 }
1576 case FileStream:
1577 {
1578 int
1579 file_descriptor;
1580
1581 extent=(MagickSizeType) blob_info->properties.st_size;
1582 if (extent == 0)
1583 extent=blob_info->size;
1584 file_descriptor=fileno(blob_info->file_info.file);
1585 if (file_descriptor == -1)
1586 break;
1587 if (fstat(file_descriptor,&blob_info->properties) == 0)
1588 extent=(MagickSizeType) blob_info->properties.st_size;
1589 break;
1590 }
1591 case PipeStream:
1592 {
1593 extent=blob_info->size;
1594 break;
1595 }
1596 case ZipStream:
1597 case BZipStream:
1598 {
1599 MagickBooleanType
1600 status;
1601
1602 status=GetPathAttributes(image->filename,&blob_info->properties);
1603 if (status != MagickFalse)
1604 extent=(MagickSizeType) blob_info->properties.st_size;
1605 break;
1606 }
1607 case FifoStream:
1608 break;
1609 case BlobStream:
1610 {
1611 extent=(MagickSizeType) blob_info->length;
1612 break;
1613 }
1614 }
1615 return(extent);
1616}
1617
1618/*
1619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1620% %
1621% %
1622% %
1623+ G e t B l o b S t r e a m D a t a %
1624% %
1625% %
1626% %
1627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1628%
1629% GetBlobStreamData() returns the stream data for the image.
1630%
1631% The format of the GetBlobStreamData method is:
1632%
1633% unsigned char *GetBlobStreamData(const Image *image)
1634%
1635% A description of each parameter follows:
1636%
1637% o image: the image.
1638%
1639*/
1640MagickExport unsigned char *GetBlobStreamData(const Image *image)
1641{
1642 assert(image != (const Image *) NULL);
1643 assert(image->signature == MagickCoreSignature);
1644 return(image->blob->data);
1645}
1646
1647/*
1648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1649% %
1650% %
1651% %
1652+ G e t B l o b S t r e a m H a n d l e r %
1653% %
1654% %
1655% %
1656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1657%
1658% GetBlobStreamHandler() returns the stream handler for the image.
1659%
1660% The format of the GetBlobStreamHandler method is:
1661%
1662% StreamHandler GetBlobStreamHandler(const Image *image)
1663%
1664% A description of each parameter follows:
1665%
1666% o image: the image.
1667%
1668*/
1669MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
1670{
1671 assert(image != (const Image *) NULL);
1672 assert(image->signature == MagickCoreSignature);
1673 if (IsEventLogging() != MagickFalse)
1674 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1675 return(image->blob->stream);
1676}
1677
1678/*
1679%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1680% %
1681% %
1682% %
1683% I m a g e T o B l o b %
1684% %
1685% %
1686% %
1687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1688%
1689% ImageToBlob() implements direct to memory image formats. It returns the
1690% image as a formatted blob and its length. The magick member of the Image
1691% structure determines the format of the returned blob (GIF, JPEG, PNG,
1692% etc.). This method is the equivalent of WriteImage(), but writes the
1693% formatted "file" to a memory buffer rather than to an actual file.
1694%
1695% The format of the ImageToBlob method is:
1696%
1697% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1698% size_t *length,ExceptionInfo *exception)
1699%
1700% A description of each parameter follows:
1701%
1702% o image_info: the image info.
1703%
1704% o image: the image.
1705%
1706% o length: return the actual length of the blob.
1707%
1708% o exception: return any errors or warnings in this structure.
1709%
1710*/
1711MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1712 Image *image,size_t *length,ExceptionInfo *exception)
1713{
1714 const MagickInfo
1715 *magick_info;
1716
1717 ImageInfo
1718 *blob_info;
1719
1720 MagickBooleanType
1721 status;
1722
1723 unsigned char
1724 *blob;
1725
1726 assert(image_info != (const ImageInfo *) NULL);
1727 assert(image_info->signature == MagickCoreSignature);
1728 assert(image != (Image *) NULL);
1729 assert(image->signature == MagickCoreSignature);
1730 assert(exception != (ExceptionInfo *) NULL);
1731 assert(exception->signature == MagickCoreSignature);
1732 if (IsEventLogging() != MagickFalse)
1733 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1734 image_info->filename);
1735 *length=0;
1736 blob=(unsigned char *) NULL;
1737 blob_info=CloneImageInfo(image_info);
1738 blob_info->adjoin=MagickFalse;
1739 (void) SetImageInfo(blob_info,1,exception);
1740 if (*blob_info->magick != '\0')
1741 (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
1742 magick_info=GetMagickInfo(image->magick,exception);
1743 if (magick_info == (const MagickInfo *) NULL)
1744 {
1745 (void) ThrowMagickException(exception,GetMagickModule(),
1746 MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
1747 image->magick);
1748 blob_info=DestroyImageInfo(blob_info);
1749 return(blob);
1750 }
1751 (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
1752 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1753 {
1754 /*
1755 Native blob support for this image format.
1756 */
1757 blob_info->length=0;
1758 blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
1759 sizeof(unsigned char));
1760 if (blob_info->blob == NULL)
1761 (void) ThrowMagickException(exception,GetMagickModule(),
1762 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1763 else
1764 {
1765 (void) CloseBlob(image);
1766 image->blob->exempt=MagickTrue;
1767 *image->filename='\0';
1768 status=WriteImage(blob_info,image);
1769 InheritException(exception,&image->exception);
1770 *length=image->blob->length;
1771 blob=DetachBlob(image->blob);
1772 if (blob != (void *) NULL)
1773 {
1774 if (status == MagickFalse)
1775 blob=(unsigned char *) RelinquishMagickMemory(blob);
1776 else
1777 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1778 sizeof(unsigned char));
1779 }
1780 else if (status == MagickFalse)
1781 blob_info->blob=RelinquishMagickMemory(blob_info->blob);
1782 }
1783 }
1784 else
1785 {
1786 char
1787 unique[MagickPathExtent];
1788
1789 int
1790 file;
1791
1792 /*
1793 Write file to disk in blob image format.
1794 */
1795 file=AcquireUniqueFileResource(unique);
1796 if (file == -1)
1797 {
1798 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1799 image_info->filename);
1800 }
1801 else
1802 {
1803 blob_info->file=fdopen(file,"wb");
1804 if (blob_info->file != (FILE *) NULL)
1805 {
1806 (void) FormatLocaleString(image->filename,MagickPathExtent,
1807 "%s:%s",image->magick,unique);
1808 status=WriteImage(blob_info,image);
1809 (void) CloseBlob(image);
1810 (void) fclose(blob_info->file);
1811 if (status == MagickFalse)
1812 InheritException(exception,&image->exception);
1813 else
1814 blob=FileToBlob(unique,SIZE_MAX,length,exception);
1815 }
1816 (void) RelinquishUniqueFileResource(unique);
1817 }
1818 }
1819 blob_info=DestroyImageInfo(blob_info);
1820 return(blob);
1821}
1822
1823/*
1824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1825% %
1826% %
1827% %
1828% I m a g e T o F i l e %
1829% %
1830% %
1831% %
1832%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1833%
1834% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1835% occurs otherwise MagickTrue.
1836%
1837% The format of the ImageToFile method is:
1838%
1839% MagickBooleanType ImageToFile(Image *image,char *filename,
1840% ExceptionInfo *exception)
1841%
1842% A description of each parameter follows:
1843%
1844% o image: the image.
1845%
1846% o filename: Write the image to this file.
1847%
1848% o exception: return any errors or warnings in this structure.
1849%
1850*/
1851MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1852 ExceptionInfo *exception)
1853{
1854 int
1855 file;
1856
1857 const unsigned char
1858 *p;
1859
1860 size_t
1861 i;
1862
1863 size_t
1864 length,
1865 quantum;
1866
1867 ssize_t
1868 count;
1869
1870 struct stat
1871 file_stats;
1872
1873 unsigned char
1874 *buffer;
1875
1876 assert(image != (Image *) NULL);
1877 assert(image->signature == MagickCoreSignature);
1878 assert(image->blob != (BlobInfo *) NULL);
1879 assert(image->blob->type != UndefinedStream);
1880 assert(filename != (const char *) NULL);
1881 if (IsEventLogging() != MagickFalse)
1882 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1883 if (*filename == '\0')
1884 file=AcquireUniqueFileResource(filename);
1885 else
1886 if (LocaleCompare(filename,"-") == 0)
1887 file=fileno(stdout);
1888 else
1889 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1890 if (file == -1)
1891 {
1892 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1893 return(MagickFalse);
1894 }
1895 quantum=(size_t) MagickMaxBufferExtent;
1896 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1897 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1898 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1899 if (buffer == (unsigned char *) NULL)
1900 {
1901 file=close(file)-1;
1902 (void) ThrowMagickException(exception,GetMagickModule(),
1903 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1904 return(MagickFalse);
1905 }
1906 length=0;
1907 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1908 for (i=0; count > 0; )
1909 {
1910 length=(size_t) count;
1911 for (i=0; i < length; i+=count)
1912 {
1913 count=write(file,p+i,(size_t) (length-i));
1914 if (count <= 0)
1915 {
1916 count=0;
1917 if (errno != EINTR)
1918 break;
1919 }
1920 }
1921 if (i < length)
1922 break;
1923 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1924 }
1925 if (LocaleCompare(filename,"-") != 0)
1926 file=close(file);
1927 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1928 if ((file == -1) || (i < length))
1929 {
1930 if (file != -1)
1931 file=close(file);
1932 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1933 return(MagickFalse);
1934 }
1935 return(MagickTrue);
1936}
1937
1938/*
1939%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1940% %
1941% %
1942% %
1943% I m a g e s T o B l o b %
1944% %
1945% %
1946% %
1947%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1948%
1949% ImagesToBlob() implements direct to memory image formats. It returns the
1950% image sequence as a blob and its length. The magick member of the ImageInfo
1951% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1952%
1953% Note, some image formats do not permit multiple images to the same image
1954% stream (e.g. JPEG). in this instance, just the first image of the
1955% sequence is returned as a blob.
1956%
1957% The format of the ImagesToBlob method is:
1958%
1959% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1960% size_t *length,ExceptionInfo *exception)
1961%
1962% A description of each parameter follows:
1963%
1964% o image_info: the image info.
1965%
1966% o images: the image list.
1967%
1968% o length: return the actual length of the blob.
1969%
1970% o exception: return any errors or warnings in this structure.
1971%
1972*/
1973MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1974 Image *images,size_t *length,ExceptionInfo *exception)
1975{
1976 const MagickInfo
1977 *magick_info;
1978
1979 ImageInfo
1980 *blob_info;
1981
1982 MagickBooleanType
1983 status;
1984
1985 unsigned char
1986 *blob;
1987
1988 assert(image_info != (const ImageInfo *) NULL);
1989 assert(image_info->signature == MagickCoreSignature);
1990 assert(images != (Image *) NULL);
1991 assert(images->signature == MagickCoreSignature);
1992 assert(exception != (ExceptionInfo *) NULL);
1993 if (IsEventLogging() != MagickFalse)
1994 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1995 image_info->filename);
1996 *length=0;
1997 blob=(unsigned char *) NULL;
1998 blob_info=CloneImageInfo(image_info);
1999 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
2000 exception);
2001 if (*blob_info->magick != '\0')
2002 (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
2003 magick_info=GetMagickInfo(images->magick,exception);
2004 if (magick_info == (const MagickInfo *) NULL)
2005 {
2006 (void) ThrowMagickException(exception,GetMagickModule(),
2007 MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2008 images->magick);
2009 blob_info=DestroyImageInfo(blob_info);
2010 return(blob);
2011 }
2012 if (GetMagickAdjoin(magick_info) == MagickFalse)
2013 {
2014 blob_info=DestroyImageInfo(blob_info);
2015 return(ImageToBlob(image_info,images,length,exception));
2016 }
2017 (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
2018 if (GetMagickBlobSupport(magick_info) != MagickFalse)
2019 {
2020 /*
2021 Native blob support for this images format.
2022 */
2023 blob_info->length=0;
2024 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
2025 sizeof(unsigned char));
2026 if (blob_info->blob == (void *) NULL)
2027 (void) ThrowMagickException(exception,GetMagickModule(),
2028 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2029 else
2030 {
2031 (void) CloseBlob(images);
2032 images->blob->exempt=MagickTrue;
2033 *images->filename='\0';
2034 status=WriteImages(blob_info,images,images->filename,exception);
2035 *length=images->blob->length;
2036 blob=DetachBlob(images->blob);
2037 if (blob != (void *) NULL)
2038 {
2039 if (status == MagickFalse)
2040 blob=(unsigned char *) RelinquishMagickMemory(blob);
2041 else
2042 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
2043 sizeof(unsigned char));
2044 }
2045 else if (status == MagickFalse)
2046 blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2047 }
2048 }
2049 else
2050 {
2051 char
2052 filename[MagickPathExtent],
2053 unique[MagickPathExtent];
2054
2055 int
2056 file;
2057
2058 /*
2059 Write file to disk in blob images format.
2060 */
2061 file=AcquireUniqueFileResource(unique);
2062 if (file == -1)
2063 {
2064 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2065 image_info->filename);
2066 }
2067 else
2068 {
2069 blob_info->file=fdopen(file,"wb");
2070 if (blob_info->file != (FILE *) NULL)
2071 {
2072 (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2073 images->magick,unique);
2074 status=WriteImages(blob_info,images,filename,exception);
2075 (void) CloseBlob(images);
2076 (void) fclose(blob_info->file);
2077 if (status == MagickFalse)
2078 InheritException(exception,&images->exception);
2079 else
2080 blob=FileToBlob(unique,SIZE_MAX,length,exception);
2081 }
2082 (void) RelinquishUniqueFileResource(unique);
2083 }
2084 }
2085 blob_info=DestroyImageInfo(blob_info);
2086 return(blob);
2087}
2088/*
2089%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2090% %
2091% %
2092% %
2093% I n j e c t I m a g e B l o b %
2094% %
2095% %
2096% %
2097%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2098%
2099% InjectImageBlob() injects the image with a copy of itself in the specified
2100% format (e.g. inject JPEG into a PDF image).
2101%
2102% The format of the InjectImageBlob method is:
2103%
2104% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2105% Image *image,Image *inject_image,const char *format,
2106% ExceptionInfo *exception)
2107%
2108% A description of each parameter follows:
2109%
2110% o image_info: the image info..
2111%
2112% o image: the image.
2113%
2114% o inject_image: inject into the image stream.
2115%
2116% o format: the image format.
2117%
2118% o exception: return any errors or warnings in this structure.
2119%
2120*/
2121MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2122 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2123{
2124 char
2125 filename[MagickPathExtent];
2126
2127 FILE
2128 *unique_file;
2129
2130 Image
2131 *byte_image;
2132
2133 ImageInfo
2134 *write_info;
2135
2136 int
2137 file;
2138
2139 MagickBooleanType
2140 status;
2141
2142 size_t
2143 quantum;
2144
2145 struct stat
2146 file_stats;
2147
2148 unsigned char
2149 *buffer;
2150
2151 /*
2152 Write inject image to a temporary file.
2153 */
2154 assert(image_info != (ImageInfo *) NULL);
2155 assert(image_info->signature == MagickCoreSignature);
2156 assert(image != (Image *) NULL);
2157 assert(image->signature == MagickCoreSignature);
2158 assert(inject_image != (Image *) NULL);
2159 assert(inject_image->signature == MagickCoreSignature);
2160 assert(exception != (ExceptionInfo *) NULL);
2161 if (IsEventLogging() != MagickFalse)
2162 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2163 unique_file=(FILE *) NULL;
2164 file=AcquireUniqueFileResource(filename);
2165 if (file != -1)
2166 unique_file=fdopen(file,"wb");
2167 if ((file == -1) || (unique_file == (FILE *) NULL))
2168 {
2169 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2170 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2171 image->filename);
2172 return(MagickFalse);
2173 }
2174 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2175 if (byte_image == (Image *) NULL)
2176 {
2177 (void) fclose(unique_file);
2178 (void) RelinquishUniqueFileResource(filename);
2179 return(MagickFalse);
2180 }
2181 (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
2182 format,filename);
2183 DestroyBlob(byte_image);
2184 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2185 write_info=CloneImageInfo(image_info);
2186 SetImageInfoFile(write_info,unique_file);
2187 status=WriteImage(write_info,byte_image);
2188 write_info=DestroyImageInfo(write_info);
2189 byte_image=DestroyImage(byte_image);
2190 (void) fclose(unique_file);
2191 if (status == MagickFalse)
2192 {
2193 (void) RelinquishUniqueFileResource(filename);
2194 return(MagickFalse);
2195 }
2196 /*
2197 Inject into image stream.
2198 */
2199 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2200 if (file == -1)
2201 {
2202 (void) RelinquishUniqueFileResource(filename);
2203 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2204 image_info->filename);
2205 return(MagickFalse);
2206 }
2207 quantum=(size_t) MagickMaxBufferExtent;
2208 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2209 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2210 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2211 if (buffer == (unsigned char *) NULL)
2212 {
2213 (void) RelinquishUniqueFileResource(filename);
2214 file=close(file);
2215 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2216 image->filename);
2217 }
2218 for ( ; ; )
2219 {
2220 ssize_t count = read(file,buffer,quantum);
2221 if (count <= 0)
2222 {
2223 count=0;
2224 if (errno != EINTR)
2225 break;
2226 }
2227 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2228 MagickFalse;
2229 }
2230 file=close(file);
2231 if (file == -1)
2232 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2233 (void) RelinquishUniqueFileResource(filename);
2234 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2235 return(status);
2236}
2237
2238/*
2239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2240% %
2241% %
2242% %
2243% I s B l o b E x e m p t %
2244% %
2245% %
2246% %
2247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2248%
2249% IsBlobExempt() returns true if the blob is exempt.
2250%
2251% The format of the IsBlobExempt method is:
2252%
2253% MagickBooleanType IsBlobExempt(const Image *image)
2254%
2255% A description of each parameter follows:
2256%
2257% o image: the image.
2258%
2259*/
2260MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2261{
2262 assert(image != (const Image *) NULL);
2263 assert(image->signature == MagickCoreSignature);
2264 if (IsEventLogging() != MagickFalse)
2265 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2266 return(image->blob->exempt);
2267}
2268
2269/*
2270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2271% %
2272% %
2273% %
2274+ I s B l o b S e e k a b l e %
2275% %
2276% %
2277% %
2278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2279%
2280% IsBlobSeekable() returns true if the blob is seekable.
2281%
2282% The format of the IsBlobSeekable method is:
2283%
2284% MagickBooleanType IsBlobSeekable(const Image *image)
2285%
2286% A description of each parameter follows:
2287%
2288% o image: the image.
2289%
2290*/
2291MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2292{
2293 BlobInfo
2294 *magick_restrict blob_info;
2295
2296 assert(image != (const Image *) NULL);
2297 assert(image->signature == MagickCoreSignature);
2298 if (IsEventLogging() != MagickFalse)
2299 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2300 blob_info=image->blob;
2301 switch (blob_info->type)
2302 {
2303 case BlobStream:
2304 return(MagickTrue);
2305 case FileStream:
2306 {
2307 int
2308 status;
2309
2310 if (blob_info->file_info.file == (FILE *) NULL)
2311 return(MagickFalse);
2312 status=fseek(blob_info->file_info.file,0,SEEK_CUR);
2313 return(status == -1 ? MagickFalse : MagickTrue);
2314 }
2315 case ZipStream:
2316 {
2317#if defined(MAGICKCORE_ZLIB_DELEGATE)
2318 MagickOffsetType
2319 offset;
2320
2321 if (blob_info->file_info.gzfile == (gzFile) NULL)
2322 return(MagickFalse);
2323 offset=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
2324 return(offset < 0 ? MagickFalse : MagickTrue);
2325#else
2326 break;
2327#endif
2328 }
2329 case UndefinedStream:
2330 case BZipStream:
2331 case FifoStream:
2332 case PipeStream:
2333 case StandardStream:
2334 break;
2335 default:
2336 break;
2337 }
2338 return(MagickFalse);
2339}
2340
2341/*
2342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2343% %
2344% %
2345% %
2346% I s B l o b T e m p o r a r y %
2347% %
2348% %
2349% %
2350%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2351%
2352% IsBlobTemporary() returns true if the blob is temporary.
2353%
2354% The format of the IsBlobTemporary method is:
2355%
2356% MagickBooleanType IsBlobTemporary(const Image *image)
2357%
2358% A description of each parameter follows:
2359%
2360% o image: the image.
2361%
2362*/
2363MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2364{
2365 assert(image != (const Image *) NULL);
2366 assert(image->signature == MagickCoreSignature);
2367 if (IsEventLogging() != MagickFalse)
2368 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2369 return(image->blob->temporary);
2370}
2371
2372/*
2373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2374% %
2375% %
2376% %
2377+ M a p B l o b %
2378% %
2379% %
2380% %
2381%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2382%
2383% MapBlob() creates a mapping from a file to a binary large object.
2384%
2385% The format of the MapBlob method is:
2386%
2387% unsigned char *MapBlob(int file,const MapMode mode,
2388% const MagickOffsetType offset,const size_t length)
2389%
2390% A description of each parameter follows:
2391%
2392% o file: map this file descriptor.
2393%
2394% o mode: ReadMode, WriteMode, or IOMode.
2395%
2396% o offset: starting at this offset within the file.
2397%
2398% o length: the length of the mapping is returned in this pointer.
2399%
2400*/
2401MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2402 const MagickOffsetType offset,const size_t length)
2403{
2404#if defined(MAGICKCORE_HAVE_MMAP)
2405 int
2406 flags,
2407 protection;
2408
2409 unsigned char
2410 *map;
2411
2412 /*
2413 Map file.
2414 */
2415 flags=0;
2416 if (file == -1)
2417#if defined(MAP_ANONYMOUS)
2418 flags|=MAP_ANONYMOUS;
2419#else
2420 return((unsigned char *) NULL);
2421#endif
2422 switch (mode)
2423 {
2424 case ReadMode:
2425 default:
2426 {
2427 protection=PROT_READ;
2428 flags|=MAP_PRIVATE;
2429 break;
2430 }
2431 case WriteMode:
2432 {
2433 protection=PROT_WRITE;
2434 flags|=MAP_SHARED;
2435 break;
2436 }
2437 case IOMode:
2438 {
2439 protection=PROT_READ | PROT_WRITE;
2440 flags|=MAP_SHARED;
2441 break;
2442 }
2443 }
2444#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2445 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,offset);
2446#else
2447 map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
2448 MAP_HUGETLB,file,offset);
2449 if (map == (unsigned char *) MAP_FAILED)
2450 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2451 offset);
2452#endif
2453 if (map == (unsigned char *) MAP_FAILED)
2454 return((unsigned char *) NULL);
2455 return(map);
2456#else
2457 (void) file;
2458 (void) mode;
2459 (void) offset;
2460 (void) length;
2461 return((unsigned char *) NULL);
2462#endif
2463}
2464
2465/*
2466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2467% %
2468% %
2469% %
2470+ M S B O r d e r L o n g %
2471% %
2472% %
2473% %
2474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2475%
2476% MSBOrderLong() converts a least-significant byte first buffer of integers to
2477% most-significant byte first.
2478%
2479% The format of the MSBOrderLong method is:
2480%
2481% void MSBOrderLong(unsigned char *buffer,const size_t length)
2482%
2483% A description of each parameter follows.
2484%
2485% o buffer: Specifies a pointer to a buffer of integers.
2486%
2487% o length: Specifies the length of the buffer.
2488%
2489*/
2490MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2491{
2492 int
2493 c;
2494
2495 unsigned char
2496 *p,
2497 *q;
2498
2499 assert(buffer != (unsigned char *) NULL);
2500 q=buffer+length;
2501 while (buffer < q)
2502 {
2503 p=buffer+3;
2504 c=(int) (*p);
2505 *p=(*buffer);
2506 *buffer++=(unsigned char) c;
2507 p=buffer+1;
2508 c=(int) (*p);
2509 *p=(*buffer);
2510 *buffer++=(unsigned char) c;
2511 buffer+=2;
2512 }
2513}
2514
2515/*
2516%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2517% %
2518% %
2519% %
2520+ M S B O r d e r S h o r t %
2521% %
2522% %
2523% %
2524%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2525%
2526% MSBOrderShort() converts a least-significant byte first buffer of integers
2527% to most-significant byte first.
2528%
2529% The format of the MSBOrderShort method is:
2530%
2531% void MSBOrderShort(unsigned char *p,const size_t length)
2532%
2533% A description of each parameter follows.
2534%
2535% o p: Specifies a pointer to a buffer of integers.
2536%
2537% o length: Specifies the length of the buffer.
2538%
2539*/
2540MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2541{
2542 int
2543 c;
2544
2545 unsigned char
2546 *q;
2547
2548 assert(p != (unsigned char *) NULL);
2549 q=p+length;
2550 while (p < q)
2551 {
2552 c=(int) (*p);
2553 *p=(*(p+1));
2554 p++;
2555 *p++=(unsigned char) c;
2556 }
2557}
2558
2559/*
2560%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2561% %
2562% %
2563% %
2564+ O p e n B l o b %
2565% %
2566% %
2567% %
2568%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2569%
2570% OpenBlob() opens a file associated with the image. A file name of '-' sets
2571% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2572% suffix is '.gz', the image is decompressed for type 'r' and compressed
2573% for type 'w'. If the filename prefix is '|', it is piped to or from a
2574% system command.
2575%
2576% The format of the OpenBlob method is:
2577%
2578% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2579% const BlobMode mode,ExceptionInfo *exception)
2580%
2581% A description of each parameter follows:
2582%
2583% o image_info: the image info.
2584%
2585% o image: the image.
2586%
2587% o mode: the mode for opening the file.
2588%
2589*/
2590
2591static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
2592 Image *image)
2593{
2594 const char
2595 *option;
2596
2597 int
2598 status;
2599
2600 size_t
2601 size;
2602
2603 size=MagickMinBufferExtent;
2604 option=GetImageOption(image_info,"stream:buffer-size");
2605 if (option != (const char *) NULL)
2606 size=StringToUnsignedLong(option);
2607 status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
2608 _IONBF : _IOFBF,size);
2609 return(status == 0 ? MagickTrue : MagickFalse);
2610}
2611
2612#if defined(MAGICKCORE_ZLIB_DELEGATE)
2613static inline gzFile gzopen_utf8(const char *path,const char *mode)
2614{
2615#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
2616 return(gzopen(path,mode));
2617#else
2618 gzFile
2619 file;
2620
2621 wchar_t
2622 *path_wide;
2623
2624 path_wide=create_wchar_path(path);
2625 if (path_wide == (wchar_t *) NULL)
2626 return((gzFile) NULL);
2627 file=gzopen_w(path_wide,mode);
2628 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
2629 return(file);
2630#endif
2631}
2632#endif
2633
2634MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2635 Image *image,const BlobMode mode,ExceptionInfo *exception)
2636{
2637 BlobInfo
2638 *magick_restrict blob_info;
2639
2640 char
2641 extension[MagickPathExtent],
2642 filename[MagickPathExtent];
2643
2644 const char
2645 *type;
2646
2647 MagickBooleanType
2648 status;
2649
2650 PolicyRights
2651 rights;
2652
2653 assert(image_info != (ImageInfo *) NULL);
2654 assert(image_info->signature == MagickCoreSignature);
2655 assert(image != (Image *) NULL);
2656 assert(image->signature == MagickCoreSignature);
2657 if (IsEventLogging() != MagickFalse)
2658 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2659 image_info->filename);
2660 blob_info=image->blob;
2661 if (image_info->blob != (void *) NULL)
2662 {
2663 if (image_info->stream != (StreamHandler) NULL)
2664 blob_info->stream=(StreamHandler) image_info->stream;
2665 AttachBlob(blob_info,image_info->blob,image_info->length);
2666 return(MagickTrue);
2667 }
2668 (void) DetachBlob(blob_info);
2669 blob_info->mode=mode;
2670 switch (mode)
2671 {
2672 default: type="r"; break;
2673 case ReadBlobMode: type="r"; break;
2674 case ReadBinaryBlobMode: type="rb"; break;
2675 case WriteBlobMode: type="w"; break;
2676 case WriteBinaryBlobMode: type="w+b"; break;
2677 case AppendBlobMode: type="a"; break;
2678 case AppendBinaryBlobMode: type="a+b"; break;
2679 }
2680 if (*type != 'r')
2681 blob_info->synchronize=image_info->synchronize;
2682 if (image_info->stream != (StreamHandler) NULL)
2683 {
2684 blob_info->stream=(StreamHandler) image_info->stream;
2685 if (*type == 'w')
2686 {
2687 blob_info->type=FifoStream;
2688 return(MagickTrue);
2689 }
2690 }
2691 /*
2692 Open image file.
2693 */
2694 *filename='\0';
2695 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2696 rights=ReadPolicyRights;
2697 if (*type == 'w')
2698 rights=WritePolicyRights;
2699 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2700 {
2701 errno=EPERM;
2702 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2703 "NotAuthorized","`%s'",filename);
2704 return(MagickFalse);
2705 }
2706 if ((LocaleCompare(filename,"-") == 0) ||
2707 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2708 {
2709 blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
2710#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2711 if (strchr(type,'b') != (char *) NULL)
2712 (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
2713#endif
2714 blob_info->type=StandardStream;
2715 blob_info->exempt=MagickTrue;
2716 return(SetStreamBuffering(image_info,image));
2717 }
2718 if ((LocaleNCompare(filename,"fd:",3) == 0) &&
2719 (IsGeometry(filename+3) != MagickFalse))
2720 {
2721 char
2722 fileMode[MagickPathExtent];
2723
2724 *fileMode=(*type);
2725 fileMode[1]='\0';
2726 blob_info->file_info.file=fdopen(StringToLong(filename+3),fileMode);
2727 if (blob_info->file_info.file == (FILE *) NULL)
2728 {
2729 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2730 return(MagickFalse);
2731 }
2732#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2733 if (strchr(type,'b') != (char *) NULL)
2734 (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
2735#endif
2736 blob_info->type=FileStream;
2737 blob_info->exempt=MagickTrue;
2738 return(SetStreamBuffering(image_info,image));
2739 }
2740#if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
2741 if (*filename == '|')
2742 {
2743 char
2744 fileMode[MagickPathExtent],
2745 *sanitize_command;
2746
2747 /*
2748 Pipe image to or from a system command.
2749 */
2750#if defined(SIGPIPE)
2751 if (*type == 'w')
2752 (void) signal(SIGPIPE,SIG_IGN);
2753#endif
2754 *fileMode=(*type);
2755 fileMode[1]='\0';
2756 sanitize_command=SanitizeString(filename+1);
2757 blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,
2758 fileMode);
2759 sanitize_command=DestroyString(sanitize_command);
2760 if (blob_info->file_info.file == (FILE *) NULL)
2761 {
2762 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2763 return(MagickFalse);
2764 }
2765 blob_info->type=PipeStream;
2766 blob_info->exempt=MagickTrue;
2767 return(SetStreamBuffering(image_info,image));
2768 }
2769#endif
2770 status=GetPathAttributes(filename,&blob_info->properties);
2771#if defined(S_ISFIFO)
2772 if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
2773 {
2774 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
2775 if (blob_info->file_info.file == (FILE *) NULL)
2776 {
2777 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2778 return(MagickFalse);
2779 }
2780 blob_info->type=FileStream;
2781 blob_info->exempt=MagickTrue;
2782 return(SetStreamBuffering(image_info,image));
2783 }
2784#endif
2785 GetPathComponent(image->filename,ExtensionPath,extension);
2786 if (*type == 'w')
2787 {
2788 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2789 if ((image_info->adjoin == MagickFalse) ||
2790 (strchr(filename,'%') != (char *) NULL))
2791 {
2792 /*
2793 Form filename for multi-part images.
2794 */
2795 (void) InterpretImageFilename(image_info,image,image->filename,(int)
2796 image->scene,filename);
2797 if ((LocaleCompare(filename,image->filename) == 0) &&
2798 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2799 (GetNextImageInList(image) != (Image *) NULL)))
2800 {
2801 char
2802 path[MagickPathExtent];
2803
2804 GetPathComponent(image->filename,RootPath,path);
2805 if (*extension == '\0')
2806 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
2807 path,(double) image->scene);
2808 else
2809 (void) FormatLocaleString(filename,MagickPathExtent,
2810 "%s-%.20g.%s",path,(double) image->scene,extension);
2811 }
2812 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2813#if defined(macintosh)
2814 SetApplicationType(filename,image_info->magick,'8BIM');
2815#endif
2816 }
2817 }
2818 if (image_info->file != (FILE *) NULL)
2819 {
2820 blob_info->file_info.file=image_info->file;
2821 blob_info->type=FileStream;
2822 blob_info->exempt=MagickTrue;
2823 }
2824 else
2825 if (*type == 'r')
2826 {
2827 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
2828 if (blob_info->file_info.file != (FILE *) NULL)
2829 {
2830 size_t
2831 count;
2832
2833 unsigned char
2834 magick[3];
2835
2836 blob_info->type=FileStream;
2837 (void) fstat(fileno(blob_info->file_info.file),
2838 &blob_info->properties);
2839 (void) SetStreamBuffering(image_info,image);
2840 (void) memset(magick,0,sizeof(magick));
2841 count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
2842 (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
2843#if defined(MAGICKCORE_POSIX_SUPPORT)
2844 (void) fflush(blob_info->file_info.file);
2845#endif
2846 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2847 " read %.20g magic header bytes",(double) count);
2848#if defined(MAGICKCORE_ZLIB_DELEGATE)
2849 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2850 ((int) magick[2] == 0x08))
2851 {
2852 gzFile
2853 gzfile = gzopen_utf8(filename,"rb");
2854
2855 if (gzfile != (gzFile) NULL)
2856 {
2857 if (blob_info->file_info.file != (FILE *) NULL)
2858 (void) fclose(blob_info->file_info.file);
2859 blob_info->file_info.file=(FILE *) NULL;
2860 blob_info->file_info.gzfile=gzfile;
2861 blob_info->type=ZipStream;
2862 }
2863 }
2864#endif
2865#if defined(MAGICKCORE_BZLIB_DELEGATE)
2866 if (strncmp((char *) magick,"BZh",3) == 0)
2867 {
2868 BZFILE
2869 *bzfile = BZ2_bzopen(filename,"r");
2870
2871 if (bzfile != (BZFILE *) NULL)
2872 {
2873 if (blob_info->file_info.file != (FILE *) NULL)
2874 (void) fclose(blob_info->file_info.file);
2875 blob_info->file_info.file=(FILE *) NULL;
2876 blob_info->file_info.bzfile=bzfile;
2877 blob_info->type=BZipStream;
2878 }
2879 }
2880#endif
2881 if (blob_info->type == FileStream)
2882 {
2883 const MagickInfo
2884 *magick_info;
2885
2887 *sans_exception;
2888
2889 size_t
2890 length;
2891
2892 sans_exception=AcquireExceptionInfo();
2893 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2894 sans_exception=DestroyExceptionInfo(sans_exception);
2895 length=(size_t) blob_info->properties.st_size;
2896 if ((magick_info != (const MagickInfo *) NULL) &&
2897 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2898 (length > MagickMaxBufferExtent) &&
2899 (AcquireMagickResource(MapResource,length) != MagickFalse))
2900 {
2901 void
2902 *blob;
2903
2904 blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
2905 length);
2906 if (blob == (void *) NULL)
2907 RelinquishMagickResource(MapResource,length);
2908 else
2909 {
2910 /*
2911 Format supports blobs-- use memory-mapped I/O.
2912 */
2913 if (image_info->file != (FILE *) NULL)
2914 blob_info->exempt=MagickFalse;
2915 else
2916 {
2917 (void) fclose(blob_info->file_info.file);
2918 blob_info->file_info.file=(FILE *) NULL;
2919 }
2920 AttachBlob(blob_info,blob,length);
2921 blob_info->mapped=MagickTrue;
2922 }
2923 }
2924 }
2925 }
2926 }
2927 else
2928#if defined(MAGICKCORE_ZLIB_DELEGATE)
2929 if ((LocaleCompare(extension,"gz") == 0) ||
2930 (LocaleCompare(extension,"wmz") == 0) ||
2931 (LocaleCompare(extension,"svgz") == 0))
2932 {
2933 blob_info->file_info.gzfile=gzopen_utf8(filename,"wb");
2934 if (blob_info->file_info.gzfile != (gzFile) NULL)
2935 blob_info->type=ZipStream;
2936 }
2937 else
2938#endif
2939#if defined(MAGICKCORE_BZLIB_DELEGATE)
2940 if (LocaleCompare(extension,"bz2") == 0)
2941 {
2942 if (mode == WriteBinaryBlobMode)
2943 type="w";
2944 blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
2945 if (blob_info->file_info.bzfile != (BZFILE *) NULL)
2946 blob_info->type=BZipStream;
2947 }
2948 else
2949#endif
2950 {
2951 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
2952 if (blob_info->file_info.file != (FILE *) NULL)
2953 {
2954 blob_info->type=FileStream;
2955 (void) SetStreamBuffering(image_info,image);
2956 }
2957 }
2958 blob_info->status=MagickFalse;
2959 blob_info->error_number=0;
2960 if (blob_info->type != UndefinedStream)
2961 blob_info->size=GetBlobSize(image);
2962 else
2963 {
2964 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2965 return(MagickFalse);
2966 }
2967 return(MagickTrue);
2968}
2969
2970/*
2971%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2972% %
2973% %
2974% %
2975+ P i n g B l o b %
2976% %
2977% %
2978% %
2979%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2980%
2981% PingBlob() returns all the attributes of an image or image sequence except
2982% for the pixels. It is much faster and consumes far less memory than
2983% BlobToImage(). On failure, a NULL image is returned and exception
2984% describes the reason for the failure.
2985%
2986% The format of the PingBlob method is:
2987%
2988% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2989% const size_t length,ExceptionInfo *exception)
2990%
2991% A description of each parameter follows:
2992%
2993% o image_info: the image info.
2994%
2995% o blob: the address of a character stream in one of the image formats
2996% understood by ImageMagick.
2997%
2998% o length: This size_t integer reflects the length in bytes of the blob.
2999%
3000% o exception: return any errors or warnings in this structure.
3001%
3002*/
3003
3004#if defined(__cplusplus) || defined(c_plusplus)
3005extern "C" {
3006#endif
3007
3008static size_t PingStream(const Image *magick_unused(image),
3009 const void *magick_unused(pixels),const size_t columns)
3010{
3011 magick_unreferenced(image);
3012 magick_unreferenced(pixels);
3013
3014 return(columns);
3015}
3016
3017#if defined(__cplusplus) || defined(c_plusplus)
3018}
3019#endif
3020
3021MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3022 const size_t length,ExceptionInfo *exception)
3023{
3024 const MagickInfo
3025 *magick_info;
3026
3027 Image
3028 *image;
3029
3030 ImageInfo
3031 *clone_info,
3032 *ping_info;
3033
3034 MagickBooleanType
3035 status;
3036
3037 assert(image_info != (ImageInfo *) NULL);
3038 assert(image_info->signature == MagickCoreSignature);
3039 assert(exception != (ExceptionInfo *) NULL);
3040 if (IsEventLogging() != MagickFalse)
3041 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3042 image_info->filename);
3043 if ((blob == (const void *) NULL) || (length == 0))
3044 {
3045 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3046 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
3047 return((Image *) NULL);
3048 }
3049 ping_info=CloneImageInfo(image_info);
3050 ping_info->blob=(void *) blob;
3051 ping_info->length=length;
3052 ping_info->ping=MagickTrue;
3053 if (*ping_info->magick == '\0')
3054 (void) SetImageInfo(ping_info,0,exception);
3055 magick_info=GetMagickInfo(ping_info->magick,exception);
3056 if (magick_info == (const MagickInfo *) NULL)
3057 {
3058 (void) ThrowMagickException(exception,GetMagickModule(),
3059 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
3060 ping_info->magick);
3061 ping_info=DestroyImageInfo(ping_info);
3062 return((Image *) NULL);
3063 }
3064 if (GetMagickBlobSupport(magick_info) != MagickFalse)
3065 {
3066 char
3067 filename[MagickPathExtent];
3068
3069 /*
3070 Native blob support for this image format.
3071 */
3072 (void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
3073 (void) FormatLocaleString(ping_info->filename,MagickPathExtent,"%s:%s",
3074 ping_info->magick,filename);
3075 image=ReadStream(ping_info,&PingStream,exception);
3076 if (image != (Image *) NULL)
3077 (void) DetachBlob(image->blob);
3078 ping_info=DestroyImageInfo(ping_info);
3079 return(image);
3080 }
3081 /*
3082 Write blob to a temporary file on disk.
3083 */
3084 ping_info->blob=(void *) NULL;
3085 ping_info->length=0;
3086 *ping_info->filename='\0';
3087 status=BlobToFile(ping_info->filename,blob,length,exception);
3088 if (status == MagickFalse)
3089 {
3090 (void) RelinquishUniqueFileResource(ping_info->filename);
3091 ping_info=DestroyImageInfo(ping_info);
3092 return((Image *) NULL);
3093 }
3094 clone_info=CloneImageInfo(ping_info);
3095 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
3096 ping_info->magick,ping_info->filename);
3097 image=ReadStream(clone_info,&PingStream,exception);
3098 if (image != (Image *) NULL)
3099 {
3100 Image
3101 *images;
3102
3103 /*
3104 Restore original filenames and image format.
3105 */
3106 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
3107 {
3108 (void) CopyMagickString(images->filename,image_info->filename,
3109 MagickPathExtent);
3110 (void) CopyMagickString(images->magick_filename,image_info->filename,
3111 MagickPathExtent);
3112 (void) CopyMagickString(images->magick,magick_info->name,
3113 MagickPathExtent);
3114 images=GetNextImageInList(images);
3115 }
3116 }
3117 clone_info=DestroyImageInfo(clone_info);
3118 (void) RelinquishUniqueFileResource(ping_info->filename);
3119 ping_info=DestroyImageInfo(ping_info);
3120 return(image);
3121}
3122
3123/*
3124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3125% %
3126% %
3127% %
3128+ R e a d B l o b %
3129% %
3130% %
3131% %
3132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3133%
3134% ReadBlob() reads data from the blob or image file and returns it. It
3135% returns the number of bytes read. If length is zero, ReadBlob() returns
3136% zero and has no other results. If length is greater than MAGICK_SSIZE_MAX, the
3137% result is unspecified.
3138%
3139% The format of the ReadBlob method is:
3140%
3141% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
3142%
3143% A description of each parameter follows:
3144%
3145% o image: the image.
3146%
3147% o length: Specifies an integer representing the number of bytes to read
3148% from the file.
3149%
3150% o data: Specifies an area to place the information requested from the
3151% file.
3152%
3153*/
3154MagickExport ssize_t ReadBlob(Image *image,const size_t length,
3155 unsigned char *data)
3156{
3157 BlobInfo
3158 *magick_restrict blob_info;
3159
3160 int
3161 c;
3162
3163 unsigned char
3164 *q;
3165
3166 ssize_t
3167 count;
3168
3169 assert(image != (Image *) NULL);
3170 assert(image->signature == MagickCoreSignature);
3171 assert(image->blob != (BlobInfo *) NULL);
3172 assert(image->blob->type != UndefinedStream);
3173 if (length == 0)
3174 return(0);
3175 assert(data != (void *) NULL);
3176 blob_info=image->blob;
3177 count=0;
3178 q=data;
3179 switch (blob_info->type)
3180 {
3181 case UndefinedStream:
3182 break;
3183 case StandardStream:
3184 case FileStream:
3185 case PipeStream:
3186 {
3187 switch (length)
3188 {
3189 default:
3190 {
3191 count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
3192 break;
3193 }
3194 case 4:
3195 {
3196 c=getc(blob_info->file_info.file);
3197 if (c == EOF)
3198 break;
3199 *q++=(unsigned char) c;
3200 count++;
3201 magick_fallthrough;
3202 }
3203 case 3:
3204 {
3205 c=getc(blob_info->file_info.file);
3206 if (c == EOF)
3207 break;
3208 *q++=(unsigned char) c;
3209 count++;
3210 magick_fallthrough;
3211 }
3212 case 2:
3213 {
3214 c=getc(blob_info->file_info.file);
3215 if (c == EOF)
3216 break;
3217 *q++=(unsigned char) c;
3218 count++;
3219 magick_fallthrough;
3220 }
3221 case 1:
3222 {
3223 c=getc(blob_info->file_info.file);
3224 if (c == EOF)
3225 break;
3226 *q++=(unsigned char) c;
3227 count++;
3228 magick_fallthrough;
3229 }
3230 case 0:
3231 break;
3232 }
3233 if ((count != (ssize_t) length) &&
3234 (ferror(blob_info->file_info.file) != 0))
3235 ThrowBlobException(blob_info);
3236 break;
3237 }
3238 case ZipStream:
3239 {
3240#if defined(MAGICKCORE_ZLIB_DELEGATE)
3241 int
3242 status;
3243
3244 switch (length)
3245 {
3246 default:
3247 {
3248 ssize_t
3249 i;
3250
3251 for (i=0; i < (ssize_t) length; i+=count)
3252 {
3253 count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
3254 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3255 if (count <= 0)
3256 {
3257 count=0;
3258 if (errno != EINTR)
3259 break;
3260 }
3261 }
3262 count=i;
3263 break;
3264 }
3265 case 4:
3266 {
3267 c=gzgetc(blob_info->file_info.gzfile);
3268 if (c == EOF)
3269 break;
3270 *q++=(unsigned char) c;
3271 count++;
3272 magick_fallthrough;
3273 }
3274 case 3:
3275 {
3276 c=gzgetc(blob_info->file_info.gzfile);
3277 if (c == EOF)
3278 break;
3279 *q++=(unsigned char) c;
3280 count++;
3281 magick_fallthrough;
3282 }
3283 case 2:
3284 {
3285 c=gzgetc(blob_info->file_info.gzfile);
3286 if (c == EOF)
3287 break;
3288 *q++=(unsigned char) c;
3289 count++;
3290 magick_fallthrough;
3291 }
3292 case 1:
3293 {
3294 c=gzgetc(blob_info->file_info.gzfile);
3295 if (c == EOF)
3296 break;
3297 *q++=(unsigned char) c;
3298 count++;
3299 magick_fallthrough;
3300 }
3301 case 0:
3302 break;
3303 }
3304 status=Z_OK;
3305 (void) gzerror(blob_info->file_info.gzfile,&status);
3306 if ((count != (ssize_t) length) && (status != Z_OK))
3307 ThrowBlobException(blob_info);
3308 if (blob_info->eof == MagickFalse)
3309 blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
3310 MagickFalse;
3311#endif
3312 break;
3313 }
3314 case BZipStream:
3315 {
3316#if defined(MAGICKCORE_BZLIB_DELEGATE)
3317 int
3318 status;
3319
3320 ssize_t
3321 i;
3322
3323 for (i=0; i < (ssize_t) length; i+=count)
3324 {
3325 count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,
3326 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3327 if (count <= 0)
3328 {
3329 count=0;
3330 if (errno != EINTR)
3331 break;
3332 }
3333 }
3334 count=i;
3335 status=BZ_OK;
3336 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
3337 if ((count != (ssize_t) length) && (status != BZ_OK))
3338 ThrowBlobException(blob_info);
3339#endif
3340 break;
3341 }
3342 case FifoStream:
3343 break;
3344 case BlobStream:
3345 {
3346 const unsigned char
3347 *p;
3348
3349 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
3350 {
3351 blob_info->eof=MagickTrue;
3352 break;
3353 }
3354 p=blob_info->data+blob_info->offset;
3355 count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
3356 blob_info->length-blob_info->offset);
3357 blob_info->offset+=count;
3358 if (count != (ssize_t) length)
3359 blob_info->eof=MagickTrue;
3360 (void) memcpy(q,p,(size_t) count);
3361 break;
3362 }
3363 }
3364 return(count);
3365}
3366
3367/*
3368%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3369% %
3370% %
3371% %
3372+ R e a d B l o b B y t e %
3373% %
3374% %
3375% %
3376%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3377%
3378% ReadBlobByte() reads a single byte from the image file and returns it.
3379%
3380% The format of the ReadBlobByte method is:
3381%
3382% int ReadBlobByte(Image *image)
3383%
3384% A description of each parameter follows.
3385%
3386% o image: the image.
3387%
3388*/
3389MagickExport int ReadBlobByte(Image *image)
3390{
3391 BlobInfo
3392 *magick_restrict blob_info;
3393
3394 int
3395 c;
3396
3397 assert(image != (Image *) NULL);
3398 assert(image->signature == MagickCoreSignature);
3399 assert(image->blob != (BlobInfo *) NULL);
3400 assert(image->blob->type != UndefinedStream);
3401 blob_info=image->blob;
3402 switch (blob_info->type)
3403 {
3404 case StandardStream:
3405 case FileStream:
3406 case PipeStream:
3407 {
3408 c=getc(blob_info->file_info.file);
3409 if (c == EOF)
3410 {
3411 if (ferror(blob_info->file_info.file) != 0)
3412 ThrowBlobException(blob_info);
3413 return(EOF);
3414 }
3415 break;
3416 }
3417 case BlobStream:
3418 {
3419 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
3420 {
3421 blob_info->eof=MagickTrue;
3422 return(EOF);
3423 }
3424 c=(int) (*((unsigned char *) blob_info->data+blob_info->offset));
3425 blob_info->offset++;
3426 break;
3427 }
3428 default:
3429 {
3430 ssize_t
3431 count;
3432
3433 unsigned char
3434 buffer[1];
3435
3436 count=ReadBlob(image,1,buffer);
3437 if (count != 1)
3438 return(EOF);
3439 c=(int) *buffer;
3440 break;
3441 }
3442 }
3443 return(c);
3444}
3445
3446/*
3447%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3448% %
3449% %
3450% %
3451+ R e a d B l o b D o u b l e %
3452% %
3453% %
3454% %
3455%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3456%
3457% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3458% specified by the endian member of the image structure.
3459%
3460% The format of the ReadBlobDouble method is:
3461%
3462% double ReadBlobDouble(Image *image)
3463%
3464% A description of each parameter follows.
3465%
3466% o image: the image.
3467%
3468*/
3469MagickExport double ReadBlobDouble(Image *image)
3470{
3471 union
3472 {
3473 MagickSizeType
3474 unsigned_value;
3475
3476 double
3477 double_value;
3478 } quantum;
3479
3480 quantum.double_value=0.0;
3481 quantum.unsigned_value=ReadBlobLongLong(image);
3482 return(quantum.double_value);
3483}
3484
3485/*
3486%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3487% %
3488% %
3489% %
3490+ R e a d B l o b F l o a t %
3491% %
3492% %
3493% %
3494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3495%
3496% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3497% specified by the endian member of the image structure.
3498%
3499% The format of the ReadBlobFloat method is:
3500%
3501% float ReadBlobFloat(Image *image)
3502%
3503% A description of each parameter follows.
3504%
3505% o image: the image.
3506%
3507*/
3508MagickExport float ReadBlobFloat(Image *image)
3509{
3510 union
3511 {
3512 unsigned int
3513 unsigned_value;
3514
3515 float
3516 float_value;
3517 } quantum;
3518
3519 quantum.float_value=0.0;
3520 quantum.unsigned_value=ReadBlobLong(image);
3521 return(quantum.float_value);
3522}
3523
3524/*
3525%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3526% %
3527% %
3528% %
3529+ R e a d B l o b L o n g %
3530% %
3531% %
3532% %
3533%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3534%
3535% ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
3536% byte-order specified by the endian member of the image structure.
3537%
3538% The format of the ReadBlobLong method is:
3539%
3540% unsigned int ReadBlobLong(Image *image)
3541%
3542% A description of each parameter follows.
3543%
3544% o image: the image.
3545%
3546*/
3547MagickExport unsigned int ReadBlobLong(Image *image)
3548{
3549 const unsigned char
3550 *p;
3551
3552 ssize_t
3553 count;
3554
3555 unsigned char
3556 buffer[4];
3557
3558 unsigned int
3559 value;
3560
3561 assert(image != (Image *) NULL);
3562 assert(image->signature == MagickCoreSignature);
3563 *buffer='\0';
3564 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3565 if (count != 4)
3566 return(0UL);
3567 if (image->endian == LSBEndian)
3568 {
3569 value=(unsigned int) (*p++);
3570 value|=(unsigned int) (*p++) << 8;
3571 value|=(unsigned int) (*p++) << 16;
3572 value|=(unsigned int) (*p++) << 24;
3573 return(value);
3574 }
3575 value=(unsigned int) (*p++) << 24;
3576 value|=(unsigned int) (*p++) << 16;
3577 value|=(unsigned int) (*p++) << 8;
3578 value|=(unsigned int) (*p++);
3579 return(value);
3580}
3581
3582/*
3583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3584% %
3585% %
3586% %
3587+ R e a d B l o b L o n g L o n g %
3588% %
3589% %
3590% %
3591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3592%
3593% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3594% byte-order specified by the endian member of the image structure.
3595%
3596% The format of the ReadBlobLongLong method is:
3597%
3598% MagickSizeType ReadBlobLongLong(Image *image)
3599%
3600% A description of each parameter follows.
3601%
3602% o image: the image.
3603%
3604*/
3605MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3606{
3607 MagickSizeType
3608 value;
3609
3610 const unsigned char
3611 *p;
3612
3613 ssize_t
3614 count;
3615
3616 unsigned char
3617 buffer[8];
3618
3619 assert(image != (Image *) NULL);
3620 assert(image->signature == MagickCoreSignature);
3621 *buffer='\0';
3622 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3623 if (count != 8)
3624 return(MagickULLConstant(0));
3625 if (image->endian == LSBEndian)
3626 {
3627 value=(MagickSizeType) (*p++);
3628 value|=(MagickSizeType) (*p++) << 8;
3629 value|=(MagickSizeType) (*p++) << 16;
3630 value|=(MagickSizeType) (*p++) << 24;
3631 value|=(MagickSizeType) (*p++) << 32;
3632 value|=(MagickSizeType) (*p++) << 40;
3633 value|=(MagickSizeType) (*p++) << 48;
3634 value|=(MagickSizeType) (*p++) << 56;
3635 return(value);
3636 }
3637 value=(MagickSizeType) (*p++) << 56;
3638 value|=(MagickSizeType) (*p++) << 48;
3639 value|=(MagickSizeType) (*p++) << 40;
3640 value|=(MagickSizeType) (*p++) << 32;
3641 value|=(MagickSizeType) (*p++) << 24;
3642 value|=(MagickSizeType) (*p++) << 16;
3643 value|=(MagickSizeType) (*p++) << 8;
3644 value|=(MagickSizeType) (*p++);
3645 return(value);
3646}
3647
3648/*
3649%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3650% %
3651% %
3652% %
3653+ R e a d B l o b S h o r t %
3654% %
3655% %
3656% %
3657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3658%
3659% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3660% specified by the endian member of the image structure.
3661%
3662% The format of the ReadBlobShort method is:
3663%
3664% unsigned short ReadBlobShort(Image *image)
3665%
3666% A description of each parameter follows.
3667%
3668% o image: the image.
3669%
3670*/
3671MagickExport unsigned short ReadBlobShort(Image *image)
3672{
3673 const unsigned char
3674 *p;
3675
3676 unsigned short
3677 value;
3678
3679 ssize_t
3680 count;
3681
3682 unsigned char
3683 buffer[2];
3684
3685 assert(image != (Image *) NULL);
3686 assert(image->signature == MagickCoreSignature);
3687 *buffer='\0';
3688 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3689 if (count != 2)
3690 return((unsigned short) 0U);
3691 if (image->endian == LSBEndian)
3692 {
3693 value=(unsigned short) (*p++);
3694 value|=(unsigned short) (*p++) << 8;
3695 return(value);
3696 }
3697 value=(unsigned short) ((unsigned short) (*p++) << 8);
3698 value|=(unsigned short) (*p++);
3699 return(value);
3700}
3701
3702/*
3703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3704% %
3705% %
3706% %
3707+ R e a d B l o b L S B L o n g %
3708% %
3709% %
3710% %
3711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3712%
3713% ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
3714% least-significant byte first order.
3715%
3716% The format of the ReadBlobLSBLong method is:
3717%
3718% unsigned int ReadBlobLSBLong(Image *image)
3719%
3720% A description of each parameter follows.
3721%
3722% o image: the image.
3723%
3724*/
3725MagickExport unsigned int ReadBlobLSBLong(Image *image)
3726{
3727 const unsigned char
3728 *p;
3729
3730 unsigned int
3731 value;
3732
3733 ssize_t
3734 count;
3735
3736 unsigned char
3737 buffer[4];
3738
3739 assert(image != (Image *) NULL);
3740 assert(image->signature == MagickCoreSignature);
3741 *buffer='\0';
3742 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3743 if (count != 4)
3744 return(0U);
3745 value=(unsigned int) (*p++);
3746 value|=(unsigned int) (*p++) << 8;
3747 value|=(unsigned int) (*p++) << 16;
3748 value|=(unsigned int) (*p++) << 24;
3749 return(value);
3750}
3751
3752/*
3753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3754% %
3755% %
3756% %
3757+ R e a d B l o b L S B S i g n e d L o n g %
3758% %
3759% %
3760% %
3761%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3762%
3763% ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
3764% least-significant byte first order.
3765%
3766% The format of the ReadBlobLSBSignedLong method is:
3767%
3768% signed int ReadBlobLSBSignedLong(Image *image)
3769%
3770% A description of each parameter follows.
3771%
3772% o image: the image.
3773%
3774*/
3775MagickExport signed int ReadBlobLSBSignedLong(Image *image)
3776{
3777 union
3778 {
3779 unsigned int
3780 unsigned_value;
3781
3782 signed int
3783 signed_value;
3784 } quantum;
3785
3786 quantum.unsigned_value=ReadBlobLSBLong(image);
3787 return(quantum.signed_value);
3788}
3789
3790/*
3791%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3792% %
3793% %
3794% %
3795+ R e a d B l o b L S B S h o r t %
3796% %
3797% %
3798% %
3799%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3800%
3801% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3802% least-significant byte first order.
3803%
3804% The format of the ReadBlobLSBShort method is:
3805%
3806% unsigned short ReadBlobLSBShort(Image *image)
3807%
3808% A description of each parameter follows.
3809%
3810% o image: the image.
3811%
3812*/
3813MagickExport unsigned short ReadBlobLSBShort(Image *image)
3814{
3815 const unsigned char
3816 *p;
3817
3818 unsigned short
3819 value;
3820
3821 ssize_t
3822 count;
3823
3824 unsigned char
3825 buffer[2];
3826
3827 assert(image != (Image *) NULL);
3828 assert(image->signature == MagickCoreSignature);
3829 *buffer='\0';
3830 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3831 if (count != 2)
3832 return((unsigned short) 0U);
3833 value=(unsigned short) (*p++);
3834 value|=(unsigned short) (*p++) << 8;
3835 return(value);
3836}
3837
3838/*
3839%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3840% %
3841% %
3842% %
3843+ R e a d B l o b L S B S i g n e d S h o r t %
3844% %
3845% %
3846% %
3847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3848%
3849% ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
3850% least-significant byte-order.
3851%
3852% The format of the ReadBlobLSBSignedShort method is:
3853%
3854% signed short ReadBlobLSBSignedShort(Image *image)
3855%
3856% A description of each parameter follows.
3857%
3858% o image: the image.
3859%
3860*/
3861MagickExport signed short ReadBlobLSBSignedShort(Image *image)
3862{
3863 union
3864 {
3865 unsigned short
3866 unsigned_value;
3867
3868 signed short
3869 signed_value;
3870 } quantum;
3871
3872 quantum.unsigned_value=ReadBlobLSBShort(image);
3873 return(quantum.signed_value);
3874}
3875
3876/*
3877%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3878% %
3879% %
3880% %
3881+ R e a d B l o b M S B L o n g %
3882% %
3883% %
3884% %
3885%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3886%
3887% ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
3888% most-significant byte first order.
3889%
3890% The format of the ReadBlobMSBLong method is:
3891%
3892% unsigned int ReadBlobMSBLong(Image *image)
3893%
3894% A description of each parameter follows.
3895%
3896% o image: the image.
3897%
3898*/
3899MagickExport unsigned int ReadBlobMSBLong(Image *image)
3900{
3901 const unsigned char
3902 *p;
3903
3904 unsigned int
3905 value;
3906
3907 ssize_t
3908 count;
3909
3910 unsigned char
3911 buffer[4];
3912
3913 assert(image != (Image *) NULL);
3914 assert(image->signature == MagickCoreSignature);
3915 *buffer='\0';
3916 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3917 if (count != 4)
3918 return(0UL);
3919 value=(unsigned int) (*p++) << 24;
3920 value|=(unsigned int) (*p++) << 16;
3921 value|=(unsigned int) (*p++) << 8;
3922 value|=(unsigned int) (*p++);
3923 return(value);
3924}
3925
3926/*
3927%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3928% %
3929% %
3930% %
3931+ R e a d B l o b M S B L o n g L o n g %
3932% %
3933% %
3934% %
3935%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3936%
3937% ReadBlobMSBLongLong() reads a unsigned long int value as a 64-bit quantity
3938% in most-significant byte first order.
3939%
3940% The format of the ReadBlobMSBLongLong method is:
3941%
3942% unsigned int ReadBlobMSBLongLong(Image *image)
3943%
3944% A description of each parameter follows.
3945%
3946% o image: the image.
3947%
3948*/
3949MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3950{
3951 const unsigned char
3952 *p;
3953
3954 MagickSizeType
3955 value;
3956
3957 ssize_t
3958 count;
3959
3960 unsigned char
3961 buffer[8];
3962
3963 assert(image != (Image *) NULL);
3964 assert(image->signature == MagickCoreSignature);
3965 *buffer='\0';
3966 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3967 if (count != 8)
3968 return(MagickULLConstant(0));
3969 value=(MagickSizeType) (*p++) << 56;
3970 value|=(MagickSizeType) (*p++) << 48;
3971 value|=(MagickSizeType) (*p++) << 40;
3972 value|=(MagickSizeType) (*p++) << 32;
3973 value|=(MagickSizeType) (*p++) << 24;
3974 value|=(MagickSizeType) (*p++) << 16;
3975 value|=(MagickSizeType) (*p++) << 8;
3976 value|=(MagickSizeType) (*p++);
3977 return(value);
3978}
3979
3980/*
3981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3982% %
3983% %
3984% %
3985+ R e a d B l o b M S B S h o r t %
3986% %
3987% %
3988% %
3989%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3990%
3991% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3992% most-significant byte first order.
3993%
3994% The format of the ReadBlobMSBShort method is:
3995%
3996% unsigned short ReadBlobMSBShort(Image *image)
3997%
3998% A description of each parameter follows.
3999%
4000% o image: the image.
4001%
4002*/
4003MagickExport unsigned short ReadBlobMSBShort(Image *image)
4004{
4005 const unsigned char
4006 *p;
4007
4008 unsigned short
4009 value;
4010
4011 ssize_t
4012 count;
4013
4014 unsigned char
4015 buffer[2];
4016
4017 assert(image != (Image *) NULL);
4018 assert(image->signature == MagickCoreSignature);
4019 *buffer='\0';
4020 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4021 if (count != 2)
4022 return((unsigned short) 0U);
4023 value=(unsigned short) ((*p++) << 8);
4024 value|=(unsigned short) (*p++);
4025 return(value);
4026}
4027
4028/*
4029%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4030% %
4031% %
4032% %
4033+ R e a d B l o b M S B S i g n e d L o n g %
4034% %
4035% %
4036% %
4037%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4038%
4039% ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4040% most-significant byte-order.
4041%
4042% The format of the ReadBlobMSBSignedLong method is:
4043%
4044% signed int ReadBlobMSBSignedLong(Image *image)
4045%
4046% A description of each parameter follows.
4047%
4048% o image: the image.
4049%
4050*/
4051MagickExport signed int ReadBlobMSBSignedLong(Image *image)
4052{
4053 union
4054 {
4055 unsigned int
4056 unsigned_value;
4057
4058 signed int
4059 signed_value;
4060 } quantum;
4061
4062 quantum.unsigned_value=ReadBlobMSBLong(image);
4063 return(quantum.signed_value);
4064}
4065
4066/*
4067%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4068% %
4069% %
4070% %
4071+ R e a d B l o b M S B S i g n e d S h o r t %
4072% %
4073% %
4074% %
4075%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4076%
4077% ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4078% most-significant byte-order.
4079%
4080% The format of the ReadBlobMSBSignedShort method is:
4081%
4082% signed short ReadBlobMSBSignedShort(Image *image)
4083%
4084% A description of each parameter follows.
4085%
4086% o image: the image.
4087%
4088*/
4089MagickExport signed short ReadBlobMSBSignedShort(Image *image)
4090{
4091 union
4092 {
4093 unsigned short
4094 unsigned_value;
4095
4096 signed short
4097 signed_value;
4098 } quantum;
4099
4100 quantum.unsigned_value=ReadBlobMSBShort(image);
4101 return(quantum.signed_value);
4102}
4103
4104/*
4105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4106% %
4107% %
4108% %
4109+ R e a d B l o b S i g n e d L o n g %
4110% %
4111% %
4112% %
4113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4114%
4115% ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4116% byte-order specified by the endian member of the image structure.
4117%
4118% The format of the ReadBlobSignedLong method is:
4119%
4120% signed int ReadBlobSignedLong(Image *image)
4121%
4122% A description of each parameter follows.
4123%
4124% o image: the image.
4125%
4126*/
4127MagickExport signed int ReadBlobSignedLong(Image *image)
4128{
4129 union
4130 {
4131 unsigned int
4132 unsigned_value;
4133
4134 signed int
4135 signed_value;
4136 } quantum;
4137
4138 quantum.unsigned_value=ReadBlobLong(image);
4139 return(quantum.signed_value);
4140}
4141
4142/*
4143%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4144% %
4145% %
4146% %
4147+ R e a d B l o b S i g n e d S h o r t %
4148% %
4149% %
4150% %
4151%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4152%
4153% ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4154% byte-order specified by the endian member of the image structure.
4155%
4156% The format of the ReadBlobSignedShort method is:
4157%
4158% signed short ReadBlobSignedShort(Image *image)
4159%
4160% A description of each parameter follows.
4161%
4162% o image: the image.
4163%
4164*/
4165MagickExport signed short ReadBlobSignedShort(Image *image)
4166{
4167 union
4168 {
4169 unsigned short
4170 unsigned_value;
4171
4172 signed short
4173 signed_value;
4174 } quantum;
4175
4176 quantum.unsigned_value=ReadBlobShort(image);
4177 return(quantum.signed_value);
4178}
4179
4180/*
4181%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4182% %
4183% %
4184% %
4185+ R e a d B l o b S t r e a m %
4186% %
4187% %
4188% %
4189%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4190%
4191% ReadBlobStream() reads data from the blob or image file and returns it. It
4192% returns a pointer to the data buffer you supply or to the image memory
4193% buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4194% returns a count of zero and has no other results. If length is greater than
4195% MAGICK_SSIZE_MAX, the result is unspecified.
4196%
4197% The format of the ReadBlobStream method is:
4198%
4199% const void *ReadBlobStream(Image *image,const size_t length,
4200% void *magick_restrict data,ssize_t *count)
4201%
4202% A description of each parameter follows:
4203%
4204% o image: the image.
4205%
4206% o length: Specifies an integer representing the number of bytes to read
4207% from the file.
4208%
4209% o count: returns the number of bytes read.
4210%
4211% o data: Specifies an area to place the information requested from the
4212% file.
4213%
4214*/
4215MagickExport magick_hot_spot const void *ReadBlobStream(Image *image,
4216 const size_t length,void *magick_restrict data,ssize_t *count)
4217{
4218 BlobInfo
4219 *magick_restrict blob_info;
4220
4221 assert(image != (Image *) NULL);
4222 assert(image->signature == MagickCoreSignature);
4223 assert(image->blob != (BlobInfo *) NULL);
4224 assert(image->blob->type != UndefinedStream);
4225 assert(count != (ssize_t *) NULL);
4226 blob_info=image->blob;
4227 if (blob_info->type != BlobStream)
4228 {
4229 assert(data != NULL);
4230 *count=ReadBlob(image,length,(unsigned char *) data);
4231 return(data);
4232 }
4233 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4234 {
4235 *count=0;
4236 blob_info->eof=MagickTrue;
4237 return(data);
4238 }
4239 data=blob_info->data+blob_info->offset;
4240 *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4241 blob_info->length-blob_info->offset);
4242 blob_info->offset+=(*count);
4243 if (*count != (ssize_t) length)
4244 blob_info->eof=MagickTrue;
4245 return(data);
4246}
4247
4248/*
4249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4250% %
4251% %
4252% %
4253+ R e a d B l o b S t r i n g %
4254% %
4255% %
4256% %
4257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4258%
4259% ReadBlobString() reads characters from a blob or file until a newline
4260% character is read or an end-of-file condition is encountered.
4261%
4262% The format of the ReadBlobString method is:
4263%
4264% char *ReadBlobString(Image *image,char *string)
4265%
4266% A description of each parameter follows:
4267%
4268% o image: the image.
4269%
4270% o string: the address of a character buffer.
4271%
4272*/
4273MagickExport char *ReadBlobString(Image *image,char *string)
4274{
4275 BlobInfo
4276 *magick_restrict blob_info;
4277
4278 int
4279 c = -1;
4280
4281 ssize_t
4282 i = 0;
4283
4284 assert(image != (Image *) NULL);
4285 assert(image->signature == MagickCoreSignature);
4286 assert(image->blob != (BlobInfo *) NULL);
4287 assert(image->blob->type != UndefinedStream);
4288 if (IsEventLogging() != MagickFalse)
4289 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4290 *string='\0';
4291 blob_info=image->blob;
4292 switch (blob_info->type)
4293 {
4294 case UndefinedStream:
4295 break;
4296 case StandardStream:
4297 case FileStream:
4298 {
4299 char *p = fgets(string,MagickPathExtent,blob_info->file_info.file);
4300 if (p == (char *) NULL)
4301 {
4302 if (ferror(blob_info->file_info.file) != 0)
4303 ThrowBlobException(blob_info);
4304 return((char *) NULL);
4305 }
4306 i=strlen(string);
4307 break;
4308 }
4309 case ZipStream:
4310 {
4311#if defined(MAGICKCORE_ZLIB_DELEGATE)
4312 char *p = gzgets(blob_info->file_info.gzfile,string,MagickPathExtent);
4313 if (p == (char *) NULL)
4314 {
4315 int status = Z_OK;
4316 (void) gzerror(blob_info->file_info.gzfile,&status);
4317 if (status != Z_OK)
4318 ThrowBlobException(blob_info);
4319 return((char *) NULL);
4320 }
4321 i=strlen(string);
4322 break;
4323#endif
4324 }
4325 default:
4326 {
4327 do
4328 {
4329 c=ReadBlobByte(image);
4330 if (c == EOF)
4331 {
4332 blob_info->eof=MagickTrue;
4333 break;
4334 }
4335 string[i++]=c;
4336 if (c == '\n')
4337 break;
4338 } while (i < (MaxTextExtent-2));
4339 string[i]='\0';
4340 break;
4341 }
4342 }
4343 /*
4344 Strip trailing newline.
4345 */
4346 if ((string[i] == '\r') || (string[i] == '\n'))
4347 string[i]='\0';
4348 if (i >= 1)
4349 if ((string[i-1] == '\r') || (string[i-1] == '\n'))
4350 string[i-1]='\0';
4351 if ((*string == '\0') && (blob_info->eof != MagickFalse))
4352 return((char *) NULL);
4353 return(string);
4354}
4355
4356/*
4357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4358% %
4359% %
4360% %
4361+ R e f e r e n c e B l o b %
4362% %
4363% %
4364% %
4365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4366%
4367% ReferenceBlob() increments the reference count associated with the pixel
4368% blob returning a pointer to the blob.
4369%
4370% The format of the ReferenceBlob method is:
4371%
4372% BlobInfo ReferenceBlob(BlobInfo *blob_info)
4373%
4374% A description of each parameter follows:
4375%
4376% o blob_info: the blob_info.
4377%
4378*/
4379MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
4380{
4381 assert(blob != (BlobInfo *) NULL);
4382 assert(blob->signature == MagickCoreSignature);
4383 if (IsEventLogging() != MagickFalse)
4384 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4385 LockSemaphoreInfo(blob->semaphore);
4386 blob->reference_count++;
4387 UnlockSemaphoreInfo(blob->semaphore);
4388 return(blob);
4389}
4390
4391/*
4392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4393% %
4394% %
4395% %
4396+ S e e k B l o b %
4397% %
4398% %
4399% %
4400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4401%
4402% SeekBlob() sets the offset in bytes from the beginning of a blob or file
4403% and returns the resulting offset.
4404%
4405% The format of the SeekBlob method is:
4406%
4407% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
4408% const int whence)
4409%
4410% A description of each parameter follows:
4411%
4412% o image: the image.
4413%
4414% o offset: Specifies an integer representing the offset in bytes.
4415%
4416% o whence: Specifies an integer representing how the offset is
4417% treated relative to the beginning of the blob as follows:
4418%
4419% SEEK_SET Set position equal to offset bytes.
4420% SEEK_CUR Set position to current location plus offset.
4421% SEEK_END Set position to EOF plus offset.
4422%
4423*/
4424MagickExport MagickOffsetType SeekBlob(Image *image,
4425 const MagickOffsetType offset,const int whence)
4426{
4427 BlobInfo
4428 *magick_restrict blob_info;
4429
4430 assert(image != (Image *) NULL);
4431 assert(image->signature == MagickCoreSignature);
4432 assert(image->blob != (BlobInfo *) NULL);
4433 assert(image->blob->type != UndefinedStream);
4434 if (IsEventLogging() != MagickFalse)
4435 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4436 blob_info=image->blob;
4437 switch (blob_info->type)
4438 {
4439 case UndefinedStream:
4440 break;
4441 case StandardStream:
4442 case PipeStream:
4443 return(-1);
4444 case FileStream:
4445 {
4446 if ((offset < 0) && (whence == SEEK_SET))
4447 return(-1);
4448 if (fseek(blob_info->file_info.file,offset,whence) < 0)
4449 return(-1);
4450 blob_info->offset=TellBlob(image);
4451 break;
4452 }
4453 case ZipStream:
4454 {
4455#if defined(MAGICKCORE_ZLIB_DELEGATE)
4456 if (gzseek(blob_info->file_info.gzfile,offset,whence) < 0)
4457 return(-1);
4458#endif
4459 blob_info->offset=TellBlob(image);
4460 break;
4461 }
4462 case BZipStream:
4463 return(-1);
4464 case FifoStream:
4465 return(-1);
4466 case BlobStream:
4467 {
4468 switch (whence)
4469 {
4470 case SEEK_SET:
4471 default:
4472 {
4473 if (offset < 0)
4474 return(-1);
4475 blob_info->offset=offset;
4476 break;
4477 }
4478 case SEEK_CUR:
4479 {
4480 if (((offset > 0) && (blob_info->offset > (MAGICK_SSIZE_MAX-offset))) ||
4481 ((offset < 0) && (blob_info->offset < (MAGICK_SSIZE_MIN-offset))))
4482 {
4483 errno=EOVERFLOW;
4484 return(-1);
4485 }
4486 if ((blob_info->offset+offset) < 0)
4487 return(-1);
4488 blob_info->offset+=offset;
4489 break;
4490 }
4491 case SEEK_END:
4492 {
4493 if (((MagickOffsetType) blob_info->length+offset) < 0)
4494 return(-1);
4495 blob_info->offset=blob_info->length+offset;
4496 break;
4497 }
4498 }
4499 if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
4500 {
4501 blob_info->eof=MagickFalse;
4502 break;
4503 }
4504 if (blob_info->offset >= (MagickOffsetType) ((off_t) blob_info->extent))
4505 return(-1);
4506 break;
4507 }
4508 }
4509 return(blob_info->offset);
4510}
4511
4512/*
4513%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4514% %
4515% %
4516% %
4517+ S e t B l o b E x e m p t %
4518% %
4519% %
4520% %
4521%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4522%
4523% SetBlobExempt() sets the blob exempt status.
4524%
4525% The format of the SetBlobExempt method is:
4526%
4527% MagickBooleanType SetBlobExempt(const Image *image,
4528% const MagickBooleanType exempt)
4529%
4530% A description of each parameter follows:
4531%
4532% o image: the image.
4533%
4534% o exempt: Set to true if this blob is exempt from being closed.
4535%
4536*/
4537MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
4538{
4539 assert(image != (const Image *) NULL);
4540 assert(image->signature == MagickCoreSignature);
4541 if (IsEventLogging() != MagickFalse)
4542 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4543 image->blob->exempt=exempt;
4544}
4545
4546/*
4547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4548% %
4549% %
4550% %
4551+ S e t B l o b E x t e n t %
4552% %
4553% %
4554% %
4555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4556%
4557% SetBlobExtent() ensures enough space is allocated for the blob. If the
4558% method is successful, subsequent writes to bytes in the specified range are
4559% guaranteed not to fail.
4560%
4561% The format of the SetBlobExtent method is:
4562%
4563% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
4564%
4565% A description of each parameter follows:
4566%
4567% o image: the image.
4568%
4569% o extent: the blob maximum extent.
4570%
4571*/
4572MagickExport MagickBooleanType SetBlobExtent(Image *image,
4573 const MagickSizeType extent)
4574{
4575 BlobInfo
4576 *magick_restrict blob_info;
4577
4578 assert(image != (Image *) NULL);
4579 assert(image->signature == MagickCoreSignature);
4580 assert(image->blob != (BlobInfo *) NULL);
4581 assert(image->blob->type != UndefinedStream);
4582 if (IsEventLogging() != MagickFalse)
4583 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4584 blob_info=image->blob;
4585 switch (blob_info->type)
4586 {
4587 case UndefinedStream:
4588 break;
4589 case StandardStream:
4590 return(MagickFalse);
4591 case FileStream:
4592 {
4593 MagickOffsetType
4594 offset;
4595
4596 ssize_t
4597 count;
4598
4599 if (extent != (MagickSizeType) ((off_t) extent))
4600 return(MagickFalse);
4601 offset=SeekBlob(image,0,SEEK_END);
4602 if (offset < 0)
4603 return(MagickFalse);
4604 if ((MagickSizeType) offset >= extent)
4605 break;
4606 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4607 if (offset < 0)
4608 break;
4609 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4610 blob_info->file_info.file);
4611#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4612 if (blob_info->synchronize != MagickFalse)
4613 {
4614 int
4615 file;
4616
4617 file=fileno(blob_info->file_info.file);
4618 if ((file == -1) || (offset < 0))
4619 return(MagickFalse);
4620 (void) posix_fallocate(file,offset,extent-offset);
4621 }
4622#endif
4623 offset=SeekBlob(image,offset,SEEK_SET);
4624 if (count != 1)
4625 return(MagickFalse);
4626 break;
4627 }
4628 case PipeStream:
4629 case ZipStream:
4630 return(MagickFalse);
4631 case BZipStream:
4632 return(MagickFalse);
4633 case FifoStream:
4634 return(MagickFalse);
4635 case BlobStream:
4636 {
4637 if (extent != (MagickSizeType) ((size_t) extent))
4638 return(MagickFalse);
4639 if (blob_info->mapped != MagickFalse)
4640 {
4641 MagickOffsetType
4642 offset;
4643
4644 ssize_t
4645 count;
4646
4647 (void) UnmapBlob(blob_info->data,blob_info->length);
4648 RelinquishMagickResource(MapResource,blob_info->length);
4649 if (extent != (MagickSizeType) ((off_t) extent))
4650 return(MagickFalse);
4651 offset=SeekBlob(image,0,SEEK_END);
4652 if (offset < 0)
4653 return(MagickFalse);
4654 if ((MagickSizeType) offset >= extent)
4655 break;
4656 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4657 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4658 blob_info->file_info.file);
4659#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4660 if (blob_info->synchronize != MagickFalse)
4661 {
4662 int
4663 file;
4664
4665 file=fileno(blob_info->file_info.file);
4666 if ((file == -1) || (offset < 0))
4667 return(MagickFalse);
4668 (void) posix_fallocate(file,offset,extent-offset);
4669 }
4670#endif
4671 offset=SeekBlob(image,offset,SEEK_SET);
4672 if (count != 1)
4673 return(MagickFalse);
4674 (void) AcquireMagickResource(MapResource,extent);
4675 blob_info->data=(unsigned char*) MapBlob(fileno(
4676 blob_info->file_info.file),WriteMode,0,(size_t) extent);
4677 blob_info->extent=(size_t) extent;
4678 blob_info->length=(size_t) extent;
4679 (void) SyncBlob(image);
4680 break;
4681 }
4682 blob_info->extent=(size_t) extent;
4683 blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
4684 blob_info->extent+1,sizeof(*blob_info->data));
4685 (void) SyncBlob(image);
4686 if (blob_info->data == (unsigned char *) NULL)
4687 {
4688 (void) DetachBlob(blob_info);
4689 return(MagickFalse);
4690 }
4691 break;
4692 }
4693 }
4694 return(MagickTrue);
4695}
4696
4697/*
4698%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4699% %
4700% %
4701% %
4702+ S y n c B l o b %
4703% %
4704% %
4705% %
4706%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4707%
4708% SyncBlob() flushes the datastream if it is a file or synchronizes the data
4709% attributes if it is an blob.
4710%
4711% The format of the SyncBlob method is:
4712%
4713% int SyncBlob(Image *image)
4714%
4715% A description of each parameter follows:
4716%
4717% o image: the image.
4718%
4719*/
4720static int SyncBlob(Image *image)
4721{
4722 BlobInfo
4723 *magick_restrict blob_info;
4724
4725 int
4726 status;
4727
4728 assert(image != (Image *) NULL);
4729 assert(image->signature == MagickCoreSignature);
4730 assert(image->blob != (BlobInfo *) NULL);
4731 assert(image->blob->type != UndefinedStream);
4732 if (IsEventLogging() != MagickFalse)
4733 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4734 blob_info=image->blob;
4735 status=0;
4736 switch (blob_info->type)
4737 {
4738 case UndefinedStream:
4739 case StandardStream:
4740 break;
4741 case FileStream:
4742 case PipeStream:
4743 {
4744 status=fflush(blob_info->file_info.file);
4745 break;
4746 }
4747 case ZipStream:
4748 {
4749#if defined(MAGICKCORE_ZLIB_DELEGATE)
4750 status=gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
4751#endif
4752 break;
4753 }
4754 case BZipStream:
4755 {
4756#if defined(MAGICKCORE_BZLIB_DELEGATE)
4757 status=BZ2_bzflush(blob_info->file_info.bzfile);
4758#endif
4759 break;
4760 }
4761 case FifoStream:
4762 break;
4763 case BlobStream:
4764 break;
4765 }
4766 return(status);
4767}
4768
4769/*
4770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4771% %
4772% %
4773% %
4774+ T e l l B l o b %
4775% %
4776% %
4777% %
4778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4779%
4780% TellBlob() obtains the current value of the blob or file position.
4781%
4782% The format of the TellBlob method is:
4783%
4784% MagickOffsetType TellBlob(const Image *image)
4785%
4786% A description of each parameter follows:
4787%
4788% o image: the image.
4789%
4790*/
4791MagickExport MagickOffsetType TellBlob(const Image *image)
4792{
4793 BlobInfo
4794 *magick_restrict blob_info;
4795
4796 MagickOffsetType
4797 offset;
4798
4799 assert(image != (Image *) NULL);
4800 assert(image->signature == MagickCoreSignature);
4801 assert(image->blob != (BlobInfo *) NULL);
4802 assert(image->blob->type != UndefinedStream);
4803 if (IsEventLogging() != MagickFalse)
4804 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4805 blob_info=image->blob;
4806 offset=(-1);
4807 switch (blob_info->type)
4808 {
4809 case UndefinedStream:
4810 case StandardStream:
4811 break;
4812 case FileStream:
4813 {
4814 offset=ftell(blob_info->file_info.file);
4815 break;
4816 }
4817 case PipeStream:
4818 break;
4819 case ZipStream:
4820 {
4821#if defined(MAGICKCORE_ZLIB_DELEGATE)
4822 offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
4823#endif
4824 break;
4825 }
4826 case BZipStream:
4827 break;
4828 case FifoStream:
4829 break;
4830 case BlobStream:
4831 {
4832 offset=blob_info->offset;
4833 break;
4834 }
4835 }
4836 return(offset);
4837}
4838
4839/*
4840%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4841% %
4842% %
4843% %
4844+ U n m a p B l o b %
4845% %
4846% %
4847% %
4848%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4849%
4850% UnmapBlob() deallocates the binary large object previously allocated with
4851% the MapBlob method.
4852%
4853% The format of the UnmapBlob method is:
4854%
4855% MagickBooleanType UnmapBlob(void *map,const size_t length)
4856%
4857% A description of each parameter follows:
4858%
4859% o map: the address of the binary large object.
4860%
4861% o length: the length of the binary large object.
4862%
4863*/
4864MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4865{
4866#if defined(MAGICKCORE_HAVE_MMAP)
4867 int
4868 status;
4869
4870 status=munmap(map,length);
4871 return(status == -1 ? MagickFalse : MagickTrue);
4872#else
4873 (void) map;
4874 (void) length;
4875 return(MagickFalse);
4876#endif
4877}
4878
4879/*
4880%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4881% %
4882% %
4883% %
4884+ W r i t e B l o b %
4885% %
4886% %
4887% %
4888%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4889%
4890% WriteBlob() writes data to a blob or image file. It returns the number of
4891% bytes written.
4892%
4893% The format of the WriteBlob method is:
4894%
4895% ssize_t WriteBlob(Image *image,const size_t length,
4896% const unsigned char *data)
4897%
4898% A description of each parameter follows:
4899%
4900% o image: the image.
4901%
4902% o length: Specifies an integer representing the number of bytes to
4903% write to the file.
4904%
4905% o data: The address of the data to write to the blob or file.
4906%
4907*/
4908MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4909 const unsigned char *data)
4910{
4911 BlobInfo
4912 *magick_restrict blob_info;
4913
4914 int
4915 c;
4916
4917 const unsigned char
4918 *p;
4919
4920 unsigned char
4921 *q;
4922
4923 ssize_t
4924 count;
4925
4926 assert(image != (Image *) NULL);
4927 assert(image->signature == MagickCoreSignature);
4928 assert(image->blob != (BlobInfo *) NULL);
4929 assert(image->blob->type != UndefinedStream);
4930 if (length == 0)
4931 return(0);
4932 assert(data != (const unsigned char *) NULL);
4933 blob_info=image->blob;
4934 count=0;
4935 p=(const unsigned char *) data;
4936 q=(unsigned char *) data;
4937 switch (blob_info->type)
4938 {
4939 case UndefinedStream:
4940 break;
4941 case StandardStream:
4942 case FileStream:
4943 case PipeStream:
4944 {
4945 switch (length)
4946 {
4947 default:
4948 {
4949 count=(ssize_t) fwrite((const char *) data,1,length,
4950 blob_info->file_info.file);
4951 break;
4952 }
4953 case 4:
4954 {
4955 c=putc((int) *p++,blob_info->file_info.file);
4956 if (c == EOF)
4957 break;
4958 count++;
4959 magick_fallthrough;
4960 }
4961 case 3:
4962 {
4963 c=putc((int) *p++,blob_info->file_info.file);
4964 if (c == EOF)
4965 break;
4966 count++;
4967 magick_fallthrough;
4968 }
4969 case 2:
4970 {
4971 c=putc((int) *p++,blob_info->file_info.file);
4972 if (c == EOF)
4973 break;
4974 count++;
4975 magick_fallthrough;
4976 }
4977 case 1:
4978 {
4979 c=putc((int) *p++,blob_info->file_info.file);
4980 if (c == EOF)
4981 break;
4982 count++;
4983 magick_fallthrough;
4984 }
4985 case 0:
4986 break;
4987 }
4988 if ((count != (ssize_t) length) &&
4989 (ferror(blob_info->file_info.file) != 0))
4990 ThrowBlobException(blob_info);
4991 break;
4992 }
4993 case ZipStream:
4994 {
4995#if defined(MAGICKCORE_ZLIB_DELEGATE)
4996 int
4997 status;
4998
4999 switch (length)
5000 {
5001 default:
5002 {
5003 ssize_t
5004 i;
5005
5006 for (i=0; i < (ssize_t) length; i+=count)
5007 {
5008 count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
5009 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
5010 if (count <= 0)
5011 {
5012 count=0;
5013 if (errno != EINTR)
5014 break;
5015 }
5016 }
5017 count=i;
5018 break;
5019 }
5020 case 4:
5021 {
5022 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5023 if (c == EOF)
5024 break;
5025 count++;
5026 magick_fallthrough;
5027 }
5028 case 3:
5029 {
5030 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5031 if (c == EOF)
5032 break;
5033 count++;
5034 magick_fallthrough;
5035 }
5036 case 2:
5037 {
5038 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5039 if (c == EOF)
5040 break;
5041 count++;
5042 magick_fallthrough;
5043 }
5044 case 1:
5045 {
5046 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5047 if (c == EOF)
5048 break;
5049 count++;
5050 magick_fallthrough;
5051 }
5052 case 0:
5053 break;
5054 }
5055 status=Z_OK;
5056 (void) gzerror(blob_info->file_info.gzfile,&status);
5057 if ((count != (ssize_t) length) && (status != Z_OK))
5058 ThrowBlobException(blob_info);
5059#endif
5060 break;
5061 }
5062 case BZipStream:
5063 {
5064#if defined(MAGICKCORE_BZLIB_DELEGATE)
5065 int
5066 status;
5067
5068 ssize_t
5069 i;
5070
5071 for (i=0; i < (ssize_t) length; i+=count)
5072 {
5073 count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
5074 (int) MagickMin(length-i,MagickMaxBufferExtent));
5075 if (count <= 0)
5076 {
5077 count=0;
5078 if (errno != EINTR)
5079 break;
5080 }
5081 }
5082 count=i;
5083 status=BZ_OK;
5084 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
5085 if ((count != (ssize_t) length) && (status != BZ_OK))
5086 ThrowBlobException(blob_info);
5087#endif
5088 break;
5089 }
5090 case FifoStream:
5091 {
5092 count=(ssize_t) blob_info->stream(image,data,length);
5093 break;
5094 }
5095 case BlobStream:
5096 {
5097 if ((blob_info->offset+(MagickOffsetType) length) >=
5098 (MagickOffsetType) blob_info->extent)
5099 {
5100 if (blob_info->mapped != MagickFalse)
5101 return(0);
5102 blob_info->extent+=length+blob_info->quantum;
5103 blob_info->quantum<<=1;
5104 blob_info->data=(unsigned char *) ResizeQuantumMemory(
5105 blob_info->data,blob_info->extent+1,sizeof(*blob_info->data));
5106 (void) SyncBlob(image);
5107 if (blob_info->data == (unsigned char *) NULL)
5108 {
5109 (void) DetachBlob(blob_info);
5110 return(0);
5111 }
5112 }
5113 q=blob_info->data+blob_info->offset;
5114 (void) memcpy(q,p,length);
5115 blob_info->offset+=length;
5116 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
5117 blob_info->length=(size_t) blob_info->offset;
5118 count=(ssize_t) length;
5119 }
5120 }
5121 if (count != (ssize_t) length)
5122 ThrowBlobException(blob_info);
5123 return(count);
5124}
5125
5126/*
5127%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5128% %
5129% %
5130% %
5131+ W r i t e B l o b B y t e %
5132% %
5133% %
5134% %
5135%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5136%
5137% WriteBlobByte() write an integer to a blob. It returns the number of bytes
5138% written (either 0 or 1);
5139%
5140% The format of the WriteBlobByte method is:
5141%
5142% ssize_t WriteBlobByte(Image *image,const unsigned char value)
5143%
5144% A description of each parameter follows.
5145%
5146% o image: the image.
5147%
5148% o value: Specifies the value to write.
5149%
5150*/
5151MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
5152{
5153 BlobInfo
5154 *magick_restrict blob_info;
5155
5156 ssize_t
5157 count;
5158
5159 assert(image != (Image *) NULL);
5160 assert(image->signature == MagickCoreSignature);
5161 assert(image->blob != (BlobInfo *) NULL);
5162 assert(image->blob->type != UndefinedStream);
5163 blob_info=image->blob;
5164 count=0;
5165 switch (blob_info->type)
5166 {
5167 case StandardStream:
5168 case FileStream:
5169 case PipeStream:
5170 {
5171 int
5172 c;
5173
5174 c=putc((int) value,blob_info->file_info.file);
5175 if (c == EOF)
5176 {
5177 if (ferror(blob_info->file_info.file) != 0)
5178 ThrowBlobException(blob_info);
5179 break;
5180 }
5181 count++;
5182 break;
5183 }
5184 default:
5185 {
5186 count=WriteBlobStream(image,1,&value);
5187 break;
5188 }
5189 }
5190 return(count);
5191}
5192
5193/*
5194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5195% %
5196% %
5197% %
5198+ W r i t e B l o b F l o a t %
5199% %
5200% %
5201% %
5202%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5203%
5204% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
5205% specified by the endian member of the image structure.
5206%
5207% The format of the WriteBlobFloat method is:
5208%
5209% ssize_t WriteBlobFloat(Image *image,const float value)
5210%
5211% A description of each parameter follows.
5212%
5213% o image: the image.
5214%
5215% o value: Specifies the value to write.
5216%
5217*/
5218MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
5219{
5220 union
5221 {
5222 unsigned int
5223 unsigned_value;
5224
5225 float
5226 float_value;
5227 } quantum;
5228
5229 quantum.unsigned_value=0U;
5230 quantum.float_value=value;
5231 return(WriteBlobLong(image,quantum.unsigned_value));
5232}
5233
5234/*
5235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5236% %
5237% %
5238% %
5239+ W r i t e B l o b L o n g %
5240% %
5241% %
5242% %
5243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5244%
5245% WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
5246% byte-order specified by the endian member of the image structure.
5247%
5248% The format of the WriteBlobLong method is:
5249%
5250% ssize_t WriteBlobLong(Image *image,const unsigned int value)
5251%
5252% A description of each parameter follows.
5253%
5254% o image: the image.
5255%
5256% o value: Specifies the value to write.
5257%
5258*/
5259MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
5260{
5261 unsigned char
5262 buffer[4];
5263
5264 assert(image != (Image *) NULL);
5265 assert(image->signature == MagickCoreSignature);
5266 if (image->endian == LSBEndian)
5267 {
5268 buffer[0]=(unsigned char) value;
5269 buffer[1]=(unsigned char) (value >> 8);
5270 buffer[2]=(unsigned char) (value >> 16);
5271 buffer[3]=(unsigned char) (value >> 24);
5272 return(WriteBlobStream(image,4,buffer));
5273 }
5274 buffer[0]=(unsigned char) (value >> 24);
5275 buffer[1]=(unsigned char) (value >> 16);
5276 buffer[2]=(unsigned char) (value >> 8);
5277 buffer[3]=(unsigned char) value;
5278 return(WriteBlobStream(image,4,buffer));
5279}
5280
5281/*
5282%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5283% %
5284% %
5285% %
5286+ W r i t e B l o b S h o r t %
5287% %
5288% %
5289% %
5290%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5291%
5292% WriteBlobShort() writes a short value as a 16-bit quantity in the
5293% byte-order specified by the endian member of the image structure.
5294%
5295% The format of the WriteBlobShort method is:
5296%
5297% ssize_t WriteBlobShort(Image *image,const unsigned short value)
5298%
5299% A description of each parameter follows.
5300%
5301% o image: the image.
5302%
5303% o value: Specifies the value to write.
5304%
5305*/
5306MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
5307{
5308 unsigned char
5309 buffer[2];
5310
5311 assert(image != (Image *) NULL);
5312 assert(image->signature == MagickCoreSignature);
5313 if (image->endian == LSBEndian)
5314 {
5315 buffer[0]=(unsigned char) value;
5316 buffer[1]=(unsigned char) (value >> 8);
5317 return(WriteBlobStream(image,2,buffer));
5318 }
5319 buffer[0]=(unsigned char) (value >> 8);
5320 buffer[1]=(unsigned char) value;
5321 return(WriteBlobStream(image,2,buffer));
5322}
5323
5324/*
5325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5326% %
5327% %
5328% %
5329+ W r i t e B l o b L S B L o n g %
5330% %
5331% %
5332% %
5333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5334%
5335% WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
5336% least-significant byte first order.
5337%
5338% The format of the WriteBlobLSBLong method is:
5339%
5340% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5341%
5342% A description of each parameter follows.
5343%
5344% o image: the image.
5345%
5346% o value: Specifies the value to write.
5347%
5348*/
5349MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5350{
5351 unsigned char
5352 buffer[4];
5353
5354 assert(image != (Image *) NULL);
5355 assert(image->signature == MagickCoreSignature);
5356 buffer[0]=(unsigned char) value;
5357 buffer[1]=(unsigned char) (value >> 8);
5358 buffer[2]=(unsigned char) (value >> 16);
5359 buffer[3]=(unsigned char) (value >> 24);
5360 return(WriteBlobStream(image,4,buffer));
5361}
5362
5363/*
5364%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5365% %
5366% %
5367% %
5368+ W r i t e B l o b L S B S h o r t %
5369% %
5370% %
5371% %
5372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5373%
5374% WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
5375% least-significant byte first order.
5376%
5377% The format of the WriteBlobLSBShort method is:
5378%
5379% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5380%
5381% A description of each parameter follows.
5382%
5383% o image: the image.
5384%
5385% o value: Specifies the value to write.
5386%
5387*/
5388MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5389{
5390 unsigned char
5391 buffer[2];
5392
5393 assert(image != (Image *) NULL);
5394 assert(image->signature == MagickCoreSignature);
5395 buffer[0]=(unsigned char) value;
5396 buffer[1]=(unsigned char) (value >> 8);
5397 return(WriteBlobStream(image,2,buffer));
5398}
5399
5400/*
5401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5402% %
5403% %
5404% %
5405+ W r i t e B l o b L S B S i g n e d L o n g %
5406% %
5407% %
5408% %
5409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5410%
5411% WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
5412% least-significant byte first order.
5413%
5414% The format of the WriteBlobLSBSignedLong method is:
5415%
5416% ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5417%
5418% A description of each parameter follows.
5419%
5420% o image: the image.
5421%
5422% o value: Specifies the value to write.
5423%
5424*/
5425MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5426{
5427 union
5428 {
5429 unsigned int
5430 unsigned_value;
5431
5432 signed int
5433 signed_value;
5434 } quantum;
5435
5436 unsigned char
5437 buffer[4];
5438
5439 assert(image != (Image *) NULL);
5440 assert(image->signature == MagickCoreSignature);
5441 quantum.signed_value=value;
5442 buffer[0]=(unsigned char) quantum.unsigned_value;
5443 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5444 buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
5445 buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
5446 return(WriteBlobStream(image,4,buffer));
5447}
5448
5449/*
5450%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5451% %
5452% %
5453% %
5454+ W r i t e B l o b L S B S i g n e d S h o r t %
5455% %
5456% %
5457% %
5458%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5459%
5460% WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
5461% in least-significant byte first order.
5462%
5463% The format of the WriteBlobLSBSignedShort method is:
5464%
5465% ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
5466%
5467% A description of each parameter follows.
5468%
5469% o image: the image.
5470%
5471% o value: Specifies the value to write.
5472%
5473*/
5474MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
5475 const signed short value)
5476{
5477 union
5478 {
5479 unsigned short
5480 unsigned_value;
5481
5482 signed short
5483 signed_value;
5484 } quantum;
5485
5486 unsigned char
5487 buffer[2];
5488
5489 assert(image != (Image *) NULL);
5490 assert(image->signature == MagickCoreSignature);
5491 quantum.signed_value=value;
5492 buffer[0]=(unsigned char) quantum.unsigned_value;
5493 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5494 return(WriteBlobStream(image,2,buffer));
5495}
5496
5497/*
5498%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5499% %
5500% %
5501% %
5502+ W r i t e B l o b M S B L o n g %
5503% %
5504% %
5505% %
5506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5507%
5508% WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
5509% most-significant byte first order.
5510%
5511% The format of the WriteBlobMSBLong method is:
5512%
5513% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5514%
5515% A description of each parameter follows.
5516%
5517% o value: Specifies the value to write.
5518%
5519% o image: the image.
5520%
5521*/
5522MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5523{
5524 unsigned char
5525 buffer[4];
5526
5527 assert(image != (Image *) NULL);
5528 assert(image->signature == MagickCoreSignature);
5529 buffer[0]=(unsigned char) (value >> 24);
5530 buffer[1]=(unsigned char) (value >> 16);
5531 buffer[2]=(unsigned char) (value >> 8);
5532 buffer[3]=(unsigned char) value;
5533 return(WriteBlobStream(image,4,buffer));
5534}
5535
5536/*
5537%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5538% %
5539% %
5540% %
5541+ W r i t e B l o b M S B L o n g L o n g %
5542% %
5543% %
5544% %
5545%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5546%
5547% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
5548% most-significant byte first order.
5549%
5550% The format of the WriteBlobMSBLongLong method is:
5551%
5552% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
5553%
5554% A description of each parameter follows.
5555%
5556% o value: Specifies the value to write.
5557%
5558% o image: the image.
5559%
5560*/
5561MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
5562 const MagickSizeType value)
5563{
5564 unsigned char
5565 buffer[8];
5566
5567 assert(image != (Image *) NULL);
5568 assert(image->signature == MagickCoreSignature);
5569 buffer[0]=(unsigned char) (value >> 56);
5570 buffer[1]=(unsigned char) (value >> 48);
5571 buffer[2]=(unsigned char) (value >> 40);
5572 buffer[3]=(unsigned char) (value >> 32);
5573 buffer[4]=(unsigned char) (value >> 24);
5574 buffer[5]=(unsigned char) (value >> 16);
5575 buffer[6]=(unsigned char) (value >> 8);
5576 buffer[7]=(unsigned char) value;
5577 return(WriteBlobStream(image,8,buffer));
5578}
5579
5580/*
5581%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5582% %
5583% %
5584% %
5585+ W r i t e B l o b M S B S h o r t %
5586% %
5587% %
5588% %
5589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5590%
5591% WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
5592% most-significant byte first order.
5593%
5594% The format of the WriteBlobMSBShort method is:
5595%
5596% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5597%
5598% A description of each parameter follows.
5599%
5600% o value: Specifies the value to write.
5601%
5602% o file: Specifies the file to write the data to.
5603%
5604*/
5605MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5606{
5607 unsigned char
5608 buffer[2];
5609
5610 assert(image != (Image *) NULL);
5611 assert(image->signature == MagickCoreSignature);
5612 buffer[0]=(unsigned char) (value >> 8);
5613 buffer[1]=(unsigned char) value;
5614 return(WriteBlobStream(image,2,buffer));
5615}
5616
5617/*
5618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5619% %
5620% %
5621% %
5622+ W r i t e B l o b M S B S i g n e d L o n g %
5623% %
5624% %
5625% %
5626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5627%
5628% WriteBlobMSBSignedLong() writes a signed value as a 32-bit quantity in
5629% most-significant byte first order.
5630%
5631% The format of the WriteBlobMSBSignedLong method is:
5632%
5633% ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5634%
5635% A description of each parameter follows.
5636%
5637% o image: the image.
5638%
5639% o value: Specifies the value to write.
5640%
5641*/
5642MagickExport ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5643{
5644 union
5645 {
5646 unsigned int
5647 unsigned_value;
5648
5649 signed int
5650 signed_value;
5651 } quantum;
5652
5653 unsigned char
5654 buffer[4];
5655
5656 assert(image != (Image *) NULL);
5657 assert(image->signature == MagickCoreSignature);
5658 quantum.signed_value=value;
5659 buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
5660 buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
5661 buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
5662 buffer[3]=(unsigned char) quantum.unsigned_value;
5663 return(WriteBlobStream(image,4,buffer));
5664}
5665
5666/*
5667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5668% %
5669% %
5670% %
5671+ W r i t e B l o b M S B S i g n e d S h o r t %
5672% %
5673% %
5674% %
5675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5676%
5677% WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
5678% in most-significant byte first order.
5679%
5680% The format of the WriteBlobMSBSignedShort method is:
5681%
5682% ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
5683%
5684% A description of each parameter follows.
5685%
5686% o image: the image.
5687%
5688% o value: Specifies the value to write.
5689%
5690*/
5691MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
5692 const signed short value)
5693{
5694 union
5695 {
5696 unsigned short
5697 unsigned_value;
5698
5699 signed short
5700 signed_value;
5701 } quantum;
5702
5703 unsigned char
5704 buffer[2];
5705
5706 assert(image != (Image *) NULL);
5707 assert(image->signature == MagickCoreSignature);
5708 quantum.signed_value=value;
5709 buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
5710 buffer[1]=(unsigned char) quantum.unsigned_value;
5711 return(WriteBlobStream(image,2,buffer));
5712}
5713
5714/*
5715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5716% %
5717% %
5718% %
5719+ W r i t e B l o b S t r i n g %
5720% %
5721% %
5722% %
5723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5724%
5725% WriteBlobString() write a string to a blob. It returns the number of
5726% characters written.
5727%
5728% The format of the WriteBlobString method is:
5729%
5730% ssize_t WriteBlobString(Image *image,const char *string)
5731%
5732% A description of each parameter follows.
5733%
5734% o image: the image.
5735%
5736% o string: Specifies the string to write.
5737%
5738*/
5739MagickExport ssize_t WriteBlobString(Image *image,const char *string)
5740{
5741 assert(image != (Image *) NULL);
5742 assert(image->signature == MagickCoreSignature);
5743 assert(string != (const char *) NULL);
5744 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
5745}