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