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->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 SyncBlobStream(blob_info,image,image);
1770 InheritException(exception,&image->exception);
1771 *length=image->blob->length;
1772 blob=DetachBlob(image->blob);
1773 if (blob != (void *) NULL)
1774 {
1775 if (status == MagickFalse)
1776 blob=(unsigned char *) RelinquishMagickMemory(blob);
1777 else
1778 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1779 sizeof(unsigned char));
1780 }
1781 else if (status == MagickFalse)
1782 blob_info->blob=RelinquishMagickMemory(blob_info->blob);
1783 }
1784 }
1785 else
1786 {
1787 char
1788 unique[MagickPathExtent];
1789
1790 int
1791 file;
1792
1793 /*
1794 Write file to disk in blob image format.
1795 */
1796 file=AcquireUniqueFileResource(unique);
1797 if (file == -1)
1798 {
1799 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1800 image_info->filename);
1801 }
1802 else
1803 {
1804 blob_info->file=fdopen(file,"wb");
1805 if (blob_info->file != (FILE *) NULL)
1806 {
1807 (void) FormatLocaleString(image->filename,MagickPathExtent,
1808 "%s:%s",image->magick,unique);
1809 status=WriteImage(blob_info,image);
1810 (void) CloseBlob(image);
1811 (void) fclose(blob_info->file);
1812 if (status == MagickFalse)
1813 InheritException(exception,&image->exception);
1814 else
1815 blob=FileToBlob(unique,SIZE_MAX,length,exception);
1816 }
1817 (void) RelinquishUniqueFileResource(unique);
1818 }
1819 }
1820 blob_info=DestroyImageInfo(blob_info);
1821 return(blob);
1822}
1823␌
1824/*
1825%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1826% %
1827% %
1828% %
1829% I m a g e T o F i l e %
1830% %
1831% %
1832% %
1833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1834%
1835% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1836% occurs otherwise MagickTrue.
1837%
1838% The format of the ImageToFile method is:
1839%
1840% MagickBooleanType ImageToFile(Image *image,char *filename,
1841% ExceptionInfo *exception)
1842%
1843% A description of each parameter follows:
1844%
1845% o image: the image.
1846%
1847% o filename: Write the image to this file.
1848%
1849% o exception: return any errors or warnings in this structure.
1850%
1851*/
1852MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1853 ExceptionInfo *exception)
1854{
1855 int
1856 file;
1857
1858 const unsigned char
1859 *p;
1860
1861 size_t
1862 i;
1863
1864 size_t
1865 length,
1866 quantum;
1867
1868 ssize_t
1869 count;
1870
1871 struct stat
1872 file_stats;
1873
1874 unsigned char
1875 *buffer;
1876
1877 assert(image != (Image *) NULL);
1878 assert(image->signature == MagickCoreSignature);
1879 assert(image->blob != (BlobInfo *) NULL);
1880 assert(image->blob->type != UndefinedStream);
1881 assert(filename != (const char *) NULL);
1882 if (IsEventLogging() != MagickFalse)
1883 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1884 if (*filename == '\0')
1885 file=AcquireUniqueFileResource(filename);
1886 else
1887 if (LocaleCompare(filename,"-") == 0)
1888 file=fileno(stdout);
1889 else
1890 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1891 if (file == -1)
1892 {
1893 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1894 return(MagickFalse);
1895 }
1896 quantum=(size_t) MagickMaxBufferExtent;
1897 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1898 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1899 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1900 if (buffer == (unsigned char *) NULL)
1901 {
1902 file=close(file)-1;
1903 (void) ThrowMagickException(exception,GetMagickModule(),
1904 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1905 return(MagickFalse);
1906 }
1907 length=0;
1908 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1909 for (i=0; count > 0; )
1910 {
1911 length=(size_t) count;
1912 for (i=0; i < length; i+=count)
1913 {
1914 count=write(file,p+i,(size_t) (length-i));
1915 if (count <= 0)
1916 {
1917 count=0;
1918 if (errno != EINTR)
1919 break;
1920 }
1921 }
1922 if (i < length)
1923 break;
1924 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1925 }
1926 if (LocaleCompare(filename,"-") != 0)
1927 file=close(file);
1928 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1929 if ((file == -1) || (i < length))
1930 {
1931 if (file != -1)
1932 file=close(file);
1933 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1934 return(MagickFalse);
1935 }
1936 return(MagickTrue);
1937}
1938␌
1939/*
1940%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1941% %
1942% %
1943% %
1944% I m a g e s T o B l o b %
1945% %
1946% %
1947% %
1948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1949%
1950% ImagesToBlob() implements direct to memory image formats. It returns the
1951% image sequence as a blob and its length. The magick member of the ImageInfo
1952% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1953%
1954% Note, some image formats do not permit multiple images to the same image
1955% stream (e.g. JPEG). in this instance, just the first image of the
1956% sequence is returned as a blob.
1957%
1958% The format of the ImagesToBlob method is:
1959%
1960% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1961% size_t *length,ExceptionInfo *exception)
1962%
1963% A description of each parameter follows:
1964%
1965% o image_info: the image info.
1966%
1967% o images: the image list.
1968%
1969% o length: return the actual length of the blob.
1970%
1971% o exception: return any errors or warnings in this structure.
1972%
1973*/
1974MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1975 Image *images,size_t *length,ExceptionInfo *exception)
1976{
1977 const MagickInfo
1978 *magick_info;
1979
1980 ImageInfo
1981 *blob_info;
1982
1983 MagickBooleanType
1984 status;
1985
1986 unsigned char
1987 *blob;
1988
1989 assert(image_info != (const ImageInfo *) NULL);
1990 assert(image_info->signature == MagickCoreSignature);
1991 assert(images != (Image *) NULL);
1992 assert(images->signature == MagickCoreSignature);
1993 assert(exception != (ExceptionInfo *) NULL);
1994 if (IsEventLogging() != MagickFalse)
1995 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1996 image_info->filename);
1997 *length=0;
1998 blob=(unsigned char *) NULL;
1999 blob_info=CloneImageInfo(image_info);
2000 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
2001 exception);
2002 if (*blob_info->magick != '\0')
2003 (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
2004 magick_info=GetMagickInfo(images->magick,exception);
2005 if (magick_info == (const MagickInfo *) NULL)
2006 {
2007 (void) ThrowMagickException(exception,GetMagickModule(),
2008 MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2009 images->magick);
2010 blob_info=DestroyImageInfo(blob_info);
2011 return(blob);
2012 }
2013 if (GetMagickAdjoin(magick_info) == MagickFalse)
2014 {
2015 blob_info=DestroyImageInfo(blob_info);
2016 return(ImageToBlob(image_info,images,length,exception));
2017 }
2018 (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
2019 if (GetMagickBlobSupport(magick_info) != MagickFalse)
2020 {
2021 /*
2022 Native blob support for this images format.
2023 */
2024 blob_info->length=0;
2025 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
2026 sizeof(unsigned char));
2027 if (blob_info->blob == (void *) NULL)
2028 (void) ThrowMagickException(exception,GetMagickModule(),
2029 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2030 else
2031 {
2032 (void) CloseBlob(images);
2033 images->blob->exempt=MagickTrue;
2034 *images->filename='\0';
2035 status=WriteImages(blob_info,images,images->filename,exception);
2036 SyncBlobStream(blob_info,images,images);
2037 *length=images->blob->length;
2038 blob=DetachBlob(images->blob);
2039 if (blob != (void *) NULL)
2040 {
2041 if (status == MagickFalse)
2042 blob=(unsigned char *) RelinquishMagickMemory(blob);
2043 else
2044 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
2045 sizeof(unsigned char));
2046 }
2047 else if (status == MagickFalse)
2048 blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2049 }
2050 }
2051 else
2052 {
2053 char
2054 filename[MagickPathExtent],
2055 unique[MagickPathExtent];
2056
2057 int
2058 file;
2059
2060 /*
2061 Write file to disk in blob images format.
2062 */
2063 file=AcquireUniqueFileResource(unique);
2064 if (file == -1)
2065 {
2066 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2067 image_info->filename);
2068 }
2069 else
2070 {
2071 blob_info->file=fdopen(file,"wb");
2072 if (blob_info->file != (FILE *) NULL)
2073 {
2074 (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2075 images->magick,unique);
2076 status=WriteImages(blob_info,images,filename,exception);
2077 (void) CloseBlob(images);
2078 (void) fclose(blob_info->file);
2079 if (status == MagickFalse)
2080 InheritException(exception,&images->exception);
2081 else
2082 blob=FileToBlob(unique,SIZE_MAX,length,exception);
2083 }
2084 (void) RelinquishUniqueFileResource(unique);
2085 }
2086 }
2087 blob_info=DestroyImageInfo(blob_info);
2088 return(blob);
2089}
2090/*
2091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2092% %
2093% %
2094% %
2095% I n j e c t I m a g e B l o b %
2096% %
2097% %
2098% %
2099%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2100%
2101% InjectImageBlob() injects the image with a copy of itself in the specified
2102% format (e.g. inject JPEG into a PDF image).
2103%
2104% The format of the InjectImageBlob method is:
2105%
2106% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2107% Image *image,Image *inject_image,const char *format,
2108% ExceptionInfo *exception)
2109%
2110% A description of each parameter follows:
2111%
2112% o image_info: the image info..
2113%
2114% o image: the image.
2115%
2116% o inject_image: inject into the image stream.
2117%
2118% o format: the image format.
2119%
2120% o exception: return any errors or warnings in this structure.
2121%
2122*/
2123MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2124 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2125{
2126 char
2127 filename[MagickPathExtent];
2128
2129 FILE
2130 *unique_file;
2131
2132 Image
2133 *byte_image;
2134
2135 ImageInfo
2136 *write_info;
2137
2138 int
2139 file;
2140
2141 MagickBooleanType
2142 status;
2143
2144 size_t
2145 quantum;
2146
2147 struct stat
2148 file_stats;
2149
2150 unsigned char
2151 *buffer;
2152
2153 /*
2154 Write inject image to a temporary file.
2155 */
2156 assert(image_info != (ImageInfo *) NULL);
2157 assert(image_info->signature == MagickCoreSignature);
2158 assert(image != (Image *) NULL);
2159 assert(image->signature == MagickCoreSignature);
2160 assert(inject_image != (Image *) NULL);
2161 assert(inject_image->signature == MagickCoreSignature);
2162 assert(exception != (ExceptionInfo *) NULL);
2163 if (IsEventLogging() != MagickFalse)
2164 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2165 unique_file=(FILE *) NULL;
2166 file=AcquireUniqueFileResource(filename);
2167 if (file != -1)
2168 unique_file=fdopen(file,"wb");
2169 if ((file == -1) || (unique_file == (FILE *) NULL))
2170 {
2171 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2172 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2173 image->filename);
2174 return(MagickFalse);
2175 }
2176 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2177 if (byte_image == (Image *) NULL)
2178 {
2179 (void) fclose(unique_file);
2180 (void) RelinquishUniqueFileResource(filename);
2181 return(MagickFalse);
2182 }
2183 (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
2184 format,filename);
2185 DestroyBlob(byte_image);
2186 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2187 write_info=CloneImageInfo(image_info);
2188 SetImageInfoFile(write_info,unique_file);
2189 status=WriteImage(write_info,byte_image);
2190 write_info=DestroyImageInfo(write_info);
2191 byte_image=DestroyImage(byte_image);
2192 (void) fclose(unique_file);
2193 if (status == MagickFalse)
2194 {
2195 (void) RelinquishUniqueFileResource(filename);
2196 return(MagickFalse);
2197 }
2198 /*
2199 Inject into image stream.
2200 */
2201 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2202 if (file == -1)
2203 {
2204 (void) RelinquishUniqueFileResource(filename);
2205 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2206 image_info->filename);
2207 return(MagickFalse);
2208 }
2209 quantum=(size_t) MagickMaxBufferExtent;
2210 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2211 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2212 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2213 if (buffer == (unsigned char *) NULL)
2214 {
2215 (void) RelinquishUniqueFileResource(filename);
2216 file=close(file);
2217 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2218 image->filename);
2219 }
2220 for ( ; ; )
2221 {
2222 ssize_t count = read(file,buffer,quantum);
2223 if (count <= 0)
2224 {
2225 count=0;
2226 if (errno != EINTR)
2227 break;
2228 }
2229 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2230 MagickFalse;
2231 }
2232 file=close(file);
2233 if (file == -1)
2234 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2235 (void) RelinquishUniqueFileResource(filename);
2236 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2237 return(status);
2238}
2239␌
2240/*
2241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2242% %
2243% %
2244% %
2245% I s B l o b E x e m p t %
2246% %
2247% %
2248% %
2249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2250%
2251% IsBlobExempt() returns true if the blob is exempt.
2252%
2253% The format of the IsBlobExempt method is:
2254%
2255% MagickBooleanType IsBlobExempt(const Image *image)
2256%
2257% A description of each parameter follows:
2258%
2259% o image: the image.
2260%
2261*/
2262MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2263{
2264 assert(image != (const Image *) NULL);
2265 assert(image->signature == MagickCoreSignature);
2266 if (IsEventLogging() != MagickFalse)
2267 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2268 return(image->blob->exempt);
2269}
2270␌
2271/*
2272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2273% %
2274% %
2275% %
2276+ I s B l o b S e e k a b l e %
2277% %
2278% %
2279% %
2280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2281%
2282% IsBlobSeekable() returns true if the blob is seekable.
2283%
2284% The format of the IsBlobSeekable method is:
2285%
2286% MagickBooleanType IsBlobSeekable(const Image *image)
2287%
2288% A description of each parameter follows:
2289%
2290% o image: the image.
2291%
2292*/
2293MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2294{
2295 BlobInfo
2296 *magick_restrict blob_info;
2297
2298 assert(image != (const Image *) NULL);
2299 assert(image->signature == MagickCoreSignature);
2300 if (IsEventLogging() != MagickFalse)
2301 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2302 blob_info=image->blob;
2303 switch (blob_info->type)
2304 {
2305 case BlobStream:
2306 return(MagickTrue);
2307 case FileStream:
2308 {
2309 int
2310 status;
2311
2312 if (blob_info->file_info.file == (FILE *) NULL)
2313 return(MagickFalse);
2314 status=fseek(blob_info->file_info.file,0,SEEK_CUR);
2315 return(status == -1 ? MagickFalse : MagickTrue);
2316 }
2317 case ZipStream:
2318 {
2319#if defined(MAGICKCORE_ZLIB_DELEGATE)
2320 MagickOffsetType
2321 offset;
2322
2323 if (blob_info->file_info.gzfile == (gzFile) NULL)
2324 return(MagickFalse);
2325 offset=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
2326 return(offset < 0 ? MagickFalse : MagickTrue);
2327#else
2328 break;
2329#endif
2330 }
2331 case UndefinedStream:
2332 case BZipStream:
2333 case FifoStream:
2334 case PipeStream:
2335 case StandardStream:
2336 break;
2337 default:
2338 break;
2339 }
2340 return(MagickFalse);
2341}
2342␌
2343/*
2344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2345% %
2346% %
2347% %
2348% I s B l o b T e m p o r a r y %
2349% %
2350% %
2351% %
2352%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2353%
2354% IsBlobTemporary() returns true if the blob is temporary.
2355%
2356% The format of the IsBlobTemporary method is:
2357%
2358% MagickBooleanType IsBlobTemporary(const Image *image)
2359%
2360% A description of each parameter follows:
2361%
2362% o image: the image.
2363%
2364*/
2365MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2366{
2367 assert(image != (const Image *) NULL);
2368 assert(image->signature == MagickCoreSignature);
2369 if (IsEventLogging() != MagickFalse)
2370 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2371 return(image->blob->temporary);
2372}
2373␌
2374/*
2375%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2376% %
2377% %
2378% %
2379+ M a p B l o b %
2380% %
2381% %
2382% %
2383%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2384%
2385% MapBlob() creates a mapping from a file to a binary large object.
2386%
2387% The format of the MapBlob method is:
2388%
2389% unsigned char *MapBlob(int file,const MapMode mode,
2390% const MagickOffsetType offset,const size_t length)
2391%
2392% A description of each parameter follows:
2393%
2394% o file: map this file descriptor.
2395%
2396% o mode: ReadMode, WriteMode, or IOMode.
2397%
2398% o offset: starting at this offset within the file.
2399%
2400% o length: the length of the mapping is returned in this pointer.
2401%
2402*/
2403MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2404 const MagickOffsetType offset,const size_t length)
2405{
2406#if defined(MAGICKCORE_HAVE_MMAP)
2407 int
2408 flags,
2409 protection;
2410
2411 unsigned char
2412 *map;
2413
2414 /*
2415 Map file.
2416 */
2417 flags=0;
2418 if (file == -1)
2419#if defined(MAP_ANONYMOUS)
2420 flags|=MAP_ANONYMOUS;
2421#else
2422 return((unsigned char *) NULL);
2423#endif
2424 switch (mode)
2425 {
2426 case ReadMode:
2427 default:
2428 {
2429 protection=PROT_READ;
2430 flags|=MAP_PRIVATE;
2431 break;
2432 }
2433 case WriteMode:
2434 {
2435 protection=PROT_WRITE;
2436 flags|=MAP_SHARED;
2437 break;
2438 }
2439 case IOMode:
2440 {
2441 protection=PROT_READ | PROT_WRITE;
2442 flags|=MAP_SHARED;
2443 break;
2444 }
2445 }
2446#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2447 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,offset);
2448#else
2449 map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
2450 MAP_HUGETLB,file,offset);
2451 if (map == (unsigned char *) MAP_FAILED)
2452 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2453 offset);
2454#endif
2455 if (map == (unsigned char *) MAP_FAILED)
2456 return((unsigned char *) NULL);
2457 return(map);
2458#else
2459 (void) file;
2460 (void) mode;
2461 (void) offset;
2462 (void) length;
2463 return((unsigned char *) NULL);
2464#endif
2465}
2466␌
2467/*
2468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2469% %
2470% %
2471% %
2472+ M S B O r d e r L o n g %
2473% %
2474% %
2475% %
2476%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2477%
2478% MSBOrderLong() converts a least-significant byte first buffer of integers to
2479% most-significant byte first.
2480%
2481% The format of the MSBOrderLong method is:
2482%
2483% void MSBOrderLong(unsigned char *buffer,const size_t length)
2484%
2485% A description of each parameter follows.
2486%
2487% o buffer: Specifies a pointer to a buffer of integers.
2488%
2489% o length: Specifies the length of the buffer.
2490%
2491*/
2492MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2493{
2494 int
2495 c;
2496
2497 unsigned char
2498 *p,
2499 *q;
2500
2501 assert(buffer != (unsigned char *) NULL);
2502 q=buffer+length;
2503 while (buffer < q)
2504 {
2505 p=buffer+3;
2506 c=(int) (*p);
2507 *p=(*buffer);
2508 *buffer++=(unsigned char) c;
2509 p=buffer+1;
2510 c=(int) (*p);
2511 *p=(*buffer);
2512 *buffer++=(unsigned char) c;
2513 buffer+=2;
2514 }
2515}
2516␌
2517/*
2518%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2519% %
2520% %
2521% %
2522+ M S B O r d e r S h o r t %
2523% %
2524% %
2525% %
2526%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2527%
2528% MSBOrderShort() converts a least-significant byte first buffer of integers
2529% to most-significant byte first.
2530%
2531% The format of the MSBOrderShort method is:
2532%
2533% void MSBOrderShort(unsigned char *p,const size_t length)
2534%
2535% A description of each parameter follows.
2536%
2537% o p: Specifies a pointer to a buffer of integers.
2538%
2539% o length: Specifies the length of the buffer.
2540%
2541*/
2542MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2543{
2544 int
2545 c;
2546
2547 unsigned char
2548 *q;
2549
2550 assert(p != (unsigned char *) NULL);
2551 q=p+length;
2552 while (p < q)
2553 {
2554 c=(int) (*p);
2555 *p=(*(p+1));
2556 p++;
2557 *p++=(unsigned char) c;
2558 }
2559}
2560␌
2561/*
2562%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2563% %
2564% %
2565% %
2566+ O p e n B l o b %
2567% %
2568% %
2569% %
2570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2571%
2572% OpenBlob() opens a file associated with the image. A file name of '-' sets
2573% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2574% suffix is '.gz', the image is decompressed for type 'r' and compressed
2575% for type 'w'. If the filename prefix is '|', it is piped to or from a
2576% system command.
2577%
2578% The format of the OpenBlob method is:
2579%
2580% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2581% const BlobMode mode,ExceptionInfo *exception)
2582%
2583% A description of each parameter follows:
2584%
2585% o image_info: the image info.
2586%
2587% o image: the image.
2588%
2589% o mode: the mode for opening the file.
2590%
2591*/
2592
2593static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
2594 Image *image)
2595{
2596 const char
2597 *option;
2598
2599 int
2600 status;
2601
2602 size_t
2603 size;
2604
2605 size=MagickMinBufferExtent;
2606 option=GetImageOption(image_info,"stream:buffer-size");
2607 if (option != (const char *) NULL)
2608 size=StringToUnsignedLong(option);
2609 status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
2610 _IONBF : _IOFBF,size);
2611 return(status == 0 ? MagickTrue : MagickFalse);
2612}
2613
2614#if defined(MAGICKCORE_ZLIB_DELEGATE)
2615static inline gzFile gzopen_utf8(const char *path,const char *mode)
2616{
2617#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
2618 return(gzopen(path,mode));
2619#else
2620 gzFile
2621 file;
2622
2623 wchar_t
2624 *path_wide;
2625
2626 path_wide=create_wchar_path(path);
2627 if (path_wide == (wchar_t *) NULL)
2628 return((gzFile) NULL);
2629 file=gzopen_w(path_wide,mode);
2630 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
2631 return(file);
2632#endif
2633}
2634#endif
2635
2636MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2637 Image *image,const BlobMode mode,ExceptionInfo *exception)
2638{
2639 BlobInfo
2640 *magick_restrict blob_info;
2641
2642 char
2643 extension[MagickPathExtent],
2644 filename[MagickPathExtent];
2645
2646 const char
2647 *type;
2648
2649 MagickBooleanType
2650 status;
2651
2652 PolicyRights
2653 rights;
2654
2655 assert(image_info != (ImageInfo *) NULL);
2656 assert(image_info->signature == MagickCoreSignature);
2657 assert(image != (Image *) NULL);
2658 assert(image->signature == MagickCoreSignature);
2659 if (IsEventLogging() != MagickFalse)
2660 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2661 image_info->filename);
2662 blob_info=image->blob;
2663 if (image_info->blob != (void *) NULL)
2664 {
2665 if (image_info->stream != (StreamHandler) NULL)
2666 blob_info->stream=(StreamHandler) image_info->stream;
2667 AttachBlob(blob_info,image_info->blob,image_info->length);
2668 return(MagickTrue);
2669 }
2670 (void) DetachBlob(blob_info);
2671 blob_info->mode=mode;
2672 switch (mode)
2673 {
2674 default: type="r"; break;
2675 case ReadBlobMode: type="r"; break;
2676 case ReadBinaryBlobMode: type="rb"; break;
2677 case WriteBlobMode: type="w"; break;
2678 case WriteBinaryBlobMode: type="w+b"; break;
2679 case AppendBlobMode: type="a"; break;
2680 case AppendBinaryBlobMode: type="a+b"; break;
2681 }
2682 if (*type != 'r')
2683 blob_info->synchronize=image_info->synchronize;
2684 if (image_info->stream != (StreamHandler) NULL)
2685 {
2686 blob_info->stream=(StreamHandler) image_info->stream;
2687 if (*type == 'w')
2688 {
2689 blob_info->type=FifoStream;
2690 return(MagickTrue);
2691 }
2692 }
2693 /*
2694 Open image file.
2695 */
2696 *filename='\0';
2697 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2698 rights=ReadPolicyRights;
2699 if (*type == 'w')
2700 rights=WritePolicyRights;
2701 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2702 {
2703 errno=EPERM;
2704 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2705 "NotAuthorized","`%s'",filename);
2706 return(MagickFalse);
2707 }
2708 if ((LocaleCompare(filename,"-") == 0) ||
2709 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2710 {
2711 blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
2712#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2713 if (strchr(type,'b') != (char *) NULL)
2714 (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
2715#endif
2716 blob_info->type=StandardStream;
2717 blob_info->exempt=MagickTrue;
2718 return(SetStreamBuffering(image_info,image));
2719 }
2720 if ((LocaleNCompare(filename,"fd:",3) == 0) &&
2721 (IsGeometry(filename+3) != MagickFalse))
2722 {
2723 char
2724 fileMode[MagickPathExtent];
2725
2726 *fileMode=(*type);
2727 fileMode[1]='\0';
2728 blob_info->file_info.file=fdopen(StringToLong(filename+3),fileMode);
2729 if (blob_info->file_info.file == (FILE *) NULL)
2730 {
2731 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2732 return(MagickFalse);
2733 }
2734#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2735 if (strchr(type,'b') != (char *) NULL)
2736 (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
2737#endif
2738 blob_info->type=FileStream;
2739 blob_info->exempt=MagickTrue;
2740 return(SetStreamBuffering(image_info,image));
2741 }
2742#if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
2743 if (*filename == '|')
2744 {
2745 char
2746 fileMode[MagickPathExtent],
2747 *sanitize_command;
2748
2749 /*
2750 Pipe image to or from a system command.
2751 */
2752#if defined(SIGPIPE)
2753 if (*type == 'w')
2754 (void) signal(SIGPIPE,SIG_IGN);
2755#endif
2756 *fileMode=(*type);
2757 fileMode[1]='\0';
2758 sanitize_command=SanitizeString(filename+1);
2759 blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,
2760 fileMode);
2761 sanitize_command=DestroyString(sanitize_command);
2762 if (blob_info->file_info.file == (FILE *) NULL)
2763 {
2764 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2765 return(MagickFalse);
2766 }
2767 blob_info->type=PipeStream;
2768 blob_info->exempt=MagickTrue;
2769 return(SetStreamBuffering(image_info,image));
2770 }
2771#endif
2772 status=GetPathAttributes(filename,&blob_info->properties);
2773#if defined(S_ISFIFO)
2774 if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
2775 {
2776 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
2777 if (blob_info->file_info.file == (FILE *) NULL)
2778 {
2779 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2780 return(MagickFalse);
2781 }
2782 blob_info->type=FileStream;
2783 blob_info->exempt=MagickTrue;
2784 return(SetStreamBuffering(image_info,image));
2785 }
2786#endif
2787 GetPathComponent(image->filename,ExtensionPath,extension);
2788 if (*type == 'w')
2789 {
2790 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2791 if ((image_info->adjoin == MagickFalse) ||
2792 (strchr(filename,'%') != (char *) NULL))
2793 {
2794 /*
2795 Form filename for multi-part images.
2796 */
2797 (void) InterpretImageFilename(image_info,image,image->filename,(int)
2798 image->scene,filename);
2799 if ((LocaleCompare(filename,image->filename) == 0) &&
2800 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2801 (GetNextImageInList(image) != (Image *) NULL)))
2802 {
2803 char
2804 path[MagickPathExtent];
2805
2806 GetPathComponent(image->filename,RootPath,path);
2807 if (*extension == '\0')
2808 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
2809 path,(double) image->scene);
2810 else
2811 (void) FormatLocaleString(filename,MagickPathExtent,
2812 "%s-%.20g.%s",path,(double) image->scene,extension);
2813 }
2814 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2815#if defined(macintosh)
2816 SetApplicationType(filename,image_info->magick,'8BIM');
2817#endif
2818 }
2819 }
2820 if (image_info->file != (FILE *) NULL)
2821 {
2822 blob_info->file_info.file=image_info->file;
2823 blob_info->type=FileStream;
2824 blob_info->exempt=MagickTrue;
2825 }
2826 else
2827 if (*type == 'r')
2828 {
2829 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
2830 if (blob_info->file_info.file != (FILE *) NULL)
2831 {
2832 size_t
2833 count;
2834
2835 unsigned char
2836 magick[3];
2837
2838 blob_info->type=FileStream;
2839 (void) fstat(fileno(blob_info->file_info.file),
2840 &blob_info->properties);
2841 (void) SetStreamBuffering(image_info,image);
2842 (void) memset(magick,0,sizeof(magick));
2843 count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
2844 (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
2845#if defined(MAGICKCORE_POSIX_SUPPORT)
2846 (void) fflush(blob_info->file_info.file);
2847#endif
2848 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2849 " read %.20g magic header bytes",(double) count);
2850#if defined(MAGICKCORE_ZLIB_DELEGATE)
2851 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2852 ((int) magick[2] == 0x08))
2853 {
2854 gzFile
2855 gzfile = gzopen_utf8(filename,"rb");
2856
2857 if (gzfile != (gzFile) NULL)
2858 {
2859 if (blob_info->file_info.file != (FILE *) NULL)
2860 (void) fclose(blob_info->file_info.file);
2861 blob_info->file_info.file=(FILE *) NULL;
2862 blob_info->file_info.gzfile=gzfile;
2863 blob_info->type=ZipStream;
2864 }
2865 }
2866#endif
2867#if defined(MAGICKCORE_BZLIB_DELEGATE)
2868 if (strncmp((char *) magick,"BZh",3) == 0)
2869 {
2870 BZFILE
2871 *bzfile = BZ2_bzopen(filename,"r");
2872
2873 if (bzfile != (BZFILE *) NULL)
2874 {
2875 if (blob_info->file_info.file != (FILE *) NULL)
2876 (void) fclose(blob_info->file_info.file);
2877 blob_info->file_info.file=(FILE *) NULL;
2878 blob_info->file_info.bzfile=bzfile;
2879 blob_info->type=BZipStream;
2880 }
2881 }
2882#endif
2883 if (blob_info->type == FileStream)
2884 {
2885 const MagickInfo
2886 *magick_info;
2887
2889 *sans_exception;
2890
2891 size_t
2892 length;
2893
2894 sans_exception=AcquireExceptionInfo();
2895 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2896 sans_exception=DestroyExceptionInfo(sans_exception);
2897 length=(size_t) blob_info->properties.st_size;
2898 if ((magick_info != (const MagickInfo *) NULL) &&
2899 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2900 (length > MagickMaxBufferExtent) &&
2901 (AcquireMagickResource(MapResource,length) != MagickFalse))
2902 {
2903 void
2904 *blob;
2905
2906 blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
2907 length);
2908 if (blob == (void *) NULL)
2909 RelinquishMagickResource(MapResource,length);
2910 else
2911 {
2912 /*
2913 Format supports blobs-- use memory-mapped I/O.
2914 */
2915 if (image_info->file != (FILE *) NULL)
2916 blob_info->exempt=MagickFalse;
2917 else
2918 {
2919 (void) fclose(blob_info->file_info.file);
2920 blob_info->file_info.file=(FILE *) NULL;
2921 }
2922 AttachBlob(blob_info,blob,length);
2923 blob_info->mapped=MagickTrue;
2924 }
2925 }
2926 }
2927 }
2928 }
2929 else
2930#if defined(MAGICKCORE_ZLIB_DELEGATE)
2931 if ((LocaleCompare(extension,"gz") == 0) ||
2932 (LocaleCompare(extension,"wmz") == 0) ||
2933 (LocaleCompare(extension,"svgz") == 0))
2934 {
2935 blob_info->file_info.gzfile=gzopen_utf8(filename,"wb");
2936 if (blob_info->file_info.gzfile != (gzFile) NULL)
2937 blob_info->type=ZipStream;
2938 }
2939 else
2940#endif
2941#if defined(MAGICKCORE_BZLIB_DELEGATE)
2942 if (LocaleCompare(extension,"bz2") == 0)
2943 {
2944 if (mode == WriteBinaryBlobMode)
2945 type="w";
2946 blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
2947 if (blob_info->file_info.bzfile != (BZFILE *) NULL)
2948 blob_info->type=BZipStream;
2949 }
2950 else
2951#endif
2952 {
2953 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
2954 if (blob_info->file_info.file != (FILE *) NULL)
2955 {
2956 blob_info->type=FileStream;
2957 (void) SetStreamBuffering(image_info,image);
2958 }
2959 }
2960 blob_info->status=MagickFalse;
2961 blob_info->error_number=0;
2962 if (blob_info->type != UndefinedStream)
2963 blob_info->size=GetBlobSize(image);
2964 else
2965 {
2966 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2967 return(MagickFalse);
2968 }
2969 return(MagickTrue);
2970}
2971␌
2972/*
2973%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2974% %
2975% %
2976% %
2977+ P i n g B l o b %
2978% %
2979% %
2980% %
2981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2982%
2983% PingBlob() returns all the attributes of an image or image sequence except
2984% for the pixels. It is much faster and consumes far less memory than
2985% BlobToImage(). On failure, a NULL image is returned and exception
2986% describes the reason for the failure.
2987%
2988% The format of the PingBlob method is:
2989%
2990% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2991% const size_t length,ExceptionInfo *exception)
2992%
2993% A description of each parameter follows:
2994%
2995% o image_info: the image info.
2996%
2997% o blob: the address of a character stream in one of the image formats
2998% understood by ImageMagick.
2999%
3000% o length: This size_t integer reflects the length in bytes of the blob.
3001%
3002% o exception: return any errors or warnings in this structure.
3003%
3004*/
3005
3006#if defined(__cplusplus) || defined(c_plusplus)
3007extern "C" {
3008#endif
3009
3010static size_t PingStream(const Image *magick_unused(image),
3011 const void *magick_unused(pixels),const size_t columns)
3012{
3013 magick_unreferenced(image);
3014 magick_unreferenced(pixels);
3015
3016 return(columns);
3017}
3018
3019#if defined(__cplusplus) || defined(c_plusplus)
3020}
3021#endif
3022
3023MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3024 const size_t length,ExceptionInfo *exception)
3025{
3026 const MagickInfo
3027 *magick_info;
3028
3029 Image
3030 *image;
3031
3032 ImageInfo
3033 *clone_info,
3034 *ping_info;
3035
3036 MagickBooleanType
3037 status;
3038
3039 assert(image_info != (ImageInfo *) NULL);
3040 assert(image_info->signature == MagickCoreSignature);
3041 assert(exception != (ExceptionInfo *) NULL);
3042 if (IsEventLogging() != MagickFalse)
3043 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3044 image_info->filename);
3045 if ((blob == (const void *) NULL) || (length == 0))
3046 {
3047 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3048 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
3049 return((Image *) NULL);
3050 }
3051 ping_info=CloneImageInfo(image_info);
3052 ping_info->blob=(void *) blob;
3053 ping_info->length=length;
3054 ping_info->ping=MagickTrue;
3055 if (*ping_info->magick == '\0')
3056 (void) SetImageInfo(ping_info,0,exception);
3057 magick_info=GetMagickInfo(ping_info->magick,exception);
3058 if (magick_info == (const MagickInfo *) NULL)
3059 {
3060 (void) ThrowMagickException(exception,GetMagickModule(),
3061 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
3062 ping_info->magick);
3063 ping_info=DestroyImageInfo(ping_info);
3064 return((Image *) NULL);
3065 }
3066 if (GetMagickBlobSupport(magick_info) != MagickFalse)
3067 {
3068 char
3069 filename[MagickPathExtent];
3070
3071 /*
3072 Native blob support for this image format.
3073 */
3074 (void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
3075 (void) FormatLocaleString(ping_info->filename,MagickPathExtent,"%s:%s",
3076 ping_info->magick,filename);
3077 image=ReadStream(ping_info,&PingStream,exception);
3078 if (image != (Image *) NULL)
3079 (void) DetachBlob(image->blob);
3080 ping_info=DestroyImageInfo(ping_info);
3081 return(image);
3082 }
3083 /*
3084 Write blob to a temporary file on disk.
3085 */
3086 ping_info->blob=(void *) NULL;
3087 ping_info->length=0;
3088 *ping_info->filename='\0';
3089 status=BlobToFile(ping_info->filename,blob,length,exception);
3090 if (status == MagickFalse)
3091 {
3092 (void) RelinquishUniqueFileResource(ping_info->filename);
3093 ping_info=DestroyImageInfo(ping_info);
3094 return((Image *) NULL);
3095 }
3096 clone_info=CloneImageInfo(ping_info);
3097 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
3098 ping_info->magick,ping_info->filename);
3099 image=ReadStream(clone_info,&PingStream,exception);
3100 if (image != (Image *) NULL)
3101 {
3102 Image
3103 *images;
3104
3105 /*
3106 Restore original filenames and image format.
3107 */
3108 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
3109 {
3110 (void) CopyMagickString(images->filename,image_info->filename,
3111 MagickPathExtent);
3112 (void) CopyMagickString(images->magick_filename,image_info->filename,
3113 MagickPathExtent);
3114 (void) CopyMagickString(images->magick,magick_info->name,
3115 MagickPathExtent);
3116 images=GetNextImageInList(images);
3117 }
3118 }
3119 clone_info=DestroyImageInfo(clone_info);
3120 (void) RelinquishUniqueFileResource(ping_info->filename);
3121 ping_info=DestroyImageInfo(ping_info);
3122 return(image);
3123}
3124␌
3125/*
3126%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3127% %
3128% %
3129% %
3130+ R e a d B l o b %
3131% %
3132% %
3133% %
3134%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3135%
3136% ReadBlob() reads data from the blob or image file and returns it. It
3137% returns the number of bytes read. If length is zero, ReadBlob() returns
3138% zero and has no other results. If length is greater than MAGICK_SSIZE_MAX, the
3139% result is unspecified.
3140%
3141% The format of the ReadBlob method is:
3142%
3143% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
3144%
3145% A description of each parameter follows:
3146%
3147% o image: the image.
3148%
3149% o length: Specifies an integer representing the number of bytes to read
3150% from the file.
3151%
3152% o data: Specifies an area to place the information requested from the
3153% file.
3154%
3155*/
3156MagickExport ssize_t ReadBlob(Image *image,const size_t length,
3157 unsigned char *data)
3158{
3159 BlobInfo
3160 *magick_restrict blob_info;
3161
3162 int
3163 c;
3164
3165 unsigned char
3166 *q;
3167
3168 ssize_t
3169 count;
3170
3171 assert(image != (Image *) NULL);
3172 assert(image->signature == MagickCoreSignature);
3173 assert(image->blob != (BlobInfo *) NULL);
3174 assert(image->blob->type != UndefinedStream);
3175 if (length == 0)
3176 return(0);
3177 assert(data != (void *) NULL);
3178 blob_info=image->blob;
3179 count=0;
3180 q=data;
3181 switch (blob_info->type)
3182 {
3183 case UndefinedStream:
3184 break;
3185 case StandardStream:
3186 case FileStream:
3187 case PipeStream:
3188 {
3189 switch (length)
3190 {
3191 default:
3192 {
3193 count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
3194 break;
3195 }
3196 case 4:
3197 {
3198 c=getc(blob_info->file_info.file);
3199 if (c == EOF)
3200 break;
3201 *q++=(unsigned char) c;
3202 count++;
3203 magick_fallthrough;
3204 }
3205 case 3:
3206 {
3207 c=getc(blob_info->file_info.file);
3208 if (c == EOF)
3209 break;
3210 *q++=(unsigned char) c;
3211 count++;
3212 magick_fallthrough;
3213 }
3214 case 2:
3215 {
3216 c=getc(blob_info->file_info.file);
3217 if (c == EOF)
3218 break;
3219 *q++=(unsigned char) c;
3220 count++;
3221 magick_fallthrough;
3222 }
3223 case 1:
3224 {
3225 c=getc(blob_info->file_info.file);
3226 if (c == EOF)
3227 break;
3228 *q++=(unsigned char) c;
3229 count++;
3230 magick_fallthrough;
3231 }
3232 case 0:
3233 break;
3234 }
3235 if ((count != (ssize_t) length) &&
3236 (ferror(blob_info->file_info.file) != 0))
3237 ThrowBlobException(blob_info);
3238 break;
3239 }
3240 case ZipStream:
3241 {
3242#if defined(MAGICKCORE_ZLIB_DELEGATE)
3243 int
3244 status;
3245
3246 switch (length)
3247 {
3248 default:
3249 {
3250 ssize_t
3251 i;
3252
3253 for (i=0; i < (ssize_t) length; i+=count)
3254 {
3255 count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
3256 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3257 if (count <= 0)
3258 {
3259 count=0;
3260 if (errno != EINTR)
3261 break;
3262 }
3263 }
3264 count=i;
3265 break;
3266 }
3267 case 4:
3268 {
3269 c=gzgetc(blob_info->file_info.gzfile);
3270 if (c == EOF)
3271 break;
3272 *q++=(unsigned char) c;
3273 count++;
3274 magick_fallthrough;
3275 }
3276 case 3:
3277 {
3278 c=gzgetc(blob_info->file_info.gzfile);
3279 if (c == EOF)
3280 break;
3281 *q++=(unsigned char) c;
3282 count++;
3283 magick_fallthrough;
3284 }
3285 case 2:
3286 {
3287 c=gzgetc(blob_info->file_info.gzfile);
3288 if (c == EOF)
3289 break;
3290 *q++=(unsigned char) c;
3291 count++;
3292 magick_fallthrough;
3293 }
3294 case 1:
3295 {
3296 c=gzgetc(blob_info->file_info.gzfile);
3297 if (c == EOF)
3298 break;
3299 *q++=(unsigned char) c;
3300 count++;
3301 magick_fallthrough;
3302 }
3303 case 0:
3304 break;
3305 }
3306 status=Z_OK;
3307 (void) gzerror(blob_info->file_info.gzfile,&status);
3308 if ((count != (ssize_t) length) && (status != Z_OK))
3309 ThrowBlobException(blob_info);
3310 if (blob_info->eof == MagickFalse)
3311 blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
3312 MagickFalse;
3313#endif
3314 break;
3315 }
3316 case BZipStream:
3317 {
3318#if defined(MAGICKCORE_BZLIB_DELEGATE)
3319 int
3320 status;
3321
3322 ssize_t
3323 i;
3324
3325 for (i=0; i < (ssize_t) length; i+=count)
3326 {
3327 count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,
3328 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3329 if (count <= 0)
3330 {
3331 count=0;
3332 if (errno != EINTR)
3333 break;
3334 }
3335 }
3336 count=i;
3337 status=BZ_OK;
3338 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
3339 if ((count != (ssize_t) length) && (status != BZ_OK))
3340 ThrowBlobException(blob_info);
3341#endif
3342 break;
3343 }
3344 case FifoStream:
3345 break;
3346 case BlobStream:
3347 {
3348 const unsigned char
3349 *p;
3350
3351 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
3352 {
3353 blob_info->eof=MagickTrue;
3354 break;
3355 }
3356 p=blob_info->data+blob_info->offset;
3357 count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
3358 blob_info->length-blob_info->offset);
3359 blob_info->offset+=count;
3360 if (count != (ssize_t) length)
3361 blob_info->eof=MagickTrue;
3362 (void) memcpy(q,p,(size_t) count);
3363 break;
3364 }
3365 }
3366 return(count);
3367}
3368␌
3369/*
3370%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3371% %
3372% %
3373% %
3374+ R e a d B l o b B y t e %
3375% %
3376% %
3377% %
3378%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3379%
3380% ReadBlobByte() reads a single byte from the image file and returns it.
3381%
3382% The format of the ReadBlobByte method is:
3383%
3384% int ReadBlobByte(Image *image)
3385%
3386% A description of each parameter follows.
3387%
3388% o image: the image.
3389%
3390*/
3391MagickExport int ReadBlobByte(Image *image)
3392{
3393 BlobInfo
3394 *magick_restrict blob_info;
3395
3396 int
3397 c;
3398
3399 assert(image != (Image *) NULL);
3400 assert(image->signature == MagickCoreSignature);
3401 assert(image->blob != (BlobInfo *) NULL);
3402 assert(image->blob->type != UndefinedStream);
3403 blob_info=image->blob;
3404 switch (blob_info->type)
3405 {
3406 case StandardStream:
3407 case FileStream:
3408 case PipeStream:
3409 {
3410 c=getc(blob_info->file_info.file);
3411 if (c == EOF)
3412 {
3413 if (ferror(blob_info->file_info.file) != 0)
3414 ThrowBlobException(blob_info);
3415 return(EOF);
3416 }
3417 break;
3418 }
3419 case BlobStream:
3420 {
3421 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
3422 {
3423 blob_info->eof=MagickTrue;
3424 return(EOF);
3425 }
3426 c=(int) (*((unsigned char *) blob_info->data+blob_info->offset));
3427 blob_info->offset++;
3428 break;
3429 }
3430 default:
3431 {
3432 ssize_t
3433 count;
3434
3435 unsigned char
3436 buffer[1];
3437
3438 count=ReadBlob(image,1,buffer);
3439 if (count != 1)
3440 return(EOF);
3441 c=(int) *buffer;
3442 break;
3443 }
3444 }
3445 return(c);
3446}
3447␌
3448/*
3449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3450% %
3451% %
3452% %
3453+ R e a d B l o b D o u b l e %
3454% %
3455% %
3456% %
3457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3458%
3459% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3460% specified by the endian member of the image structure.
3461%
3462% The format of the ReadBlobDouble method is:
3463%
3464% double ReadBlobDouble(Image *image)
3465%
3466% A description of each parameter follows.
3467%
3468% o image: the image.
3469%
3470*/
3471MagickExport double ReadBlobDouble(Image *image)
3472{
3473 union
3474 {
3475 MagickSizeType
3476 unsigned_value;
3477
3478 double
3479 double_value;
3480 } quantum;
3481
3482 quantum.double_value=0.0;
3483 quantum.unsigned_value=ReadBlobLongLong(image);
3484 return(quantum.double_value);
3485}
3486␌
3487/*
3488%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3489% %
3490% %
3491% %
3492+ R e a d B l o b F l o a t %
3493% %
3494% %
3495% %
3496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3497%
3498% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3499% specified by the endian member of the image structure.
3500%
3501% The format of the ReadBlobFloat method is:
3502%
3503% float ReadBlobFloat(Image *image)
3504%
3505% A description of each parameter follows.
3506%
3507% o image: the image.
3508%
3509*/
3510MagickExport float ReadBlobFloat(Image *image)
3511{
3512 union
3513 {
3514 unsigned int
3515 unsigned_value;
3516
3517 float
3518 float_value;
3519 } quantum;
3520
3521 quantum.float_value=0.0;
3522 quantum.unsigned_value=ReadBlobLong(image);
3523 return(quantum.float_value);
3524}
3525␌
3526/*
3527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3528% %
3529% %
3530% %
3531+ R e a d B l o b L o n g %
3532% %
3533% %
3534% %
3535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3536%
3537% ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
3538% byte-order specified by the endian member of the image structure.
3539%
3540% The format of the ReadBlobLong method is:
3541%
3542% unsigned int ReadBlobLong(Image *image)
3543%
3544% A description of each parameter follows.
3545%
3546% o image: the image.
3547%
3548*/
3549MagickExport unsigned int ReadBlobLong(Image *image)
3550{
3551 const unsigned char
3552 *p;
3553
3554 ssize_t
3555 count;
3556
3557 unsigned char
3558 buffer[4];
3559
3560 unsigned int
3561 value;
3562
3563 assert(image != (Image *) NULL);
3564 assert(image->signature == MagickCoreSignature);
3565 *buffer='\0';
3566 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3567 if (count != 4)
3568 return(0UL);
3569 if (image->endian == LSBEndian)
3570 {
3571 value=(unsigned int) (*p++);
3572 value|=(unsigned int) (*p++) << 8;
3573 value|=(unsigned int) (*p++) << 16;
3574 value|=(unsigned int) (*p++) << 24;
3575 return(value);
3576 }
3577 value=(unsigned int) (*p++) << 24;
3578 value|=(unsigned int) (*p++) << 16;
3579 value|=(unsigned int) (*p++) << 8;
3580 value|=(unsigned int) (*p++);
3581 return(value);
3582}
3583␌
3584/*
3585%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3586% %
3587% %
3588% %
3589+ R e a d B l o b L o n g L o n g %
3590% %
3591% %
3592% %
3593%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3594%
3595% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3596% byte-order specified by the endian member of the image structure.
3597%
3598% The format of the ReadBlobLongLong method is:
3599%
3600% MagickSizeType ReadBlobLongLong(Image *image)
3601%
3602% A description of each parameter follows.
3603%
3604% o image: the image.
3605%
3606*/
3607MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3608{
3609 MagickSizeType
3610 value;
3611
3612 const unsigned char
3613 *p;
3614
3615 ssize_t
3616 count;
3617
3618 unsigned char
3619 buffer[8];
3620
3621 assert(image != (Image *) NULL);
3622 assert(image->signature == MagickCoreSignature);
3623 *buffer='\0';
3624 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3625 if (count != 8)
3626 return(MagickULLConstant(0));
3627 if (image->endian == LSBEndian)
3628 {
3629 value=(MagickSizeType) (*p++);
3630 value|=(MagickSizeType) (*p++) << 8;
3631 value|=(MagickSizeType) (*p++) << 16;
3632 value|=(MagickSizeType) (*p++) << 24;
3633 value|=(MagickSizeType) (*p++) << 32;
3634 value|=(MagickSizeType) (*p++) << 40;
3635 value|=(MagickSizeType) (*p++) << 48;
3636 value|=(MagickSizeType) (*p++) << 56;
3637 return(value);
3638 }
3639 value=(MagickSizeType) (*p++) << 56;
3640 value|=(MagickSizeType) (*p++) << 48;
3641 value|=(MagickSizeType) (*p++) << 40;
3642 value|=(MagickSizeType) (*p++) << 32;
3643 value|=(MagickSizeType) (*p++) << 24;
3644 value|=(MagickSizeType) (*p++) << 16;
3645 value|=(MagickSizeType) (*p++) << 8;
3646 value|=(MagickSizeType) (*p++);
3647 return(value);
3648}
3649␌
3650/*
3651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3652% %
3653% %
3654% %
3655+ R e a d B l o b S h o r t %
3656% %
3657% %
3658% %
3659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3660%
3661% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3662% specified by the endian member of the image structure.
3663%
3664% The format of the ReadBlobShort method is:
3665%
3666% unsigned short ReadBlobShort(Image *image)
3667%
3668% A description of each parameter follows.
3669%
3670% o image: the image.
3671%
3672*/
3673MagickExport unsigned short ReadBlobShort(Image *image)
3674{
3675 const unsigned char
3676 *p;
3677
3678 unsigned short
3679 value;
3680
3681 ssize_t
3682 count;
3683
3684 unsigned char
3685 buffer[2];
3686
3687 assert(image != (Image *) NULL);
3688 assert(image->signature == MagickCoreSignature);
3689 *buffer='\0';
3690 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3691 if (count != 2)
3692 return((unsigned short) 0U);
3693 if (image->endian == LSBEndian)
3694 {
3695 value=(unsigned short) (*p++);
3696 value|=(unsigned short) (*p++) << 8;
3697 return(value);
3698 }
3699 value=(unsigned short) ((unsigned short) (*p++) << 8);
3700 value|=(unsigned short) (*p++);
3701 return(value);
3702}
3703␌
3704/*
3705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3706% %
3707% %
3708% %
3709+ R e a d B l o b L S B L o n g %
3710% %
3711% %
3712% %
3713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3714%
3715% ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
3716% least-significant byte first order.
3717%
3718% The format of the ReadBlobLSBLong method is:
3719%
3720% unsigned int ReadBlobLSBLong(Image *image)
3721%
3722% A description of each parameter follows.
3723%
3724% o image: the image.
3725%
3726*/
3727MagickExport unsigned int ReadBlobLSBLong(Image *image)
3728{
3729 const unsigned char
3730 *p;
3731
3732 unsigned int
3733 value;
3734
3735 ssize_t
3736 count;
3737
3738 unsigned char
3739 buffer[4];
3740
3741 assert(image != (Image *) NULL);
3742 assert(image->signature == MagickCoreSignature);
3743 *buffer='\0';
3744 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3745 if (count != 4)
3746 return(0U);
3747 value=(unsigned int) (*p++);
3748 value|=(unsigned int) (*p++) << 8;
3749 value|=(unsigned int) (*p++) << 16;
3750 value|=(unsigned int) (*p++) << 24;
3751 return(value);
3752}
3753␌
3754/*
3755%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3756% %
3757% %
3758% %
3759+ R e a d B l o b L S B S i g n e d L o n g %
3760% %
3761% %
3762% %
3763%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3764%
3765% ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
3766% least-significant byte first order.
3767%
3768% The format of the ReadBlobLSBSignedLong method is:
3769%
3770% signed int ReadBlobLSBSignedLong(Image *image)
3771%
3772% A description of each parameter follows.
3773%
3774% o image: the image.
3775%
3776*/
3777MagickExport signed int ReadBlobLSBSignedLong(Image *image)
3778{
3779 union
3780 {
3781 unsigned int
3782 unsigned_value;
3783
3784 signed int
3785 signed_value;
3786 } quantum;
3787
3788 quantum.unsigned_value=ReadBlobLSBLong(image);
3789 return(quantum.signed_value);
3790}
3791␌
3792/*
3793%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3794% %
3795% %
3796% %
3797+ R e a d B l o b L S B S h o r t %
3798% %
3799% %
3800% %
3801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3802%
3803% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3804% least-significant byte first order.
3805%
3806% The format of the ReadBlobLSBShort method is:
3807%
3808% unsigned short ReadBlobLSBShort(Image *image)
3809%
3810% A description of each parameter follows.
3811%
3812% o image: the image.
3813%
3814*/
3815MagickExport unsigned short ReadBlobLSBShort(Image *image)
3816{
3817 const unsigned char
3818 *p;
3819
3820 unsigned short
3821 value;
3822
3823 ssize_t
3824 count;
3825
3826 unsigned char
3827 buffer[2];
3828
3829 assert(image != (Image *) NULL);
3830 assert(image->signature == MagickCoreSignature);
3831 *buffer='\0';
3832 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3833 if (count != 2)
3834 return((unsigned short) 0U);
3835 value=(unsigned short) (*p++);
3836 value|=(unsigned short) (*p++) << 8;
3837 return(value);
3838}
3839␌
3840/*
3841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3842% %
3843% %
3844% %
3845+ R e a d B l o b L S B S i g n e d S h o r t %
3846% %
3847% %
3848% %
3849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3850%
3851% ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
3852% least-significant byte-order.
3853%
3854% The format of the ReadBlobLSBSignedShort method is:
3855%
3856% signed short ReadBlobLSBSignedShort(Image *image)
3857%
3858% A description of each parameter follows.
3859%
3860% o image: the image.
3861%
3862*/
3863MagickExport signed short ReadBlobLSBSignedShort(Image *image)
3864{
3865 union
3866 {
3867 unsigned short
3868 unsigned_value;
3869
3870 signed short
3871 signed_value;
3872 } quantum;
3873
3874 quantum.unsigned_value=ReadBlobLSBShort(image);
3875 return(quantum.signed_value);
3876}
3877␌
3878/*
3879%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3880% %
3881% %
3882% %
3883+ R e a d B l o b M S B L o n g %
3884% %
3885% %
3886% %
3887%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3888%
3889% ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
3890% most-significant byte first order.
3891%
3892% The format of the ReadBlobMSBLong method is:
3893%
3894% unsigned int ReadBlobMSBLong(Image *image)
3895%
3896% A description of each parameter follows.
3897%
3898% o image: the image.
3899%
3900*/
3901MagickExport unsigned int ReadBlobMSBLong(Image *image)
3902{
3903 const unsigned char
3904 *p;
3905
3906 unsigned int
3907 value;
3908
3909 ssize_t
3910 count;
3911
3912 unsigned char
3913 buffer[4];
3914
3915 assert(image != (Image *) NULL);
3916 assert(image->signature == MagickCoreSignature);
3917 *buffer='\0';
3918 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3919 if (count != 4)
3920 return(0UL);
3921 value=(unsigned int) (*p++) << 24;
3922 value|=(unsigned int) (*p++) << 16;
3923 value|=(unsigned int) (*p++) << 8;
3924 value|=(unsigned int) (*p++);
3925 return(value);
3926}
3927␌
3928/*
3929%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3930% %
3931% %
3932% %
3933+ R e a d B l o b M S B L o n g L o n g %
3934% %
3935% %
3936% %
3937%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3938%
3939% ReadBlobMSBLongLong() reads a unsigned long int value as a 64-bit quantity
3940% in most-significant byte first order.
3941%
3942% The format of the ReadBlobMSBLongLong method is:
3943%
3944% unsigned int ReadBlobMSBLongLong(Image *image)
3945%
3946% A description of each parameter follows.
3947%
3948% o image: the image.
3949%
3950*/
3951MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3952{
3953 const unsigned char
3954 *p;
3955
3956 MagickSizeType
3957 value;
3958
3959 ssize_t
3960 count;
3961
3962 unsigned char
3963 buffer[8];
3964
3965 assert(image != (Image *) NULL);
3966 assert(image->signature == MagickCoreSignature);
3967 *buffer='\0';
3968 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3969 if (count != 8)
3970 return(MagickULLConstant(0));
3971 value=(MagickSizeType) (*p++) << 56;
3972 value|=(MagickSizeType) (*p++) << 48;
3973 value|=(MagickSizeType) (*p++) << 40;
3974 value|=(MagickSizeType) (*p++) << 32;
3975 value|=(MagickSizeType) (*p++) << 24;
3976 value|=(MagickSizeType) (*p++) << 16;
3977 value|=(MagickSizeType) (*p++) << 8;
3978 value|=(MagickSizeType) (*p++);
3979 return(value);
3980}
3981␌
3982/*
3983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3984% %
3985% %
3986% %
3987+ R e a d B l o b M S B S h o r t %
3988% %
3989% %
3990% %
3991%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3992%
3993% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3994% most-significant byte first order.
3995%
3996% The format of the ReadBlobMSBShort method is:
3997%
3998% unsigned short ReadBlobMSBShort(Image *image)
3999%
4000% A description of each parameter follows.
4001%
4002% o image: the image.
4003%
4004*/
4005MagickExport unsigned short ReadBlobMSBShort(Image *image)
4006{
4007 const unsigned char
4008 *p;
4009
4010 unsigned short
4011 value;
4012
4013 ssize_t
4014 count;
4015
4016 unsigned char
4017 buffer[2];
4018
4019 assert(image != (Image *) NULL);
4020 assert(image->signature == MagickCoreSignature);
4021 *buffer='\0';
4022 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4023 if (count != 2)
4024 return((unsigned short) 0U);
4025 value=(unsigned short) ((*p++) << 8);
4026 value|=(unsigned short) (*p++);
4027 return(value);
4028}
4029␌
4030/*
4031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4032% %
4033% %
4034% %
4035+ R e a d B l o b M S B S i g n e d L o n g %
4036% %
4037% %
4038% %
4039%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4040%
4041% ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4042% most-significant byte-order.
4043%
4044% The format of the ReadBlobMSBSignedLong method is:
4045%
4046% signed int ReadBlobMSBSignedLong(Image *image)
4047%
4048% A description of each parameter follows.
4049%
4050% o image: the image.
4051%
4052*/
4053MagickExport signed int ReadBlobMSBSignedLong(Image *image)
4054{
4055 union
4056 {
4057 unsigned int
4058 unsigned_value;
4059
4060 signed int
4061 signed_value;
4062 } quantum;
4063
4064 quantum.unsigned_value=ReadBlobMSBLong(image);
4065 return(quantum.signed_value);
4066}
4067␌
4068/*
4069%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4070% %
4071% %
4072% %
4073+ R e a d B l o b M S B S i g n e d S h o r t %
4074% %
4075% %
4076% %
4077%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4078%
4079% ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4080% most-significant byte-order.
4081%
4082% The format of the ReadBlobMSBSignedShort method is:
4083%
4084% signed short ReadBlobMSBSignedShort(Image *image)
4085%
4086% A description of each parameter follows.
4087%
4088% o image: the image.
4089%
4090*/
4091MagickExport signed short ReadBlobMSBSignedShort(Image *image)
4092{
4093 union
4094 {
4095 unsigned short
4096 unsigned_value;
4097
4098 signed short
4099 signed_value;
4100 } quantum;
4101
4102 quantum.unsigned_value=ReadBlobMSBShort(image);
4103 return(quantum.signed_value);
4104}
4105␌
4106/*
4107%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4108% %
4109% %
4110% %
4111+ R e a d B l o b S i g n e d L o n g %
4112% %
4113% %
4114% %
4115%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4116%
4117% ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4118% byte-order specified by the endian member of the image structure.
4119%
4120% The format of the ReadBlobSignedLong method is:
4121%
4122% signed int ReadBlobSignedLong(Image *image)
4123%
4124% A description of each parameter follows.
4125%
4126% o image: the image.
4127%
4128*/
4129MagickExport signed int ReadBlobSignedLong(Image *image)
4130{
4131 union
4132 {
4133 unsigned int
4134 unsigned_value;
4135
4136 signed int
4137 signed_value;
4138 } quantum;
4139
4140 quantum.unsigned_value=ReadBlobLong(image);
4141 return(quantum.signed_value);
4142}
4143␌
4144/*
4145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4146% %
4147% %
4148% %
4149+ R e a d B l o b S i g n e d S h o r t %
4150% %
4151% %
4152% %
4153%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4154%
4155% ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4156% byte-order specified by the endian member of the image structure.
4157%
4158% The format of the ReadBlobSignedShort method is:
4159%
4160% signed short ReadBlobSignedShort(Image *image)
4161%
4162% A description of each parameter follows.
4163%
4164% o image: the image.
4165%
4166*/
4167MagickExport signed short ReadBlobSignedShort(Image *image)
4168{
4169 union
4170 {
4171 unsigned short
4172 unsigned_value;
4173
4174 signed short
4175 signed_value;
4176 } quantum;
4177
4178 quantum.unsigned_value=ReadBlobShort(image);
4179 return(quantum.signed_value);
4180}
4181␌
4182/*
4183%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4184% %
4185% %
4186% %
4187+ R e a d B l o b S t r e a m %
4188% %
4189% %
4190% %
4191%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4192%
4193% ReadBlobStream() reads data from the blob or image file and returns it. It
4194% returns a pointer to the data buffer you supply or to the image memory
4195% buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4196% returns a count of zero and has no other results. If length is greater than
4197% MAGICK_SSIZE_MAX, the result is unspecified.
4198%
4199% The format of the ReadBlobStream method is:
4200%
4201% const void *ReadBlobStream(Image *image,const size_t length,
4202% void *magick_restrict data,ssize_t *count)
4203%
4204% A description of each parameter follows:
4205%
4206% o image: the image.
4207%
4208% o length: Specifies an integer representing the number of bytes to read
4209% from the file.
4210%
4211% o count: returns the number of bytes read.
4212%
4213% o data: Specifies an area to place the information requested from the
4214% file.
4215%
4216*/
4217MagickExport magick_hot_spot const void *ReadBlobStream(Image *image,
4218 const size_t length,void *magick_restrict data,ssize_t *count)
4219{
4220 BlobInfo
4221 *magick_restrict blob_info;
4222
4223 assert(image != (Image *) NULL);
4224 assert(image->signature == MagickCoreSignature);
4225 assert(image->blob != (BlobInfo *) NULL);
4226 assert(image->blob->type != UndefinedStream);
4227 assert(count != (ssize_t *) NULL);
4228 blob_info=image->blob;
4229 if (blob_info->type != BlobStream)
4230 {
4231 assert(data != NULL);
4232 *count=ReadBlob(image,length,(unsigned char *) data);
4233 return(data);
4234 }
4235 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4236 {
4237 *count=0;
4238 blob_info->eof=MagickTrue;
4239 return(data);
4240 }
4241 data=blob_info->data+blob_info->offset;
4242 *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4243 blob_info->length-blob_info->offset);
4244 blob_info->offset+=(*count);
4245 if (*count != (ssize_t) length)
4246 blob_info->eof=MagickTrue;
4247 return(data);
4248}
4249␌
4250/*
4251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4252% %
4253% %
4254% %
4255+ R e a d B l o b S t r i n g %
4256% %
4257% %
4258% %
4259%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4260%
4261% ReadBlobString() reads characters from a blob or file until a newline
4262% character is read or an end-of-file condition is encountered.
4263%
4264% The format of the ReadBlobString method is:
4265%
4266% char *ReadBlobString(Image *image,char *string)
4267%
4268% A description of each parameter follows:
4269%
4270% o image: the image.
4271%
4272% o string: the address of a character buffer.
4273%
4274*/
4275MagickExport char *ReadBlobString(Image *image,char *string)
4276{
4277 BlobInfo
4278 *magick_restrict blob_info;
4279
4280 int
4281 c = -1;
4282
4283 ssize_t
4284 i = 0;
4285
4286 assert(image != (Image *) NULL);
4287 assert(image->signature == MagickCoreSignature);
4288 assert(image->blob != (BlobInfo *) NULL);
4289 assert(image->blob->type != UndefinedStream);
4290 if (IsEventLogging() != MagickFalse)
4291 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4292 *string='\0';
4293 blob_info=image->blob;
4294 switch (blob_info->type)
4295 {
4296 case UndefinedStream:
4297 break;
4298 case StandardStream:
4299 case FileStream:
4300 {
4301 char *p = fgets(string,MagickPathExtent,blob_info->file_info.file);
4302 if (p == (char *) NULL)
4303 {
4304 if (ferror(blob_info->file_info.file) != 0)
4305 ThrowBlobException(blob_info);
4306 return((char *) NULL);
4307 }
4308 i=strlen(string);
4309 break;
4310 }
4311 case ZipStream:
4312 {
4313#if defined(MAGICKCORE_ZLIB_DELEGATE)
4314 char *p = gzgets(blob_info->file_info.gzfile,string,MagickPathExtent);
4315 if (p == (char *) NULL)
4316 {
4317 int status = Z_OK;
4318 (void) gzerror(blob_info->file_info.gzfile,&status);
4319 if (status != Z_OK)
4320 ThrowBlobException(blob_info);
4321 return((char *) NULL);
4322 }
4323 i=strlen(string);
4324 break;
4325#endif
4326 }
4327 default:
4328 {
4329 do
4330 {
4331 c=ReadBlobByte(image);
4332 if (c == EOF)
4333 {
4334 blob_info->eof=MagickTrue;
4335 break;
4336 }
4337 string[i++]=c;
4338 if (c == '\n')
4339 break;
4340 } while (i < (MaxTextExtent-2));
4341 string[i]='\0';
4342 break;
4343 }
4344 }
4345 /*
4346 Strip trailing newline.
4347 */
4348 if ((string[i] == '\r') || (string[i] == '\n'))
4349 string[i]='\0';
4350 if (i >= 1)
4351 if ((string[i-1] == '\r') || (string[i-1] == '\n'))
4352 string[i-1]='\0';
4353 if ((*string == '\0') && (blob_info->eof != MagickFalse))
4354 return((char *) NULL);
4355 return(string);
4356}
4357␌
4358/*
4359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4360% %
4361% %
4362% %
4363+ R e f e r e n c e B l o b %
4364% %
4365% %
4366% %
4367%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4368%
4369% ReferenceBlob() increments the reference count associated with the pixel
4370% blob returning a pointer to the blob.
4371%
4372% The format of the ReferenceBlob method is:
4373%
4374% BlobInfo ReferenceBlob(BlobInfo *blob_info)
4375%
4376% A description of each parameter follows:
4377%
4378% o blob_info: the blob_info.
4379%
4380*/
4381MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
4382{
4383 assert(blob != (BlobInfo *) NULL);
4384 assert(blob->signature == MagickCoreSignature);
4385 if (IsEventLogging() != MagickFalse)
4386 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4387 LockSemaphoreInfo(blob->semaphore);
4388 blob->reference_count++;
4389 UnlockSemaphoreInfo(blob->semaphore);
4390 return(blob);
4391}
4392␌
4393/*
4394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4395% %
4396% %
4397% %
4398+ S e e k B l o b %
4399% %
4400% %
4401% %
4402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4403%
4404% SeekBlob() sets the offset in bytes from the beginning of a blob or file
4405% and returns the resulting offset.
4406%
4407% The format of the SeekBlob method is:
4408%
4409% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
4410% const int whence)
4411%
4412% A description of each parameter follows:
4413%
4414% o image: the image.
4415%
4416% o offset: Specifies an integer representing the offset in bytes.
4417%
4418% o whence: Specifies an integer representing how the offset is
4419% treated relative to the beginning of the blob as follows:
4420%
4421% SEEK_SET Set position equal to offset bytes.
4422% SEEK_CUR Set position to current location plus offset.
4423% SEEK_END Set position to EOF plus offset.
4424%
4425*/
4426MagickExport MagickOffsetType SeekBlob(Image *image,
4427 const MagickOffsetType offset,const int whence)
4428{
4429 BlobInfo
4430 *magick_restrict blob_info;
4431
4432 assert(image != (Image *) NULL);
4433 assert(image->signature == MagickCoreSignature);
4434 assert(image->blob != (BlobInfo *) NULL);
4435 assert(image->blob->type != UndefinedStream);
4436 if (IsEventLogging() != MagickFalse)
4437 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4438 blob_info=image->blob;
4439 switch (blob_info->type)
4440 {
4441 case UndefinedStream:
4442 break;
4443 case StandardStream:
4444 case PipeStream:
4445 return(-1);
4446 case FileStream:
4447 {
4448 if ((offset < 0) && (whence == SEEK_SET))
4449 return(-1);
4450 if (fseek(blob_info->file_info.file,offset,whence) < 0)
4451 return(-1);
4452 blob_info->offset=TellBlob(image);
4453 break;
4454 }
4455 case ZipStream:
4456 {
4457#if defined(MAGICKCORE_ZLIB_DELEGATE)
4458 if (gzseek(blob_info->file_info.gzfile,offset,whence) < 0)
4459 return(-1);
4460#endif
4461 blob_info->offset=TellBlob(image);
4462 break;
4463 }
4464 case BZipStream:
4465 return(-1);
4466 case FifoStream:
4467 return(-1);
4468 case BlobStream:
4469 {
4470 switch (whence)
4471 {
4472 case SEEK_SET:
4473 default:
4474 {
4475 if (offset < 0)
4476 return(-1);
4477 blob_info->offset=offset;
4478 break;
4479 }
4480 case SEEK_CUR:
4481 {
4482 if (((offset > 0) && (blob_info->offset > (MAGICK_SSIZE_MAX-offset))) ||
4483 ((offset < 0) && (blob_info->offset < (MAGICK_SSIZE_MIN-offset))))
4484 {
4485 errno=EOVERFLOW;
4486 return(-1);
4487 }
4488 if ((blob_info->offset+offset) < 0)
4489 return(-1);
4490 blob_info->offset+=offset;
4491 break;
4492 }
4493 case SEEK_END:
4494 {
4495 if (((MagickOffsetType) blob_info->length+offset) < 0)
4496 return(-1);
4497 blob_info->offset=blob_info->length+offset;
4498 break;
4499 }
4500 }
4501 if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
4502 {
4503 blob_info->eof=MagickFalse;
4504 break;
4505 }
4506 if (blob_info->offset >= (MagickOffsetType) ((off_t) blob_info->extent))
4507 return(-1);
4508 break;
4509 }
4510 }
4511 return(blob_info->offset);
4512}
4513␌
4514/*
4515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4516% %
4517% %
4518% %
4519+ S e t B l o b E x e m p t %
4520% %
4521% %
4522% %
4523%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4524%
4525% SetBlobExempt() sets the blob exempt status.
4526%
4527% The format of the SetBlobExempt method is:
4528%
4529% MagickBooleanType SetBlobExempt(const Image *image,
4530% const MagickBooleanType exempt)
4531%
4532% A description of each parameter follows:
4533%
4534% o image: the image.
4535%
4536% o exempt: Set to true if this blob is exempt from being closed.
4537%
4538*/
4539MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
4540{
4541 assert(image != (const Image *) NULL);
4542 assert(image->signature == MagickCoreSignature);
4543 if (IsEventLogging() != MagickFalse)
4544 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4545 image->blob->exempt=exempt;
4546}
4547␌
4548/*
4549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4550% %
4551% %
4552% %
4553+ S e t B l o b E x t e n t %
4554% %
4555% %
4556% %
4557%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4558%
4559% SetBlobExtent() ensures enough space is allocated for the blob. If the
4560% method is successful, subsequent writes to bytes in the specified range are
4561% guaranteed not to fail.
4562%
4563% The format of the SetBlobExtent method is:
4564%
4565% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
4566%
4567% A description of each parameter follows:
4568%
4569% o image: the image.
4570%
4571% o extent: the blob maximum extent.
4572%
4573*/
4574MagickExport MagickBooleanType SetBlobExtent(Image *image,
4575 const MagickSizeType extent)
4576{
4577 BlobInfo
4578 *magick_restrict blob_info;
4579
4580 assert(image != (Image *) NULL);
4581 assert(image->signature == MagickCoreSignature);
4582 assert(image->blob != (BlobInfo *) NULL);
4583 assert(image->blob->type != UndefinedStream);
4584 if (IsEventLogging() != MagickFalse)
4585 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4586 blob_info=image->blob;
4587 switch (blob_info->type)
4588 {
4589 case UndefinedStream:
4590 break;
4591 case StandardStream:
4592 return(MagickFalse);
4593 case FileStream:
4594 {
4595 MagickOffsetType
4596 offset;
4597
4598 ssize_t
4599 count;
4600
4601 if (extent != (MagickSizeType) ((off_t) extent))
4602 return(MagickFalse);
4603 offset=SeekBlob(image,0,SEEK_END);
4604 if (offset < 0)
4605 return(MagickFalse);
4606 if ((MagickSizeType) offset >= extent)
4607 break;
4608 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4609 if (offset < 0)
4610 break;
4611 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4612 blob_info->file_info.file);
4613#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4614 if (blob_info->synchronize != MagickFalse)
4615 {
4616 int
4617 file;
4618
4619 file=fileno(blob_info->file_info.file);
4620 if ((file == -1) || (offset < 0))
4621 return(MagickFalse);
4622 (void) posix_fallocate(file,offset,extent-offset);
4623 }
4624#endif
4625 offset=SeekBlob(image,offset,SEEK_SET);
4626 if (count != 1)
4627 return(MagickFalse);
4628 break;
4629 }
4630 case PipeStream:
4631 case ZipStream:
4632 return(MagickFalse);
4633 case BZipStream:
4634 return(MagickFalse);
4635 case FifoStream:
4636 return(MagickFalse);
4637 case BlobStream:
4638 {
4639 if (extent != (MagickSizeType) ((size_t) extent))
4640 return(MagickFalse);
4641 if (blob_info->mapped != MagickFalse)
4642 {
4643 MagickOffsetType
4644 offset;
4645
4646 ssize_t
4647 count;
4648
4649 (void) UnmapBlob(blob_info->data,blob_info->length);
4650 RelinquishMagickResource(MapResource,blob_info->length);
4651 if (extent != (MagickSizeType) ((off_t) extent))
4652 return(MagickFalse);
4653 offset=SeekBlob(image,0,SEEK_END);
4654 if (offset < 0)
4655 return(MagickFalse);
4656 if ((MagickSizeType) offset >= extent)
4657 break;
4658 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4659 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4660 blob_info->file_info.file);
4661#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4662 if (blob_info->synchronize != MagickFalse)
4663 {
4664 int
4665 file;
4666
4667 file=fileno(blob_info->file_info.file);
4668 if ((file == -1) || (offset < 0))
4669 return(MagickFalse);
4670 (void) posix_fallocate(file,offset,extent-offset);
4671 }
4672#endif
4673 offset=SeekBlob(image,offset,SEEK_SET);
4674 if (count != 1)
4675 return(MagickFalse);
4676 (void) AcquireMagickResource(MapResource,extent);
4677 blob_info->data=(unsigned char*) MapBlob(fileno(
4678 blob_info->file_info.file),WriteMode,0,(size_t) extent);
4679 blob_info->extent=(size_t) extent;
4680 blob_info->length=(size_t) extent;
4681 (void) SyncBlob(image);
4682 break;
4683 }
4684 blob_info->extent=(size_t) extent;
4685 blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
4686 blob_info->extent+1,sizeof(*blob_info->data));
4687 (void) SyncBlob(image);
4688 if (blob_info->data == (unsigned char *) NULL)
4689 {
4690 (void) DetachBlob(blob_info);
4691 return(MagickFalse);
4692 }
4693 break;
4694 }
4695 }
4696 return(MagickTrue);
4697}
4698␌
4699/*
4700%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4701% %
4702% %
4703% %
4704+ S y n c B l o b %
4705% %
4706% %
4707% %
4708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4709%
4710% SyncBlob() flushes the datastream if it is a file or synchronizes the data
4711% attributes if it is an blob.
4712%
4713% The format of the SyncBlob method is:
4714%
4715% int SyncBlob(Image *image)
4716%
4717% A description of each parameter follows:
4718%
4719% o image: the image.
4720%
4721*/
4722static int SyncBlob(Image *image)
4723{
4724 BlobInfo
4725 *magick_restrict blob_info;
4726
4727 int
4728 status;
4729
4730 assert(image != (Image *) NULL);
4731 assert(image->signature == MagickCoreSignature);
4732 assert(image->blob != (BlobInfo *) NULL);
4733 assert(image->blob->type != UndefinedStream);
4734 if (IsEventLogging() != MagickFalse)
4735 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4736 blob_info=image->blob;
4737 status=0;
4738 switch (blob_info->type)
4739 {
4740 case UndefinedStream:
4741 case StandardStream:
4742 break;
4743 case FileStream:
4744 case PipeStream:
4745 {
4746 status=fflush(blob_info->file_info.file);
4747 break;
4748 }
4749 case ZipStream:
4750 {
4751#if defined(MAGICKCORE_ZLIB_DELEGATE)
4752 status=gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
4753#endif
4754 break;
4755 }
4756 case BZipStream:
4757 {
4758#if defined(MAGICKCORE_BZLIB_DELEGATE)
4759 status=BZ2_bzflush(blob_info->file_info.bzfile);
4760#endif
4761 break;
4762 }
4763 case FifoStream:
4764 break;
4765 case BlobStream:
4766 break;
4767 }
4768 return(status);
4769}
4770␌
4771/*
4772%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4773% %
4774% %
4775% %
4776+ S y n c B l o b S t r e a m %
4777% %
4778% %
4779% %
4780%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4781%
4782% SyncBlobStream() transfers ownership of an in-memory blob stream from the
4783% image that has just been written back to the owner image and to image info.
4784% The method copies the current buffer state onto the owner, refreshes
4785% image info, and detaches the borrower so exactly one object owns the memory.
4786%
4787% The format of the SyncBlobStream method is:
4788%
4789% void SyncBlobStream(ImageInfo *image,const Image *image,Image *owner)
4790%
4791% A description of each parameter follows:
4792%
4793% o image_info: image info whose blob/length members are refreshed; may be
4794% NULL.
4795%
4796% o owner: the image ImagesToBlob()/ImageToBlob() harvests the blob from
4797% (the head of the list).
4798%
4799% o image: the image that was just written; may be the owner.
4800%
4801*/
4802MagickPrivate void SyncBlobStream(ImageInfo *image_info,Image *image,
4803 Image *owner)
4804{
4805 assert(owner != (Image *) NULL);
4806 assert(image != (Image *) NULL);
4807 assert(image->signature == MagickCoreSignature);
4808 if (image->blob == (BlobInfo *) NULL)
4809 return;
4810 if (image->blob->data == (unsigned char *) NULL)
4811 return;
4812 if (image_info != (ImageInfo *) NULL)
4813 {
4814 image_info->blob=(void *) image->blob->data;
4815 image_info->length=image->blob->length;
4816 }
4817 if ((image == owner) || (owner->blob == (BlobInfo *) NULL))
4818 return;
4819 if (owner->blob == (BlobInfo *) NULL)
4820 return;
4821 /*
4822 Promote the live buffer onto the owner before detaching the borrower;
4823 DetachBlob() clears image->blob->data.
4824 */
4825 owner->blob->data=image->blob->data;
4826 owner->blob->extent=image->blob->extent;
4827 owner->blob->length=image->blob->length;
4828 owner->blob->offset=image->blob->offset;
4829 owner->blob->quantum=image->blob->quantum;
4830 owner->blob->type=BlobStream;
4831 owner->blob->exempt=MagickTrue;
4832 (void) DetachBlob(image->blob);
4833}
4834␌
4835/*
4836%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4837% %
4838% %
4839% %
4840+ T e l l B l o b %
4841% %
4842% %
4843% %
4844%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4845%
4846% TellBlob() obtains the current value of the blob or file position.
4847%
4848% The format of the TellBlob method is:
4849%
4850% MagickOffsetType TellBlob(const Image *image)
4851%
4852% A description of each parameter follows:
4853%
4854% o image: the image.
4855%
4856*/
4857MagickExport MagickOffsetType TellBlob(const Image *image)
4858{
4859 BlobInfo
4860 *magick_restrict blob_info;
4861
4862 MagickOffsetType
4863 offset;
4864
4865 assert(image != (Image *) NULL);
4866 assert(image->signature == MagickCoreSignature);
4867 assert(image->blob != (BlobInfo *) NULL);
4868 assert(image->blob->type != UndefinedStream);
4869 if (IsEventLogging() != MagickFalse)
4870 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4871 blob_info=image->blob;
4872 offset=(-1);
4873 switch (blob_info->type)
4874 {
4875 case UndefinedStream:
4876 case StandardStream:
4877 break;
4878 case FileStream:
4879 {
4880 offset=ftell(blob_info->file_info.file);
4881 break;
4882 }
4883 case PipeStream:
4884 break;
4885 case ZipStream:
4886 {
4887#if defined(MAGICKCORE_ZLIB_DELEGATE)
4888 offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
4889#endif
4890 break;
4891 }
4892 case BZipStream:
4893 break;
4894 case FifoStream:
4895 break;
4896 case BlobStream:
4897 {
4898 offset=blob_info->offset;
4899 break;
4900 }
4901 }
4902 return(offset);
4903}
4904␌
4905/*
4906%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4907% %
4908% %
4909% %
4910+ U n m a p B l o b %
4911% %
4912% %
4913% %
4914%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4915%
4916% UnmapBlob() deallocates the binary large object previously allocated with
4917% the MapBlob method.
4918%
4919% The format of the UnmapBlob method is:
4920%
4921% MagickBooleanType UnmapBlob(void *map,const size_t length)
4922%
4923% A description of each parameter follows:
4924%
4925% o map: the address of the binary large object.
4926%
4927% o length: the length of the binary large object.
4928%
4929*/
4930MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4931{
4932#if defined(MAGICKCORE_HAVE_MMAP)
4933 int
4934 status;
4935
4936 status=munmap(map,length);
4937 return(status == -1 ? MagickFalse : MagickTrue);
4938#else
4939 (void) map;
4940 (void) length;
4941 return(MagickFalse);
4942#endif
4943}
4944␌
4945/*
4946%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4947% %
4948% %
4949% %
4950+ W r i t e B l o b %
4951% %
4952% %
4953% %
4954%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4955%
4956% WriteBlob() writes data to a blob or image file. It returns the number of
4957% bytes written.
4958%
4959% The format of the WriteBlob method is:
4960%
4961% ssize_t WriteBlob(Image *image,const size_t length,
4962% const unsigned char *data)
4963%
4964% A description of each parameter follows:
4965%
4966% o image: the image.
4967%
4968% o length: Specifies an integer representing the number of bytes to
4969% write to the file.
4970%
4971% o data: The address of the data to write to the blob or file.
4972%
4973*/
4974MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4975 const unsigned char *data)
4976{
4977 BlobInfo
4978 *magick_restrict blob_info;
4979
4980 int
4981 c;
4982
4983 const unsigned char
4984 *p;
4985
4986 unsigned char
4987 *q;
4988
4989 ssize_t
4990 count;
4991
4992 assert(image != (Image *) NULL);
4993 assert(image->signature == MagickCoreSignature);
4994 assert(image->blob != (BlobInfo *) NULL);
4995 assert(image->blob->type != UndefinedStream);
4996 if (length == 0)
4997 return(0);
4998 assert(data != (const unsigned char *) NULL);
4999 blob_info=image->blob;
5000 count=0;
5001 p=(const unsigned char *) data;
5002 q=(unsigned char *) data;
5003 switch (blob_info->type)
5004 {
5005 case UndefinedStream:
5006 break;
5007 case StandardStream:
5008 case FileStream:
5009 case PipeStream:
5010 {
5011 switch (length)
5012 {
5013 default:
5014 {
5015 count=(ssize_t) fwrite((const char *) data,1,length,
5016 blob_info->file_info.file);
5017 break;
5018 }
5019 case 4:
5020 {
5021 c=putc((int) *p++,blob_info->file_info.file);
5022 if (c == EOF)
5023 break;
5024 count++;
5025 magick_fallthrough;
5026 }
5027 case 3:
5028 {
5029 c=putc((int) *p++,blob_info->file_info.file);
5030 if (c == EOF)
5031 break;
5032 count++;
5033 magick_fallthrough;
5034 }
5035 case 2:
5036 {
5037 c=putc((int) *p++,blob_info->file_info.file);
5038 if (c == EOF)
5039 break;
5040 count++;
5041 magick_fallthrough;
5042 }
5043 case 1:
5044 {
5045 c=putc((int) *p++,blob_info->file_info.file);
5046 if (c == EOF)
5047 break;
5048 count++;
5049 magick_fallthrough;
5050 }
5051 case 0:
5052 break;
5053 }
5054 if ((count != (ssize_t) length) &&
5055 (ferror(blob_info->file_info.file) != 0))
5056 ThrowBlobException(blob_info);
5057 break;
5058 }
5059 case ZipStream:
5060 {
5061#if defined(MAGICKCORE_ZLIB_DELEGATE)
5062 int
5063 status;
5064
5065 switch (length)
5066 {
5067 default:
5068 {
5069 ssize_t
5070 i;
5071
5072 for (i=0; i < (ssize_t) length; i+=count)
5073 {
5074 count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
5075 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
5076 if (count <= 0)
5077 {
5078 count=0;
5079 if (errno != EINTR)
5080 break;
5081 }
5082 }
5083 count=i;
5084 break;
5085 }
5086 case 4:
5087 {
5088 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5089 if (c == EOF)
5090 break;
5091 count++;
5092 magick_fallthrough;
5093 }
5094 case 3:
5095 {
5096 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5097 if (c == EOF)
5098 break;
5099 count++;
5100 magick_fallthrough;
5101 }
5102 case 2:
5103 {
5104 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5105 if (c == EOF)
5106 break;
5107 count++;
5108 magick_fallthrough;
5109 }
5110 case 1:
5111 {
5112 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5113 if (c == EOF)
5114 break;
5115 count++;
5116 magick_fallthrough;
5117 }
5118 case 0:
5119 break;
5120 }
5121 status=Z_OK;
5122 (void) gzerror(blob_info->file_info.gzfile,&status);
5123 if ((count != (ssize_t) length) && (status != Z_OK))
5124 ThrowBlobException(blob_info);
5125#endif
5126 break;
5127 }
5128 case BZipStream:
5129 {
5130#if defined(MAGICKCORE_BZLIB_DELEGATE)
5131 int
5132 status;
5133
5134 ssize_t
5135 i;
5136
5137 for (i=0; i < (ssize_t) length; i+=count)
5138 {
5139 count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
5140 (int) MagickMin(length-i,MagickMaxBufferExtent));
5141 if (count <= 0)
5142 {
5143 count=0;
5144 if (errno != EINTR)
5145 break;
5146 }
5147 }
5148 count=i;
5149 status=BZ_OK;
5150 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
5151 if ((count != (ssize_t) length) && (status != BZ_OK))
5152 ThrowBlobException(blob_info);
5153#endif
5154 break;
5155 }
5156 case FifoStream:
5157 {
5158 count=(ssize_t) blob_info->stream(image,data,length);
5159 break;
5160 }
5161 case BlobStream:
5162 {
5163 MagickSizeType
5164 extent;
5165
5166 extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
5167 if (extent >= blob_info->extent)
5168 {
5169 if (blob_info->mapped != MagickFalse)
5170 return(0);
5171 blob_info->extent=extent+blob_info->quantum+length;
5172 blob_info->quantum<<=1;
5173 blob_info->data=(unsigned char *) ResizeQuantumMemory(
5174 blob_info->data,blob_info->extent+1,sizeof(*blob_info->data));
5175 (void) SyncBlob(image);
5176 if (blob_info->data == (unsigned char *) NULL)
5177 {
5178 (void) DetachBlob(blob_info);
5179 return(0);
5180 }
5181 }
5182 q=blob_info->data+blob_info->offset;
5183 (void) memcpy(q,p,length);
5184 blob_info->offset+=length;
5185 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
5186 blob_info->length=(size_t) blob_info->offset;
5187 count=(ssize_t) length;
5188 }
5189 }
5190 if (count != (ssize_t) length)
5191 ThrowBlobException(blob_info);
5192 return(count);
5193}
5194␌
5195/*
5196%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5197% %
5198% %
5199% %
5200+ W r i t e B l o b B y t e %
5201% %
5202% %
5203% %
5204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5205%
5206% WriteBlobByte() write an integer to a blob. It returns the number of bytes
5207% written (either 0 or 1);
5208%
5209% The format of the WriteBlobByte method is:
5210%
5211% ssize_t WriteBlobByte(Image *image,const unsigned char value)
5212%
5213% A description of each parameter follows.
5214%
5215% o image: the image.
5216%
5217% o value: Specifies the value to write.
5218%
5219*/
5220MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
5221{
5222 BlobInfo
5223 *magick_restrict blob_info;
5224
5225 ssize_t
5226 count;
5227
5228 assert(image != (Image *) NULL);
5229 assert(image->signature == MagickCoreSignature);
5230 assert(image->blob != (BlobInfo *) NULL);
5231 assert(image->blob->type != UndefinedStream);
5232 blob_info=image->blob;
5233 count=0;
5234 switch (blob_info->type)
5235 {
5236 case StandardStream:
5237 case FileStream:
5238 case PipeStream:
5239 {
5240 int
5241 c;
5242
5243 c=putc((int) value,blob_info->file_info.file);
5244 if (c == EOF)
5245 {
5246 if (ferror(blob_info->file_info.file) != 0)
5247 ThrowBlobException(blob_info);
5248 break;
5249 }
5250 count++;
5251 break;
5252 }
5253 default:
5254 {
5255 count=WriteBlobStream(image,1,&value);
5256 break;
5257 }
5258 }
5259 return(count);
5260}
5261␌
5262/*
5263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5264% %
5265% %
5266% %
5267+ W r i t e B l o b F l o a t %
5268% %
5269% %
5270% %
5271%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5272%
5273% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
5274% specified by the endian member of the image structure.
5275%
5276% The format of the WriteBlobFloat method is:
5277%
5278% ssize_t WriteBlobFloat(Image *image,const float value)
5279%
5280% A description of each parameter follows.
5281%
5282% o image: the image.
5283%
5284% o value: Specifies the value to write.
5285%
5286*/
5287MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
5288{
5289 union
5290 {
5291 unsigned int
5292 unsigned_value;
5293
5294 float
5295 float_value;
5296 } quantum;
5297
5298 quantum.unsigned_value=0U;
5299 quantum.float_value=value;
5300 return(WriteBlobLong(image,quantum.unsigned_value));
5301}
5302␌
5303/*
5304%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5305% %
5306% %
5307% %
5308+ W r i t e B l o b L o n g %
5309% %
5310% %
5311% %
5312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5313%
5314% WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
5315% byte-order specified by the endian member of the image structure.
5316%
5317% The format of the WriteBlobLong method is:
5318%
5319% ssize_t WriteBlobLong(Image *image,const unsigned int value)
5320%
5321% A description of each parameter follows.
5322%
5323% o image: the image.
5324%
5325% o value: Specifies the value to write.
5326%
5327*/
5328MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
5329{
5330 unsigned char
5331 buffer[4];
5332
5333 assert(image != (Image *) NULL);
5334 assert(image->signature == MagickCoreSignature);
5335 if (image->endian == LSBEndian)
5336 {
5337 buffer[0]=(unsigned char) value;
5338 buffer[1]=(unsigned char) (value >> 8);
5339 buffer[2]=(unsigned char) (value >> 16);
5340 buffer[3]=(unsigned char) (value >> 24);
5341 return(WriteBlobStream(image,4,buffer));
5342 }
5343 buffer[0]=(unsigned char) (value >> 24);
5344 buffer[1]=(unsigned char) (value >> 16);
5345 buffer[2]=(unsigned char) (value >> 8);
5346 buffer[3]=(unsigned char) value;
5347 return(WriteBlobStream(image,4,buffer));
5348}
5349␌
5350/*
5351%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5352% %
5353% %
5354% %
5355+ W r i t e B l o b S h o r t %
5356% %
5357% %
5358% %
5359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5360%
5361% WriteBlobShort() writes a short value as a 16-bit quantity in the
5362% byte-order specified by the endian member of the image structure.
5363%
5364% The format of the WriteBlobShort method is:
5365%
5366% ssize_t WriteBlobShort(Image *image,const unsigned short value)
5367%
5368% A description of each parameter follows.
5369%
5370% o image: the image.
5371%
5372% o value: Specifies the value to write.
5373%
5374*/
5375MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
5376{
5377 unsigned char
5378 buffer[2];
5379
5380 assert(image != (Image *) NULL);
5381 assert(image->signature == MagickCoreSignature);
5382 if (image->endian == LSBEndian)
5383 {
5384 buffer[0]=(unsigned char) value;
5385 buffer[1]=(unsigned char) (value >> 8);
5386 return(WriteBlobStream(image,2,buffer));
5387 }
5388 buffer[0]=(unsigned char) (value >> 8);
5389 buffer[1]=(unsigned char) value;
5390 return(WriteBlobStream(image,2,buffer));
5391}
5392␌
5393/*
5394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5395% %
5396% %
5397% %
5398+ W r i t e B l o b L S B L o n g %
5399% %
5400% %
5401% %
5402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5403%
5404% WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
5405% least-significant byte first order.
5406%
5407% The format of the WriteBlobLSBLong method is:
5408%
5409% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5410%
5411% A description of each parameter follows.
5412%
5413% o image: the image.
5414%
5415% o value: Specifies the value to write.
5416%
5417*/
5418MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5419{
5420 unsigned char
5421 buffer[4];
5422
5423 assert(image != (Image *) NULL);
5424 assert(image->signature == MagickCoreSignature);
5425 buffer[0]=(unsigned char) value;
5426 buffer[1]=(unsigned char) (value >> 8);
5427 buffer[2]=(unsigned char) (value >> 16);
5428 buffer[3]=(unsigned char) (value >> 24);
5429 return(WriteBlobStream(image,4,buffer));
5430}
5431␌
5432/*
5433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5434% %
5435% %
5436% %
5437+ W r i t e B l o b L S B S h o r t %
5438% %
5439% %
5440% %
5441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5442%
5443% WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
5444% least-significant byte first order.
5445%
5446% The format of the WriteBlobLSBShort method is:
5447%
5448% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5449%
5450% A description of each parameter follows.
5451%
5452% o image: the image.
5453%
5454% o value: Specifies the value to write.
5455%
5456*/
5457MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5458{
5459 unsigned char
5460 buffer[2];
5461
5462 assert(image != (Image *) NULL);
5463 assert(image->signature == MagickCoreSignature);
5464 buffer[0]=(unsigned char) value;
5465 buffer[1]=(unsigned char) (value >> 8);
5466 return(WriteBlobStream(image,2,buffer));
5467}
5468␌
5469/*
5470%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5471% %
5472% %
5473% %
5474+ W r i t e B l o b L S B S i g n e d L o n g %
5475% %
5476% %
5477% %
5478%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5479%
5480% WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
5481% least-significant byte first order.
5482%
5483% The format of the WriteBlobLSBSignedLong method is:
5484%
5485% ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5486%
5487% A description of each parameter follows.
5488%
5489% o image: the image.
5490%
5491% o value: Specifies the value to write.
5492%
5493*/
5494MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5495{
5496 union
5497 {
5498 unsigned int
5499 unsigned_value;
5500
5501 signed int
5502 signed_value;
5503 } quantum;
5504
5505 unsigned char
5506 buffer[4];
5507
5508 assert(image != (Image *) NULL);
5509 assert(image->signature == MagickCoreSignature);
5510 quantum.signed_value=value;
5511 buffer[0]=(unsigned char) quantum.unsigned_value;
5512 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5513 buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
5514 buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
5515 return(WriteBlobStream(image,4,buffer));
5516}
5517␌
5518/*
5519%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5520% %
5521% %
5522% %
5523+ W r i t e B l o b L S B S i g n e d S h o r t %
5524% %
5525% %
5526% %
5527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5528%
5529% WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
5530% in least-significant byte first order.
5531%
5532% The format of the WriteBlobLSBSignedShort method is:
5533%
5534% ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
5535%
5536% A description of each parameter follows.
5537%
5538% o image: the image.
5539%
5540% o value: Specifies the value to write.
5541%
5542*/
5543MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
5544 const signed short value)
5545{
5546 union
5547 {
5548 unsigned short
5549 unsigned_value;
5550
5551 signed short
5552 signed_value;
5553 } quantum;
5554
5555 unsigned char
5556 buffer[2];
5557
5558 assert(image != (Image *) NULL);
5559 assert(image->signature == MagickCoreSignature);
5560 quantum.signed_value=value;
5561 buffer[0]=(unsigned char) quantum.unsigned_value;
5562 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5563 return(WriteBlobStream(image,2,buffer));
5564}
5565␌
5566/*
5567%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5568% %
5569% %
5570% %
5571+ W r i t e B l o b M S B L o n g %
5572% %
5573% %
5574% %
5575%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5576%
5577% WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
5578% most-significant byte first order.
5579%
5580% The format of the WriteBlobMSBLong method is:
5581%
5582% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5583%
5584% A description of each parameter follows.
5585%
5586% o value: Specifies the value to write.
5587%
5588% o image: the image.
5589%
5590*/
5591MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5592{
5593 unsigned char
5594 buffer[4];
5595
5596 assert(image != (Image *) NULL);
5597 assert(image->signature == MagickCoreSignature);
5598 buffer[0]=(unsigned char) (value >> 24);
5599 buffer[1]=(unsigned char) (value >> 16);
5600 buffer[2]=(unsigned char) (value >> 8);
5601 buffer[3]=(unsigned char) value;
5602 return(WriteBlobStream(image,4,buffer));
5603}
5604␌
5605/*
5606%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5607% %
5608% %
5609% %
5610+ W r i t e B l o b M S B L o n g L o n g %
5611% %
5612% %
5613% %
5614%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5615%
5616% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
5617% most-significant byte first order.
5618%
5619% The format of the WriteBlobMSBLongLong method is:
5620%
5621% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
5622%
5623% A description of each parameter follows.
5624%
5625% o value: Specifies the value to write.
5626%
5627% o image: the image.
5628%
5629*/
5630MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
5631 const MagickSizeType value)
5632{
5633 unsigned char
5634 buffer[8];
5635
5636 assert(image != (Image *) NULL);
5637 assert(image->signature == MagickCoreSignature);
5638 buffer[0]=(unsigned char) (value >> 56);
5639 buffer[1]=(unsigned char) (value >> 48);
5640 buffer[2]=(unsigned char) (value >> 40);
5641 buffer[3]=(unsigned char) (value >> 32);
5642 buffer[4]=(unsigned char) (value >> 24);
5643 buffer[5]=(unsigned char) (value >> 16);
5644 buffer[6]=(unsigned char) (value >> 8);
5645 buffer[7]=(unsigned char) value;
5646 return(WriteBlobStream(image,8,buffer));
5647}
5648␌
5649/*
5650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5651% %
5652% %
5653% %
5654+ W r i t e B l o b M S B S h o r t %
5655% %
5656% %
5657% %
5658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5659%
5660% WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
5661% most-significant byte first order.
5662%
5663% The format of the WriteBlobMSBShort method is:
5664%
5665% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5666%
5667% A description of each parameter follows.
5668%
5669% o value: Specifies the value to write.
5670%
5671% o file: Specifies the file to write the data to.
5672%
5673*/
5674MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5675{
5676 unsigned char
5677 buffer[2];
5678
5679 assert(image != (Image *) NULL);
5680 assert(image->signature == MagickCoreSignature);
5681 buffer[0]=(unsigned char) (value >> 8);
5682 buffer[1]=(unsigned char) value;
5683 return(WriteBlobStream(image,2,buffer));
5684}
5685␌
5686/*
5687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5688% %
5689% %
5690% %
5691+ W r i t e B l o b M S B S i g n e d L o n g %
5692% %
5693% %
5694% %
5695%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5696%
5697% WriteBlobMSBSignedLong() writes a signed value as a 32-bit quantity in
5698% most-significant byte first order.
5699%
5700% The format of the WriteBlobMSBSignedLong method is:
5701%
5702% ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5703%
5704% A description of each parameter follows.
5705%
5706% o image: the image.
5707%
5708% o value: Specifies the value to write.
5709%
5710*/
5711MagickExport ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5712{
5713 union
5714 {
5715 unsigned int
5716 unsigned_value;
5717
5718 signed int
5719 signed_value;
5720 } quantum;
5721
5722 unsigned char
5723 buffer[4];
5724
5725 assert(image != (Image *) NULL);
5726 assert(image->signature == MagickCoreSignature);
5727 quantum.signed_value=value;
5728 buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
5729 buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
5730 buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
5731 buffer[3]=(unsigned char) quantum.unsigned_value;
5732 return(WriteBlobStream(image,4,buffer));
5733}
5734␌
5735/*
5736%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5737% %
5738% %
5739% %
5740+ W r i t e B l o b M S B S i g n e d S h o r t %
5741% %
5742% %
5743% %
5744%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5745%
5746% WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
5747% in most-significant byte first order.
5748%
5749% The format of the WriteBlobMSBSignedShort method is:
5750%
5751% ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
5752%
5753% A description of each parameter follows.
5754%
5755% o image: the image.
5756%
5757% o value: Specifies the value to write.
5758%
5759*/
5760MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
5761 const signed short value)
5762{
5763 union
5764 {
5765 unsigned short
5766 unsigned_value;
5767
5768 signed short
5769 signed_value;
5770 } quantum;
5771
5772 unsigned char
5773 buffer[2];
5774
5775 assert(image != (Image *) NULL);
5776 assert(image->signature == MagickCoreSignature);
5777 quantum.signed_value=value;
5778 buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
5779 buffer[1]=(unsigned char) quantum.unsigned_value;
5780 return(WriteBlobStream(image,2,buffer));
5781}
5782␌
5783/*
5784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5785% %
5786% %
5787% %
5788+ W r i t e B l o b S t r i n g %
5789% %
5790% %
5791% %
5792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5793%
5794% WriteBlobString() write a string to a blob. It returns the number of
5795% characters written.
5796%
5797% The format of the WriteBlobString method is:
5798%
5799% ssize_t WriteBlobString(Image *image,const char *string)
5800%
5801% A description of each parameter follows.
5802%
5803% o image: the image.
5804%
5805% o string: Specifies the string to write.
5806%
5807*/
5808MagickExport ssize_t WriteBlobString(Image *image,const char *string)
5809{
5810 assert(image != (Image *) NULL);
5811 assert(image->signature == MagickCoreSignature);
5812 assert(string != (const char *) NULL);
5813 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
5814}