blob: 51fc9a920e70b1be5c0cde33738c65f051e5be73 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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% John Cristy %
17% July 1999 %
18% %
19% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% 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*/
cristy4c08aed2011-07-01 19:47:50 +000043#include "MagickCore/studio.h"
cristyd2d11ec2012-03-28 13:53:49 +000044#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000045#include "MagickCore/blob.h"
46#include "MagickCore/blob-private.h"
47#include "MagickCore/cache.h"
48#include "MagickCore/client.h"
49#include "MagickCore/constitute.h"
50#include "MagickCore/delegate.h"
51#include "MagickCore/exception.h"
52#include "MagickCore/exception-private.h"
53#include "MagickCore/image-private.h"
54#include "MagickCore/list.h"
55#include "MagickCore/locale_.h"
56#include "MagickCore/log.h"
57#include "MagickCore/magick.h"
58#include "MagickCore/memory_.h"
59#include "MagickCore/policy.h"
60#include "MagickCore/resource_.h"
61#include "MagickCore/semaphore.h"
62#include "MagickCore/string_.h"
63#include "MagickCore/string-private.h"
64#include "MagickCore/token.h"
65#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000066#include "MagickCore/utility-private.h"
cristy0157aea2010-04-24 21:12:18 +000067#if defined(MAGICKCORE_HAVE_MMAP_FILEIO) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +000068# include <sys/mman.h>
69#endif
70#if defined(MAGICKCORE_ZLIB_DELEGATE)
71#include "zlib.h"
72#endif
73#if defined(MAGICKCORE_BZLIB_DELEGATE)
74#include "bzlib.h"
75#endif
76
77/*
78 Define declarations.
79*/
80#define MagickMaxBlobExtent 65541
cristy3ed852e2009-09-05 21:47:34 +000081#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
82# define MAP_ANONYMOUS MAP_ANON
83#endif
84#if !defined(MAP_FAILED)
85#define MAP_FAILED ((void *) -1)
86#endif
87#if !defined(MS_SYNC)
88#define MS_SYNC 0x04
89#endif
90#if defined(__OS2__)
91#include <io.h>
92#define _O_BINARY O_BINARY
93#endif
94
95/*
96 Typedef declarations.
97*/
98struct _BlobInfo
99{
100 size_t
101 length,
102 extent,
103 quantum;
104
105 MagickBooleanType
106 mapped,
107 eof;
108
109 MagickOffsetType
110 offset;
111
112 MagickSizeType
113 size;
114
115 MagickBooleanType
116 exempt,
117 synchronize,
118 status,
119 temporary;
120
121 StreamType
122 type;
123
cristy95888612012-04-04 21:56:52 +0000124 union _stream_info {
cristycfd11422012-01-31 14:34:38 +0000125 FILE
126 *file;
127
128#if defined(MAGICKCORE_ZLIB_DELEGATE)
129 gzFile
130 gzfile;
131#endif
132
133#if defined(MAGICKCORE_BZLIB_DELEGATE)
134 BZFILE
135 *bzfile;
136#endif
cristy95888612012-04-04 21:56:52 +0000137 } stream_info;
cristy3ed852e2009-09-05 21:47:34 +0000138
139 struct stat
140 properties;
141
142 StreamHandler
143 stream;
144
145 unsigned char
146 *data;
147
148 MagickBooleanType
149 debug;
150
151 SemaphoreInfo
152 *semaphore;
153
cristybb503372010-05-27 20:51:26 +0000154 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000155 reference_count;
156
cristybb503372010-05-27 20:51:26 +0000157 size_t
cristy3ed852e2009-09-05 21:47:34 +0000158 signature;
159};
160
161/*
162 Forward declarations.
163*/
164static int
165 SyncBlob(Image *);
166
167/*
168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169% %
170% %
171% %
172+ A t t a c h B l o b %
173% %
174% %
175% %
176%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177%
178% AttachBlob() attaches a blob to the BlobInfo structure.
179%
180% The format of the AttachBlob method is:
181%
182% void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
183%
184% A description of each parameter follows:
185%
186% o blob_info: Specifies a pointer to a BlobInfo structure.
187%
188% o blob: the address of a character stream in one of the image formats
189% understood by ImageMagick.
190%
191% o length: This size_t integer reflects the length in bytes of the blob.
192%
193*/
194MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
195 const size_t length)
196{
197 assert(blob_info != (BlobInfo *) NULL);
198 if (blob_info->debug != MagickFalse)
199 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
200 blob_info->length=length;
201 blob_info->extent=length;
202 blob_info->quantum=(size_t) MagickMaxBlobExtent;
203 blob_info->offset=0;
204 blob_info->type=BlobStream;
cristy95888612012-04-04 21:56:52 +0000205 blob_info->stream_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000206 blob_info->data=(unsigned char *) blob;
207 blob_info->mapped=MagickFalse;
208}
209
210/*
211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212% %
213% %
214% %
215+ B l o b T o F i l e %
216% %
217% %
218% %
219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220%
221% BlobToFile() writes a blob to a file. It returns MagickFalse if an error
222% occurs otherwise MagickTrue.
223%
224% The format of the BlobToFile method is:
225%
226% MagickBooleanType BlobToFile(char *filename,const void *blob,
227% const size_t length,ExceptionInfo *exception)
228%
229% A description of each parameter follows:
230%
231% o filename: Write the blob to this file.
232%
233% o blob: the address of a blob.
234%
235% o length: This length in bytes of the blob.
236%
237% o exception: return any errors or warnings in this structure.
238%
239*/
240
cristy7753b2a2011-02-19 18:36:52 +0000241static inline MagickSizeType MagickMin(const MagickSizeType x,
242 const MagickSizeType y)
cristy3ed852e2009-09-05 21:47:34 +0000243{
244 if (x < y)
245 return(x);
246 return(y);
247}
248
249MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
250 const size_t length,ExceptionInfo *exception)
251{
252 int
253 file;
254
255 register size_t
256 i;
257
258 ssize_t
259 count;
260
261 assert(filename != (const char *) NULL);
262 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
263 assert(blob != (const void *) NULL);
264 if (*filename == '\0')
265 file=AcquireUniqueFileResource(filename);
266 else
cristy18c6c272011-09-23 14:40:37 +0000267 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +0000268 if (file == -1)
269 {
270 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
271 return(MagickFalse);
272 }
273 for (i=0; i < length; i+=count)
274 {
cristy7753b2a2011-02-19 18:36:52 +0000275 count=(ssize_t) write(file,(const char *) blob+i,(size_t) MagickMin(length-
276 i,(MagickSizeType) SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +0000277 if (count <= 0)
278 {
279 count=0;
280 if (errno != EINTR)
281 break;
282 }
283 }
cristya7cb4312010-06-26 00:47:03 +0000284 file=close(file);
285 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +0000286 {
287 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
288 return(MagickFalse);
289 }
290 return(MagickTrue);
291}
292
293/*
294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
295% %
296% %
297% %
298% B l o b T o I m a g e %
299% %
300% %
301% %
302%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303%
304% BlobToImage() implements direct to memory image formats. It returns the
305% blob as an image.
306%
307% The format of the BlobToImage method is:
308%
309% Image *BlobToImage(const ImageInfo *image_info,const void *blob,
310% const size_t length,ExceptionInfo *exception)
311%
312% A description of each parameter follows:
313%
314% o image_info: the image info.
315%
316% o blob: the address of a character stream in one of the image formats
317% understood by ImageMagick.
318%
319% o length: This size_t integer reflects the length in bytes of the blob.
320%
321% o exception: return any errors or warnings in this structure.
322%
323*/
324MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
325 const size_t length,ExceptionInfo *exception)
326{
327 const MagickInfo
328 *magick_info;
329
330 Image
331 *image;
332
333 ImageInfo
334 *blob_info,
335 *clone_info;
336
337 MagickBooleanType
338 status;
339
340 assert(image_info != (ImageInfo *) NULL);
341 assert(image_info->signature == MagickSignature);
342 if (image_info->debug != MagickFalse)
343 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
344 image_info->filename);
345 assert(exception != (ExceptionInfo *) NULL);
346 if ((blob == (const void *) NULL) || (length == 0))
347 {
348 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
349 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
350 return((Image *) NULL);
351 }
352 blob_info=CloneImageInfo(image_info);
353 blob_info->blob=(void *) blob;
354 blob_info->length=length;
355 if (*blob_info->magick == '\0')
cristyd965a422010-03-03 17:47:35 +0000356 (void) SetImageInfo(blob_info,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000357 magick_info=GetMagickInfo(blob_info->magick,exception);
358 if (magick_info == (const MagickInfo *) NULL)
359 {
360 blob_info=DestroyImageInfo(blob_info);
361 (void) ThrowMagickException(exception,GetMagickModule(),
362 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
363 image_info->filename);
364 return((Image *) NULL);
365 }
366 if (GetMagickBlobSupport(magick_info) != MagickFalse)
367 {
368 /*
369 Native blob support for this image format.
370 */
371 (void) CopyMagickString(blob_info->filename,image_info->filename,
372 MaxTextExtent);
373 (void) CopyMagickString(blob_info->magick,image_info->magick,
374 MaxTextExtent);
375 image=ReadImage(blob_info,exception);
376 if (image != (Image *) NULL)
377 (void) DetachBlob(image->blob);
378 blob_info=DestroyImageInfo(blob_info);
379 return(image);
380 }
381 /*
382 Write blob to a temporary file on disk.
383 */
384 blob_info->blob=(void *) NULL;
385 blob_info->length=0;
386 *blob_info->filename='\0';
387 status=BlobToFile(blob_info->filename,blob,length,exception);
388 if (status == MagickFalse)
389 {
390 (void) RelinquishUniqueFileResource(blob_info->filename);
391 blob_info=DestroyImageInfo(blob_info);
392 return((Image *) NULL);
393 }
394 clone_info=CloneImageInfo(blob_info);
cristyb51dff52011-05-19 16:55:47 +0000395 (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +0000396 blob_info->magick,blob_info->filename);
397 image=ReadImage(clone_info,exception);
398 clone_info=DestroyImageInfo(clone_info);
399 (void) RelinquishUniqueFileResource(blob_info->filename);
400 blob_info=DestroyImageInfo(blob_info);
401 return(image);
402}
403
404/*
405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406% %
407% %
408% %
409+ C l o n e B l o b I n f o %
410% %
411% %
412% %
413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414%
415% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
416% blob info is NULL, a new one.
417%
418% The format of the CloneBlobInfo method is:
419%
420% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
421%
422% A description of each parameter follows:
423%
424% o blob_info: the blob info.
425%
426*/
427MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
428{
429 BlobInfo
430 *clone_info;
431
cristy73bd4a52010-10-05 11:24:23 +0000432 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
cristy3ed852e2009-09-05 21:47:34 +0000433 if (clone_info == (BlobInfo *) NULL)
434 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
435 GetBlobInfo(clone_info);
436 if (blob_info == (BlobInfo *) NULL)
437 return(clone_info);
438 clone_info->length=blob_info->length;
439 clone_info->extent=blob_info->extent;
440 clone_info->synchronize=blob_info->synchronize;
441 clone_info->quantum=blob_info->quantum;
442 clone_info->mapped=blob_info->mapped;
443 clone_info->eof=blob_info->eof;
444 clone_info->offset=blob_info->offset;
445 clone_info->size=blob_info->size;
446 clone_info->exempt=blob_info->exempt;
447 clone_info->status=blob_info->status;
448 clone_info->temporary=blob_info->temporary;
449 clone_info->type=blob_info->type;
cristy95888612012-04-04 21:56:52 +0000450 clone_info->stream_info.file=blob_info->stream_info.file;
cristy3ed852e2009-09-05 21:47:34 +0000451 clone_info->properties=blob_info->properties;
452 clone_info->stream=blob_info->stream;
453 clone_info->data=blob_info->data;
454 clone_info->debug=IsEventLogging();
455 clone_info->reference_count=1;
456 return(clone_info);
457}
458
459/*
460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461% %
462% %
463% %
464+ C l o s e B l o b %
465% %
466% %
467% %
468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
469%
470% CloseBlob() closes a stream associated with the image.
471%
472% The format of the CloseBlob method is:
473%
474% MagickBooleanType CloseBlob(Image *image)
475%
476% A description of each parameter follows:
477%
478% o image: the image.
479%
480*/
481MagickExport MagickBooleanType CloseBlob(Image *image)
482{
483 int
484 status;
485
486 /*
487 Close image file.
488 */
489 assert(image != (Image *) NULL);
490 assert(image->signature == MagickSignature);
491 if (image->debug != MagickFalse)
492 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
493 assert(image->blob != (BlobInfo *) NULL);
494 if (image->blob->type == UndefinedStream)
495 return(MagickTrue);
496 if (image->blob->synchronize != MagickFalse)
497 SyncBlob(image);
498 image->blob->size=GetBlobSize(image);
cristy81b8ce52010-02-05 01:53:17 +0000499 image->extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +0000500 image->blob->eof=MagickFalse;
501 if (image->blob->exempt != MagickFalse)
502 {
503 image->blob->type=UndefinedStream;
504 return(MagickTrue);
505 }
506 status=0;
507 switch (image->blob->type)
508 {
509 case UndefinedStream:
510 break;
511 case FileStream:
512 case StandardStream:
513 case PipeStream:
514 {
cristy95888612012-04-04 21:56:52 +0000515 status=ferror(image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000516 break;
517 }
518 case ZipStream:
519 {
520#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristy95888612012-04-04 21:56:52 +0000521 (void) gzerror(image->blob->stream_info.gzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000522#endif
523 break;
524 }
525 case BZipStream:
526 {
527#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy95888612012-04-04 21:56:52 +0000528 (void) BZ2_bzerror(image->blob->stream_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000529#endif
530 break;
531 }
532 case FifoStream:
533 case BlobStream:
534 break;
535 }
536 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
537 switch (image->blob->type)
538 {
539 case UndefinedStream:
540 break;
541 case FileStream:
542 case StandardStream:
543 {
544 if (image->blob->synchronize != MagickFalse)
cristyff483372010-10-16 17:00:58 +0000545 {
cristy95888612012-04-04 21:56:52 +0000546 status=fflush(image->blob->stream_info.file);
547 status=fsync(fileno(image->blob->stream_info.file));
cristyff483372010-10-16 17:00:58 +0000548 }
cristy95888612012-04-04 21:56:52 +0000549 status=fclose(image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000550 break;
551 }
552 case PipeStream:
553 {
554#if defined(MAGICKCORE_HAVE_PCLOSE)
cristy95888612012-04-04 21:56:52 +0000555 status=pclose(image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000556#endif
557 break;
558 }
559 case ZipStream:
560 {
561#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristy95888612012-04-04 21:56:52 +0000562 status=gzclose(image->blob->stream_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +0000563#endif
564 break;
565 }
566 case BZipStream:
567 {
568#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy95888612012-04-04 21:56:52 +0000569 BZ2_bzclose(image->blob->stream_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +0000570#endif
571 break;
572 }
573 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000574 break;
cristyff483372010-10-16 17:00:58 +0000575 case BlobStream:
576 {
cristy95888612012-04-04 21:56:52 +0000577 if (image->blob->stream_info.file != (FILE *) NULL)
cristyff483372010-10-16 17:00:58 +0000578 {
579 if (image->blob->synchronize != MagickFalse)
cristy95888612012-04-04 21:56:52 +0000580 (void) fsync(fileno(image->blob->stream_info.file));
581 status=fclose(image->blob->stream_info.file);
cristyff483372010-10-16 17:00:58 +0000582 }
583 break;
584 }
cristy3ed852e2009-09-05 21:47:34 +0000585 }
586 (void) DetachBlob(image->blob);
587 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
588 return(image->blob->status);
589}
590
591/*
592%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
593% %
594% %
595% %
596+ D e s t r o y B l o b %
597% %
598% %
599% %
600%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
601%
602% DestroyBlob() deallocates memory associated with a blob.
603%
604% The format of the DestroyBlob method is:
605%
606% void DestroyBlob(Image *image)
607%
608% A description of each parameter follows:
609%
610% o image: the image.
611%
612*/
613MagickExport void DestroyBlob(Image *image)
614{
615 MagickBooleanType
616 destroy;
617
618 assert(image != (Image *) NULL);
619 assert(image->signature == MagickSignature);
620 if (image->debug != MagickFalse)
621 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
622 assert(image->blob != (BlobInfo *) NULL);
623 assert(image->blob->signature == MagickSignature);
624 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000625 LockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000626 image->blob->reference_count--;
627 assert(image->blob->reference_count >= 0);
628 if (image->blob->reference_count == 0)
629 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000630 UnlockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000631 if (destroy == MagickFalse)
632 return;
633 (void) CloseBlob(image);
634 if (image->blob->mapped != MagickFalse)
635 (void) UnmapBlob(image->blob->data,image->blob->length);
636 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
637 DestroySemaphoreInfo(&image->blob->semaphore);
638 image->blob->signature=(~MagickSignature);
639 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
640}
641
642/*
643%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644% %
645% %
646% %
647+ D e t a c h B l o b %
648% %
649% %
650% %
651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652%
653% DetachBlob() detaches a blob from the BlobInfo structure.
654%
655% The format of the DetachBlob method is:
656%
657% unsigned char *DetachBlob(BlobInfo *blob_info)
658%
659% A description of each parameter follows:
660%
661% o blob_info: Specifies a pointer to a BlobInfo structure.
662%
663*/
664MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
665{
666 unsigned char
667 *data;
668
669 assert(blob_info != (BlobInfo *) NULL);
670 if (blob_info->debug != MagickFalse)
671 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
672 if (blob_info->mapped != MagickFalse)
673 (void) UnmapBlob(blob_info->data,blob_info->length);
674 blob_info->mapped=MagickFalse;
675 blob_info->length=0;
676 blob_info->offset=0;
677 blob_info->eof=MagickFalse;
678 blob_info->exempt=MagickFalse;
679 blob_info->type=UndefinedStream;
cristy95888612012-04-04 21:56:52 +0000680 blob_info->stream_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000681 data=blob_info->data;
682 blob_info->data=(unsigned char *) NULL;
683 blob_info->stream=(StreamHandler) NULL;
684 return(data);
685}
686
687/*
688%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689% %
690% %
691% %
cristyc1af14f2010-09-16 20:01:21 +0000692+ D i s c a r d B l o b B y t e s %
693% %
694% %
695% %
696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697%
698% DiscardBlobBytes() discards bytes in a blob.
699%
700% The format of the DiscardBlobBytes method is:
701%
702% MagickBooleanType DiscardBlobBytes(Image *image,const size_t length)
703%
704% A description of each parameter follows.
705%
706% o image: the image.
707%
708% o length: the number of bytes to skip.
709%
710*/
711
712static inline const unsigned char *ReadBlobStream(Image *image,
713 const size_t length,unsigned char *data,ssize_t *count)
714{
715 assert(count != (ssize_t *) NULL);
716 assert(image->blob != (BlobInfo *) NULL);
717 if (image->blob->type != BlobStream)
718 {
719 *count=ReadBlob(image,length,data);
720 return(data);
721 }
722 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
723 {
724 *count=0;
725 image->blob->eof=MagickTrue;
726 return(data);
727 }
728 data=image->blob->data+image->blob->offset;
cristy7753b2a2011-02-19 18:36:52 +0000729 *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
cristyc1af14f2010-09-16 20:01:21 +0000730 image->blob->offset));
731 image->blob->offset+=(*count);
732 if (*count != (ssize_t) length)
733 image->blob->eof=MagickTrue;
734 return(data);
735}
736
737MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
cristy7753b2a2011-02-19 18:36:52 +0000738 const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000739{
cristy7753b2a2011-02-19 18:36:52 +0000740 register MagickOffsetType
cristyc1af14f2010-09-16 20:01:21 +0000741 i;
742
743 size_t
744 quantum;
745
746 ssize_t
747 count;
748
749 unsigned char
cristyf55846d2010-09-17 19:01:10 +0000750 buffer[16384];
cristyc1af14f2010-09-16 20:01:21 +0000751
752 assert(image != (Image *) NULL);
753 assert(image->signature == MagickSignature);
754 count=0;
cristy7753b2a2011-02-19 18:36:52 +0000755 for (i=0; i < (MagickOffsetType) length; i+=count)
cristyc1af14f2010-09-16 20:01:21 +0000756 {
cristy7753b2a2011-02-19 18:36:52 +0000757 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
cristyc1af14f2010-09-16 20:01:21 +0000758 (void) ReadBlobStream(image,quantum,buffer,&count);
759 if (count <= 0)
760 {
761 count=0;
762 if (errno != EINTR)
763 break;
764 }
765 }
cristy7753b2a2011-02-19 18:36:52 +0000766 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
cristyc1af14f2010-09-16 20:01:21 +0000767}
768
769/*
770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
771% %
772% %
773% %
cristy3ed852e2009-09-05 21:47:34 +0000774+ D u p l i c a t e s B l o b %
775% %
776% %
777% %
778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
779%
780% DuplicateBlob() duplicates a blob descriptor.
781%
782% The format of the DuplicateBlob method is:
783%
784% void DuplicateBlob(Image *image,const Image *duplicate)
785%
786% A description of each parameter follows:
787%
788% o image: the image.
789%
790% o duplicate: the duplicate image.
791%
792*/
793MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
794{
795 assert(image != (Image *) NULL);
796 assert(image->signature == MagickSignature);
797 if (image->debug != MagickFalse)
798 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
799 assert(duplicate != (Image *) NULL);
800 assert(duplicate->signature == MagickSignature);
801 DestroyBlob(image);
802 image->blob=ReferenceBlob(duplicate->blob);
803}
804
805/*
806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
807% %
808% %
809% %
810+ E O F B l o b %
811% %
812% %
813% %
814%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
815%
816% EOFBlob() returns a non-zero value when EOF has been detected reading from
817% a blob or file.
818%
819% The format of the EOFBlob method is:
820%
821% int EOFBlob(const Image *image)
822%
823% A description of each parameter follows:
824%
825% o image: the image.
826%
827*/
828MagickExport int EOFBlob(const Image *image)
829{
830 assert(image != (Image *) NULL);
831 assert(image->signature == MagickSignature);
832 if (image->debug != MagickFalse)
833 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
834 assert(image->blob != (BlobInfo *) NULL);
835 assert(image->blob->type != UndefinedStream);
836 switch (image->blob->type)
837 {
838 case UndefinedStream:
839 break;
840 case FileStream:
841 case StandardStream:
842 case PipeStream:
843 {
cristy95888612012-04-04 21:56:52 +0000844 image->blob->eof=feof(image->blob->stream_info.file) != 0 ? MagickTrue :
845 MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000846 break;
847 }
848 case ZipStream:
849 {
850 image->blob->eof=MagickFalse;
851 break;
852 }
853 case BZipStream:
854 {
855#if defined(MAGICKCORE_BZLIB_DELEGATE)
856 int
857 status;
858
859 status=0;
cristy95888612012-04-04 21:56:52 +0000860 (void) BZ2_bzerror(image->blob->stream_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000861 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
862#endif
863 break;
864 }
865 case FifoStream:
866 {
867 image->blob->eof=MagickFalse;
868 break;
869 }
870 case BlobStream:
871 break;
872 }
873 return((int) image->blob->eof);
874}
875
876/*
877%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
878% %
879% %
880% %
881+ F i l e T o B l o b %
882% %
883% %
884% %
885%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
886%
cristy178edaf2011-01-23 03:42:39 +0000887% FileToBlob() returns the contents of a file as a buffer terminated with
888% the '\0' character. The length of the buffer (not including the extra
889% terminating '\0' character) is returned via the 'length' parameter. Free
890% the buffer with RelinquishMagickMemory().
cristy3ed852e2009-09-05 21:47:34 +0000891%
892% The format of the FileToBlob method is:
893%
894% unsigned char *FileToBlob(const char *filename,const size_t extent,
895% size_t *length,ExceptionInfo *exception)
896%
897% A description of each parameter follows:
898%
899% o blob: FileToBlob() returns the contents of a file as a blob. If
900% an error occurs NULL is returned.
901%
902% o filename: the filename.
903%
904% o extent: The maximum length of the blob.
905%
906% o length: On return, this reflects the actual length of the blob.
907%
908% o exception: return any errors or warnings in this structure.
909%
910*/
911MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
912 size_t *length,ExceptionInfo *exception)
913{
914 int
915 file;
916
917 MagickOffsetType
918 offset;
919
920 register size_t
921 i;
922
923 ssize_t
924 count;
925
926 unsigned char
927 *blob;
928
929 void
930 *map;
931
932 assert(filename != (const char *) NULL);
933 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
934 assert(exception != (ExceptionInfo *) NULL);
935 *length=0;
936 file=fileno(stdin);
937 if (LocaleCompare(filename,"-") != 0)
cristy18c6c272011-09-23 14:40:37 +0000938 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +0000939 if (file == -1)
940 {
941 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
942 return((unsigned char *) NULL);
943 }
cristy7f317702011-02-18 20:40:28 +0000944 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
cristy3ed852e2009-09-05 21:47:34 +0000945 count=0;
946 if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset)))
947 {
948 size_t
949 quantum;
950
951 struct stat
952 file_info;
953
954 /*
955 Stream is not seekable.
956 */
957 quantum=(size_t) MagickMaxBufferExtent;
958 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
cristy7753b2a2011-02-19 18:36:52 +0000959 quantum=(size_t) MagickMin((MagickSizeType) file_info.st_size,
960 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +0000961 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
962 for (i=0; blob != (unsigned char *) NULL; i+=count)
963 {
964 count=(ssize_t) read(file,blob+i,quantum);
965 if (count <= 0)
966 {
967 count=0;
968 if (errno != EINTR)
969 break;
970 }
971 if (~(1UL*i) < (quantum+1))
972 {
973 blob=(unsigned char *) RelinquishMagickMemory(blob);
974 break;
975 }
976 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
977 sizeof(*blob));
978 if ((size_t) (i+count) >= extent)
979 break;
980 }
cristy54439632010-07-15 00:43:34 +0000981 if (LocaleCompare(filename,"-") != 0)
982 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +0000983 if (blob == (unsigned char *) NULL)
984 {
985 (void) ThrowMagickException(exception,GetMagickModule(),
986 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
987 return((unsigned char *) NULL);
988 }
cristya7cb4312010-06-26 00:47:03 +0000989 if (file == -1)
990 {
991 blob=(unsigned char *) RelinquishMagickMemory(blob);
992 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
993 return((unsigned char *) NULL);
994 }
cristy7753b2a2011-02-19 18:36:52 +0000995 *length=(size_t) MagickMin(i+count,extent);
cristy3ed852e2009-09-05 21:47:34 +0000996 blob[*length]='\0';
997 return(blob);
998 }
cristy7753b2a2011-02-19 18:36:52 +0000999 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
cristy3ed852e2009-09-05 21:47:34 +00001000 blob=(unsigned char *) NULL;
cristy37e0b382011-06-07 13:31:21 +00001001 if (~(*length) >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +00001002 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1003 sizeof(*blob));
1004 if (blob == (unsigned char *) NULL)
1005 {
cristy54439632010-07-15 00:43:34 +00001006 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001007 (void) ThrowMagickException(exception,GetMagickModule(),
1008 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1009 return((unsigned char *) NULL);
1010 }
1011 map=MapBlob(file,ReadMode,0,*length);
1012 if (map != (unsigned char *) NULL)
1013 {
cristy54aad5e2010-09-03 16:02:04 +00001014 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +00001015 (void) UnmapBlob(map,*length);
1016 }
1017 else
1018 {
cristy7f317702011-02-18 20:40:28 +00001019 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001020 for (i=0; i < *length; i+=count)
1021 {
cristy7753b2a2011-02-19 18:36:52 +00001022 count=(ssize_t) read(file,blob+i,(size_t) MagickMin(*length-i,
1023 (MagickSizeType) SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001024 if (count <= 0)
1025 {
1026 count=0;
1027 if (errno != EINTR)
1028 break;
1029 }
1030 }
1031 if (i < *length)
1032 {
1033 file=close(file)-1;
1034 blob=(unsigned char *) RelinquishMagickMemory(blob);
1035 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1036 return((unsigned char *) NULL);
1037 }
1038 }
cristy3ed852e2009-09-05 21:47:34 +00001039 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001040 if (LocaleCompare(filename,"-") != 0)
1041 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001042 if (file == -1)
1043 {
1044 blob=(unsigned char *) RelinquishMagickMemory(blob);
1045 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1046 }
cristy3ed852e2009-09-05 21:47:34 +00001047 return(blob);
1048}
1049
1050/*
1051%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1052% %
1053% %
1054% %
1055% F i l e T o I m a g e %
1056% %
1057% %
1058% %
1059%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1060%
1061% FileToImage() write the contents of a file to an image.
1062%
1063% The format of the FileToImage method is:
1064%
1065% MagickBooleanType FileToImage(Image *,const char *filename)
1066%
1067% A description of each parameter follows:
1068%
1069% o image: the image.
1070%
1071% o filename: the filename.
1072%
1073*/
1074
1075static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1076 const unsigned char *data)
1077{
1078 MagickSizeType
1079 extent;
1080
1081 register unsigned char
1082 *q;
1083
1084 assert(image->blob != (BlobInfo *) NULL);
1085 if (image->blob->type != BlobStream)
1086 return(WriteBlob(image,length,data));
1087 assert(image->blob->type != UndefinedStream);
1088 assert(data != (void *) NULL);
1089 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1090 if (extent >= image->blob->extent)
1091 {
1092 image->blob->quantum<<=1;
1093 extent=image->blob->extent+image->blob->quantum+length;
1094 if (SetBlobExtent(image,extent) == MagickFalse)
1095 return(0);
1096 }
1097 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001098 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001099 image->blob->offset+=length;
1100 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1101 image->blob->length=(size_t) image->blob->offset;
1102 return((ssize_t) length);
1103}
1104
cristyc82a27b2011-10-21 01:07:16 +00001105MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1106 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001107{
1108 int
1109 file;
1110
1111 size_t
1112 length,
1113 quantum;
1114
1115 ssize_t
1116 count;
1117
1118 struct stat
1119 file_info;
1120
1121 unsigned char
1122 *blob;
1123
1124 assert(image != (const Image *) NULL);
1125 assert(image->signature == MagickSignature);
1126 assert(filename != (const char *) NULL);
1127 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
cristy18c6c272011-09-23 14:40:37 +00001128 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001129 if (file == -1)
1130 {
cristyc82a27b2011-10-21 01:07:16 +00001131 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001132 return(MagickFalse);
1133 }
1134 quantum=(size_t) MagickMaxBufferExtent;
1135 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
cristy7753b2a2011-02-19 18:36:52 +00001136 quantum=(size_t) MagickMin(file_info.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001137 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1138 if (blob == (unsigned char *) NULL)
1139 {
cristyc82a27b2011-10-21 01:07:16 +00001140 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1141 filename);
cristy3ed852e2009-09-05 21:47:34 +00001142 return(MagickFalse);
1143 }
1144 for ( ; ; )
1145 {
1146 count=(ssize_t) read(file,blob,quantum);
1147 if (count <= 0)
1148 {
1149 count=0;
1150 if (errno != EINTR)
1151 break;
1152 }
1153 length=(size_t) count;
1154 count=WriteBlobStream(image,length,blob);
1155 if (count != (ssize_t) length)
1156 {
cristyc82a27b2011-10-21 01:07:16 +00001157 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001158 break;
1159 }
1160 }
cristya7cb4312010-06-26 00:47:03 +00001161 file=close(file);
1162 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001163 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001164 blob=(unsigned char *) RelinquishMagickMemory(blob);
1165 return(MagickTrue);
1166}
1167
1168/*
1169%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1170% %
1171% %
1172% %
1173+ G e t B l o b E r r o r %
1174% %
1175% %
1176% %
1177%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1178%
1179% GetBlobError() returns MagickTrue if the blob associated with the specified
1180% image encountered an error.
1181%
1182% The format of the GetBlobError method is:
1183%
1184% MagickBooleanType GetBlobError(const Image *image)
1185%
1186% A description of each parameter follows:
1187%
1188% o image: the image.
1189%
1190*/
cristy7832dc22011-09-05 01:21:53 +00001191MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001192{
1193 assert(image != (const Image *) NULL);
1194 assert(image->signature == MagickSignature);
1195 if (image->debug != MagickFalse)
1196 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1197 return(image->blob->status);
1198}
1199
1200/*
1201%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1202% %
1203% %
1204% %
1205+ G e t B l o b F i l e H a n d l e %
1206% %
1207% %
1208% %
1209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1210%
1211% GetBlobFileHandle() returns the file handle associated with the image blob.
1212%
1213% The format of the GetBlobFile method is:
1214%
1215% FILE *GetBlobFileHandle(const Image *image)
1216%
1217% A description of each parameter follows:
1218%
1219% o image: the image.
1220%
1221*/
1222MagickExport FILE *GetBlobFileHandle(const Image *image)
1223{
1224 assert(image != (const Image *) NULL);
1225 assert(image->signature == MagickSignature);
cristy95888612012-04-04 21:56:52 +00001226 return(image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001227}
1228
1229/*
1230%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1231% %
1232% %
1233% %
1234+ G e t B l o b I n f o %
1235% %
1236% %
1237% %
1238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1239%
1240% GetBlobInfo() initializes the BlobInfo structure.
1241%
1242% The format of the GetBlobInfo method is:
1243%
1244% void GetBlobInfo(BlobInfo *blob_info)
1245%
1246% A description of each parameter follows:
1247%
1248% o blob_info: Specifies a pointer to a BlobInfo structure.
1249%
1250*/
cristy7832dc22011-09-05 01:21:53 +00001251MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001252{
1253 assert(blob_info != (BlobInfo *) NULL);
1254 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1255 blob_info->type=UndefinedStream;
1256 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1257 blob_info->properties.st_mtime=time((time_t *) NULL);
1258 blob_info->properties.st_ctime=time((time_t *) NULL);
1259 blob_info->debug=IsEventLogging();
1260 blob_info->reference_count=1;
1261 blob_info->semaphore=AllocateSemaphoreInfo();
1262 blob_info->signature=MagickSignature;
1263}
1264
1265/*
1266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1267% %
1268% %
1269% %
1270% G e t B l o b P r o p e r t i e s %
1271% %
1272% %
1273% %
1274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1275%
1276% GetBlobProperties() returns information about an image blob.
1277%
1278% The format of the GetBlobProperties method is:
1279%
1280% const struct stat *GetBlobProperties(const Image *image)
1281%
1282% A description of each parameter follows:
1283%
1284% o image: the image.
1285%
1286*/
cristy7832dc22011-09-05 01:21:53 +00001287MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001288{
1289 assert(image != (Image *) NULL);
1290 assert(image->signature == MagickSignature);
1291 if (image->debug != MagickFalse)
1292 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1293 return(&image->blob->properties);
1294}
1295
1296/*
1297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1298% %
1299% %
1300% %
1301+ G e t B l o b S i z e %
1302% %
1303% %
1304% %
1305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1306%
1307% GetBlobSize() returns the current length of the image file or blob; zero is
1308% returned if the size cannot be determined.
1309%
1310% The format of the GetBlobSize method is:
1311%
1312% MagickSizeType GetBlobSize(const Image *image)
1313%
1314% A description of each parameter follows:
1315%
1316% o image: the image.
1317%
1318*/
1319MagickExport MagickSizeType GetBlobSize(const Image *image)
1320{
1321 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001322 extent;
cristy3ed852e2009-09-05 21:47:34 +00001323
1324 assert(image != (Image *) NULL);
1325 assert(image->signature == MagickSignature);
1326 if (image->debug != MagickFalse)
1327 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1328 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001329 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001330 switch (image->blob->type)
1331 {
1332 case UndefinedStream:
1333 {
cristy81b8ce52010-02-05 01:53:17 +00001334 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001335 break;
1336 }
1337 case FileStream:
1338 {
cristy95888612012-04-04 21:56:52 +00001339 if (fstat(fileno(image->blob->stream_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001340 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001341 break;
1342 }
1343 case StandardStream:
1344 case PipeStream:
1345 {
cristy81b8ce52010-02-05 01:53:17 +00001346 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001347 break;
1348 }
1349 case ZipStream:
1350 case BZipStream:
1351 {
1352 MagickBooleanType
1353 status;
1354
1355 status=GetPathAttributes(image->filename,&image->blob->properties);
1356 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001357 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001358 break;
1359 }
1360 case FifoStream:
1361 break;
1362 case BlobStream:
1363 {
cristy891dc792010-03-04 01:47:16 +00001364 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001365 break;
1366 }
1367 }
cristy81b8ce52010-02-05 01:53:17 +00001368 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001369}
1370
1371/*
1372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1373% %
1374% %
1375% %
1376+ G e t B l o b S t r e a m D a t a %
1377% %
1378% %
1379% %
1380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1381%
1382% GetBlobStreamData() returns the stream data for the image.
1383%
1384% The format of the GetBlobStreamData method is:
1385%
1386% unsigned char *GetBlobStreamData(const Image *image)
1387%
1388% A description of each parameter follows:
1389%
1390% o image: the image.
1391%
1392*/
1393MagickExport unsigned char *GetBlobStreamData(const Image *image)
1394{
1395 assert(image != (const Image *) NULL);
1396 assert(image->signature == MagickSignature);
1397 return(image->blob->data);
1398}
1399
1400/*
1401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1402% %
1403% %
1404% %
1405+ G e t B l o b S t r e a m H a n d l e r %
1406% %
1407% %
1408% %
1409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1410%
1411% GetBlobStreamHandler() returns the stream handler for the image.
1412%
1413% The format of the GetBlobStreamHandler method is:
1414%
1415% StreamHandler GetBlobStreamHandler(const Image *image)
1416%
1417% A description of each parameter follows:
1418%
1419% o image: the image.
1420%
1421*/
cristy7832dc22011-09-05 01:21:53 +00001422MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001423{
1424 assert(image != (const Image *) NULL);
1425 assert(image->signature == MagickSignature);
1426 if (image->debug != MagickFalse)
1427 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1428 return(image->blob->stream);
1429}
1430
1431/*
1432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1433% %
1434% %
1435% %
1436% I m a g e T o B l o b %
1437% %
1438% %
1439% %
1440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1441%
1442% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001443% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001444% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001445% etc.). This method is the equivalent of WriteImage(), but writes the
1446% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001447%
1448% The format of the ImageToBlob method is:
1449%
1450% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1451% size_t *length,ExceptionInfo *exception)
1452%
1453% A description of each parameter follows:
1454%
1455% o image_info: the image info.
1456%
1457% o image: the image.
1458%
1459% o length: This pointer to a size_t integer sets the initial length of the
1460% blob. On return, it reflects the actual length of the blob.
1461%
1462% o exception: return any errors or warnings in this structure.
1463%
1464*/
1465MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1466 Image *image,size_t *length,ExceptionInfo *exception)
1467{
1468 const MagickInfo
1469 *magick_info;
1470
1471 ImageInfo
1472 *blob_info;
1473
1474 MagickBooleanType
1475 status;
1476
1477 unsigned char
1478 *blob;
1479
1480 assert(image_info != (const ImageInfo *) NULL);
1481 assert(image_info->signature == MagickSignature);
1482 if (image_info->debug != MagickFalse)
1483 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1484 image_info->filename);
1485 assert(image != (Image *) NULL);
1486 assert(image->signature == MagickSignature);
1487 assert(exception != (ExceptionInfo *) NULL);
1488 *length=0;
1489 blob=(unsigned char *) NULL;
1490 blob_info=CloneImageInfo(image_info);
1491 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001492 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001493 if (*blob_info->magick != '\0')
1494 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1495 magick_info=GetMagickInfo(image->magick,exception);
1496 if (magick_info == (const MagickInfo *) NULL)
1497 {
1498 (void) ThrowMagickException(exception,GetMagickModule(),
1499 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1500 image->filename);
1501 return(blob);
1502 }
1503 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1504 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1505 {
1506 /*
1507 Native blob support for this image format.
1508 */
1509 blob_info->length=0;
1510 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1511 sizeof(unsigned char));
1512 if (blob_info->blob == (void *) NULL)
1513 (void) ThrowMagickException(exception,GetMagickModule(),
1514 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1515 else
1516 {
1517 (void) CloseBlob(image);
1518 image->blob->exempt=MagickTrue;
1519 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001520 status=WriteImage(blob_info,image,exception);
1521 if ((status != MagickFalse) && (image->blob->length != 0))
cristy3ed852e2009-09-05 21:47:34 +00001522 {
1523 *length=image->blob->length;
1524 blob=DetachBlob(image->blob);
1525 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1526 sizeof(*blob));
1527 }
1528 }
1529 }
1530 else
1531 {
1532 char
1533 unique[MaxTextExtent];
1534
1535 int
1536 file;
1537
1538 /*
1539 Write file to disk in blob image format.
1540 */
1541 file=AcquireUniqueFileResource(unique);
1542 if (file == -1)
1543 {
1544 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1545 image_info->filename);
1546 }
1547 else
1548 {
1549 blob_info->file=fdopen(file,"wb");
1550 if (blob_info->file != (FILE *) NULL)
1551 {
cristyb51dff52011-05-19 16:55:47 +00001552 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001553 image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001554 status=WriteImage(blob_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001555 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001556 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001557 blob=FileToBlob(image->filename,~0UL,length,exception);
1558 }
1559 (void) RelinquishUniqueFileResource(unique);
1560 }
1561 }
1562 blob_info=DestroyImageInfo(blob_info);
1563 return(blob);
1564}
1565
1566/*
1567%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1568% %
1569% %
1570% %
1571% I m a g e T o F i l e %
1572% %
1573% %
1574% %
1575%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1576%
1577% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1578% occurs otherwise MagickTrue.
1579%
1580% The format of the ImageToFile method is:
1581%
1582% MagickBooleanType ImageToFile(Image *image,char *filename,
1583% ExceptionInfo *exception)
1584%
1585% A description of each parameter follows:
1586%
1587% o image: the image.
1588%
1589% o filename: Write the image to this file.
1590%
1591% o exception: return any errors or warnings in this structure.
1592%
1593*/
cristy3ed852e2009-09-05 21:47:34 +00001594MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1595 ExceptionInfo *exception)
1596{
1597 int
1598 file;
1599
1600 register const unsigned char
1601 *p;
1602
1603 register size_t
1604 i;
1605
1606 size_t
1607 length,
1608 quantum;
1609
1610 ssize_t
1611 count;
1612
1613 struct stat
1614 file_info;
1615
1616 unsigned char
1617 *buffer;
1618
1619 assert(image != (Image *) NULL);
1620 assert(image->signature == MagickSignature);
1621 assert(image->blob != (BlobInfo *) NULL);
1622 assert(image->blob->type != UndefinedStream);
1623 if (image->debug != MagickFalse)
1624 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1625 assert(filename != (const char *) NULL);
1626 if (*filename == '\0')
1627 file=AcquireUniqueFileResource(filename);
1628 else
1629 if (LocaleCompare(filename,"-") == 0)
1630 file=fileno(stdout);
1631 else
cristyb70aab92012-01-31 15:04:04 +00001632 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001633 if (file == -1)
1634 {
1635 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1636 return(MagickFalse);
1637 }
1638 quantum=(size_t) MagickMaxBufferExtent;
1639 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
cristy7753b2a2011-02-19 18:36:52 +00001640 quantum=(size_t) MagickMin((MagickSizeType) file_info.st_size,
1641 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001642 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1643 if (buffer == (unsigned char *) NULL)
1644 {
1645 file=close(file)-1;
1646 (void) ThrowMagickException(exception,GetMagickModule(),
1647 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1648 return(MagickFalse);
1649 }
1650 length=0;
1651 p=ReadBlobStream(image,quantum,buffer,&count);
1652 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1653 {
1654 length=(size_t) count;
1655 for (i=0; i < length; i+=count)
1656 {
1657 count=write(file,p+i,(size_t) (length-i));
1658 if (count <= 0)
1659 {
1660 count=0;
1661 if (errno != EINTR)
1662 break;
1663 }
1664 }
1665 if (i < length)
1666 break;
1667 }
cristy54439632010-07-15 00:43:34 +00001668 if (LocaleCompare(filename,"-") != 0)
1669 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001670 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001671 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001672 {
1673 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1674 return(MagickFalse);
1675 }
1676 return(MagickTrue);
1677}
1678
1679/*
1680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1681% %
1682% %
1683% %
1684% I m a g e s T o B l o b %
1685% %
1686% %
1687% %
1688%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1689%
1690% ImagesToBlob() implements direct to memory image formats. It returns the
1691% image sequence as a blob and its length. The magick member of the ImageInfo
1692% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1693%
1694% Note, some image formats do not permit multiple images to the same image
1695% stream (e.g. JPEG). in this instance, just the first image of the
1696% sequence is returned as a blob.
1697%
1698% The format of the ImagesToBlob method is:
1699%
1700% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1701% size_t *length,ExceptionInfo *exception)
1702%
1703% A description of each parameter follows:
1704%
1705% o image_info: the image info.
1706%
1707% o images: the image list.
1708%
1709% o length: This pointer to a size_t integer sets the initial length of the
1710% blob. On return, it reflects the actual length of the blob.
1711%
1712% o exception: return any errors or warnings in this structure.
1713%
1714*/
1715MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1716 Image *images,size_t *length,ExceptionInfo *exception)
1717{
1718 const MagickInfo
1719 *magick_info;
1720
1721 ImageInfo
1722 *blob_info;
1723
1724 MagickBooleanType
1725 status;
1726
1727 unsigned char
1728 *blob;
1729
1730 assert(image_info != (const ImageInfo *) NULL);
1731 assert(image_info->signature == MagickSignature);
1732 if (image_info->debug != MagickFalse)
1733 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1734 image_info->filename);
1735 assert(images != (Image *) NULL);
1736 assert(images->signature == MagickSignature);
1737 assert(exception != (ExceptionInfo *) NULL);
1738 *length=0;
1739 blob=(unsigned char *) NULL;
1740 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001741 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1742 exception);
cristy3ed852e2009-09-05 21:47:34 +00001743 if (*blob_info->magick != '\0')
1744 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1745 if (blob_info->adjoin == MagickFalse)
1746 {
1747 blob_info=DestroyImageInfo(blob_info);
1748 return(ImageToBlob(image_info,images,length,exception));
1749 }
1750 magick_info=GetMagickInfo(images->magick,exception);
1751 if (magick_info == (const MagickInfo *) NULL)
1752 {
1753 (void) ThrowMagickException(exception,GetMagickModule(),
1754 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1755 images->filename);
1756 return(blob);
1757 }
1758 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1759 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1760 {
1761 /*
1762 Native blob support for this images format.
1763 */
1764 blob_info->length=0;
1765 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1766 sizeof(unsigned char));
1767 if (blob_info->blob == (void *) NULL)
1768 (void) ThrowMagickException(exception,GetMagickModule(),
1769 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
1770 else
1771 {
1772 images->blob->exempt=MagickTrue;
1773 *images->filename='\0';
1774 status=WriteImages(blob_info,images,images->filename,exception);
cristyb24e2402011-10-07 00:48:39 +00001775 if ((status != MagickFalse) && (images->blob->length != 0))
cristy3ed852e2009-09-05 21:47:34 +00001776 {
1777 *length=images->blob->length;
1778 blob=DetachBlob(images->blob);
1779 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1780 sizeof(*blob));
1781 }
1782 }
1783 }
1784 else
1785 {
1786 char
1787 filename[MaxTextExtent],
1788 unique[MaxTextExtent];
1789
1790 int
1791 file;
1792
1793 /*
1794 Write file to disk in blob images format.
1795 */
1796 file=AcquireUniqueFileResource(unique);
1797 if (file == -1)
1798 {
1799 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1800 image_info->filename);
1801 }
1802 else
1803 {
1804 blob_info->file=fdopen(file,"wb");
1805 if (blob_info->file != (FILE *) NULL)
1806 {
cristyb51dff52011-05-19 16:55:47 +00001807 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001808 images->magick,unique);
1809 status=WriteImages(blob_info,images,filename,exception);
1810 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001811 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001812 blob=FileToBlob(images->filename,~0UL,length,exception);
1813 }
1814 (void) RelinquishUniqueFileResource(unique);
1815 }
1816 }
1817 blob_info=DestroyImageInfo(blob_info);
1818 return(blob);
1819}
1820/*
1821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1822% %
1823% %
1824% %
1825% I n j e c t I m a g e B l o b %
1826% %
1827% %
1828% %
1829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1830%
1831% InjectImageBlob() injects the image with a copy of itself in the specified
1832% format (e.g. inject JPEG into a PDF image).
1833%
1834% The format of the InjectImageBlob method is:
1835%
1836% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1837% Image *image,Image *inject_image,const char *format,
1838% ExceptionInfo *exception)
1839%
1840% A description of each parameter follows:
1841%
1842% o image_info: the image info..
1843%
1844% o image: the image.
1845%
1846% o inject_image: inject into the image stream.
1847%
1848% o format: the image format.
1849%
1850% o exception: return any errors or warnings in this structure.
1851%
1852*/
1853MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1854 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1855{
1856 char
1857 filename[MaxTextExtent];
1858
1859 FILE
1860 *unique_file;
1861
1862 Image
1863 *byte_image;
1864
1865 ImageInfo
1866 *write_info;
1867
1868 int
1869 file;
1870
1871 MagickBooleanType
1872 status;
1873
cristybb503372010-05-27 20:51:26 +00001874 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001875 i;
1876
1877 size_t
1878 quantum;
1879
1880 ssize_t
1881 count;
1882
1883 struct stat
1884 file_info;
1885
1886 unsigned char
1887 *buffer;
1888
1889 /*
1890 Write inject image to a temporary file.
1891 */
1892 assert(image_info != (ImageInfo *) NULL);
1893 assert(image_info->signature == MagickSignature);
1894 assert(image != (Image *) NULL);
1895 assert(image->signature == MagickSignature);
1896 if (image->debug != MagickFalse)
1897 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1898 assert(inject_image != (Image *) NULL);
1899 assert(inject_image->signature == MagickSignature);
1900 assert(exception != (ExceptionInfo *) NULL);
1901 unique_file=(FILE *) NULL;
1902 file=AcquireUniqueFileResource(filename);
1903 if (file != -1)
1904 unique_file=fdopen(file,"wb");
1905 if ((file == -1) || (unique_file == (FILE *) NULL))
1906 {
1907 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1908 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1909 image->filename);
1910 return(MagickFalse);
1911 }
1912 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1913 if (byte_image == (Image *) NULL)
1914 {
1915 (void) fclose(unique_file);
1916 (void) RelinquishUniqueFileResource(filename);
1917 return(MagickFalse);
1918 }
cristyb51dff52011-05-19 16:55:47 +00001919 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001920 filename);
1921 DestroyBlob(byte_image);
1922 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1923 write_info=CloneImageInfo(image_info);
1924 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001925 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001926 write_info=DestroyImageInfo(write_info);
1927 byte_image=DestroyImage(byte_image);
1928 (void) fclose(unique_file);
1929 if (status == MagickFalse)
1930 {
1931 (void) RelinquishUniqueFileResource(filename);
1932 return(MagickFalse);
1933 }
1934 /*
1935 Inject into image stream.
1936 */
cristy18c6c272011-09-23 14:40:37 +00001937 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001938 if (file == -1)
1939 {
1940 (void) RelinquishUniqueFileResource(filename);
1941 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1942 image_info->filename);
1943 return(MagickFalse);
1944 }
1945 quantum=(size_t) MagickMaxBufferExtent;
1946 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
cristy7753b2a2011-02-19 18:36:52 +00001947 quantum=(size_t) MagickMin(file_info.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001948 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1949 if (buffer == (unsigned char *) NULL)
1950 {
1951 (void) RelinquishUniqueFileResource(filename);
1952 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1953 image->filename);
1954 }
1955 for (i=0; ; i+=count)
1956 {
1957 count=(ssize_t) read(file,buffer,quantum);
1958 if (count <= 0)
1959 {
1960 count=0;
1961 if (errno != EINTR)
1962 break;
1963 }
1964 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1965 MagickFalse;
1966 }
cristya7cb4312010-06-26 00:47:03 +00001967 file=close(file);
1968 if (file == -1)
1969 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001970 (void) RelinquishUniqueFileResource(filename);
1971 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1972 return(status);
1973}
1974
1975/*
1976%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1977% %
1978% %
1979% %
1980+ I s B l o b E x e m p t %
1981% %
1982% %
1983% %
1984%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1985%
1986% IsBlobExempt() returns true if the blob is exempt.
1987%
1988% The format of the IsBlobExempt method is:
1989%
1990% MagickBooleanType IsBlobExempt(const Image *image)
1991%
1992% A description of each parameter follows:
1993%
1994% o image: the image.
1995%
1996*/
cristy7832dc22011-09-05 01:21:53 +00001997MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001998{
1999 assert(image != (const Image *) NULL);
2000 assert(image->signature == MagickSignature);
2001 if (image->debug != MagickFalse)
2002 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2003 return(image->blob->exempt);
2004}
2005
2006/*
2007%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2008% %
2009% %
2010% %
2011+ I s B l o b S e e k a b l e %
2012% %
2013% %
2014% %
2015%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2016%
2017% IsBlobSeekable() returns true if the blob is seekable.
2018%
2019% The format of the IsBlobSeekable method is:
2020%
2021% MagickBooleanType IsBlobSeekable(const Image *image)
2022%
2023% A description of each parameter follows:
2024%
2025% o image: the image.
2026%
2027*/
cristy7832dc22011-09-05 01:21:53 +00002028MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002029{
2030 MagickBooleanType
2031 seekable;
2032
2033 assert(image != (const Image *) NULL);
2034 assert(image->signature == MagickSignature);
2035 if (image->debug != MagickFalse)
2036 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002037 switch (image->blob->type)
2038 {
2039 case FileStream:
2040 case BlobStream:
2041 case ZipStream:
2042 {
2043 seekable=MagickTrue;
2044 break;
2045 }
2046 default:
2047 {
2048 seekable=MagickFalse;
2049 break;
2050 }
2051 }
cristy3ed852e2009-09-05 21:47:34 +00002052 return(seekable);
2053}
2054
2055/*
2056%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2057% %
2058% %
2059% %
2060+ I s B l o b T e m p o r a r y %
2061% %
2062% %
2063% %
2064%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2065%
2066% IsBlobTemporary() returns true if the blob is temporary.
2067%
2068% The format of the IsBlobTemporary method is:
2069%
2070% MagickBooleanType IsBlobTemporary(const Image *image)
2071%
2072% A description of each parameter follows:
2073%
2074% o image: the image.
2075%
2076*/
cristy7832dc22011-09-05 01:21:53 +00002077MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002078{
2079 assert(image != (const Image *) NULL);
2080 assert(image->signature == MagickSignature);
2081 if (image->debug != MagickFalse)
2082 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2083 return(image->blob->temporary);
2084}
2085
2086/*
2087%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2088% %
2089% %
2090% %
2091+ M a p B l o b %
2092% %
2093% %
2094% %
2095%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2096%
2097% MapBlob() creates a mapping from a file to a binary large object.
2098%
2099% The format of the MapBlob method is:
2100%
2101% unsigned char *MapBlob(int file,const MapMode mode,
2102% const MagickOffsetType offset,const size_t length)
2103%
2104% A description of each parameter follows:
2105%
2106% o file: map this file descriptor.
2107%
2108% o mode: ReadMode, WriteMode, or IOMode.
2109%
2110% o offset: starting at this offset within the file.
2111%
2112% o length: the length of the mapping is returned in this pointer.
2113%
2114*/
2115MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2116 const MagickOffsetType offset,const size_t length)
2117{
2118#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
2119 int
2120 flags,
2121 protection;
2122
2123 unsigned char
2124 *map;
2125
2126 /*
2127 Map file.
2128 */
2129 flags=0;
2130 if (file == -1)
2131#if defined(MAP_ANONYMOUS)
2132 flags|=MAP_ANONYMOUS;
2133#else
2134 return((unsigned char *) NULL);
2135#endif
2136 switch (mode)
2137 {
2138 case ReadMode:
2139 default:
2140 {
2141 protection=PROT_READ;
2142 flags|=MAP_PRIVATE;
2143 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2144 (off_t) offset);
2145 break;
2146 }
2147 case WriteMode:
2148 {
2149 protection=PROT_WRITE;
2150 flags|=MAP_SHARED;
2151 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2152 (off_t) offset);
cristy2a9e7cb2010-03-05 02:15:05 +00002153#if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
2154 (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
2155 POSIX_MADV_WILLNEED);
2156#endif
cristy3ed852e2009-09-05 21:47:34 +00002157 break;
2158 }
2159 case IOMode:
2160 {
2161 protection=PROT_READ | PROT_WRITE;
2162 flags|=MAP_SHARED;
2163 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2164 (off_t) offset);
2165 break;
2166 }
2167 }
2168 if (map == (unsigned char *) MAP_FAILED)
2169 return((unsigned char *) NULL);
2170 return(map);
2171#else
2172 (void) file;
2173 (void) mode;
2174 (void) offset;
2175 (void) length;
2176 return((unsigned char *) NULL);
2177#endif
2178}
2179
2180/*
2181%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2182% %
2183% %
2184% %
2185+ M S B O r d e r L o n g %
2186% %
2187% %
2188% %
2189%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2190%
2191% MSBOrderLong() converts a least-significant byte first buffer of integers to
2192% most-significant byte first.
2193%
2194% The format of the MSBOrderLong method is:
2195%
2196% void MSBOrderLong(unsigned char *buffer,const size_t length)
2197%
2198% A description of each parameter follows.
2199%
2200% o buffer: Specifies a pointer to a buffer of integers.
2201%
2202% o length: Specifies the length of the buffer.
2203%
2204*/
2205MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2206{
2207 int
2208 c;
2209
2210 register unsigned char
2211 *p,
2212 *q;
2213
2214 assert(buffer != (unsigned char *) NULL);
2215 q=buffer+length;
2216 while (buffer < q)
2217 {
2218 p=buffer+3;
2219 c=(int) (*p);
2220 *p=(*buffer);
2221 *buffer++=(unsigned char) c;
2222 p=buffer+1;
2223 c=(int) (*p);
2224 *p=(*buffer);
2225 *buffer++=(unsigned char) c;
2226 buffer+=2;
2227 }
2228}
2229
2230/*
2231%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2232% %
2233% %
2234% %
2235+ M S B O r d e r S h o r t %
2236% %
2237% %
2238% %
2239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2240%
2241% MSBOrderShort() converts a least-significant byte first buffer of integers
2242% to most-significant byte first.
2243%
2244% The format of the MSBOrderShort method is:
2245%
2246% void MSBOrderShort(unsigned char *p,const size_t length)
2247%
2248% A description of each parameter follows.
2249%
2250% o p: Specifies a pointer to a buffer of integers.
2251%
2252% o length: Specifies the length of the buffer.
2253%
2254*/
2255MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2256{
2257 int
2258 c;
2259
2260 register unsigned char
2261 *q;
2262
2263 assert(p != (unsigned char *) NULL);
2264 q=p+length;
2265 while (p < q)
2266 {
2267 c=(int) (*p);
2268 *p=(*(p+1));
2269 p++;
2270 *p++=(unsigned char) c;
2271 }
2272}
2273
2274/*
2275%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2276% %
2277% %
2278% %
2279+ O p e n B l o b %
2280% %
2281% %
2282% %
2283%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2284%
2285% OpenBlob() opens a file associated with the image. A file name of '-' sets
2286% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2287% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2288% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2289% from a system command.
2290%
2291% The format of the OpenBlob method is:
2292%
2293% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2294% const BlobMode mode,ExceptionInfo *exception)
2295%
2296% A description of each parameter follows:
2297%
2298% o image_info: the image info.
2299%
2300% o image: the image.
2301%
2302% o mode: the mode for opening the file.
2303%
2304*/
2305MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2306 Image *image,const BlobMode mode,ExceptionInfo *exception)
2307{
2308 char
cristybf6a7092010-06-11 02:12:15 +00002309 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002310 filename[MaxTextExtent];
2311
2312 const char
2313 *type;
2314
2315 MagickBooleanType
2316 status;
2317
2318 PolicyRights
2319 rights;
2320
2321 assert(image_info != (ImageInfo *) NULL);
2322 assert(image_info->signature == MagickSignature);
2323 if (image_info->debug != MagickFalse)
2324 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2325 image_info->filename);
2326 assert(image != (Image *) NULL);
2327 assert(image->signature == MagickSignature);
2328 if (image_info->blob != (void *) NULL)
2329 {
2330 if (image_info->stream != (StreamHandler) NULL)
2331 image->blob->stream=(StreamHandler) image_info->stream;
2332 AttachBlob(image->blob,image_info->blob,image_info->length);
2333 return(MagickTrue);
2334 }
2335 (void) DetachBlob(image->blob);
2336 switch (mode)
2337 {
2338 default: type="r"; break;
2339 case ReadBlobMode: type="r"; break;
2340 case ReadBinaryBlobMode: type="rb"; break;
2341 case WriteBlobMode: type="w"; break;
2342 case WriteBinaryBlobMode: type="w+b"; break;
2343 case AppendBlobMode: type="a"; break;
2344 case AppendBinaryBlobMode: type="a+b"; break;
2345 }
2346 if (*type != 'r')
2347 image->blob->synchronize=image_info->synchronize;
2348 if (image_info->stream != (StreamHandler) NULL)
2349 {
2350 image->blob->stream=(StreamHandler) image_info->stream;
2351 if (*type == 'w')
2352 {
2353 image->blob->type=FifoStream;
2354 return(MagickTrue);
2355 }
2356 }
2357 /*
2358 Open image file.
2359 */
2360 *filename='\0';
2361 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2362 rights=ReadPolicyRights;
2363 if (*type == 'w')
2364 rights=WritePolicyRights;
2365 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2366 {
cristya9197f62010-01-12 02:23:34 +00002367 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002368 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2369 "NotAuthorized","`%s'",filename);
2370 return(MagickFalse);
2371 }
2372 if ((LocaleCompare(filename,"-") == 0) ||
2373 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2374 {
cristy95888612012-04-04 21:56:52 +00002375 image->blob->stream_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002376#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002377 if (strchr(type,'b') != (char *) NULL)
cristy95888612012-04-04 21:56:52 +00002378 setmode(_fileno(image->blob->stream_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002379#endif
2380 image->blob->type=StandardStream;
2381 image->blob->exempt=MagickTrue;
2382 return(MagickTrue);
2383 }
2384 if (LocaleNCompare(filename,"fd:",3) == 0)
2385 {
2386 char
2387 mode[MaxTextExtent];
2388
2389 *mode=(*type);
2390 mode[1]='\0';
cristy95888612012-04-04 21:56:52 +00002391 image->blob->stream_info.file=fdopen(StringToLong(filename+3),mode);
cristy0157aea2010-04-24 21:12:18 +00002392#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002393 if (strchr(type,'b') != (char *) NULL)
cristy95888612012-04-04 21:56:52 +00002394 setmode(_fileno(image->blob->stream_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002395#endif
2396 image->blob->type=StandardStream;
2397 image->blob->exempt=MagickTrue;
2398 return(MagickTrue);
2399 }
2400#if defined(MAGICKCORE_HAVE_POPEN)
2401 if (*filename == '|')
2402 {
2403 char
2404 mode[MaxTextExtent];
2405
2406 /*
2407 Pipe image to or from a system command.
2408 */
2409#if defined(SIGPIPE)
2410 if (*type == 'w')
2411 (void) signal(SIGPIPE,SIG_IGN);
2412#endif
2413 *mode=(*type);
2414 mode[1]='\0';
cristy95888612012-04-04 21:56:52 +00002415 image->blob->stream_info.file=(FILE *) popen_utf8(filename+1,mode);
2416 if (image->blob->stream_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002417 {
2418 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2419 return(MagickFalse);
2420 }
2421 image->blob->type=PipeStream;
2422 image->blob->exempt=MagickTrue;
2423 return(MagickTrue);
2424 }
2425#endif
2426 status=GetPathAttributes(filename,&image->blob->properties);
2427#if defined(S_ISFIFO)
2428 if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2429 {
cristy95888612012-04-04 21:56:52 +00002430 image->blob->stream_info.file=(FILE *) fopen_utf8(filename,type);
2431 if (image->blob->stream_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002432 {
2433 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2434 return(MagickFalse);
2435 }
2436 image->blob->type=FileStream;
2437 image->blob->exempt=MagickTrue;
2438 return(MagickTrue);
2439 }
2440#endif
cristybf6a7092010-06-11 02:12:15 +00002441 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002442 if (*type == 'w')
2443 {
cristye8939e72010-02-03 17:05:25 +00002444 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002445 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002446 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002447 {
2448 /*
2449 Form filename for multi-part images.
2450 */
2451 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002452 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002453 if ((LocaleCompare(filename,image->filename) == 0) &&
2454 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2455 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002456 {
cristybf7fa0d2010-02-04 00:51:10 +00002457 char
cristybf7fa0d2010-02-04 00:51:10 +00002458 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002459
cristybf7fa0d2010-02-04 00:51:10 +00002460 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002461 if (*extension == '\0')
cristyb51dff52011-05-19 16:55:47 +00002462 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002463 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002464 else
cristyb51dff52011-05-19 16:55:47 +00002465 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002466 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002467 }
2468 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002469#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002470 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002471#endif
cristye8939e72010-02-03 17:05:25 +00002472 }
cristy3ed852e2009-09-05 21:47:34 +00002473 }
cristybf6a7092010-06-11 02:12:15 +00002474 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002475 {
cristy95888612012-04-04 21:56:52 +00002476 image->blob->stream_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002477 image->blob->type=FileStream;
2478 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002479 }
2480 else
cristybf6a7092010-06-11 02:12:15 +00002481 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002482 {
cristy95888612012-04-04 21:56:52 +00002483 image->blob->stream_info.file=(FILE *) fopen_utf8(filename,type);
2484 if (image->blob->stream_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002485 {
2486 size_t
cristybf6a7092010-06-11 02:12:15 +00002487 count;
cristy3ed852e2009-09-05 21:47:34 +00002488
cristybf6a7092010-06-11 02:12:15 +00002489 unsigned char
2490 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002491
cristybf6a7092010-06-11 02:12:15 +00002492 image->blob->type=FileStream;
2493#if defined(MAGICKCORE_HAVE_SETVBUF)
cristy95888612012-04-04 21:56:52 +00002494 (void) setvbuf(image->blob->stream_info.file,(char *) NULL,
2495 (int) _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002496#endif
2497 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristy95888612012-04-04 21:56:52 +00002498 count=fread(magick,1,sizeof(magick),image->blob->stream_info.file);
2499 (void) rewind(image->blob->stream_info.file);
cristybf6a7092010-06-11 02:12:15 +00002500 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2501 " read %.20g magic header bytes",(double) count);
2502#if defined(MAGICKCORE_ZLIB_DELEGATE)
2503 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2504 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002505 {
cristy95888612012-04-04 21:56:52 +00002506 (void) fclose(image->blob->stream_info.file);
2507 image->blob->stream_info.gzfile=gzopen(filename,type);
2508 if (image->blob->stream_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002509 image->blob->type=ZipStream;
2510 }
2511#endif
2512#if defined(MAGICKCORE_BZLIB_DELEGATE)
2513 if (strncmp((char *) magick,"BZh",3) == 0)
2514 {
cristy95888612012-04-04 21:56:52 +00002515 (void) fclose(image->blob->stream_info.file);
2516 image->blob->stream_info.bzfile=BZ2_bzopen(filename,type);
2517 if (image->blob->stream_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002518 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002519 }
cristybf6a7092010-06-11 02:12:15 +00002520#endif
cristyc6c589d2010-07-06 01:34:57 +00002521 if (image->blob->type == FileStream)
2522 {
2523 const MagickInfo
2524 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002525
cristyc6c589d2010-07-06 01:34:57 +00002526 ExceptionInfo
2527 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002528
cristyc6c589d2010-07-06 01:34:57 +00002529 struct stat
2530 *properties;
cristybf6a7092010-06-11 02:12:15 +00002531
cristyc6c589d2010-07-06 01:34:57 +00002532 sans_exception=AcquireExceptionInfo();
2533 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2534 sans_exception=DestroyExceptionInfo(sans_exception);
2535 properties=(&image->blob->properties);
2536 if ((magick_info != (const MagickInfo *) NULL) &&
2537 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2538 (properties->st_size <= MagickMaxBufferExtent))
2539 {
2540 size_t
2541 length;
cristybf6a7092010-06-11 02:12:15 +00002542
cristyc6c589d2010-07-06 01:34:57 +00002543 void
2544 *blob;
cristybf6a7092010-06-11 02:12:15 +00002545
cristyc6c589d2010-07-06 01:34:57 +00002546 length=(size_t) properties->st_size;
cristy95888612012-04-04 21:56:52 +00002547 blob=MapBlob(fileno(image->blob->stream_info.file),ReadMode,
2548 0,length);
cristyc6c589d2010-07-06 01:34:57 +00002549 if (blob != (void *) NULL)
2550 {
2551 /*
2552 Format supports blobs-- use memory-mapped I/O.
2553 */
2554 if (image_info->file != (FILE *) NULL)
2555 image->blob->exempt=MagickFalse;
2556 else
2557 {
cristy95888612012-04-04 21:56:52 +00002558 (void) fclose(image->blob->stream_info.file);
2559 image->blob->stream_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002560 }
2561 AttachBlob(image->blob,blob,length);
2562 image->blob->mapped=MagickTrue;
2563 }
2564 }
2565 }
cristy3ed852e2009-09-05 21:47:34 +00002566 }
cristybf6a7092010-06-11 02:12:15 +00002567 }
2568 else
2569#if defined(MAGICKCORE_ZLIB_DELEGATE)
2570 if ((LocaleCompare(extension,"Z") == 0) ||
2571 (LocaleCompare(extension,"gz") == 0) ||
2572 (LocaleCompare(extension,"wmz") == 0) ||
2573 (LocaleCompare(extension,"svgz") == 0))
2574 {
2575 if (mode == WriteBinaryBlobMode)
2576 type="wb";
cristy95888612012-04-04 21:56:52 +00002577 image->blob->stream_info.gzfile=gzopen(filename,type);
2578 if (image->blob->stream_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002579 image->blob->type=ZipStream;
2580 }
2581 else
2582#endif
2583#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002584 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002585 {
cristy95888612012-04-04 21:56:52 +00002586 image->blob->stream_info.bzfile=BZ2_bzopen(filename,type);
2587 if (image->blob->stream_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002588 image->blob->type=BZipStream;
2589 }
2590 else
2591#endif
2592 {
cristy95888612012-04-04 21:56:52 +00002593 image->blob->stream_info.file=(FILE *) fopen_utf8(filename,type);
2594 if (image->blob->stream_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002595 {
2596 image->blob->type=FileStream;
2597#if defined(MAGICKCORE_HAVE_SETVBUF)
cristy95888612012-04-04 21:56:52 +00002598 (void) setvbuf(image->blob->stream_info.file,(char *) NULL,(int) _IOFBF,
cristybf6a7092010-06-11 02:12:15 +00002599 16384);
2600#endif
2601 }
2602 }
cristy3ed852e2009-09-05 21:47:34 +00002603 image->blob->status=MagickFalse;
2604 if (image->blob->type != UndefinedStream)
2605 image->blob->size=GetBlobSize(image);
2606 else
2607 {
2608 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2609 return(MagickFalse);
2610 }
2611 return(MagickTrue);
2612}
2613
2614/*
2615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2616% %
2617% %
2618% %
2619+ P i n g B l o b %
2620% %
2621% %
2622% %
2623%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2624%
2625% PingBlob() returns all the attributes of an image or image sequence except
2626% for the pixels. It is much faster and consumes far less memory than
2627% BlobToImage(). On failure, a NULL image is returned and exception
2628% describes the reason for the failure.
2629%
2630% The format of the PingBlob method is:
2631%
2632% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2633% const size_t length,ExceptionInfo *exception)
2634%
2635% A description of each parameter follows:
2636%
2637% o image_info: the image info.
2638%
2639% o blob: the address of a character stream in one of the image formats
2640% understood by ImageMagick.
2641%
2642% o length: This size_t integer reflects the length in bytes of the blob.
2643%
2644% o exception: return any errors or warnings in this structure.
2645%
2646*/
2647
2648#if defined(__cplusplus) || defined(c_plusplus)
2649extern "C" {
2650#endif
2651
2652static size_t PingStream(const Image *magick_unused(image),
2653 const void *magick_unused(pixels),const size_t columns)
2654{
2655 return(columns);
2656}
2657
2658#if defined(__cplusplus) || defined(c_plusplus)
2659}
2660#endif
2661
2662MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2663 const size_t length,ExceptionInfo *exception)
2664{
2665 Image
2666 *image;
2667
2668 ImageInfo
2669 *ping_info;
2670
2671 assert(image_info != (ImageInfo *) NULL);
2672 assert(image_info->signature == MagickSignature);
2673 if (image_info->debug != MagickFalse)
2674 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2675 image_info->filename);
2676 assert(exception != (ExceptionInfo *) NULL);
2677 if ((blob == (const void *) NULL) || (length == 0))
2678 {
2679 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
2680 "UnrecognizedImageFormat","`%s'",image_info->magick);
2681 return((Image *) NULL);
2682 }
2683 ping_info=CloneImageInfo(image_info);
2684 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2685 if (ping_info->blob == (const void *) NULL)
2686 {
2687 (void) ThrowMagickException(exception,GetMagickModule(),
2688 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
2689 return((Image *) NULL);
2690 }
cristy54aad5e2010-09-03 16:02:04 +00002691 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002692 ping_info->length=length;
2693 ping_info->ping=MagickTrue;
2694 image=ReadStream(ping_info,&PingStream,exception);
2695 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2696 ping_info=DestroyImageInfo(ping_info);
2697 return(image);
2698}
2699
2700/*
2701%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2702% %
2703% %
2704% %
2705+ R e a d B l o b %
2706% %
2707% %
2708% %
2709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2710%
2711% ReadBlob() reads data from the blob or image file and returns it. It
2712% returns the number of bytes read.
2713%
2714% The format of the ReadBlob method is:
2715%
2716% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2717%
2718% A description of each parameter follows:
2719%
2720% o image: the image.
2721%
2722% o length: Specifies an integer representing the number of bytes to read
2723% from the file.
2724%
2725% o data: Specifies an area to place the information requested from the
2726% file.
2727%
2728*/
2729MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2730 unsigned char *data)
2731{
2732 int
2733 c;
2734
2735 register unsigned char
2736 *q;
2737
2738 ssize_t
2739 count;
2740
2741 assert(image != (Image *) NULL);
2742 assert(image->signature == MagickSignature);
2743 assert(image->blob != (BlobInfo *) NULL);
2744 assert(image->blob->type != UndefinedStream);
2745 if (length == 0)
2746 return(0);
2747 assert(data != (void *) NULL);
2748 count=0;
2749 q=data;
2750 switch (image->blob->type)
2751 {
2752 case UndefinedStream:
2753 break;
2754 case FileStream:
2755 case StandardStream:
2756 case PipeStream:
2757 {
2758 switch (length)
2759 {
2760 default:
2761 {
cristy95888612012-04-04 21:56:52 +00002762 count=(ssize_t) fread(q,1,length,image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002763 break;
2764 }
2765 case 2:
2766 {
cristy95888612012-04-04 21:56:52 +00002767 c=getc(image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002768 if (c == EOF)
2769 break;
2770 *q++=(unsigned char) c;
2771 count++;
2772 }
2773 case 1:
2774 {
cristy95888612012-04-04 21:56:52 +00002775 c=getc(image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002776 if (c == EOF)
2777 break;
2778 *q++=(unsigned char) c;
2779 count++;
2780 }
2781 case 0:
2782 break;
2783 }
2784 break;
2785 }
2786 case ZipStream:
2787 {
2788#if defined(MAGICKCORE_ZLIB_DELEGATE)
2789 switch (length)
2790 {
2791 default:
2792 {
cristy95888612012-04-04 21:56:52 +00002793 count=(ssize_t) gzread(image->blob->stream_info.gzfile,q,
2794 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002795 break;
2796 }
2797 case 2:
2798 {
cristy95888612012-04-04 21:56:52 +00002799 c=gzgetc(image->blob->stream_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002800 if (c == EOF)
2801 break;
2802 *q++=(unsigned char) c;
2803 count++;
2804 }
2805 case 1:
2806 {
cristy95888612012-04-04 21:56:52 +00002807 c=gzgetc(image->blob->stream_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002808 if (c == EOF)
2809 break;
2810 *q++=(unsigned char) c;
2811 count++;
2812 }
2813 case 0:
2814 break;
2815 }
2816#endif
2817 break;
2818 }
2819 case BZipStream:
2820 {
2821#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy95888612012-04-04 21:56:52 +00002822 count=(ssize_t) BZ2_bzread(image->blob->stream_info.bzfile,q,
2823 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00002824#endif
2825 break;
2826 }
2827 case FifoStream:
2828 break;
2829 case BlobStream:
2830 {
2831 register const unsigned char
2832 *p;
2833
2834 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2835 {
2836 image->blob->eof=MagickTrue;
2837 break;
2838 }
2839 p=image->blob->data+image->blob->offset;
cristy7753b2a2011-02-19 18:36:52 +00002840 count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
cristy3ed852e2009-09-05 21:47:34 +00002841 image->blob->offset+=count;
2842 if (count != (ssize_t) length)
2843 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002844 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002845 break;
2846 }
2847 }
2848 return(count);
2849}
2850
2851/*
2852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2853% %
2854% %
2855% %
2856+ R e a d B l o b B y t e %
2857% %
2858% %
2859% %
2860%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2861%
2862% ReadBlobByte() reads a single byte from the image file and returns it.
2863%
2864% The format of the ReadBlobByte method is:
2865%
2866% int ReadBlobByte(Image *image)
2867%
2868% A description of each parameter follows.
2869%
2870% o image: the image.
2871%
2872*/
2873MagickExport int ReadBlobByte(Image *image)
2874{
2875 register const unsigned char
2876 *p;
2877
2878 ssize_t
2879 count;
2880
2881 unsigned char
2882 buffer[1];
2883
2884 assert(image != (Image *) NULL);
2885 assert(image->signature == MagickSignature);
2886 p=ReadBlobStream(image,1,buffer,&count);
2887 if (count != 1)
2888 return(EOF);
2889 return((int) (*p));
2890}
2891
2892/*
2893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2894% %
2895% %
2896% %
2897+ R e a d B l o b D o u b l e %
2898% %
2899% %
2900% %
2901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2902%
2903% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2904% specified by the endian member of the image structure.
2905%
2906% The format of the ReadBlobDouble method is:
2907%
2908% double ReadBlobDouble(Image *image)
2909%
2910% A description of each parameter follows.
2911%
2912% o image: the image.
2913%
2914*/
2915MagickExport double ReadBlobDouble(Image *image)
2916{
2917 union
2918 {
2919 MagickSizeType
2920 unsigned_value;
2921
2922 double
2923 double_value;
2924 } quantum;
2925
2926 quantum.double_value=0.0;
2927 quantum.unsigned_value=ReadBlobLongLong(image);
2928 return(quantum.double_value);
2929}
2930
2931/*
2932%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2933% %
2934% %
2935% %
2936+ R e a d B l o b F l o a t %
2937% %
2938% %
2939% %
2940%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2941%
2942% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2943% specified by the endian member of the image structure.
2944%
2945% The format of the ReadBlobFloat method is:
2946%
2947% float ReadBlobFloat(Image *image)
2948%
2949% A description of each parameter follows.
2950%
2951% o image: the image.
2952%
2953*/
2954MagickExport float ReadBlobFloat(Image *image)
2955{
2956 union
2957 {
2958 unsigned int
2959 unsigned_value;
2960
2961 float
2962 float_value;
2963 } quantum;
2964
2965 quantum.float_value=0.0;
2966 quantum.unsigned_value=ReadBlobLong(image);
2967 return(quantum.float_value);
2968}
2969
2970/*
2971%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2972% %
2973% %
2974% %
2975+ R e a d B l o b L o n g %
2976% %
2977% %
2978% %
2979%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2980%
cristybb503372010-05-27 20:51:26 +00002981% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00002982% specified by the endian member of the image structure.
2983%
2984% The format of the ReadBlobLong method is:
2985%
2986% unsigned int ReadBlobLong(Image *image)
2987%
2988% A description of each parameter follows.
2989%
2990% o image: the image.
2991%
2992*/
2993MagickExport unsigned int ReadBlobLong(Image *image)
2994{
2995 register const unsigned char
2996 *p;
2997
2998 ssize_t
2999 count;
3000
3001 unsigned char
3002 buffer[4];
3003
3004 unsigned int
3005 value;
3006
3007 assert(image != (Image *) NULL);
3008 assert(image->signature == MagickSignature);
3009 *buffer='\0';
3010 p=ReadBlobStream(image,4,buffer,&count);
3011 if (count != 4)
3012 return(0UL);
3013 if (image->endian == LSBEndian)
3014 {
3015 value=(unsigned int) (*p++);
3016 value|=((unsigned int) (*p++)) << 8;
3017 value|=((unsigned int) (*p++)) << 16;
3018 value|=((unsigned int) (*p++)) << 24;
3019 return(value);
3020 }
3021 value=((unsigned int) (*p++)) << 24;
3022 value|=((unsigned int) (*p++)) << 16;
3023 value|=((unsigned int) (*p++)) << 8;
3024 value|=((unsigned int) (*p++));
3025 return(value);
3026}
3027
3028/*
3029%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3030% %
3031% %
3032% %
3033+ R e a d B l o b L o n g L o n g %
3034% %
3035% %
3036% %
3037%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3038%
cristy4cb162a2010-05-30 03:04:47 +00003039% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3040% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003041%
cristy4cb162a2010-05-30 03:04:47 +00003042% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003043%
cristy4cb162a2010-05-30 03:04:47 +00003044% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003045%
3046% A description of each parameter follows.
3047%
3048% o image: the image.
3049%
3050*/
3051MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3052{
cristy0286d852010-10-12 18:38:07 +00003053 MagickSizeType
3054 value;
3055
cristy3ed852e2009-09-05 21:47:34 +00003056 register const unsigned char
3057 *p;
3058
3059 ssize_t
3060 count;
3061
3062 unsigned char
3063 buffer[8];
3064
cristy3ed852e2009-09-05 21:47:34 +00003065 assert(image != (Image *) NULL);
3066 assert(image->signature == MagickSignature);
3067 *buffer='\0';
3068 p=ReadBlobStream(image,8,buffer,&count);
3069 if (count != 8)
3070 return(MagickULLConstant(0));
3071 if (image->endian == LSBEndian)
3072 {
3073 value=(MagickSizeType) (*p++);
3074 value|=((MagickSizeType) (*p++)) << 8;
3075 value|=((MagickSizeType) (*p++)) << 16;
3076 value|=((MagickSizeType) (*p++)) << 24;
3077 value|=((MagickSizeType) (*p++)) << 32;
3078 value|=((MagickSizeType) (*p++)) << 40;
3079 value|=((MagickSizeType) (*p++)) << 48;
3080 value|=((MagickSizeType) (*p++)) << 56;
3081 return(value & MagickULLConstant(0xffffffffffffffff));
3082 }
3083 value=((MagickSizeType) (*p++)) << 56;
3084 value|=((MagickSizeType) (*p++)) << 48;
3085 value|=((MagickSizeType) (*p++)) << 40;
3086 value|=((MagickSizeType) (*p++)) << 32;
3087 value|=((MagickSizeType) (*p++)) << 24;
3088 value|=((MagickSizeType) (*p++)) << 16;
3089 value|=((MagickSizeType) (*p++)) << 8;
3090 value|=((MagickSizeType) (*p++));
3091 return(value & MagickULLConstant(0xffffffffffffffff));
3092}
3093
3094/*
3095%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3096% %
3097% %
3098% %
3099+ R e a d B l o b S h o r t %
3100% %
3101% %
3102% %
3103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3104%
3105% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3106% specified by the endian member of the image structure.
3107%
3108% The format of the ReadBlobShort method is:
3109%
3110% unsigned short ReadBlobShort(Image *image)
3111%
3112% A description of each parameter follows.
3113%
3114% o image: the image.
3115%
3116*/
3117MagickExport unsigned short ReadBlobShort(Image *image)
3118{
3119 register const unsigned char
3120 *p;
3121
3122 register unsigned int
3123 value;
3124
3125 ssize_t
3126 count;
3127
3128 unsigned char
3129 buffer[2];
3130
3131 assert(image != (Image *) NULL);
3132 assert(image->signature == MagickSignature);
3133 *buffer='\0';
3134 p=ReadBlobStream(image,2,buffer,&count);
3135 if (count != 2)
3136 return((unsigned short) 0U);
3137 if (image->endian == LSBEndian)
3138 {
3139 value=(unsigned int) (*p++);
3140 value|=((unsigned int) (*p++)) << 8;
3141 return((unsigned short) (value & 0xffff));
3142 }
3143 value=(unsigned int) ((*p++) << 8);
3144 value|=(unsigned int) (*p++);
3145 return((unsigned short) (value & 0xffff));
3146}
3147
3148/*
3149%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3150% %
3151% %
3152% %
3153+ R e a d B l o b L S B L o n g %
3154% %
3155% %
3156% %
3157%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3158%
cristybb503372010-05-27 20:51:26 +00003159% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003160% least-significant byte first order.
3161%
3162% The format of the ReadBlobLSBLong method is:
3163%
3164% unsigned int ReadBlobLSBLong(Image *image)
3165%
3166% A description of each parameter follows.
3167%
3168% o image: the image.
3169%
3170*/
3171MagickExport unsigned int ReadBlobLSBLong(Image *image)
3172{
3173 register const unsigned char
3174 *p;
3175
3176 register unsigned int
3177 value;
3178
3179 ssize_t
3180 count;
3181
3182 unsigned char
3183 buffer[4];
3184
3185 assert(image != (Image *) NULL);
3186 assert(image->signature == MagickSignature);
3187 *buffer='\0';
3188 p=ReadBlobStream(image,4,buffer,&count);
3189 if (count != 4)
3190 return(0U);
3191 value=(unsigned int) (*p++);
3192 value|=((unsigned int) (*p++)) << 8;
3193 value|=((unsigned int) (*p++)) << 16;
3194 value|=((unsigned int) (*p++)) << 24;
3195 return(value);
3196}
3197
3198/*
3199%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3200% %
3201% %
3202% %
3203+ R e a d B l o b L S B S h o r t %
3204% %
3205% %
3206% %
3207%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3208%
3209% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3210% least-significant byte first order.
3211%
3212% The format of the ReadBlobLSBShort method is:
3213%
3214% unsigned short ReadBlobLSBShort(Image *image)
3215%
3216% A description of each parameter follows.
3217%
3218% o image: the image.
3219%
3220*/
3221MagickExport unsigned short ReadBlobLSBShort(Image *image)
3222{
3223 register const unsigned char
3224 *p;
3225
3226 register unsigned int
3227 value;
3228
3229 ssize_t
3230 count;
3231
3232 unsigned char
3233 buffer[2];
3234
3235 assert(image != (Image *) NULL);
3236 assert(image->signature == MagickSignature);
3237 *buffer='\0';
3238 p=ReadBlobStream(image,2,buffer,&count);
3239 if (count != 2)
3240 return((unsigned short) 0U);
3241 value=(unsigned int) (*p++);
3242 value|=((unsigned int) ((*p++)) << 8);
3243 return((unsigned short) (value & 0xffff));
3244}
3245
3246/*
3247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3248% %
3249% %
3250% %
3251+ R e a d B l o b M S B L o n g %
3252% %
3253% %
3254% %
3255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3256%
cristybb503372010-05-27 20:51:26 +00003257% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003258% most-significant byte first order.
3259%
3260% The format of the ReadBlobMSBLong method is:
3261%
3262% unsigned int ReadBlobMSBLong(Image *image)
3263%
3264% A description of each parameter follows.
3265%
3266% o image: the image.
3267%
3268*/
3269MagickExport unsigned int ReadBlobMSBLong(Image *image)
3270{
3271 register const unsigned char
3272 *p;
3273
3274 register unsigned int
3275 value;
3276
3277 ssize_t
3278 count;
3279
3280 unsigned char
3281 buffer[4];
3282
3283 assert(image != (Image *) NULL);
3284 assert(image->signature == MagickSignature);
3285 *buffer='\0';
3286 p=ReadBlobStream(image,4,buffer,&count);
3287 if (count != 4)
3288 return(0UL);
3289 value=((unsigned int) (*p++) << 24);
3290 value|=((unsigned int) (*p++) << 16);
3291 value|=((unsigned int) (*p++) << 8);
3292 value|=(unsigned int) (*p++);
3293 return(value);
3294}
3295
3296/*
3297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3298% %
3299% %
3300% %
cristy2d3d87f2010-03-01 00:23:08 +00003301+ R e a d B l o b M S B L o n g L o n g %
3302% %
3303% %
3304% %
3305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3306%
cristybb503372010-05-27 20:51:26 +00003307% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003308% most-significant byte first order.
3309%
3310% The format of the ReadBlobMSBLongLong method is:
3311%
3312% unsigned int ReadBlobMSBLongLong(Image *image)
3313%
3314% A description of each parameter follows.
3315%
3316% o image: the image.
3317%
3318*/
3319MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3320{
3321 register const unsigned char
3322 *p;
3323
3324 register MagickSizeType
3325 value;
3326
3327 ssize_t
3328 count;
3329
3330 unsigned char
cristy0286d852010-10-12 18:38:07 +00003331 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003332
3333 assert(image != (Image *) NULL);
3334 assert(image->signature == MagickSignature);
3335 *buffer='\0';
3336 p=ReadBlobStream(image,8,buffer,&count);
3337 if (count != 8)
3338 return(MagickULLConstant(0));
3339 value=((MagickSizeType) (*p++)) << 56;
3340 value|=((MagickSizeType) (*p++)) << 48;
3341 value|=((MagickSizeType) (*p++)) << 40;
3342 value|=((MagickSizeType) (*p++)) << 32;
3343 value|=((MagickSizeType) (*p++)) << 24;
3344 value|=((MagickSizeType) (*p++)) << 16;
3345 value|=((MagickSizeType) (*p++)) << 8;
3346 value|=((MagickSizeType) (*p++));
3347 return(value & MagickULLConstant(0xffffffffffffffff));
3348}
3349
3350/*
3351%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3352% %
3353% %
3354% %
cristy3ed852e2009-09-05 21:47:34 +00003355+ R e a d B l o b M S B S h o r t %
3356% %
3357% %
3358% %
3359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3360%
3361% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3362% most-significant byte first order.
3363%
3364% The format of the ReadBlobMSBShort method is:
3365%
3366% unsigned short ReadBlobMSBShort(Image *image)
3367%
3368% A description of each parameter follows.
3369%
3370% o image: the image.
3371%
3372*/
3373MagickExport unsigned short ReadBlobMSBShort(Image *image)
3374{
3375 register const unsigned char
3376 *p;
3377
3378 register unsigned int
3379 value;
3380
3381 ssize_t
3382 count;
3383
3384 unsigned char
3385 buffer[2];
3386
3387 assert(image != (Image *) NULL);
3388 assert(image->signature == MagickSignature);
3389 *buffer='\0';
3390 p=ReadBlobStream(image,2,buffer,&count);
3391 if (count != 2)
3392 return((unsigned short) 0U);
3393 value=(unsigned int) ((*p++) << 8);
3394 value|=(unsigned int) (*p++);
3395 return((unsigned short) (value & 0xffff));
3396}
3397
3398/*
3399%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3400% %
3401% %
3402% %
3403+ R e a d B l o b S t r i n g %
3404% %
3405% %
3406% %
3407%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3408%
3409% ReadBlobString() reads characters from a blob or file until a newline
3410% character is read or an end-of-file condition is encountered.
3411%
3412% The format of the ReadBlobString method is:
3413%
3414% char *ReadBlobString(Image *image,char *string)
3415%
3416% A description of each parameter follows:
3417%
3418% o image: the image.
3419%
3420% o string: the address of a character buffer.
3421%
3422*/
3423MagickExport char *ReadBlobString(Image *image,char *string)
3424{
3425 register const unsigned char
3426 *p;
3427
cristybb503372010-05-27 20:51:26 +00003428 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003429 i;
3430
3431 ssize_t
3432 count;
3433
3434 unsigned char
3435 buffer[1];
3436
3437 assert(image != (Image *) NULL);
3438 assert(image->signature == MagickSignature);
3439 for (i=0; i < (MaxTextExtent-1L); i++)
3440 {
3441 p=ReadBlobStream(image,1,buffer,&count);
3442 if (count != 1)
3443 {
3444 if (i == 0)
3445 return((char *) NULL);
3446 break;
3447 }
3448 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003449 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003450 break;
3451 }
cristy2b5db102010-06-09 01:07:28 +00003452 if (string[i] == '\r')
3453 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003454 string[i]='\0';
3455 return(string);
3456}
3457
3458/*
3459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3460% %
3461% %
3462% %
3463+ R e f e r e n c e B l o b %
3464% %
3465% %
3466% %
3467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3468%
3469% ReferenceBlob() increments the reference count associated with the pixel
3470% blob returning a pointer to the blob.
3471%
3472% The format of the ReferenceBlob method is:
3473%
3474% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3475%
3476% A description of each parameter follows:
3477%
3478% o blob_info: the blob_info.
3479%
3480*/
3481MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3482{
3483 assert(blob != (BlobInfo *) NULL);
3484 assert(blob->signature == MagickSignature);
3485 if (blob->debug != MagickFalse)
3486 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003487 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003488 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003489 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003490 return(blob);
3491}
3492
3493/*
3494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3495% %
3496% %
3497% %
3498+ S e e k B l o b %
3499% %
3500% %
3501% %
3502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3503%
3504% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3505% and returns the resulting offset.
3506%
3507% The format of the SeekBlob method is:
3508%
3509% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3510% const int whence)
3511%
3512% A description of each parameter follows:
3513%
3514% o image: the image.
3515%
3516% o offset: Specifies an integer representing the offset in bytes.
3517%
3518% o whence: Specifies an integer representing how the offset is
3519% treated relative to the beginning of the blob as follows:
3520%
3521% SEEK_SET Set position equal to offset bytes.
3522% SEEK_CUR Set position to current location plus offset.
3523% SEEK_END Set position to EOF plus offset.
3524%
3525*/
3526MagickExport MagickOffsetType SeekBlob(Image *image,
3527 const MagickOffsetType offset,const int whence)
3528{
3529 assert(image != (Image *) NULL);
3530 assert(image->signature == MagickSignature);
3531 if (image->debug != MagickFalse)
3532 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3533 assert(image->blob != (BlobInfo *) NULL);
3534 assert(image->blob->type != UndefinedStream);
3535 switch (image->blob->type)
3536 {
3537 case UndefinedStream:
3538 break;
3539 case FileStream:
3540 {
cristy95888612012-04-04 21:56:52 +00003541 if (fseek(image->blob->stream_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003542 return(-1);
3543 image->blob->offset=TellBlob(image);
3544 break;
3545 }
3546 case StandardStream:
3547 case PipeStream:
3548 case ZipStream:
3549 {
3550#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristy95888612012-04-04 21:56:52 +00003551 if (gzseek(image->blob->stream_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003552 return(-1);
3553#endif
3554 image->blob->offset=TellBlob(image);
3555 break;
3556 }
3557 case BZipStream:
3558 return(-1);
3559 case FifoStream:
3560 return(-1);
3561 case BlobStream:
3562 {
3563 switch (whence)
3564 {
3565 case SEEK_SET:
3566 default:
3567 {
3568 if (offset < 0)
3569 return(-1);
3570 image->blob->offset=offset;
3571 break;
3572 }
3573 case SEEK_CUR:
3574 {
3575 if ((image->blob->offset+offset) < 0)
3576 return(-1);
3577 image->blob->offset+=offset;
3578 break;
3579 }
3580 case SEEK_END:
3581 {
3582 if (((MagickOffsetType) image->blob->length+offset) < 0)
3583 return(-1);
3584 image->blob->offset=image->blob->length+offset;
3585 break;
3586 }
3587 }
3588 if (image->blob->offset <= (MagickOffsetType)
3589 ((off_t) image->blob->length))
3590 image->blob->eof=MagickFalse;
3591 else
3592 if (image->blob->mapped != MagickFalse)
3593 return(-1);
3594 else
3595 {
3596 image->blob->extent=(size_t) (image->blob->offset+
3597 image->blob->quantum);
3598 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3599 image->blob->data,image->blob->extent+1,
3600 sizeof(*image->blob->data));
3601 (void) SyncBlob(image);
3602 if (image->blob->data == (unsigned char *) NULL)
3603 {
3604 (void) DetachBlob(image->blob);
3605 return(-1);
3606 }
3607 }
3608 break;
3609 }
3610 }
3611 return(image->blob->offset);
3612}
3613
3614/*
3615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3616% %
3617% %
3618% %
3619+ S e t B l o b E x e m p t %
3620% %
3621% %
3622% %
3623%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3624%
3625% SetBlobExempt() sets the blob exempt status.
3626%
3627% The format of the SetBlobExempt method is:
3628%
3629% MagickBooleanType SetBlobExempt(const Image *image,
3630% const MagickBooleanType exempt)
3631%
3632% A description of each parameter follows:
3633%
3634% o image: the image.
3635%
3636% o exempt: Set to true if this blob is exempt from being closed.
3637%
3638*/
cristy7832dc22011-09-05 01:21:53 +00003639MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003640{
3641 assert(image != (const Image *) NULL);
3642 assert(image->signature == MagickSignature);
3643 if (image->debug != MagickFalse)
3644 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3645 image->blob->exempt=exempt;
3646}
3647
3648/*
3649%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3650% %
3651% %
3652% %
3653+ S e t B l o b E x t e n t %
3654% %
3655% %
3656% %
3657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3658%
3659% SetBlobExtent() ensures enough space is allocated for the blob. If the
3660% method is successful, subsequent writes to bytes in the specified range are
3661% guaranteed not to fail.
3662%
3663% The format of the SetBlobExtent method is:
3664%
3665% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3666%
3667% A description of each parameter follows:
3668%
3669% o image: the image.
3670%
3671% o extent: the blob maximum extent.
3672%
3673*/
cristy7832dc22011-09-05 01:21:53 +00003674MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003675 const MagickSizeType extent)
3676{
3677 assert(image != (Image *) NULL);
3678 assert(image->signature == MagickSignature);
3679 if (image->debug != MagickFalse)
3680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3681 assert(image->blob != (BlobInfo *) NULL);
3682 assert(image->blob->type != UndefinedStream);
3683 switch (image->blob->type)
3684 {
3685 case UndefinedStream:
3686 break;
3687 case FileStream:
3688 {
3689 if (extent != (MagickSizeType) ((off_t) extent))
3690 return(MagickFalse);
3691#if !defined(MAGICKCORE_POSIX_FALLOCATE)
3692 return(MagickFalse);
3693#else
3694 {
3695 int
3696 status;
3697
3698 MagickOffsetType
3699 offset;
3700
3701 offset=TellBlob(image);
cristy95888612012-04-04 21:56:52 +00003702 status=posix_fallocate(fileno(image->blob->stream_info.file),
3703 (off_t) offset,(off_t) (extent-offset));
cristy3ed852e2009-09-05 21:47:34 +00003704 if (status != 0)
3705 return(MagickFalse);
3706 }
3707#endif
3708 break;
3709 }
3710 case StandardStream:
3711 case PipeStream:
3712 case ZipStream:
3713 return(MagickFalse);
3714 case BZipStream:
3715 return(MagickFalse);
3716 case FifoStream:
3717 return(MagickFalse);
3718 case BlobStream:
3719 {
3720 if (image->blob->mapped != MagickFalse)
3721 {
cristy95888612012-04-04 21:56:52 +00003722 if (image->blob->stream_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003723 return(MagickFalse);
3724 (void) UnmapBlob(image->blob->data,image->blob->length);
3725#if !defined(MAGICKCORE_POSIX_FALLOCATE)
3726 return(MagickFalse);
3727#else
3728 {
3729 int
3730 status;
3731
3732 MagickOffsetType
3733 offset;
3734
3735 offset=TellBlob(image);
cristy95888612012-04-04 21:56:52 +00003736 status=posix_fallocate(fileno(image->blob->stream_info.file),
3737 (off_t) offset,(off_t) (extent-offset));
cristy3ed852e2009-09-05 21:47:34 +00003738 if (status != 0)
3739 return(MagickFalse);
3740 }
cristy95888612012-04-04 21:56:52 +00003741 image->blob->data=(unsigned char*) MapBlob(fileno(
3742 image->blob->stream_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003743 image->blob->extent=(size_t) extent;
3744 image->blob->length=(size_t) extent;
3745 (void) SyncBlob(image);
3746 break;
3747#endif
3748 }
3749 if (extent != (MagickSizeType) ((size_t) extent))
3750 return(MagickFalse);
3751 image->blob->extent=(size_t) extent;
3752 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3753 image->blob->extent+1,sizeof(*image->blob->data));
3754 (void) SyncBlob(image);
3755 if (image->blob->data == (unsigned char *) NULL)
3756 {
3757 (void) DetachBlob(image->blob);
3758 return(MagickFalse);
3759 }
3760 break;
3761 }
3762 }
3763 return(MagickTrue);
3764}
3765
3766/*
3767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3768% %
3769% %
3770% %
3771+ S y n c B l o b %
3772% %
3773% %
3774% %
3775%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3776%
3777% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3778% attributes if it is an blob.
3779%
3780% The format of the SyncBlob method is:
3781%
3782% int SyncBlob(Image *image)
3783%
3784% A description of each parameter follows:
3785%
3786% o image: the image.
3787%
3788*/
3789static int SyncBlob(Image *image)
3790{
3791 int
3792 status;
3793
3794 assert(image != (Image *) NULL);
3795 assert(image->signature == MagickSignature);
3796 if (image->debug != MagickFalse)
3797 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3798 assert(image->blob != (BlobInfo *) NULL);
3799 assert(image->blob->type != UndefinedStream);
3800 status=0;
3801 switch (image->blob->type)
3802 {
3803 case UndefinedStream:
3804 break;
3805 case FileStream:
3806 case StandardStream:
3807 case PipeStream:
3808 {
cristy95888612012-04-04 21:56:52 +00003809 status=fflush(image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003810 break;
3811 }
3812 case ZipStream:
3813 {
3814#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristy95888612012-04-04 21:56:52 +00003815 status=gzflush(image->blob->stream_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003816#endif
3817 break;
3818 }
3819 case BZipStream:
3820 {
3821#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy95888612012-04-04 21:56:52 +00003822 status=BZ2_bzflush(image->blob->stream_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003823#endif
3824 break;
3825 }
3826 case FifoStream:
3827 break;
3828 case BlobStream:
3829 {
3830#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3831 if (image->blob->mapped != MagickFalse)
3832 status=msync(image->blob->data,image->blob->length,MS_SYNC);
3833#endif
3834 break;
3835 }
3836 }
3837 return(status);
3838}
3839
3840/*
3841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3842% %
3843% %
3844% %
3845+ T e l l B l o b %
3846% %
3847% %
3848% %
3849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3850%
3851% TellBlob() obtains the current value of the blob or file position.
3852%
3853% The format of the TellBlob method is:
3854%
3855% MagickOffsetType TellBlob(const Image *image)
3856%
3857% A description of each parameter follows:
3858%
3859% o image: the image.
3860%
3861*/
3862MagickExport MagickOffsetType TellBlob(const Image *image)
3863{
3864 MagickOffsetType
3865 offset;
3866
3867 assert(image != (Image *) NULL);
3868 assert(image->signature == MagickSignature);
3869 if (image->debug != MagickFalse)
3870 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3871 assert(image->blob != (BlobInfo *) NULL);
3872 assert(image->blob->type != UndefinedStream);
3873 offset=(-1);
3874 switch (image->blob->type)
3875 {
3876 case UndefinedStream:
3877 break;
3878 case FileStream:
3879 {
cristy95888612012-04-04 21:56:52 +00003880 offset=ftell(image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003881 break;
3882 }
3883 case StandardStream:
3884 case PipeStream:
3885 break;
3886 case ZipStream:
3887 {
3888#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristy95888612012-04-04 21:56:52 +00003889 offset=(MagickOffsetType) gztell(image->blob->stream_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003890#endif
3891 break;
3892 }
3893 case BZipStream:
3894 break;
3895 case FifoStream:
3896 break;
3897 case BlobStream:
3898 {
3899 offset=image->blob->offset;
3900 break;
3901 }
3902 }
3903 return(offset);
3904}
3905
3906/*
3907%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3908% %
3909% %
3910% %
3911+ U n m a p B l o b %
3912% %
3913% %
3914% %
3915%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3916%
3917% UnmapBlob() deallocates the binary large object previously allocated with
3918% the MapBlob method.
3919%
3920% The format of the UnmapBlob method is:
3921%
3922% MagickBooleanType UnmapBlob(void *map,const size_t length)
3923%
3924% A description of each parameter follows:
3925%
3926% o map: the address of the binary large object.
3927%
3928% o length: the length of the binary large object.
3929%
3930*/
3931MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3932{
3933#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3934 int
3935 status;
3936
3937 status=munmap(map,length);
3938 return(status == -1 ? MagickFalse : MagickTrue);
3939#else
3940 (void) map;
3941 (void) length;
3942 return(MagickFalse);
3943#endif
3944}
3945
3946/*
3947%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3948% %
3949% %
3950% %
3951+ W r i t e B l o b %
3952% %
3953% %
3954% %
3955%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3956%
3957% WriteBlob() writes data to a blob or image file. It returns the number of
3958% bytes written.
3959%
3960% The format of the WriteBlob method is:
3961%
3962% ssize_t WriteBlob(Image *image,const size_t length,
3963% const unsigned char *data)
3964%
3965% A description of each parameter follows:
3966%
3967% o image: the image.
3968%
3969% o length: Specifies an integer representing the number of bytes to
3970% write to the file.
3971%
3972% o data: The address of the data to write to the blob or file.
3973%
3974*/
3975MagickExport ssize_t WriteBlob(Image *image,const size_t length,
3976 const unsigned char *data)
3977{
3978 int
3979 c;
3980
3981 register const unsigned char
3982 *p;
3983
3984 ssize_t
3985 count;
3986
3987 assert(image != (Image *) NULL);
3988 assert(image->signature == MagickSignature);
3989 assert(data != (const unsigned char *) NULL);
3990 assert(image->blob != (BlobInfo *) NULL);
3991 assert(image->blob->type != UndefinedStream);
3992 if (length == 0)
3993 return(0);
3994 count=0;
3995 p=data;
3996 switch (image->blob->type)
3997 {
3998 case UndefinedStream:
3999 break;
4000 case FileStream:
4001 case StandardStream:
4002 case PipeStream:
4003 {
4004 switch (length)
4005 {
4006 default:
4007 {
4008 count=(ssize_t) fwrite((const char *) data,1,length,
cristy95888612012-04-04 21:56:52 +00004009 image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004010 break;
4011 }
4012 case 2:
4013 {
cristy95888612012-04-04 21:56:52 +00004014 c=putc((int) *p++,image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004015 if (c == EOF)
4016 break;
4017 count++;
4018 }
4019 case 1:
4020 {
cristy95888612012-04-04 21:56:52 +00004021 c=putc((int) *p++,image->blob->stream_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004022 if (c == EOF)
4023 break;
4024 count++;
4025 }
4026 case 0:
4027 break;
4028 }
4029 break;
4030 }
4031 case ZipStream:
4032 {
4033#if defined(MAGICKCORE_ZLIB_DELEGATE)
4034 switch (length)
4035 {
4036 default:
4037 {
cristy95888612012-04-04 21:56:52 +00004038 count=(ssize_t) gzwrite(image->blob->stream_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004039 (unsigned int) length);
4040 break;
4041 }
4042 case 2:
4043 {
cristy95888612012-04-04 21:56:52 +00004044 c=gzputc(image->blob->stream_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004045 if (c == EOF)
4046 break;
4047 count++;
4048 }
4049 case 1:
4050 {
cristy95888612012-04-04 21:56:52 +00004051 c=gzputc(image->blob->stream_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004052 if (c == EOF)
4053 break;
4054 count++;
4055 }
4056 case 0:
4057 break;
4058 }
4059#endif
4060 break;
4061 }
4062 case BZipStream:
4063 {
4064#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy95888612012-04-04 21:56:52 +00004065 count=(ssize_t) BZ2_bzwrite(image->blob->stream_info.bzfile,(void *) data,
4066 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004067#endif
4068 break;
4069 }
4070 case FifoStream:
4071 {
4072 count=(ssize_t) image->blob->stream(image,data,length);
4073 break;
4074 }
4075 case BlobStream:
4076 {
4077 register unsigned char
4078 *q;
4079
4080 if ((image->blob->offset+(MagickOffsetType) length) >=
4081 (MagickOffsetType) image->blob->extent)
4082 {
4083 if (image->blob->mapped != MagickFalse)
4084 return(0);
4085 image->blob->quantum<<=1;
4086 image->blob->extent+=length+image->blob->quantum;
4087 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4088 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4089 (void) SyncBlob(image);
4090 if (image->blob->data == (unsigned char *) NULL)
4091 {
4092 (void) DetachBlob(image->blob);
4093 return(0);
4094 }
4095 }
4096 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004097 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004098 image->blob->offset+=length;
4099 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4100 image->blob->length=(size_t) image->blob->offset;
4101 count=(ssize_t) length;
4102 }
4103 }
4104 return(count);
4105}
4106
4107/*
4108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4109% %
4110% %
4111% %
4112+ W r i t e B l o b B y t e %
4113% %
4114% %
4115% %
4116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4117%
4118% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4119% written (either 0 or 1);
4120%
4121% The format of the WriteBlobByte method is:
4122%
4123% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4124%
4125% A description of each parameter follows.
4126%
4127% o image: the image.
4128%
4129% o value: Specifies the value to write.
4130%
4131*/
4132MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4133{
4134 assert(image != (Image *) NULL);
4135 assert(image->signature == MagickSignature);
4136 return(WriteBlobStream(image,1,&value));
4137}
4138
4139/*
4140%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4141% %
4142% %
4143% %
4144+ W r i t e B l o b F l o a t %
4145% %
4146% %
4147% %
4148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4149%
4150% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4151% specified by the endian member of the image structure.
4152%
4153% The format of the WriteBlobFloat method is:
4154%
4155% ssize_t WriteBlobFloat(Image *image,const float value)
4156%
4157% A description of each parameter follows.
4158%
4159% o image: the image.
4160%
4161% o value: Specifies the value to write.
4162%
4163*/
4164MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4165{
4166 union
4167 {
4168 unsigned int
4169 unsigned_value;
4170
4171 float
4172 float_value;
4173 } quantum;
4174
4175 quantum.unsigned_value=0U;
4176 quantum.float_value=value;
4177 return(WriteBlobLong(image,quantum.unsigned_value));
4178}
4179
4180/*
4181%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4182% %
4183% %
4184% %
4185+ W r i t e B l o b L o n g %
4186% %
4187% %
4188% %
4189%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4190%
cristybb503372010-05-27 20:51:26 +00004191% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004192% specified by the endian member of the image structure.
4193%
4194% The format of the WriteBlobLong method is:
4195%
4196% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4197%
4198% A description of each parameter follows.
4199%
4200% o image: the image.
4201%
4202% o value: Specifies the value to write.
4203%
4204*/
4205MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4206{
4207 unsigned char
4208 buffer[4];
4209
4210 assert(image != (Image *) NULL);
4211 assert(image->signature == MagickSignature);
4212 if (image->endian == LSBEndian)
4213 {
4214 buffer[0]=(unsigned char) value;
4215 buffer[1]=(unsigned char) (value >> 8);
4216 buffer[2]=(unsigned char) (value >> 16);
4217 buffer[3]=(unsigned char) (value >> 24);
4218 return(WriteBlobStream(image,4,buffer));
4219 }
4220 buffer[0]=(unsigned char) (value >> 24);
4221 buffer[1]=(unsigned char) (value >> 16);
4222 buffer[2]=(unsigned char) (value >> 8);
4223 buffer[3]=(unsigned char) value;
4224 return(WriteBlobStream(image,4,buffer));
4225}
4226
4227/*
4228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4229% %
4230% %
4231% %
4232+ W r i t e B l o b S h o r t %
4233% %
4234% %
4235% %
4236%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4237%
4238% WriteBlobShort() writes a short value as a 16-bit quantity in the
4239% byte-order specified by the endian member of the image structure.
4240%
4241% The format of the WriteBlobShort method is:
4242%
4243% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4244%
4245% A description of each parameter follows.
4246%
4247% o image: the image.
4248%
4249% o value: Specifies the value to write.
4250%
4251*/
4252MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4253{
4254 unsigned char
4255 buffer[2];
4256
4257 assert(image != (Image *) NULL);
4258 assert(image->signature == MagickSignature);
4259 if (image->endian == LSBEndian)
4260 {
4261 buffer[0]=(unsigned char) value;
4262 buffer[1]=(unsigned char) (value >> 8);
4263 return(WriteBlobStream(image,2,buffer));
4264 }
4265 buffer[0]=(unsigned char) (value >> 8);
4266 buffer[1]=(unsigned char) value;
4267 return(WriteBlobStream(image,2,buffer));
4268}
4269
4270/*
4271%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4272% %
4273% %
4274% %
4275+ W r i t e B l o b L S B L o n g %
4276% %
4277% %
4278% %
4279%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4280%
cristybb503372010-05-27 20:51:26 +00004281% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004282% least-significant byte first order.
4283%
4284% The format of the WriteBlobLSBLong method is:
4285%
4286% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4287%
4288% A description of each parameter follows.
4289%
4290% o image: the image.
4291%
4292% o value: Specifies the value to write.
4293%
4294*/
4295MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4296{
4297 unsigned char
4298 buffer[4];
4299
4300 assert(image != (Image *) NULL);
4301 assert(image->signature == MagickSignature);
4302 buffer[0]=(unsigned char) value;
4303 buffer[1]=(unsigned char) (value >> 8);
4304 buffer[2]=(unsigned char) (value >> 16);
4305 buffer[3]=(unsigned char) (value >> 24);
4306 return(WriteBlobStream(image,4,buffer));
4307}
4308
4309/*
4310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4311% %
4312% %
4313% %
4314+ W r i t e B l o b L S B S h o r t %
4315% %
4316% %
4317% %
4318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4319%
cristybb503372010-05-27 20:51:26 +00004320% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004321% least-significant byte first order.
4322%
4323% The format of the WriteBlobLSBShort method is:
4324%
4325% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4326%
4327% A description of each parameter follows.
4328%
4329% o image: the image.
4330%
4331% o value: Specifies the value to write.
4332%
4333*/
4334MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4335{
4336 unsigned char
4337 buffer[2];
4338
4339 assert(image != (Image *) NULL);
4340 assert(image->signature == MagickSignature);
4341 buffer[0]=(unsigned char) value;
4342 buffer[1]=(unsigned char) (value >> 8);
4343 return(WriteBlobStream(image,2,buffer));
4344}
4345
4346/*
4347%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4348% %
4349% %
4350% %
4351+ W r i t e B l o b M S B L o n g %
4352% %
4353% %
4354% %
4355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4356%
cristybb503372010-05-27 20:51:26 +00004357% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004358% most-significant byte first order.
4359%
4360% The format of the WriteBlobMSBLong method is:
4361%
4362% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4363%
4364% A description of each parameter follows.
4365%
4366% o value: Specifies the value to write.
4367%
4368% o image: the image.
4369%
4370*/
4371MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4372{
4373 unsigned char
4374 buffer[4];
4375
4376 assert(image != (Image *) NULL);
4377 assert(image->signature == MagickSignature);
4378 buffer[0]=(unsigned char) (value >> 24);
4379 buffer[1]=(unsigned char) (value >> 16);
4380 buffer[2]=(unsigned char) (value >> 8);
4381 buffer[3]=(unsigned char) value;
4382 return(WriteBlobStream(image,4,buffer));
4383}
4384
4385/*
4386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4387% %
4388% %
4389% %
cristy2ca49922010-03-06 02:54:01 +00004390+ W r i t e B l o b M S B L o n g L o n g %
4391% %
4392% %
4393% %
4394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4395%
4396% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4397% most-significant byte first order.
4398%
4399% The format of the WriteBlobMSBLongLong method is:
4400%
4401% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4402%
4403% A description of each parameter follows.
4404%
4405% o value: Specifies the value to write.
4406%
4407% o image: the image.
4408%
4409*/
4410MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4411 const MagickSizeType value)
4412{
4413 unsigned char
4414 buffer[8];
4415
4416 assert(image != (Image *) NULL);
4417 assert(image->signature == MagickSignature);
4418 buffer[0]=(unsigned char) (value >> 56);
4419 buffer[1]=(unsigned char) (value >> 48);
4420 buffer[2]=(unsigned char) (value >> 40);
4421 buffer[3]=(unsigned char) (value >> 32);
4422 buffer[4]=(unsigned char) (value >> 24);
4423 buffer[5]=(unsigned char) (value >> 16);
4424 buffer[6]=(unsigned char) (value >> 8);
4425 buffer[7]=(unsigned char) value;
4426 return(WriteBlobStream(image,8,buffer));
4427}
4428
4429/*
4430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4431% %
4432% %
4433% %
cristy3ed852e2009-09-05 21:47:34 +00004434+ W r i t e B l o b M S B S h o r t %
4435% %
4436% %
4437% %
4438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4439%
cristybb503372010-05-27 20:51:26 +00004440% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004441% most-significant byte first order.
4442%
4443% The format of the WriteBlobMSBShort method is:
4444%
4445% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4446%
4447% A description of each parameter follows.
4448%
4449% o value: Specifies the value to write.
4450%
4451% o file: Specifies the file to write the data to.
4452%
4453*/
4454MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4455{
4456 unsigned char
4457 buffer[2];
4458
4459 assert(image != (Image *) NULL);
4460 assert(image->signature == MagickSignature);
4461 buffer[0]=(unsigned char) (value >> 8);
4462 buffer[1]=(unsigned char) value;
4463 return(WriteBlobStream(image,2,buffer));
4464}
4465
4466/*
4467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4468% %
4469% %
4470% %
4471+ W r i t e B l o b S t r i n g %
4472% %
4473% %
4474% %
4475%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4476%
4477% WriteBlobString() write a string to a blob. It returns the number of
4478% characters written.
4479%
4480% The format of the WriteBlobString method is:
4481%
4482% ssize_t WriteBlobString(Image *image,const char *string)
4483%
4484% A description of each parameter follows.
4485%
4486% o image: the image.
4487%
4488% o string: Specifies the string to write.
4489%
4490*/
4491MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4492{
4493 assert(image != (Image *) NULL);
4494 assert(image->signature == MagickSignature);
4495 assert(string != (const char *) NULL);
4496 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4497}