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