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