blob: 0bd7413bbdc53fc225fb3111507e551e86daffe7 [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*/
cristye7b28372012-06-17 13:59:06 +000098typedef union FileInfo
99{
100 FILE
101 *file;
102
103#if defined(MAGICKCORE_ZLIB_DELEGATE)
104 gzFile
105 gzfile;
106#endif
107
108#if defined(MAGICKCORE_BZLIB_DELEGATE)
109 BZFILE
110 *bzfile;
111#endif
112} FileInfo;
113
cristy3ed852e2009-09-05 21:47:34 +0000114struct _BlobInfo
115{
116 size_t
117 length,
118 extent,
119 quantum;
120
121 MagickBooleanType
122 mapped,
123 eof;
124
125 MagickOffsetType
126 offset;
127
128 MagickSizeType
129 size;
130
131 MagickBooleanType
132 exempt,
133 synchronize,
134 status,
135 temporary;
136
137 StreamType
138 type;
139
cristye7b28372012-06-17 13:59:06 +0000140 FileInfo
141 file_info;
cristy3ed852e2009-09-05 21:47:34 +0000142
143 struct stat
144 properties;
145
146 StreamHandler
147 stream;
148
149 unsigned char
150 *data;
151
152 MagickBooleanType
153 debug;
154
155 SemaphoreInfo
156 *semaphore;
157
cristybb503372010-05-27 20:51:26 +0000158 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000159 reference_count;
160
cristybb503372010-05-27 20:51:26 +0000161 size_t
cristy3ed852e2009-09-05 21:47:34 +0000162 signature;
163};
164
165/*
166 Forward declarations.
167*/
168static int
169 SyncBlob(Image *);
170
171/*
172%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173% %
174% %
175% %
176+ A t t a c h B l o b %
177% %
178% %
179% %
180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181%
182% AttachBlob() attaches a blob to the BlobInfo structure.
183%
184% The format of the AttachBlob method is:
185%
186% void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
187%
188% A description of each parameter follows:
189%
190% o blob_info: Specifies a pointer to a BlobInfo structure.
191%
192% o blob: the address of a character stream in one of the image formats
193% understood by ImageMagick.
194%
195% o length: This size_t integer reflects the length in bytes of the blob.
196%
197*/
198MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
199 const size_t length)
200{
201 assert(blob_info != (BlobInfo *) NULL);
202 if (blob_info->debug != MagickFalse)
203 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
204 blob_info->length=length;
205 blob_info->extent=length;
206 blob_info->quantum=(size_t) MagickMaxBlobExtent;
207 blob_info->offset=0;
208 blob_info->type=BlobStream;
cristye7b28372012-06-17 13:59:06 +0000209 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000210 blob_info->data=(unsigned char *) blob;
211 blob_info->mapped=MagickFalse;
212}
213
214/*
215%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216% %
217% %
218% %
219+ B l o b T o F i l e %
220% %
221% %
222% %
223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224%
225% BlobToFile() writes a blob to a file. It returns MagickFalse if an error
226% occurs otherwise MagickTrue.
227%
228% The format of the BlobToFile method is:
229%
230% MagickBooleanType BlobToFile(char *filename,const void *blob,
231% const size_t length,ExceptionInfo *exception)
232%
233% A description of each parameter follows:
234%
235% o filename: Write the blob to this file.
236%
237% o blob: the address of a blob.
238%
239% o length: This length in bytes of the blob.
240%
241% o exception: return any errors or warnings in this structure.
242%
243*/
244
cristy7753b2a2011-02-19 18:36:52 +0000245static inline MagickSizeType MagickMin(const MagickSizeType x,
246 const MagickSizeType y)
cristy3ed852e2009-09-05 21:47:34 +0000247{
248 if (x < y)
249 return(x);
250 return(y);
251}
252
253MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
254 const size_t length,ExceptionInfo *exception)
255{
256 int
257 file;
258
259 register size_t
260 i;
261
262 ssize_t
263 count;
264
265 assert(filename != (const char *) NULL);
266 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
267 assert(blob != (const void *) NULL);
268 if (*filename == '\0')
269 file=AcquireUniqueFileResource(filename);
270 else
cristy18c6c272011-09-23 14:40:37 +0000271 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +0000272 if (file == -1)
273 {
274 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
275 return(MagickFalse);
276 }
277 for (i=0; i < length; i+=count)
278 {
cristy7753b2a2011-02-19 18:36:52 +0000279 count=(ssize_t) write(file,(const char *) blob+i,(size_t) MagickMin(length-
280 i,(MagickSizeType) SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +0000281 if (count <= 0)
282 {
283 count=0;
284 if (errno != EINTR)
285 break;
286 }
287 }
cristya7cb4312010-06-26 00:47:03 +0000288 file=close(file);
289 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +0000290 {
291 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
292 return(MagickFalse);
293 }
294 return(MagickTrue);
295}
296
297/*
298%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299% %
300% %
301% %
302% B l o b T o I m a g e %
303% %
304% %
305% %
306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307%
308% BlobToImage() implements direct to memory image formats. It returns the
309% blob as an image.
310%
311% The format of the BlobToImage method is:
312%
313% Image *BlobToImage(const ImageInfo *image_info,const void *blob,
314% const size_t length,ExceptionInfo *exception)
315%
316% A description of each parameter follows:
317%
318% o image_info: the image info.
319%
320% o blob: the address of a character stream in one of the image formats
321% understood by ImageMagick.
322%
323% o length: This size_t integer reflects the length in bytes of the blob.
324%
325% o exception: return any errors or warnings in this structure.
326%
327*/
328MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
329 const size_t length,ExceptionInfo *exception)
330{
331 const MagickInfo
332 *magick_info;
333
334 Image
335 *image;
336
337 ImageInfo
338 *blob_info,
339 *clone_info;
340
341 MagickBooleanType
342 status;
343
344 assert(image_info != (ImageInfo *) NULL);
345 assert(image_info->signature == MagickSignature);
346 if (image_info->debug != MagickFalse)
347 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
348 image_info->filename);
349 assert(exception != (ExceptionInfo *) NULL);
350 if ((blob == (const void *) NULL) || (length == 0))
351 {
352 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
anthonye5b39652012-04-21 05:37:29 +0000353 "ZeroLengthBlobNotPermitted","'%s'",image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +0000354 return((Image *) NULL);
355 }
356 blob_info=CloneImageInfo(image_info);
357 blob_info->blob=(void *) blob;
358 blob_info->length=length;
359 if (*blob_info->magick == '\0')
cristyd965a422010-03-03 17:47:35 +0000360 (void) SetImageInfo(blob_info,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000361 magick_info=GetMagickInfo(blob_info->magick,exception);
362 if (magick_info == (const MagickInfo *) NULL)
363 {
364 blob_info=DestroyImageInfo(blob_info);
365 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000366 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'",
cristy3ed852e2009-09-05 21:47:34 +0000367 image_info->filename);
368 return((Image *) NULL);
369 }
370 if (GetMagickBlobSupport(magick_info) != MagickFalse)
371 {
372 /*
373 Native blob support for this image format.
374 */
375 (void) CopyMagickString(blob_info->filename,image_info->filename,
376 MaxTextExtent);
377 (void) CopyMagickString(blob_info->magick,image_info->magick,
378 MaxTextExtent);
379 image=ReadImage(blob_info,exception);
380 if (image != (Image *) NULL)
381 (void) DetachBlob(image->blob);
382 blob_info=DestroyImageInfo(blob_info);
383 return(image);
384 }
385 /*
386 Write blob to a temporary file on disk.
387 */
388 blob_info->blob=(void *) NULL;
389 blob_info->length=0;
390 *blob_info->filename='\0';
391 status=BlobToFile(blob_info->filename,blob,length,exception);
392 if (status == MagickFalse)
393 {
394 (void) RelinquishUniqueFileResource(blob_info->filename);
395 blob_info=DestroyImageInfo(blob_info);
396 return((Image *) NULL);
397 }
398 clone_info=CloneImageInfo(blob_info);
cristyb51dff52011-05-19 16:55:47 +0000399 (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +0000400 blob_info->magick,blob_info->filename);
401 image=ReadImage(clone_info,exception);
cristy540a22c2012-06-10 15:22:16 +0000402 if (image != (Image *) NULL)
403 {
404 Image
405 *images;
406
407 /*
408 Restore original filenames.
409 */
410 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
411 {
412 (void) CopyMagickMemory(images->magick_filename,image_info->filename,
413 sizeof(images->magick_filename));
414 (void) CopyMagickMemory(images->filename,image_info->filename,
415 sizeof(images->filename));
416 images=GetNextImageInList(images);
417 }
418 }
cristy3ed852e2009-09-05 21:47:34 +0000419 clone_info=DestroyImageInfo(clone_info);
420 (void) RelinquishUniqueFileResource(blob_info->filename);
421 blob_info=DestroyImageInfo(blob_info);
422 return(image);
423}
424
425/*
426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427% %
428% %
429% %
430+ C l o n e B l o b I n f o %
431% %
432% %
433% %
434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435%
436% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
437% blob info is NULL, a new one.
438%
439% The format of the CloneBlobInfo method is:
440%
441% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
442%
443% A description of each parameter follows:
444%
445% o blob_info: the blob info.
446%
447*/
448MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
449{
450 BlobInfo
451 *clone_info;
452
cristy73bd4a52010-10-05 11:24:23 +0000453 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
cristy3ed852e2009-09-05 21:47:34 +0000454 if (clone_info == (BlobInfo *) NULL)
455 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
456 GetBlobInfo(clone_info);
457 if (blob_info == (BlobInfo *) NULL)
458 return(clone_info);
459 clone_info->length=blob_info->length;
460 clone_info->extent=blob_info->extent;
461 clone_info->synchronize=blob_info->synchronize;
462 clone_info->quantum=blob_info->quantum;
463 clone_info->mapped=blob_info->mapped;
464 clone_info->eof=blob_info->eof;
465 clone_info->offset=blob_info->offset;
466 clone_info->size=blob_info->size;
467 clone_info->exempt=blob_info->exempt;
468 clone_info->status=blob_info->status;
469 clone_info->temporary=blob_info->temporary;
470 clone_info->type=blob_info->type;
cristye7b28372012-06-17 13:59:06 +0000471 clone_info->file_info.file=blob_info->file_info.file;
cristy3ed852e2009-09-05 21:47:34 +0000472 clone_info->properties=blob_info->properties;
473 clone_info->stream=blob_info->stream;
474 clone_info->data=blob_info->data;
475 clone_info->debug=IsEventLogging();
476 clone_info->reference_count=1;
477 return(clone_info);
478}
479
480/*
481%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482% %
483% %
484% %
485+ C l o s e B l o b %
486% %
487% %
488% %
489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490%
491% CloseBlob() closes a stream associated with the image.
492%
493% The format of the CloseBlob method is:
494%
495% MagickBooleanType CloseBlob(Image *image)
496%
497% A description of each parameter follows:
498%
499% o image: the image.
500%
501*/
502MagickExport MagickBooleanType CloseBlob(Image *image)
503{
504 int
505 status;
506
507 /*
508 Close image file.
509 */
510 assert(image != (Image *) NULL);
511 assert(image->signature == MagickSignature);
512 if (image->debug != MagickFalse)
513 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
514 assert(image->blob != (BlobInfo *) NULL);
515 if (image->blob->type == UndefinedStream)
516 return(MagickTrue);
517 if (image->blob->synchronize != MagickFalse)
518 SyncBlob(image);
519 image->blob->size=GetBlobSize(image);
cristy81b8ce52010-02-05 01:53:17 +0000520 image->extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +0000521 image->blob->eof=MagickFalse;
522 if (image->blob->exempt != MagickFalse)
523 {
524 image->blob->type=UndefinedStream;
525 return(MagickTrue);
526 }
527 status=0;
528 switch (image->blob->type)
529 {
530 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000531 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000532 break;
533 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000534 case PipeStream:
535 {
cristye7b28372012-06-17 13:59:06 +0000536 status=ferror(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000537 break;
538 }
539 case ZipStream:
540 {
541#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000542 (void) gzerror(image->blob->file_info.gzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000543#endif
544 break;
545 }
546 case BZipStream:
547 {
548#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000549 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000550#endif
551 break;
552 }
553 case FifoStream:
554 case BlobStream:
555 break;
556 }
557 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
558 switch (image->blob->type)
559 {
560 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000561 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000562 break;
563 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000564 {
565 if (image->blob->synchronize != MagickFalse)
cristyff483372010-10-16 17:00:58 +0000566 {
cristye7b28372012-06-17 13:59:06 +0000567 status=fflush(image->blob->file_info.file);
568 status=fsync(fileno(image->blob->file_info.file));
cristyff483372010-10-16 17:00:58 +0000569 }
cristye7b28372012-06-17 13:59:06 +0000570 status=fclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000571 break;
572 }
573 case PipeStream:
574 {
575#if defined(MAGICKCORE_HAVE_PCLOSE)
cristye7b28372012-06-17 13:59:06 +0000576 status=pclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000577#endif
578 break;
579 }
580 case ZipStream:
581 {
582#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000583 status=gzclose(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +0000584#endif
585 break;
586 }
587 case BZipStream:
588 {
589#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000590 BZ2_bzclose(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +0000591#endif
592 break;
593 }
594 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000595 break;
cristyff483372010-10-16 17:00:58 +0000596 case BlobStream:
597 {
cristye7b28372012-06-17 13:59:06 +0000598 if (image->blob->file_info.file != (FILE *) NULL)
cristyff483372010-10-16 17:00:58 +0000599 {
600 if (image->blob->synchronize != MagickFalse)
cristye7b28372012-06-17 13:59:06 +0000601 (void) fsync(fileno(image->blob->file_info.file));
602 status=fclose(image->blob->file_info.file);
cristyff483372010-10-16 17:00:58 +0000603 }
604 break;
605 }
cristy3ed852e2009-09-05 21:47:34 +0000606 }
607 (void) DetachBlob(image->blob);
608 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
609 return(image->blob->status);
610}
611
612/*
613%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
614% %
615% %
616% %
617+ D e s t r o y B l o b %
618% %
619% %
620% %
621%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
622%
623% DestroyBlob() deallocates memory associated with a blob.
624%
625% The format of the DestroyBlob method is:
626%
627% void DestroyBlob(Image *image)
628%
629% A description of each parameter follows:
630%
631% o image: the image.
632%
633*/
634MagickExport void DestroyBlob(Image *image)
635{
636 MagickBooleanType
637 destroy;
638
639 assert(image != (Image *) NULL);
640 assert(image->signature == MagickSignature);
641 if (image->debug != MagickFalse)
642 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
643 assert(image->blob != (BlobInfo *) NULL);
644 assert(image->blob->signature == MagickSignature);
645 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000646 LockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000647 image->blob->reference_count--;
648 assert(image->blob->reference_count >= 0);
649 if (image->blob->reference_count == 0)
650 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000651 UnlockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000652 if (destroy == MagickFalse)
653 return;
654 (void) CloseBlob(image);
655 if (image->blob->mapped != MagickFalse)
656 (void) UnmapBlob(image->blob->data,image->blob->length);
657 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
658 DestroySemaphoreInfo(&image->blob->semaphore);
659 image->blob->signature=(~MagickSignature);
660 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
661}
662
663/*
664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665% %
666% %
667% %
668+ D e t a c h B l o b %
669% %
670% %
671% %
672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673%
674% DetachBlob() detaches a blob from the BlobInfo structure.
675%
676% The format of the DetachBlob method is:
677%
678% unsigned char *DetachBlob(BlobInfo *blob_info)
679%
680% A description of each parameter follows:
681%
682% o blob_info: Specifies a pointer to a BlobInfo structure.
683%
684*/
685MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
686{
687 unsigned char
688 *data;
689
690 assert(blob_info != (BlobInfo *) NULL);
691 if (blob_info->debug != MagickFalse)
692 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
693 if (blob_info->mapped != MagickFalse)
694 (void) UnmapBlob(blob_info->data,blob_info->length);
695 blob_info->mapped=MagickFalse;
696 blob_info->length=0;
697 blob_info->offset=0;
698 blob_info->eof=MagickFalse;
699 blob_info->exempt=MagickFalse;
700 blob_info->type=UndefinedStream;
cristye7b28372012-06-17 13:59:06 +0000701 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000702 data=blob_info->data;
703 blob_info->data=(unsigned char *) NULL;
704 blob_info->stream=(StreamHandler) NULL;
705 return(data);
706}
707
708/*
709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
710% %
711% %
712% %
cristyc1af14f2010-09-16 20:01:21 +0000713+ D i s c a r d B l o b B y t e s %
714% %
715% %
716% %
717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
718%
719% DiscardBlobBytes() discards bytes in a blob.
720%
721% The format of the DiscardBlobBytes method is:
722%
723% MagickBooleanType DiscardBlobBytes(Image *image,const size_t length)
724%
725% A description of each parameter follows.
726%
727% o image: the image.
728%
729% o length: the number of bytes to skip.
730%
731*/
732
733static inline const unsigned char *ReadBlobStream(Image *image,
734 const size_t length,unsigned char *data,ssize_t *count)
735{
736 assert(count != (ssize_t *) NULL);
737 assert(image->blob != (BlobInfo *) NULL);
738 if (image->blob->type != BlobStream)
739 {
740 *count=ReadBlob(image,length,data);
741 return(data);
742 }
743 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
744 {
745 *count=0;
746 image->blob->eof=MagickTrue;
747 return(data);
748 }
749 data=image->blob->data+image->blob->offset;
cristy7753b2a2011-02-19 18:36:52 +0000750 *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
cristyc1af14f2010-09-16 20:01:21 +0000751 image->blob->offset));
752 image->blob->offset+=(*count);
753 if (*count != (ssize_t) length)
754 image->blob->eof=MagickTrue;
755 return(data);
756}
757
758MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
cristy7753b2a2011-02-19 18:36:52 +0000759 const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000760{
cristy7753b2a2011-02-19 18:36:52 +0000761 register MagickOffsetType
cristyc1af14f2010-09-16 20:01:21 +0000762 i;
763
764 size_t
765 quantum;
766
767 ssize_t
768 count;
769
770 unsigned char
cristyf55846d2010-09-17 19:01:10 +0000771 buffer[16384];
cristyc1af14f2010-09-16 20:01:21 +0000772
773 assert(image != (Image *) NULL);
774 assert(image->signature == MagickSignature);
775 count=0;
cristy7753b2a2011-02-19 18:36:52 +0000776 for (i=0; i < (MagickOffsetType) length; i+=count)
cristyc1af14f2010-09-16 20:01:21 +0000777 {
cristy7753b2a2011-02-19 18:36:52 +0000778 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
cristyc1af14f2010-09-16 20:01:21 +0000779 (void) ReadBlobStream(image,quantum,buffer,&count);
780 if (count <= 0)
781 {
782 count=0;
783 if (errno != EINTR)
784 break;
785 }
786 }
cristy7753b2a2011-02-19 18:36:52 +0000787 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
cristyc1af14f2010-09-16 20:01:21 +0000788}
789
790/*
791%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
792% %
793% %
794% %
cristy3ed852e2009-09-05 21:47:34 +0000795+ D u p l i c a t e s B l o b %
796% %
797% %
798% %
799%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
800%
801% DuplicateBlob() duplicates a blob descriptor.
802%
803% The format of the DuplicateBlob method is:
804%
805% void DuplicateBlob(Image *image,const Image *duplicate)
806%
807% A description of each parameter follows:
808%
809% o image: the image.
810%
811% o duplicate: the duplicate image.
812%
813*/
814MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
815{
816 assert(image != (Image *) NULL);
817 assert(image->signature == MagickSignature);
818 if (image->debug != MagickFalse)
819 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
820 assert(duplicate != (Image *) NULL);
821 assert(duplicate->signature == MagickSignature);
822 DestroyBlob(image);
823 image->blob=ReferenceBlob(duplicate->blob);
824}
825
826/*
827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
828% %
829% %
830% %
831+ E O F B l o b %
832% %
833% %
834% %
835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
836%
837% EOFBlob() returns a non-zero value when EOF has been detected reading from
838% a blob or file.
839%
840% The format of the EOFBlob method is:
841%
842% int EOFBlob(const Image *image)
843%
844% A description of each parameter follows:
845%
846% o image: the image.
847%
848*/
849MagickExport int EOFBlob(const Image *image)
850{
851 assert(image != (Image *) NULL);
852 assert(image->signature == MagickSignature);
853 if (image->debug != MagickFalse)
854 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
855 assert(image->blob != (BlobInfo *) NULL);
856 assert(image->blob->type != UndefinedStream);
857 switch (image->blob->type)
858 {
859 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000860 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000861 break;
862 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000863 case PipeStream:
864 {
cristye7b28372012-06-17 13:59:06 +0000865 image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
cristy95888612012-04-04 21:56:52 +0000866 MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000867 break;
868 }
869 case ZipStream:
870 {
871 image->blob->eof=MagickFalse;
872 break;
873 }
874 case BZipStream:
875 {
876#if defined(MAGICKCORE_BZLIB_DELEGATE)
877 int
878 status;
879
880 status=0;
cristye7b28372012-06-17 13:59:06 +0000881 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000882 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
883#endif
884 break;
885 }
886 case FifoStream:
887 {
888 image->blob->eof=MagickFalse;
889 break;
890 }
891 case BlobStream:
892 break;
893 }
894 return((int) image->blob->eof);
895}
896
897/*
898%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
899% %
900% %
901% %
902+ F i l e T o B l o b %
903% %
904% %
905% %
906%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
907%
cristy178edaf2011-01-23 03:42:39 +0000908% FileToBlob() returns the contents of a file as a buffer terminated with
909% the '\0' character. The length of the buffer (not including the extra
910% terminating '\0' character) is returned via the 'length' parameter. Free
911% the buffer with RelinquishMagickMemory().
cristy3ed852e2009-09-05 21:47:34 +0000912%
913% The format of the FileToBlob method is:
914%
915% unsigned char *FileToBlob(const char *filename,const size_t extent,
916% size_t *length,ExceptionInfo *exception)
917%
918% A description of each parameter follows:
919%
920% o blob: FileToBlob() returns the contents of a file as a blob. If
921% an error occurs NULL is returned.
922%
923% o filename: the filename.
924%
925% o extent: The maximum length of the blob.
926%
927% o length: On return, this reflects the actual length of the blob.
928%
929% o exception: return any errors or warnings in this structure.
930%
931*/
932MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
933 size_t *length,ExceptionInfo *exception)
934{
935 int
936 file;
937
938 MagickOffsetType
939 offset;
940
941 register size_t
942 i;
943
944 ssize_t
945 count;
946
947 unsigned char
948 *blob;
949
950 void
951 *map;
952
953 assert(filename != (const char *) NULL);
954 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
955 assert(exception != (ExceptionInfo *) NULL);
956 *length=0;
957 file=fileno(stdin);
958 if (LocaleCompare(filename,"-") != 0)
cristy18c6c272011-09-23 14:40:37 +0000959 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +0000960 if (file == -1)
961 {
962 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
963 return((unsigned char *) NULL);
964 }
cristy7f317702011-02-18 20:40:28 +0000965 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
cristy3ed852e2009-09-05 21:47:34 +0000966 count=0;
967 if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset)))
968 {
969 size_t
970 quantum;
971
972 struct stat
cristye7b28372012-06-17 13:59:06 +0000973 file_stats;
cristy3ed852e2009-09-05 21:47:34 +0000974
975 /*
976 Stream is not seekable.
977 */
978 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +0000979 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
980 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +0000981 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +0000982 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
983 for (i=0; blob != (unsigned char *) NULL; i+=count)
984 {
985 count=(ssize_t) read(file,blob+i,quantum);
986 if (count <= 0)
987 {
988 count=0;
989 if (errno != EINTR)
990 break;
991 }
cristy9c66d8c2012-08-10 11:05:36 +0000992 if (~((size_t) i) < (quantum+1))
cristy3ed852e2009-09-05 21:47:34 +0000993 {
994 blob=(unsigned char *) RelinquishMagickMemory(blob);
995 break;
996 }
997 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
998 sizeof(*blob));
999 if ((size_t) (i+count) >= extent)
1000 break;
1001 }
cristy54439632010-07-15 00:43:34 +00001002 if (LocaleCompare(filename,"-") != 0)
1003 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001004 if (blob == (unsigned char *) NULL)
1005 {
1006 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001007 ResourceLimitError,"MemoryAllocationFailed","'%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001008 return((unsigned char *) NULL);
1009 }
cristya7cb4312010-06-26 00:47:03 +00001010 if (file == -1)
1011 {
1012 blob=(unsigned char *) RelinquishMagickMemory(blob);
1013 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1014 return((unsigned char *) NULL);
1015 }
cristy7753b2a2011-02-19 18:36:52 +00001016 *length=(size_t) MagickMin(i+count,extent);
cristy3ed852e2009-09-05 21:47:34 +00001017 blob[*length]='\0';
1018 return(blob);
1019 }
cristy7753b2a2011-02-19 18:36:52 +00001020 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
cristy3ed852e2009-09-05 21:47:34 +00001021 blob=(unsigned char *) NULL;
cristy37e0b382011-06-07 13:31:21 +00001022 if (~(*length) >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +00001023 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1024 sizeof(*blob));
1025 if (blob == (unsigned char *) NULL)
1026 {
cristy54439632010-07-15 00:43:34 +00001027 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001028 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001029 ResourceLimitError,"MemoryAllocationFailed","'%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001030 return((unsigned char *) NULL);
1031 }
1032 map=MapBlob(file,ReadMode,0,*length);
1033 if (map != (unsigned char *) NULL)
1034 {
cristy54aad5e2010-09-03 16:02:04 +00001035 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +00001036 (void) UnmapBlob(map,*length);
1037 }
1038 else
1039 {
cristy7f317702011-02-18 20:40:28 +00001040 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001041 for (i=0; i < *length; i+=count)
1042 {
cristy7753b2a2011-02-19 18:36:52 +00001043 count=(ssize_t) read(file,blob+i,(size_t) MagickMin(*length-i,
1044 (MagickSizeType) SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001045 if (count <= 0)
1046 {
1047 count=0;
1048 if (errno != EINTR)
1049 break;
1050 }
1051 }
1052 if (i < *length)
1053 {
1054 file=close(file)-1;
1055 blob=(unsigned char *) RelinquishMagickMemory(blob);
1056 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1057 return((unsigned char *) NULL);
1058 }
1059 }
cristy3ed852e2009-09-05 21:47:34 +00001060 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001061 if (LocaleCompare(filename,"-") != 0)
1062 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001063 if (file == -1)
1064 {
1065 blob=(unsigned char *) RelinquishMagickMemory(blob);
1066 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1067 }
cristy3ed852e2009-09-05 21:47:34 +00001068 return(blob);
1069}
1070
1071/*
1072%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1073% %
1074% %
1075% %
1076% F i l e T o I m a g e %
1077% %
1078% %
1079% %
1080%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1081%
1082% FileToImage() write the contents of a file to an image.
1083%
1084% The format of the FileToImage method is:
1085%
1086% MagickBooleanType FileToImage(Image *,const char *filename)
1087%
1088% A description of each parameter follows:
1089%
1090% o image: the image.
1091%
1092% o filename: the filename.
1093%
1094*/
1095
1096static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1097 const unsigned char *data)
1098{
1099 MagickSizeType
1100 extent;
1101
1102 register unsigned char
1103 *q;
1104
1105 assert(image->blob != (BlobInfo *) NULL);
1106 if (image->blob->type != BlobStream)
1107 return(WriteBlob(image,length,data));
1108 assert(image->blob->type != UndefinedStream);
1109 assert(data != (void *) NULL);
1110 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1111 if (extent >= image->blob->extent)
1112 {
1113 image->blob->quantum<<=1;
1114 extent=image->blob->extent+image->blob->quantum+length;
1115 if (SetBlobExtent(image,extent) == MagickFalse)
1116 return(0);
1117 }
1118 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001119 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001120 image->blob->offset+=length;
1121 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1122 image->blob->length=(size_t) image->blob->offset;
1123 return((ssize_t) length);
1124}
1125
cristyc82a27b2011-10-21 01:07:16 +00001126MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1127 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001128{
1129 int
1130 file;
1131
1132 size_t
1133 length,
1134 quantum;
1135
1136 ssize_t
1137 count;
1138
1139 struct stat
cristye7b28372012-06-17 13:59:06 +00001140 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001141
1142 unsigned char
1143 *blob;
1144
1145 assert(image != (const Image *) NULL);
1146 assert(image->signature == MagickSignature);
1147 assert(filename != (const char *) NULL);
1148 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
cristy18c6c272011-09-23 14:40:37 +00001149 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001150 if (file == -1)
1151 {
cristyc82a27b2011-10-21 01:07:16 +00001152 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001153 return(MagickFalse);
1154 }
1155 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001156 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1157 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001158 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1159 if (blob == (unsigned char *) NULL)
1160 {
cristyc82a27b2011-10-21 01:07:16 +00001161 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1162 filename);
cristy3ed852e2009-09-05 21:47:34 +00001163 return(MagickFalse);
1164 }
1165 for ( ; ; )
1166 {
1167 count=(ssize_t) read(file,blob,quantum);
1168 if (count <= 0)
1169 {
1170 count=0;
1171 if (errno != EINTR)
1172 break;
1173 }
1174 length=(size_t) count;
1175 count=WriteBlobStream(image,length,blob);
1176 if (count != (ssize_t) length)
1177 {
cristyc82a27b2011-10-21 01:07:16 +00001178 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001179 break;
1180 }
1181 }
cristya7cb4312010-06-26 00:47:03 +00001182 file=close(file);
1183 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001184 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001185 blob=(unsigned char *) RelinquishMagickMemory(blob);
1186 return(MagickTrue);
1187}
1188
1189/*
1190%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1191% %
1192% %
1193% %
1194+ G e t B l o b E r r o r %
1195% %
1196% %
1197% %
1198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1199%
1200% GetBlobError() returns MagickTrue if the blob associated with the specified
1201% image encountered an error.
1202%
1203% The format of the GetBlobError method is:
1204%
1205% MagickBooleanType GetBlobError(const Image *image)
1206%
1207% A description of each parameter follows:
1208%
1209% o image: the image.
1210%
1211*/
cristy7832dc22011-09-05 01:21:53 +00001212MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001213{
1214 assert(image != (const Image *) NULL);
1215 assert(image->signature == MagickSignature);
1216 if (image->debug != MagickFalse)
1217 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1218 return(image->blob->status);
1219}
1220
1221/*
1222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1223% %
1224% %
1225% %
1226+ G e t B l o b F i l e H a n d l e %
1227% %
1228% %
1229% %
1230%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1231%
1232% GetBlobFileHandle() returns the file handle associated with the image blob.
1233%
1234% The format of the GetBlobFile method is:
1235%
1236% FILE *GetBlobFileHandle(const Image *image)
1237%
1238% A description of each parameter follows:
1239%
1240% o image: the image.
1241%
1242*/
1243MagickExport FILE *GetBlobFileHandle(const Image *image)
1244{
1245 assert(image != (const Image *) NULL);
1246 assert(image->signature == MagickSignature);
cristye7b28372012-06-17 13:59:06 +00001247 return(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001248}
1249
1250/*
1251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1252% %
1253% %
1254% %
1255+ G e t B l o b I n f o %
1256% %
1257% %
1258% %
1259%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1260%
1261% GetBlobInfo() initializes the BlobInfo structure.
1262%
1263% The format of the GetBlobInfo method is:
1264%
1265% void GetBlobInfo(BlobInfo *blob_info)
1266%
1267% A description of each parameter follows:
1268%
1269% o blob_info: Specifies a pointer to a BlobInfo structure.
1270%
1271*/
cristy7832dc22011-09-05 01:21:53 +00001272MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001273{
1274 assert(blob_info != (BlobInfo *) NULL);
1275 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1276 blob_info->type=UndefinedStream;
1277 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1278 blob_info->properties.st_mtime=time((time_t *) NULL);
1279 blob_info->properties.st_ctime=time((time_t *) NULL);
1280 blob_info->debug=IsEventLogging();
1281 blob_info->reference_count=1;
1282 blob_info->semaphore=AllocateSemaphoreInfo();
1283 blob_info->signature=MagickSignature;
1284}
1285
1286/*
1287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1288% %
1289% %
1290% %
1291% G e t B l o b P r o p e r t i e s %
1292% %
1293% %
1294% %
1295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1296%
1297% GetBlobProperties() returns information about an image blob.
1298%
1299% The format of the GetBlobProperties method is:
1300%
1301% const struct stat *GetBlobProperties(const Image *image)
1302%
1303% A description of each parameter follows:
1304%
1305% o image: the image.
1306%
1307*/
cristy7832dc22011-09-05 01:21:53 +00001308MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001309{
1310 assert(image != (Image *) NULL);
1311 assert(image->signature == MagickSignature);
1312 if (image->debug != MagickFalse)
1313 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1314 return(&image->blob->properties);
1315}
1316
1317/*
1318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1319% %
1320% %
1321% %
1322+ G e t B l o b S i z e %
1323% %
1324% %
1325% %
1326%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1327%
1328% GetBlobSize() returns the current length of the image file or blob; zero is
1329% returned if the size cannot be determined.
1330%
1331% The format of the GetBlobSize method is:
1332%
1333% MagickSizeType GetBlobSize(const Image *image)
1334%
1335% A description of each parameter follows:
1336%
1337% o image: the image.
1338%
1339*/
1340MagickExport MagickSizeType GetBlobSize(const Image *image)
1341{
1342 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001343 extent;
cristy3ed852e2009-09-05 21:47:34 +00001344
1345 assert(image != (Image *) NULL);
1346 assert(image->signature == MagickSignature);
1347 if (image->debug != MagickFalse)
1348 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1349 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001350 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001351 switch (image->blob->type)
1352 {
1353 case UndefinedStream:
1354 {
cristy81b8ce52010-02-05 01:53:17 +00001355 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001356 break;
1357 }
cristybc20d112012-07-29 20:27:00 +00001358 case StandardStream:
1359 {
1360 extent=image->blob->size;
1361 break;
1362 }
cristy3ed852e2009-09-05 21:47:34 +00001363 case FileStream:
1364 {
cristye7b28372012-06-17 13:59:06 +00001365 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001366 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001367 break;
1368 }
cristy3ed852e2009-09-05 21:47:34 +00001369 case PipeStream:
1370 {
cristy81b8ce52010-02-05 01:53:17 +00001371 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001372 break;
1373 }
1374 case ZipStream:
1375 case BZipStream:
1376 {
1377 MagickBooleanType
1378 status;
1379
1380 status=GetPathAttributes(image->filename,&image->blob->properties);
1381 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001382 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001383 break;
1384 }
1385 case FifoStream:
1386 break;
1387 case BlobStream:
1388 {
cristy891dc792010-03-04 01:47:16 +00001389 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001390 break;
1391 }
1392 }
cristy81b8ce52010-02-05 01:53:17 +00001393 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001394}
1395
1396/*
1397%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1398% %
1399% %
1400% %
1401+ G e t B l o b S t r e a m D a t a %
1402% %
1403% %
1404% %
1405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1406%
1407% GetBlobStreamData() returns the stream data for the image.
1408%
1409% The format of the GetBlobStreamData method is:
1410%
1411% unsigned char *GetBlobStreamData(const Image *image)
1412%
1413% A description of each parameter follows:
1414%
1415% o image: the image.
1416%
1417*/
1418MagickExport unsigned char *GetBlobStreamData(const Image *image)
1419{
1420 assert(image != (const Image *) NULL);
1421 assert(image->signature == MagickSignature);
1422 return(image->blob->data);
1423}
1424
1425/*
1426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1427% %
1428% %
1429% %
1430+ G e t B l o b S t r e a m H a n d l e r %
1431% %
1432% %
1433% %
1434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1435%
1436% GetBlobStreamHandler() returns the stream handler for the image.
1437%
1438% The format of the GetBlobStreamHandler method is:
1439%
1440% StreamHandler GetBlobStreamHandler(const Image *image)
1441%
1442% A description of each parameter follows:
1443%
1444% o image: the image.
1445%
1446*/
cristy7832dc22011-09-05 01:21:53 +00001447MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001448{
1449 assert(image != (const Image *) NULL);
1450 assert(image->signature == MagickSignature);
1451 if (image->debug != MagickFalse)
1452 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1453 return(image->blob->stream);
1454}
1455
1456/*
1457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1458% %
1459% %
1460% %
1461% I m a g e T o B l o b %
1462% %
1463% %
1464% %
1465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1466%
1467% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001468% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001469% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001470% etc.). This method is the equivalent of WriteImage(), but writes the
1471% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001472%
1473% The format of the ImageToBlob method is:
1474%
1475% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1476% size_t *length,ExceptionInfo *exception)
1477%
1478% A description of each parameter follows:
1479%
1480% o image_info: the image info.
1481%
1482% o image: the image.
1483%
1484% o length: This pointer to a size_t integer sets the initial length of the
1485% blob. On return, it reflects the actual length of the blob.
1486%
1487% o exception: return any errors or warnings in this structure.
1488%
1489*/
1490MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1491 Image *image,size_t *length,ExceptionInfo *exception)
1492{
1493 const MagickInfo
1494 *magick_info;
1495
1496 ImageInfo
1497 *blob_info;
1498
1499 MagickBooleanType
1500 status;
1501
1502 unsigned char
1503 *blob;
1504
1505 assert(image_info != (const ImageInfo *) NULL);
1506 assert(image_info->signature == MagickSignature);
1507 if (image_info->debug != MagickFalse)
1508 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1509 image_info->filename);
1510 assert(image != (Image *) NULL);
1511 assert(image->signature == MagickSignature);
1512 assert(exception != (ExceptionInfo *) NULL);
1513 *length=0;
1514 blob=(unsigned char *) NULL;
1515 blob_info=CloneImageInfo(image_info);
1516 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001517 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001518 if (*blob_info->magick != '\0')
1519 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1520 magick_info=GetMagickInfo(image->magick,exception);
1521 if (magick_info == (const MagickInfo *) NULL)
1522 {
1523 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001524 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'",
cristy3ed852e2009-09-05 21:47:34 +00001525 image->filename);
1526 return(blob);
1527 }
1528 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1529 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1530 {
1531 /*
1532 Native blob support for this image format.
1533 */
1534 blob_info->length=0;
1535 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1536 sizeof(unsigned char));
1537 if (blob_info->blob == (void *) NULL)
1538 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001539 ResourceLimitError,"MemoryAllocationFailed","'%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001540 else
1541 {
1542 (void) CloseBlob(image);
1543 image->blob->exempt=MagickTrue;
1544 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001545 status=WriteImage(blob_info,image,exception);
1546 if ((status != MagickFalse) && (image->blob->length != 0))
cristy3ed852e2009-09-05 21:47:34 +00001547 {
1548 *length=image->blob->length;
1549 blob=DetachBlob(image->blob);
1550 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1551 sizeof(*blob));
1552 }
1553 }
1554 }
1555 else
1556 {
1557 char
1558 unique[MaxTextExtent];
1559
1560 int
1561 file;
1562
1563 /*
1564 Write file to disk in blob image format.
1565 */
1566 file=AcquireUniqueFileResource(unique);
1567 if (file == -1)
1568 {
1569 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1570 image_info->filename);
1571 }
1572 else
1573 {
1574 blob_info->file=fdopen(file,"wb");
1575 if (blob_info->file != (FILE *) NULL)
1576 {
cristyb51dff52011-05-19 16:55:47 +00001577 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001578 image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001579 status=WriteImage(blob_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001580 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001581 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001582 blob=FileToBlob(image->filename,~0UL,length,exception);
1583 }
1584 (void) RelinquishUniqueFileResource(unique);
1585 }
1586 }
1587 blob_info=DestroyImageInfo(blob_info);
1588 return(blob);
1589}
1590
1591/*
1592%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1593% %
1594% %
1595% %
1596% I m a g e T o F i l e %
1597% %
1598% %
1599% %
1600%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1601%
1602% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1603% occurs otherwise MagickTrue.
1604%
1605% The format of the ImageToFile method is:
1606%
1607% MagickBooleanType ImageToFile(Image *image,char *filename,
1608% ExceptionInfo *exception)
1609%
1610% A description of each parameter follows:
1611%
1612% o image: the image.
1613%
1614% o filename: Write the image to this file.
1615%
1616% o exception: return any errors or warnings in this structure.
1617%
1618*/
cristy3ed852e2009-09-05 21:47:34 +00001619MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1620 ExceptionInfo *exception)
1621{
1622 int
1623 file;
1624
1625 register const unsigned char
1626 *p;
1627
1628 register size_t
1629 i;
1630
1631 size_t
1632 length,
1633 quantum;
1634
1635 ssize_t
1636 count;
1637
1638 struct stat
cristye7b28372012-06-17 13:59:06 +00001639 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001640
1641 unsigned char
1642 *buffer;
1643
1644 assert(image != (Image *) NULL);
1645 assert(image->signature == MagickSignature);
1646 assert(image->blob != (BlobInfo *) NULL);
1647 assert(image->blob->type != UndefinedStream);
1648 if (image->debug != MagickFalse)
1649 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1650 assert(filename != (const char *) NULL);
1651 if (*filename == '\0')
1652 file=AcquireUniqueFileResource(filename);
1653 else
1654 if (LocaleCompare(filename,"-") == 0)
1655 file=fileno(stdout);
1656 else
cristyb70aab92012-01-31 15:04:04 +00001657 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001658 if (file == -1)
1659 {
1660 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1661 return(MagickFalse);
1662 }
1663 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001664 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1665 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001666 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001667 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1668 if (buffer == (unsigned char *) NULL)
1669 {
1670 file=close(file)-1;
1671 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001672 ResourceLimitError,"MemoryAllocationError","'%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001673 return(MagickFalse);
1674 }
1675 length=0;
1676 p=ReadBlobStream(image,quantum,buffer,&count);
1677 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1678 {
1679 length=(size_t) count;
1680 for (i=0; i < length; i+=count)
1681 {
1682 count=write(file,p+i,(size_t) (length-i));
1683 if (count <= 0)
1684 {
1685 count=0;
1686 if (errno != EINTR)
1687 break;
1688 }
1689 }
1690 if (i < length)
1691 break;
1692 }
cristy54439632010-07-15 00:43:34 +00001693 if (LocaleCompare(filename,"-") != 0)
1694 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001695 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001696 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001697 {
1698 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1699 return(MagickFalse);
1700 }
1701 return(MagickTrue);
1702}
1703
1704/*
1705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1706% %
1707% %
1708% %
1709% I m a g e s T o B l o b %
1710% %
1711% %
1712% %
1713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1714%
1715% ImagesToBlob() implements direct to memory image formats. It returns the
1716% image sequence as a blob and its length. The magick member of the ImageInfo
1717% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1718%
1719% Note, some image formats do not permit multiple images to the same image
1720% stream (e.g. JPEG). in this instance, just the first image of the
1721% sequence is returned as a blob.
1722%
1723% The format of the ImagesToBlob method is:
1724%
1725% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1726% size_t *length,ExceptionInfo *exception)
1727%
1728% A description of each parameter follows:
1729%
1730% o image_info: the image info.
1731%
1732% o images: the image list.
1733%
1734% o length: This pointer to a size_t integer sets the initial length of the
1735% blob. On return, it reflects the actual length of the blob.
1736%
1737% o exception: return any errors or warnings in this structure.
1738%
1739*/
1740MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1741 Image *images,size_t *length,ExceptionInfo *exception)
1742{
1743 const MagickInfo
1744 *magick_info;
1745
1746 ImageInfo
1747 *blob_info;
1748
1749 MagickBooleanType
1750 status;
1751
1752 unsigned char
1753 *blob;
1754
1755 assert(image_info != (const ImageInfo *) NULL);
1756 assert(image_info->signature == MagickSignature);
1757 if (image_info->debug != MagickFalse)
1758 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1759 image_info->filename);
1760 assert(images != (Image *) NULL);
1761 assert(images->signature == MagickSignature);
1762 assert(exception != (ExceptionInfo *) NULL);
1763 *length=0;
1764 blob=(unsigned char *) NULL;
1765 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001766 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1767 exception);
cristy3ed852e2009-09-05 21:47:34 +00001768 if (*blob_info->magick != '\0')
1769 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1770 if (blob_info->adjoin == MagickFalse)
1771 {
1772 blob_info=DestroyImageInfo(blob_info);
1773 return(ImageToBlob(image_info,images,length,exception));
1774 }
1775 magick_info=GetMagickInfo(images->magick,exception);
1776 if (magick_info == (const MagickInfo *) NULL)
1777 {
1778 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001779 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'",
cristy3ed852e2009-09-05 21:47:34 +00001780 images->filename);
1781 return(blob);
1782 }
1783 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1784 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1785 {
1786 /*
1787 Native blob support for this images format.
1788 */
1789 blob_info->length=0;
1790 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1791 sizeof(unsigned char));
1792 if (blob_info->blob == (void *) NULL)
1793 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001794 ResourceLimitError,"MemoryAllocationFailed","'%s'",images->filename);
cristy3ed852e2009-09-05 21:47:34 +00001795 else
1796 {
1797 images->blob->exempt=MagickTrue;
1798 *images->filename='\0';
1799 status=WriteImages(blob_info,images,images->filename,exception);
cristyb24e2402011-10-07 00:48:39 +00001800 if ((status != MagickFalse) && (images->blob->length != 0))
cristy3ed852e2009-09-05 21:47:34 +00001801 {
1802 *length=images->blob->length;
1803 blob=DetachBlob(images->blob);
1804 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1805 sizeof(*blob));
1806 }
1807 }
1808 }
1809 else
1810 {
1811 char
1812 filename[MaxTextExtent],
1813 unique[MaxTextExtent];
1814
1815 int
1816 file;
1817
1818 /*
1819 Write file to disk in blob images format.
1820 */
1821 file=AcquireUniqueFileResource(unique);
1822 if (file == -1)
1823 {
1824 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1825 image_info->filename);
1826 }
1827 else
1828 {
1829 blob_info->file=fdopen(file,"wb");
1830 if (blob_info->file != (FILE *) NULL)
1831 {
cristyb51dff52011-05-19 16:55:47 +00001832 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001833 images->magick,unique);
1834 status=WriteImages(blob_info,images,filename,exception);
1835 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001836 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001837 blob=FileToBlob(images->filename,~0UL,length,exception);
1838 }
1839 (void) RelinquishUniqueFileResource(unique);
1840 }
1841 }
1842 blob_info=DestroyImageInfo(blob_info);
1843 return(blob);
1844}
1845/*
1846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1847% %
1848% %
1849% %
1850% I n j e c t I m a g e B l o b %
1851% %
1852% %
1853% %
1854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1855%
1856% InjectImageBlob() injects the image with a copy of itself in the specified
1857% format (e.g. inject JPEG into a PDF image).
1858%
1859% The format of the InjectImageBlob method is:
1860%
1861% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1862% Image *image,Image *inject_image,const char *format,
1863% ExceptionInfo *exception)
1864%
1865% A description of each parameter follows:
1866%
1867% o image_info: the image info..
1868%
1869% o image: the image.
1870%
1871% o inject_image: inject into the image stream.
1872%
1873% o format: the image format.
1874%
1875% o exception: return any errors or warnings in this structure.
1876%
1877*/
1878MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1879 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1880{
1881 char
1882 filename[MaxTextExtent];
1883
1884 FILE
1885 *unique_file;
1886
1887 Image
1888 *byte_image;
1889
1890 ImageInfo
1891 *write_info;
1892
1893 int
1894 file;
1895
1896 MagickBooleanType
1897 status;
1898
cristybb503372010-05-27 20:51:26 +00001899 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001900 i;
1901
1902 size_t
1903 quantum;
1904
1905 ssize_t
1906 count;
1907
1908 struct stat
cristye7b28372012-06-17 13:59:06 +00001909 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001910
1911 unsigned char
1912 *buffer;
1913
1914 /*
1915 Write inject image to a temporary file.
1916 */
1917 assert(image_info != (ImageInfo *) NULL);
1918 assert(image_info->signature == MagickSignature);
1919 assert(image != (Image *) NULL);
1920 assert(image->signature == MagickSignature);
1921 if (image->debug != MagickFalse)
1922 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1923 assert(inject_image != (Image *) NULL);
1924 assert(inject_image->signature == MagickSignature);
1925 assert(exception != (ExceptionInfo *) NULL);
1926 unique_file=(FILE *) NULL;
1927 file=AcquireUniqueFileResource(filename);
1928 if (file != -1)
1929 unique_file=fdopen(file,"wb");
1930 if ((file == -1) || (unique_file == (FILE *) NULL))
1931 {
1932 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1933 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1934 image->filename);
1935 return(MagickFalse);
1936 }
1937 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1938 if (byte_image == (Image *) NULL)
1939 {
1940 (void) fclose(unique_file);
1941 (void) RelinquishUniqueFileResource(filename);
1942 return(MagickFalse);
1943 }
cristyb51dff52011-05-19 16:55:47 +00001944 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001945 filename);
1946 DestroyBlob(byte_image);
1947 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1948 write_info=CloneImageInfo(image_info);
1949 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001950 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001951 write_info=DestroyImageInfo(write_info);
1952 byte_image=DestroyImage(byte_image);
1953 (void) fclose(unique_file);
1954 if (status == MagickFalse)
1955 {
1956 (void) RelinquishUniqueFileResource(filename);
1957 return(MagickFalse);
1958 }
1959 /*
1960 Inject into image stream.
1961 */
cristy18c6c272011-09-23 14:40:37 +00001962 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001963 if (file == -1)
1964 {
1965 (void) RelinquishUniqueFileResource(filename);
1966 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1967 image_info->filename);
1968 return(MagickFalse);
1969 }
1970 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001971 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1972 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001973 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1974 if (buffer == (unsigned char *) NULL)
1975 {
1976 (void) RelinquishUniqueFileResource(filename);
1977 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1978 image->filename);
1979 }
1980 for (i=0; ; i+=count)
1981 {
1982 count=(ssize_t) read(file,buffer,quantum);
1983 if (count <= 0)
1984 {
1985 count=0;
1986 if (errno != EINTR)
1987 break;
1988 }
1989 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1990 MagickFalse;
1991 }
cristya7cb4312010-06-26 00:47:03 +00001992 file=close(file);
1993 if (file == -1)
1994 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001995 (void) RelinquishUniqueFileResource(filename);
1996 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1997 return(status);
1998}
1999
2000/*
2001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2002% %
2003% %
2004% %
2005+ I s B l o b E x e m p t %
2006% %
2007% %
2008% %
2009%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2010%
2011% IsBlobExempt() returns true if the blob is exempt.
2012%
2013% The format of the IsBlobExempt method is:
2014%
2015% MagickBooleanType IsBlobExempt(const Image *image)
2016%
2017% A description of each parameter follows:
2018%
2019% o image: the image.
2020%
2021*/
cristy7832dc22011-09-05 01:21:53 +00002022MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002023{
2024 assert(image != (const Image *) NULL);
2025 assert(image->signature == MagickSignature);
2026 if (image->debug != MagickFalse)
2027 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2028 return(image->blob->exempt);
2029}
2030
2031/*
2032%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2033% %
2034% %
2035% %
2036+ I s B l o b S e e k a b l e %
2037% %
2038% %
2039% %
2040%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2041%
2042% IsBlobSeekable() returns true if the blob is seekable.
2043%
2044% The format of the IsBlobSeekable method is:
2045%
2046% MagickBooleanType IsBlobSeekable(const Image *image)
2047%
2048% A description of each parameter follows:
2049%
2050% o image: the image.
2051%
2052*/
cristy7832dc22011-09-05 01:21:53 +00002053MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002054{
2055 MagickBooleanType
2056 seekable;
2057
2058 assert(image != (const Image *) NULL);
2059 assert(image->signature == MagickSignature);
2060 if (image->debug != MagickFalse)
2061 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002062 switch (image->blob->type)
2063 {
2064 case FileStream:
2065 case BlobStream:
2066 case ZipStream:
2067 {
2068 seekable=MagickTrue;
2069 break;
2070 }
2071 default:
2072 {
2073 seekable=MagickFalse;
2074 break;
2075 }
2076 }
cristy3ed852e2009-09-05 21:47:34 +00002077 return(seekable);
2078}
2079
2080/*
2081%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2082% %
2083% %
2084% %
2085+ I s B l o b T e m p o r a r y %
2086% %
2087% %
2088% %
2089%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2090%
2091% IsBlobTemporary() returns true if the blob is temporary.
2092%
2093% The format of the IsBlobTemporary method is:
2094%
2095% MagickBooleanType IsBlobTemporary(const Image *image)
2096%
2097% A description of each parameter follows:
2098%
2099% o image: the image.
2100%
2101*/
cristy7832dc22011-09-05 01:21:53 +00002102MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002103{
2104 assert(image != (const Image *) NULL);
2105 assert(image->signature == MagickSignature);
2106 if (image->debug != MagickFalse)
2107 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2108 return(image->blob->temporary);
2109}
2110
2111/*
2112%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2113% %
2114% %
2115% %
2116+ M a p B l o b %
2117% %
2118% %
2119% %
2120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2121%
2122% MapBlob() creates a mapping from a file to a binary large object.
2123%
2124% The format of the MapBlob method is:
2125%
2126% unsigned char *MapBlob(int file,const MapMode mode,
2127% const MagickOffsetType offset,const size_t length)
2128%
2129% A description of each parameter follows:
2130%
2131% o file: map this file descriptor.
2132%
2133% o mode: ReadMode, WriteMode, or IOMode.
2134%
2135% o offset: starting at this offset within the file.
2136%
2137% o length: the length of the mapping is returned in this pointer.
2138%
2139*/
2140MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2141 const MagickOffsetType offset,const size_t length)
2142{
2143#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
2144 int
2145 flags,
2146 protection;
2147
2148 unsigned char
2149 *map;
2150
2151 /*
2152 Map file.
2153 */
2154 flags=0;
2155 if (file == -1)
2156#if defined(MAP_ANONYMOUS)
2157 flags|=MAP_ANONYMOUS;
2158#else
2159 return((unsigned char *) NULL);
2160#endif
2161 switch (mode)
2162 {
2163 case ReadMode:
2164 default:
2165 {
2166 protection=PROT_READ;
2167 flags|=MAP_PRIVATE;
2168 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2169 (off_t) offset);
2170 break;
2171 }
2172 case WriteMode:
2173 {
2174 protection=PROT_WRITE;
2175 flags|=MAP_SHARED;
2176 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2177 (off_t) offset);
cristy2a9e7cb2010-03-05 02:15:05 +00002178#if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
2179 (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
2180 POSIX_MADV_WILLNEED);
2181#endif
cristy3ed852e2009-09-05 21:47:34 +00002182 break;
2183 }
2184 case IOMode:
2185 {
2186 protection=PROT_READ | PROT_WRITE;
2187 flags|=MAP_SHARED;
2188 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2189 (off_t) offset);
2190 break;
2191 }
2192 }
2193 if (map == (unsigned char *) MAP_FAILED)
2194 return((unsigned char *) NULL);
2195 return(map);
2196#else
2197 (void) file;
2198 (void) mode;
2199 (void) offset;
2200 (void) length;
2201 return((unsigned char *) NULL);
2202#endif
2203}
2204
2205/*
2206%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2207% %
2208% %
2209% %
2210+ M S B O r d e r L o n g %
2211% %
2212% %
2213% %
2214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2215%
2216% MSBOrderLong() converts a least-significant byte first buffer of integers to
2217% most-significant byte first.
2218%
2219% The format of the MSBOrderLong method is:
2220%
2221% void MSBOrderLong(unsigned char *buffer,const size_t length)
2222%
2223% A description of each parameter follows.
2224%
2225% o buffer: Specifies a pointer to a buffer of integers.
2226%
2227% o length: Specifies the length of the buffer.
2228%
2229*/
2230MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2231{
2232 int
2233 c;
2234
2235 register unsigned char
2236 *p,
2237 *q;
2238
2239 assert(buffer != (unsigned char *) NULL);
2240 q=buffer+length;
2241 while (buffer < q)
2242 {
2243 p=buffer+3;
2244 c=(int) (*p);
2245 *p=(*buffer);
2246 *buffer++=(unsigned char) c;
2247 p=buffer+1;
2248 c=(int) (*p);
2249 *p=(*buffer);
2250 *buffer++=(unsigned char) c;
2251 buffer+=2;
2252 }
2253}
2254
2255/*
2256%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2257% %
2258% %
2259% %
2260+ M S B O r d e r S h o r t %
2261% %
2262% %
2263% %
2264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2265%
2266% MSBOrderShort() converts a least-significant byte first buffer of integers
2267% to most-significant byte first.
2268%
2269% The format of the MSBOrderShort method is:
2270%
2271% void MSBOrderShort(unsigned char *p,const size_t length)
2272%
2273% A description of each parameter follows.
2274%
2275% o p: Specifies a pointer to a buffer of integers.
2276%
2277% o length: Specifies the length of the buffer.
2278%
2279*/
2280MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2281{
2282 int
2283 c;
2284
2285 register unsigned char
2286 *q;
2287
2288 assert(p != (unsigned char *) NULL);
2289 q=p+length;
2290 while (p < q)
2291 {
2292 c=(int) (*p);
2293 *p=(*(p+1));
2294 p++;
2295 *p++=(unsigned char) c;
2296 }
2297}
2298
2299/*
2300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2301% %
2302% %
2303% %
2304+ O p e n B l o b %
2305% %
2306% %
2307% %
2308%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2309%
2310% OpenBlob() opens a file associated with the image. A file name of '-' sets
2311% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2312% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2313% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2314% from a system command.
2315%
2316% The format of the OpenBlob method is:
2317%
2318% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2319% const BlobMode mode,ExceptionInfo *exception)
2320%
2321% A description of each parameter follows:
2322%
2323% o image_info: the image info.
2324%
2325% o image: the image.
2326%
2327% o mode: the mode for opening the file.
2328%
2329*/
2330MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2331 Image *image,const BlobMode mode,ExceptionInfo *exception)
2332{
2333 char
cristybf6a7092010-06-11 02:12:15 +00002334 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002335 filename[MaxTextExtent];
2336
2337 const char
2338 *type;
2339
2340 MagickBooleanType
2341 status;
2342
2343 PolicyRights
2344 rights;
2345
2346 assert(image_info != (ImageInfo *) NULL);
2347 assert(image_info->signature == MagickSignature);
2348 if (image_info->debug != MagickFalse)
2349 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2350 image_info->filename);
2351 assert(image != (Image *) NULL);
2352 assert(image->signature == MagickSignature);
2353 if (image_info->blob != (void *) NULL)
2354 {
2355 if (image_info->stream != (StreamHandler) NULL)
2356 image->blob->stream=(StreamHandler) image_info->stream;
2357 AttachBlob(image->blob,image_info->blob,image_info->length);
2358 return(MagickTrue);
2359 }
2360 (void) DetachBlob(image->blob);
2361 switch (mode)
2362 {
2363 default: type="r"; break;
2364 case ReadBlobMode: type="r"; break;
2365 case ReadBinaryBlobMode: type="rb"; break;
2366 case WriteBlobMode: type="w"; break;
2367 case WriteBinaryBlobMode: type="w+b"; break;
2368 case AppendBlobMode: type="a"; break;
2369 case AppendBinaryBlobMode: type="a+b"; break;
2370 }
2371 if (*type != 'r')
2372 image->blob->synchronize=image_info->synchronize;
2373 if (image_info->stream != (StreamHandler) NULL)
2374 {
2375 image->blob->stream=(StreamHandler) image_info->stream;
2376 if (*type == 'w')
2377 {
2378 image->blob->type=FifoStream;
2379 return(MagickTrue);
2380 }
2381 }
2382 /*
2383 Open image file.
2384 */
2385 *filename='\0';
2386 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2387 rights=ReadPolicyRights;
2388 if (*type == 'w')
2389 rights=WritePolicyRights;
2390 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2391 {
cristya9197f62010-01-12 02:23:34 +00002392 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002393 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
anthonye5b39652012-04-21 05:37:29 +00002394 "NotAuthorized","'%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00002395 return(MagickFalse);
2396 }
2397 if ((LocaleCompare(filename,"-") == 0) ||
2398 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2399 {
cristye7b28372012-06-17 13:59:06 +00002400 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002401#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002402 if (strchr(type,'b') != (char *) NULL)
cristye7b28372012-06-17 13:59:06 +00002403 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002404#endif
2405 image->blob->type=StandardStream;
2406 image->blob->exempt=MagickTrue;
2407 return(MagickTrue);
2408 }
cristybc20d112012-07-29 20:27:00 +00002409 if (LocaleNCompare(filename,"fd:",3) == 0)
2410 {
2411 char
2412 mode[MaxTextExtent];
2413
2414 *mode=(*type);
2415 mode[1]='\0';
2416 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2417#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2418 if (strchr(type,'b') != (char *) NULL)
2419 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2420#endif
2421 image->blob->type=StandardStream;
2422 image->blob->exempt=MagickTrue;
2423 return(MagickTrue);
2424 }
cristy3ed852e2009-09-05 21:47:34 +00002425#if defined(MAGICKCORE_HAVE_POPEN)
2426 if (*filename == '|')
2427 {
2428 char
2429 mode[MaxTextExtent];
2430
2431 /*
2432 Pipe image to or from a system command.
2433 */
2434#if defined(SIGPIPE)
2435 if (*type == 'w')
2436 (void) signal(SIGPIPE,SIG_IGN);
2437#endif
2438 *mode=(*type);
2439 mode[1]='\0';
cristye7b28372012-06-17 13:59:06 +00002440 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2441 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002442 {
2443 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2444 return(MagickFalse);
2445 }
2446 image->blob->type=PipeStream;
2447 image->blob->exempt=MagickTrue;
2448 return(MagickTrue);
2449 }
2450#endif
2451 status=GetPathAttributes(filename,&image->blob->properties);
2452#if defined(S_ISFIFO)
2453 if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2454 {
cristye7b28372012-06-17 13:59:06 +00002455 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2456 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002457 {
2458 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2459 return(MagickFalse);
2460 }
2461 image->blob->type=FileStream;
2462 image->blob->exempt=MagickTrue;
2463 return(MagickTrue);
2464 }
2465#endif
cristybf6a7092010-06-11 02:12:15 +00002466 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002467 if (*type == 'w')
2468 {
cristye8939e72010-02-03 17:05:25 +00002469 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002470 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002471 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002472 {
2473 /*
2474 Form filename for multi-part images.
2475 */
2476 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002477 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002478 if ((LocaleCompare(filename,image->filename) == 0) &&
2479 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2480 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002481 {
cristybf7fa0d2010-02-04 00:51:10 +00002482 char
cristybf7fa0d2010-02-04 00:51:10 +00002483 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002484
cristybf7fa0d2010-02-04 00:51:10 +00002485 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002486 if (*extension == '\0')
cristyb51dff52011-05-19 16:55:47 +00002487 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002488 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002489 else
cristyb51dff52011-05-19 16:55:47 +00002490 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002491 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002492 }
2493 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002494#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002495 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002496#endif
cristye8939e72010-02-03 17:05:25 +00002497 }
cristy3ed852e2009-09-05 21:47:34 +00002498 }
cristybf6a7092010-06-11 02:12:15 +00002499 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002500 {
cristye7b28372012-06-17 13:59:06 +00002501 image->blob->file_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002502 image->blob->type=FileStream;
2503 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002504 }
2505 else
cristybf6a7092010-06-11 02:12:15 +00002506 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002507 {
cristye7b28372012-06-17 13:59:06 +00002508 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2509 if (image->blob->file_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002510 {
2511 size_t
cristybf6a7092010-06-11 02:12:15 +00002512 count;
cristy3ed852e2009-09-05 21:47:34 +00002513
cristybf6a7092010-06-11 02:12:15 +00002514 unsigned char
2515 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002516
cristybf6a7092010-06-11 02:12:15 +00002517 image->blob->type=FileStream;
2518#if defined(MAGICKCORE_HAVE_SETVBUF)
cristye7b28372012-06-17 13:59:06 +00002519 (void) setvbuf(image->blob->file_info.file,(char *) NULL,
cristy95888612012-04-04 21:56:52 +00002520 (int) _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002521#endif
2522 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristye7b28372012-06-17 13:59:06 +00002523 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
2524 (void) rewind(image->blob->file_info.file);
cristybf6a7092010-06-11 02:12:15 +00002525 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2526 " read %.20g magic header bytes",(double) count);
2527#if defined(MAGICKCORE_ZLIB_DELEGATE)
2528 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2529 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002530 {
cristye7b28372012-06-17 13:59:06 +00002531 (void) fclose(image->blob->file_info.file);
2532 image->blob->file_info.gzfile=gzopen(filename,type);
2533 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002534 image->blob->type=ZipStream;
2535 }
2536#endif
2537#if defined(MAGICKCORE_BZLIB_DELEGATE)
2538 if (strncmp((char *) magick,"BZh",3) == 0)
2539 {
cristye7b28372012-06-17 13:59:06 +00002540 (void) fclose(image->blob->file_info.file);
2541 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2542 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002543 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002544 }
cristybf6a7092010-06-11 02:12:15 +00002545#endif
cristyc6c589d2010-07-06 01:34:57 +00002546 if (image->blob->type == FileStream)
2547 {
2548 const MagickInfo
2549 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002550
cristyc6c589d2010-07-06 01:34:57 +00002551 ExceptionInfo
2552 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002553
cristyc6c589d2010-07-06 01:34:57 +00002554 struct stat
2555 *properties;
cristybf6a7092010-06-11 02:12:15 +00002556
cristyc6c589d2010-07-06 01:34:57 +00002557 sans_exception=AcquireExceptionInfo();
2558 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2559 sans_exception=DestroyExceptionInfo(sans_exception);
2560 properties=(&image->blob->properties);
2561 if ((magick_info != (const MagickInfo *) NULL) &&
2562 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2563 (properties->st_size <= MagickMaxBufferExtent))
2564 {
2565 size_t
2566 length;
cristybf6a7092010-06-11 02:12:15 +00002567
cristyc6c589d2010-07-06 01:34:57 +00002568 void
2569 *blob;
cristybf6a7092010-06-11 02:12:15 +00002570
cristyc6c589d2010-07-06 01:34:57 +00002571 length=(size_t) properties->st_size;
cristye7b28372012-06-17 13:59:06 +00002572 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,
cristy95888612012-04-04 21:56:52 +00002573 0,length);
cristyc6c589d2010-07-06 01:34:57 +00002574 if (blob != (void *) NULL)
2575 {
2576 /*
2577 Format supports blobs-- use memory-mapped I/O.
2578 */
2579 if (image_info->file != (FILE *) NULL)
2580 image->blob->exempt=MagickFalse;
2581 else
2582 {
cristye7b28372012-06-17 13:59:06 +00002583 (void) fclose(image->blob->file_info.file);
2584 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002585 }
2586 AttachBlob(image->blob,blob,length);
2587 image->blob->mapped=MagickTrue;
2588 }
2589 }
2590 }
cristy3ed852e2009-09-05 21:47:34 +00002591 }
cristybf6a7092010-06-11 02:12:15 +00002592 }
2593 else
2594#if defined(MAGICKCORE_ZLIB_DELEGATE)
2595 if ((LocaleCompare(extension,"Z") == 0) ||
2596 (LocaleCompare(extension,"gz") == 0) ||
2597 (LocaleCompare(extension,"wmz") == 0) ||
2598 (LocaleCompare(extension,"svgz") == 0))
2599 {
2600 if (mode == WriteBinaryBlobMode)
2601 type="wb";
cristye7b28372012-06-17 13:59:06 +00002602 image->blob->file_info.gzfile=gzopen(filename,type);
2603 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002604 image->blob->type=ZipStream;
2605 }
2606 else
2607#endif
2608#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002609 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002610 {
cristye7b28372012-06-17 13:59:06 +00002611 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2612 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002613 image->blob->type=BZipStream;
2614 }
2615 else
2616#endif
2617 {
cristye7b28372012-06-17 13:59:06 +00002618 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2619 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002620 {
2621 image->blob->type=FileStream;
2622#if defined(MAGICKCORE_HAVE_SETVBUF)
cristye7b28372012-06-17 13:59:06 +00002623 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int) _IOFBF,
cristybf6a7092010-06-11 02:12:15 +00002624 16384);
2625#endif
2626 }
2627 }
cristy3ed852e2009-09-05 21:47:34 +00002628 image->blob->status=MagickFalse;
2629 if (image->blob->type != UndefinedStream)
2630 image->blob->size=GetBlobSize(image);
2631 else
2632 {
2633 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2634 return(MagickFalse);
2635 }
2636 return(MagickTrue);
2637}
2638
2639/*
2640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2641% %
2642% %
2643% %
2644+ P i n g B l o b %
2645% %
2646% %
2647% %
2648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2649%
2650% PingBlob() returns all the attributes of an image or image sequence except
2651% for the pixels. It is much faster and consumes far less memory than
2652% BlobToImage(). On failure, a NULL image is returned and exception
2653% describes the reason for the failure.
2654%
2655% The format of the PingBlob method is:
2656%
2657% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2658% const size_t length,ExceptionInfo *exception)
2659%
2660% A description of each parameter follows:
2661%
2662% o image_info: the image info.
2663%
2664% o blob: the address of a character stream in one of the image formats
2665% understood by ImageMagick.
2666%
2667% o length: This size_t integer reflects the length in bytes of the blob.
2668%
2669% o exception: return any errors or warnings in this structure.
2670%
2671*/
2672
2673#if defined(__cplusplus) || defined(c_plusplus)
2674extern "C" {
2675#endif
2676
2677static size_t PingStream(const Image *magick_unused(image),
2678 const void *magick_unused(pixels),const size_t columns)
2679{
2680 return(columns);
2681}
2682
2683#if defined(__cplusplus) || defined(c_plusplus)
2684}
2685#endif
2686
2687MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2688 const size_t length,ExceptionInfo *exception)
2689{
2690 Image
2691 *image;
2692
2693 ImageInfo
2694 *ping_info;
2695
2696 assert(image_info != (ImageInfo *) NULL);
2697 assert(image_info->signature == MagickSignature);
2698 if (image_info->debug != MagickFalse)
2699 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2700 image_info->filename);
2701 assert(exception != (ExceptionInfo *) NULL);
2702 if ((blob == (const void *) NULL) || (length == 0))
2703 {
2704 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
anthonye5b39652012-04-21 05:37:29 +00002705 "UnrecognizedImageFormat","'%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002706 return((Image *) NULL);
2707 }
2708 ping_info=CloneImageInfo(image_info);
2709 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2710 if (ping_info->blob == (const void *) NULL)
2711 {
2712 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00002713 ResourceLimitFatalError,"MemoryAllocationFailed","'%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002714 return((Image *) NULL);
2715 }
cristy54aad5e2010-09-03 16:02:04 +00002716 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002717 ping_info->length=length;
2718 ping_info->ping=MagickTrue;
2719 image=ReadStream(ping_info,&PingStream,exception);
2720 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2721 ping_info=DestroyImageInfo(ping_info);
2722 return(image);
2723}
2724
2725/*
2726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2727% %
2728% %
2729% %
2730+ R e a d B l o b %
2731% %
2732% %
2733% %
2734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2735%
2736% ReadBlob() reads data from the blob or image file and returns it. It
2737% returns the number of bytes read.
2738%
2739% The format of the ReadBlob method is:
2740%
2741% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2742%
2743% A description of each parameter follows:
2744%
2745% o image: the image.
2746%
2747% o length: Specifies an integer representing the number of bytes to read
2748% from the file.
2749%
2750% o data: Specifies an area to place the information requested from the
2751% file.
2752%
2753*/
2754MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2755 unsigned char *data)
2756{
2757 int
2758 c;
2759
2760 register unsigned char
2761 *q;
2762
2763 ssize_t
2764 count;
2765
2766 assert(image != (Image *) NULL);
2767 assert(image->signature == MagickSignature);
2768 assert(image->blob != (BlobInfo *) NULL);
2769 assert(image->blob->type != UndefinedStream);
2770 if (length == 0)
2771 return(0);
2772 assert(data != (void *) NULL);
2773 count=0;
2774 q=data;
2775 switch (image->blob->type)
2776 {
2777 case UndefinedStream:
2778 break;
cristy3ed852e2009-09-05 21:47:34 +00002779 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002780 {
2781 count=(ssize_t) read(fileno(image->blob->file_info.file),q,length);
2782 break;
2783 }
2784 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002785 case PipeStream:
2786 {
2787 switch (length)
2788 {
2789 default:
2790 {
cristye7b28372012-06-17 13:59:06 +00002791 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002792 break;
2793 }
2794 case 2:
2795 {
cristye7b28372012-06-17 13:59:06 +00002796 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002797 if (c == EOF)
2798 break;
2799 *q++=(unsigned char) c;
2800 count++;
2801 }
2802 case 1:
2803 {
cristye7b28372012-06-17 13:59:06 +00002804 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002805 if (c == EOF)
2806 break;
2807 *q++=(unsigned char) c;
2808 count++;
2809 }
2810 case 0:
2811 break;
2812 }
2813 break;
2814 }
2815 case ZipStream:
2816 {
2817#if defined(MAGICKCORE_ZLIB_DELEGATE)
2818 switch (length)
2819 {
2820 default:
2821 {
cristye7b28372012-06-17 13:59:06 +00002822 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002823 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002824 break;
2825 }
2826 case 2:
2827 {
cristye7b28372012-06-17 13:59:06 +00002828 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002829 if (c == EOF)
2830 break;
2831 *q++=(unsigned char) c;
2832 count++;
2833 }
2834 case 1:
2835 {
cristye7b28372012-06-17 13:59:06 +00002836 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002837 if (c == EOF)
2838 break;
2839 *q++=(unsigned char) c;
2840 count++;
2841 }
2842 case 0:
2843 break;
2844 }
2845#endif
2846 break;
2847 }
2848 case BZipStream:
2849 {
2850#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00002851 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,
cristy95888612012-04-04 21:56:52 +00002852 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00002853#endif
2854 break;
2855 }
2856 case FifoStream:
2857 break;
2858 case BlobStream:
2859 {
2860 register const unsigned char
2861 *p;
2862
2863 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2864 {
2865 image->blob->eof=MagickTrue;
2866 break;
2867 }
2868 p=image->blob->data+image->blob->offset;
cristye7b28372012-06-17 13:59:06 +00002869 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2870 image->blob->offset));
cristy3ed852e2009-09-05 21:47:34 +00002871 image->blob->offset+=count;
2872 if (count != (ssize_t) length)
2873 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002874 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002875 break;
2876 }
2877 }
2878 return(count);
2879}
2880
2881/*
2882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2883% %
2884% %
2885% %
2886+ R e a d B l o b B y t e %
2887% %
2888% %
2889% %
2890%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2891%
2892% ReadBlobByte() reads a single byte from the image file and returns it.
2893%
2894% The format of the ReadBlobByte method is:
2895%
2896% int ReadBlobByte(Image *image)
2897%
2898% A description of each parameter follows.
2899%
2900% o image: the image.
2901%
2902*/
2903MagickExport int ReadBlobByte(Image *image)
2904{
2905 register const unsigned char
2906 *p;
2907
2908 ssize_t
2909 count;
2910
2911 unsigned char
2912 buffer[1];
2913
2914 assert(image != (Image *) NULL);
2915 assert(image->signature == MagickSignature);
2916 p=ReadBlobStream(image,1,buffer,&count);
2917 if (count != 1)
2918 return(EOF);
2919 return((int) (*p));
2920}
2921
2922/*
2923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2924% %
2925% %
2926% %
2927+ R e a d B l o b D o u b l e %
2928% %
2929% %
2930% %
2931%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2932%
2933% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2934% specified by the endian member of the image structure.
2935%
2936% The format of the ReadBlobDouble method is:
2937%
2938% double ReadBlobDouble(Image *image)
2939%
2940% A description of each parameter follows.
2941%
2942% o image: the image.
2943%
2944*/
2945MagickExport double ReadBlobDouble(Image *image)
2946{
2947 union
2948 {
2949 MagickSizeType
2950 unsigned_value;
2951
2952 double
2953 double_value;
2954 } quantum;
2955
2956 quantum.double_value=0.0;
2957 quantum.unsigned_value=ReadBlobLongLong(image);
2958 return(quantum.double_value);
2959}
2960
2961/*
2962%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2963% %
2964% %
2965% %
2966+ R e a d B l o b F l o a t %
2967% %
2968% %
2969% %
2970%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2971%
2972% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2973% specified by the endian member of the image structure.
2974%
2975% The format of the ReadBlobFloat method is:
2976%
2977% float ReadBlobFloat(Image *image)
2978%
2979% A description of each parameter follows.
2980%
2981% o image: the image.
2982%
2983*/
2984MagickExport float ReadBlobFloat(Image *image)
2985{
2986 union
2987 {
2988 unsigned int
2989 unsigned_value;
2990
2991 float
2992 float_value;
2993 } quantum;
2994
2995 quantum.float_value=0.0;
2996 quantum.unsigned_value=ReadBlobLong(image);
2997 return(quantum.float_value);
2998}
2999
3000/*
3001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3002% %
3003% %
3004% %
3005+ R e a d B l o b L o n g %
3006% %
3007% %
3008% %
3009%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3010%
cristybb503372010-05-27 20:51:26 +00003011% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003012% specified by the endian member of the image structure.
3013%
3014% The format of the ReadBlobLong method is:
3015%
3016% unsigned int ReadBlobLong(Image *image)
3017%
3018% A description of each parameter follows.
3019%
3020% o image: the image.
3021%
3022*/
3023MagickExport unsigned int ReadBlobLong(Image *image)
3024{
3025 register const unsigned char
3026 *p;
3027
3028 ssize_t
3029 count;
3030
3031 unsigned char
3032 buffer[4];
3033
3034 unsigned int
3035 value;
3036
3037 assert(image != (Image *) NULL);
3038 assert(image->signature == MagickSignature);
3039 *buffer='\0';
3040 p=ReadBlobStream(image,4,buffer,&count);
3041 if (count != 4)
3042 return(0UL);
3043 if (image->endian == LSBEndian)
3044 {
3045 value=(unsigned int) (*p++);
3046 value|=((unsigned int) (*p++)) << 8;
3047 value|=((unsigned int) (*p++)) << 16;
3048 value|=((unsigned int) (*p++)) << 24;
3049 return(value);
3050 }
3051 value=((unsigned int) (*p++)) << 24;
3052 value|=((unsigned int) (*p++)) << 16;
3053 value|=((unsigned int) (*p++)) << 8;
3054 value|=((unsigned int) (*p++));
3055 return(value);
3056}
3057
3058/*
3059%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3060% %
3061% %
3062% %
3063+ R e a d B l o b L o n g L o n g %
3064% %
3065% %
3066% %
3067%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3068%
cristy4cb162a2010-05-30 03:04:47 +00003069% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3070% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003071%
cristy4cb162a2010-05-30 03:04:47 +00003072% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003073%
cristy4cb162a2010-05-30 03:04:47 +00003074% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003075%
3076% A description of each parameter follows.
3077%
3078% o image: the image.
3079%
3080*/
3081MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3082{
cristy0286d852010-10-12 18:38:07 +00003083 MagickSizeType
3084 value;
3085
cristy3ed852e2009-09-05 21:47:34 +00003086 register const unsigned char
3087 *p;
3088
3089 ssize_t
3090 count;
3091
3092 unsigned char
3093 buffer[8];
3094
cristy3ed852e2009-09-05 21:47:34 +00003095 assert(image != (Image *) NULL);
3096 assert(image->signature == MagickSignature);
3097 *buffer='\0';
3098 p=ReadBlobStream(image,8,buffer,&count);
3099 if (count != 8)
3100 return(MagickULLConstant(0));
3101 if (image->endian == LSBEndian)
3102 {
3103 value=(MagickSizeType) (*p++);
3104 value|=((MagickSizeType) (*p++)) << 8;
3105 value|=((MagickSizeType) (*p++)) << 16;
3106 value|=((MagickSizeType) (*p++)) << 24;
3107 value|=((MagickSizeType) (*p++)) << 32;
3108 value|=((MagickSizeType) (*p++)) << 40;
3109 value|=((MagickSizeType) (*p++)) << 48;
3110 value|=((MagickSizeType) (*p++)) << 56;
3111 return(value & MagickULLConstant(0xffffffffffffffff));
3112 }
3113 value=((MagickSizeType) (*p++)) << 56;
3114 value|=((MagickSizeType) (*p++)) << 48;
3115 value|=((MagickSizeType) (*p++)) << 40;
3116 value|=((MagickSizeType) (*p++)) << 32;
3117 value|=((MagickSizeType) (*p++)) << 24;
3118 value|=((MagickSizeType) (*p++)) << 16;
3119 value|=((MagickSizeType) (*p++)) << 8;
3120 value|=((MagickSizeType) (*p++));
3121 return(value & MagickULLConstant(0xffffffffffffffff));
3122}
3123
3124/*
3125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3126% %
3127% %
3128% %
3129+ R e a d B l o b S h o r t %
3130% %
3131% %
3132% %
3133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3134%
3135% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3136% specified by the endian member of the image structure.
3137%
3138% The format of the ReadBlobShort method is:
3139%
3140% unsigned short ReadBlobShort(Image *image)
3141%
3142% A description of each parameter follows.
3143%
3144% o image: the image.
3145%
3146*/
3147MagickExport unsigned short ReadBlobShort(Image *image)
3148{
3149 register const unsigned char
3150 *p;
3151
3152 register unsigned int
3153 value;
3154
3155 ssize_t
3156 count;
3157
3158 unsigned char
3159 buffer[2];
3160
3161 assert(image != (Image *) NULL);
3162 assert(image->signature == MagickSignature);
3163 *buffer='\0';
3164 p=ReadBlobStream(image,2,buffer,&count);
3165 if (count != 2)
3166 return((unsigned short) 0U);
3167 if (image->endian == LSBEndian)
3168 {
3169 value=(unsigned int) (*p++);
3170 value|=((unsigned int) (*p++)) << 8;
3171 return((unsigned short) (value & 0xffff));
3172 }
3173 value=(unsigned int) ((*p++) << 8);
3174 value|=(unsigned int) (*p++);
3175 return((unsigned short) (value & 0xffff));
3176}
3177
3178/*
3179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3180% %
3181% %
3182% %
3183+ R e a d B l o b L S B L o n g %
3184% %
3185% %
3186% %
3187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3188%
cristybb503372010-05-27 20:51:26 +00003189% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003190% least-significant byte first order.
3191%
3192% The format of the ReadBlobLSBLong method is:
3193%
3194% unsigned int ReadBlobLSBLong(Image *image)
3195%
3196% A description of each parameter follows.
3197%
3198% o image: the image.
3199%
3200*/
3201MagickExport unsigned int ReadBlobLSBLong(Image *image)
3202{
3203 register const unsigned char
3204 *p;
3205
3206 register unsigned int
3207 value;
3208
3209 ssize_t
3210 count;
3211
3212 unsigned char
3213 buffer[4];
3214
3215 assert(image != (Image *) NULL);
3216 assert(image->signature == MagickSignature);
3217 *buffer='\0';
3218 p=ReadBlobStream(image,4,buffer,&count);
3219 if (count != 4)
3220 return(0U);
3221 value=(unsigned int) (*p++);
3222 value|=((unsigned int) (*p++)) << 8;
3223 value|=((unsigned int) (*p++)) << 16;
3224 value|=((unsigned int) (*p++)) << 24;
3225 return(value);
3226}
3227
3228/*
3229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3230% %
3231% %
3232% %
3233+ R e a d B l o b L S B S h o r t %
3234% %
3235% %
3236% %
3237%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3238%
3239% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3240% least-significant byte first order.
3241%
3242% The format of the ReadBlobLSBShort method is:
3243%
3244% unsigned short ReadBlobLSBShort(Image *image)
3245%
3246% A description of each parameter follows.
3247%
3248% o image: the image.
3249%
3250*/
3251MagickExport unsigned short ReadBlobLSBShort(Image *image)
3252{
3253 register const unsigned char
3254 *p;
3255
3256 register unsigned int
3257 value;
3258
3259 ssize_t
3260 count;
3261
3262 unsigned char
3263 buffer[2];
3264
3265 assert(image != (Image *) NULL);
3266 assert(image->signature == MagickSignature);
3267 *buffer='\0';
3268 p=ReadBlobStream(image,2,buffer,&count);
3269 if (count != 2)
3270 return((unsigned short) 0U);
3271 value=(unsigned int) (*p++);
3272 value|=((unsigned int) ((*p++)) << 8);
3273 return((unsigned short) (value & 0xffff));
3274}
3275
3276/*
3277%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3278% %
3279% %
3280% %
3281+ R e a d B l o b M S B L o n g %
3282% %
3283% %
3284% %
3285%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3286%
cristybb503372010-05-27 20:51:26 +00003287% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003288% most-significant byte first order.
3289%
3290% The format of the ReadBlobMSBLong method is:
3291%
3292% unsigned int ReadBlobMSBLong(Image *image)
3293%
3294% A description of each parameter follows.
3295%
3296% o image: the image.
3297%
3298*/
3299MagickExport unsigned int ReadBlobMSBLong(Image *image)
3300{
3301 register const unsigned char
3302 *p;
3303
3304 register unsigned int
3305 value;
3306
3307 ssize_t
3308 count;
3309
3310 unsigned char
3311 buffer[4];
3312
3313 assert(image != (Image *) NULL);
3314 assert(image->signature == MagickSignature);
3315 *buffer='\0';
3316 p=ReadBlobStream(image,4,buffer,&count);
3317 if (count != 4)
3318 return(0UL);
3319 value=((unsigned int) (*p++) << 24);
3320 value|=((unsigned int) (*p++) << 16);
3321 value|=((unsigned int) (*p++) << 8);
3322 value|=(unsigned int) (*p++);
3323 return(value);
3324}
3325
3326/*
3327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3328% %
3329% %
3330% %
cristy2d3d87f2010-03-01 00:23:08 +00003331+ R e a d B l o b M S B L o n g L o n g %
3332% %
3333% %
3334% %
3335%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3336%
cristybb503372010-05-27 20:51:26 +00003337% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003338% most-significant byte first order.
3339%
3340% The format of the ReadBlobMSBLongLong method is:
3341%
3342% unsigned int ReadBlobMSBLongLong(Image *image)
3343%
3344% A description of each parameter follows.
3345%
3346% o image: the image.
3347%
3348*/
3349MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3350{
3351 register const unsigned char
3352 *p;
3353
3354 register MagickSizeType
3355 value;
3356
3357 ssize_t
3358 count;
3359
3360 unsigned char
cristy0286d852010-10-12 18:38:07 +00003361 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003362
3363 assert(image != (Image *) NULL);
3364 assert(image->signature == MagickSignature);
3365 *buffer='\0';
3366 p=ReadBlobStream(image,8,buffer,&count);
3367 if (count != 8)
3368 return(MagickULLConstant(0));
3369 value=((MagickSizeType) (*p++)) << 56;
3370 value|=((MagickSizeType) (*p++)) << 48;
3371 value|=((MagickSizeType) (*p++)) << 40;
3372 value|=((MagickSizeType) (*p++)) << 32;
3373 value|=((MagickSizeType) (*p++)) << 24;
3374 value|=((MagickSizeType) (*p++)) << 16;
3375 value|=((MagickSizeType) (*p++)) << 8;
3376 value|=((MagickSizeType) (*p++));
3377 return(value & MagickULLConstant(0xffffffffffffffff));
3378}
3379
3380/*
3381%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3382% %
3383% %
3384% %
cristy3ed852e2009-09-05 21:47:34 +00003385+ R e a d B l o b M S B S h o r t %
3386% %
3387% %
3388% %
3389%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3390%
3391% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3392% most-significant byte first order.
3393%
3394% The format of the ReadBlobMSBShort method is:
3395%
3396% unsigned short ReadBlobMSBShort(Image *image)
3397%
3398% A description of each parameter follows.
3399%
3400% o image: the image.
3401%
3402*/
3403MagickExport unsigned short ReadBlobMSBShort(Image *image)
3404{
3405 register const unsigned char
3406 *p;
3407
3408 register unsigned int
3409 value;
3410
3411 ssize_t
3412 count;
3413
3414 unsigned char
3415 buffer[2];
3416
3417 assert(image != (Image *) NULL);
3418 assert(image->signature == MagickSignature);
3419 *buffer='\0';
3420 p=ReadBlobStream(image,2,buffer,&count);
3421 if (count != 2)
3422 return((unsigned short) 0U);
3423 value=(unsigned int) ((*p++) << 8);
3424 value|=(unsigned int) (*p++);
3425 return((unsigned short) (value & 0xffff));
3426}
3427
3428/*
3429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3430% %
3431% %
3432% %
3433+ R e a d B l o b S t r i n g %
3434% %
3435% %
3436% %
3437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3438%
3439% ReadBlobString() reads characters from a blob or file until a newline
3440% character is read or an end-of-file condition is encountered.
3441%
3442% The format of the ReadBlobString method is:
3443%
3444% char *ReadBlobString(Image *image,char *string)
3445%
3446% A description of each parameter follows:
3447%
3448% o image: the image.
3449%
3450% o string: the address of a character buffer.
3451%
3452*/
3453MagickExport char *ReadBlobString(Image *image,char *string)
3454{
3455 register const unsigned char
3456 *p;
3457
cristybb503372010-05-27 20:51:26 +00003458 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003459 i;
3460
3461 ssize_t
3462 count;
3463
3464 unsigned char
3465 buffer[1];
3466
3467 assert(image != (Image *) NULL);
3468 assert(image->signature == MagickSignature);
3469 for (i=0; i < (MaxTextExtent-1L); i++)
3470 {
3471 p=ReadBlobStream(image,1,buffer,&count);
3472 if (count != 1)
3473 {
3474 if (i == 0)
3475 return((char *) NULL);
3476 break;
3477 }
3478 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003479 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003480 break;
3481 }
cristy2b5db102010-06-09 01:07:28 +00003482 if (string[i] == '\r')
3483 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003484 string[i]='\0';
3485 return(string);
3486}
3487
3488/*
3489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3490% %
3491% %
3492% %
3493+ R e f e r e n c e B l o b %
3494% %
3495% %
3496% %
3497%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3498%
3499% ReferenceBlob() increments the reference count associated with the pixel
3500% blob returning a pointer to the blob.
3501%
3502% The format of the ReferenceBlob method is:
3503%
3504% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3505%
3506% A description of each parameter follows:
3507%
3508% o blob_info: the blob_info.
3509%
3510*/
3511MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3512{
3513 assert(blob != (BlobInfo *) NULL);
3514 assert(blob->signature == MagickSignature);
3515 if (blob->debug != MagickFalse)
3516 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003517 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003518 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003519 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003520 return(blob);
3521}
3522
3523/*
3524%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3525% %
3526% %
3527% %
3528+ S e e k B l o b %
3529% %
3530% %
3531% %
3532%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3533%
3534% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3535% and returns the resulting offset.
3536%
3537% The format of the SeekBlob method is:
3538%
3539% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3540% const int whence)
3541%
3542% A description of each parameter follows:
3543%
3544% o image: the image.
3545%
3546% o offset: Specifies an integer representing the offset in bytes.
3547%
3548% o whence: Specifies an integer representing how the offset is
3549% treated relative to the beginning of the blob as follows:
3550%
3551% SEEK_SET Set position equal to offset bytes.
3552% SEEK_CUR Set position to current location plus offset.
3553% SEEK_END Set position to EOF plus offset.
3554%
3555*/
3556MagickExport MagickOffsetType SeekBlob(Image *image,
3557 const MagickOffsetType offset,const int whence)
3558{
3559 assert(image != (Image *) NULL);
3560 assert(image->signature == MagickSignature);
3561 if (image->debug != MagickFalse)
3562 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3563 assert(image->blob != (BlobInfo *) NULL);
3564 assert(image->blob->type != UndefinedStream);
3565 switch (image->blob->type)
3566 {
3567 case UndefinedStream:
3568 break;
cristybc20d112012-07-29 20:27:00 +00003569 case StandardStream:
3570 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003571 case FileStream:
3572 {
cristye7b28372012-06-17 13:59:06 +00003573 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003574 return(-1);
3575 image->blob->offset=TellBlob(image);
3576 break;
3577 }
cristy3ed852e2009-09-05 21:47:34 +00003578 case PipeStream:
3579 case ZipStream:
3580 {
3581#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003582 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003583 return(-1);
3584#endif
3585 image->blob->offset=TellBlob(image);
3586 break;
3587 }
3588 case BZipStream:
3589 return(-1);
3590 case FifoStream:
3591 return(-1);
3592 case BlobStream:
3593 {
3594 switch (whence)
3595 {
3596 case SEEK_SET:
3597 default:
3598 {
3599 if (offset < 0)
3600 return(-1);
3601 image->blob->offset=offset;
3602 break;
3603 }
3604 case SEEK_CUR:
3605 {
3606 if ((image->blob->offset+offset) < 0)
3607 return(-1);
3608 image->blob->offset+=offset;
3609 break;
3610 }
3611 case SEEK_END:
3612 {
3613 if (((MagickOffsetType) image->blob->length+offset) < 0)
3614 return(-1);
3615 image->blob->offset=image->blob->length+offset;
3616 break;
3617 }
3618 }
3619 if (image->blob->offset <= (MagickOffsetType)
3620 ((off_t) image->blob->length))
3621 image->blob->eof=MagickFalse;
3622 else
3623 if (image->blob->mapped != MagickFalse)
3624 return(-1);
3625 else
3626 {
3627 image->blob->extent=(size_t) (image->blob->offset+
3628 image->blob->quantum);
3629 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3630 image->blob->data,image->blob->extent+1,
3631 sizeof(*image->blob->data));
3632 (void) SyncBlob(image);
3633 if (image->blob->data == (unsigned char *) NULL)
3634 {
3635 (void) DetachBlob(image->blob);
3636 return(-1);
3637 }
3638 }
3639 break;
3640 }
3641 }
3642 return(image->blob->offset);
3643}
3644
3645/*
3646%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3647% %
3648% %
3649% %
3650+ S e t B l o b E x e m p t %
3651% %
3652% %
3653% %
3654%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3655%
3656% SetBlobExempt() sets the blob exempt status.
3657%
3658% The format of the SetBlobExempt method is:
3659%
3660% MagickBooleanType SetBlobExempt(const Image *image,
3661% const MagickBooleanType exempt)
3662%
3663% A description of each parameter follows:
3664%
3665% o image: the image.
3666%
3667% o exempt: Set to true if this blob is exempt from being closed.
3668%
3669*/
cristy7832dc22011-09-05 01:21:53 +00003670MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003671{
3672 assert(image != (const Image *) NULL);
3673 assert(image->signature == MagickSignature);
3674 if (image->debug != MagickFalse)
3675 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3676 image->blob->exempt=exempt;
3677}
3678
3679/*
3680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3681% %
3682% %
3683% %
3684+ S e t B l o b E x t e n t %
3685% %
3686% %
3687% %
3688%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3689%
3690% SetBlobExtent() ensures enough space is allocated for the blob. If the
3691% method is successful, subsequent writes to bytes in the specified range are
3692% guaranteed not to fail.
3693%
3694% The format of the SetBlobExtent method is:
3695%
3696% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3697%
3698% A description of each parameter follows:
3699%
3700% o image: the image.
3701%
3702% o extent: the blob maximum extent.
3703%
3704*/
cristy7832dc22011-09-05 01:21:53 +00003705MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003706 const MagickSizeType extent)
3707{
3708 assert(image != (Image *) NULL);
3709 assert(image->signature == MagickSignature);
3710 if (image->debug != MagickFalse)
3711 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3712 assert(image->blob != (BlobInfo *) NULL);
3713 assert(image->blob->type != UndefinedStream);
3714 switch (image->blob->type)
3715 {
3716 case UndefinedStream:
3717 break;
cristybc20d112012-07-29 20:27:00 +00003718 case StandardStream:
3719 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003720 case FileStream:
3721 {
3722 if (extent != (MagickSizeType) ((off_t) extent))
3723 return(MagickFalse);
3724#if !defined(MAGICKCORE_POSIX_FALLOCATE)
3725 return(MagickFalse);
3726#else
3727 {
3728 int
3729 status;
3730
3731 MagickOffsetType
3732 offset;
3733
3734 offset=TellBlob(image);
cristye7b28372012-06-17 13:59:06 +00003735 status=posix_fallocate(fileno(image->blob->file_info.file),
cristy95888612012-04-04 21:56:52 +00003736 (off_t) offset,(off_t) (extent-offset));
cristy3ed852e2009-09-05 21:47:34 +00003737 if (status != 0)
3738 return(MagickFalse);
3739 }
3740#endif
3741 break;
3742 }
cristy3ed852e2009-09-05 21:47:34 +00003743 case PipeStream:
3744 case ZipStream:
3745 return(MagickFalse);
3746 case BZipStream:
3747 return(MagickFalse);
3748 case FifoStream:
3749 return(MagickFalse);
3750 case BlobStream:
3751 {
3752 if (image->blob->mapped != MagickFalse)
3753 {
cristye7b28372012-06-17 13:59:06 +00003754 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003755 return(MagickFalse);
3756 (void) UnmapBlob(image->blob->data,image->blob->length);
3757#if !defined(MAGICKCORE_POSIX_FALLOCATE)
3758 return(MagickFalse);
3759#else
3760 {
3761 int
3762 status;
3763
3764 MagickOffsetType
3765 offset;
3766
3767 offset=TellBlob(image);
cristye7b28372012-06-17 13:59:06 +00003768 status=posix_fallocate(fileno(image->blob->file_info.file),
cristy95888612012-04-04 21:56:52 +00003769 (off_t) offset,(off_t) (extent-offset));
cristy3ed852e2009-09-05 21:47:34 +00003770 if (status != 0)
3771 return(MagickFalse);
3772 }
cristy95888612012-04-04 21:56:52 +00003773 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003774 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003775 image->blob->extent=(size_t) extent;
3776 image->blob->length=(size_t) extent;
3777 (void) SyncBlob(image);
3778 break;
3779#endif
3780 }
3781 if (extent != (MagickSizeType) ((size_t) extent))
3782 return(MagickFalse);
3783 image->blob->extent=(size_t) extent;
3784 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3785 image->blob->extent+1,sizeof(*image->blob->data));
3786 (void) SyncBlob(image);
3787 if (image->blob->data == (unsigned char *) NULL)
3788 {
3789 (void) DetachBlob(image->blob);
3790 return(MagickFalse);
3791 }
3792 break;
3793 }
3794 }
3795 return(MagickTrue);
3796}
3797
3798/*
3799%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3800% %
3801% %
3802% %
3803+ S y n c B l o b %
3804% %
3805% %
3806% %
3807%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3808%
3809% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3810% attributes if it is an blob.
3811%
3812% The format of the SyncBlob method is:
3813%
3814% int SyncBlob(Image *image)
3815%
3816% A description of each parameter follows:
3817%
3818% o image: the image.
3819%
3820*/
3821static int SyncBlob(Image *image)
3822{
3823 int
3824 status;
3825
3826 assert(image != (Image *) NULL);
3827 assert(image->signature == MagickSignature);
3828 if (image->debug != MagickFalse)
3829 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3830 assert(image->blob != (BlobInfo *) NULL);
3831 assert(image->blob->type != UndefinedStream);
3832 status=0;
3833 switch (image->blob->type)
3834 {
3835 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003836 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003837 break;
3838 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003839 case PipeStream:
3840 {
cristye7b28372012-06-17 13:59:06 +00003841 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003842 break;
3843 }
3844 case ZipStream:
3845 {
3846#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003847 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003848#endif
3849 break;
3850 }
3851 case BZipStream:
3852 {
3853#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003854 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003855#endif
3856 break;
3857 }
3858 case FifoStream:
3859 break;
3860 case BlobStream:
3861 {
3862#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3863 if (image->blob->mapped != MagickFalse)
3864 status=msync(image->blob->data,image->blob->length,MS_SYNC);
3865#endif
3866 break;
3867 }
3868 }
3869 return(status);
3870}
3871
3872/*
3873%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3874% %
3875% %
3876% %
3877+ T e l l B l o b %
3878% %
3879% %
3880% %
3881%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3882%
3883% TellBlob() obtains the current value of the blob or file position.
3884%
3885% The format of the TellBlob method is:
3886%
3887% MagickOffsetType TellBlob(const Image *image)
3888%
3889% A description of each parameter follows:
3890%
3891% o image: the image.
3892%
3893*/
3894MagickExport MagickOffsetType TellBlob(const Image *image)
3895{
3896 MagickOffsetType
3897 offset;
3898
3899 assert(image != (Image *) NULL);
3900 assert(image->signature == MagickSignature);
3901 if (image->debug != MagickFalse)
3902 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3903 assert(image->blob != (BlobInfo *) NULL);
3904 assert(image->blob->type != UndefinedStream);
3905 offset=(-1);
3906 switch (image->blob->type)
3907 {
3908 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003909 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003910 break;
3911 case FileStream:
3912 {
cristye7b28372012-06-17 13:59:06 +00003913 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003914 break;
3915 }
cristy3ed852e2009-09-05 21:47:34 +00003916 case PipeStream:
3917 break;
3918 case ZipStream:
3919 {
3920#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003921 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003922#endif
3923 break;
3924 }
3925 case BZipStream:
3926 break;
3927 case FifoStream:
3928 break;
3929 case BlobStream:
3930 {
3931 offset=image->blob->offset;
3932 break;
3933 }
3934 }
3935 return(offset);
3936}
3937
3938/*
3939%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3940% %
3941% %
3942% %
3943+ U n m a p B l o b %
3944% %
3945% %
3946% %
3947%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3948%
3949% UnmapBlob() deallocates the binary large object previously allocated with
3950% the MapBlob method.
3951%
3952% The format of the UnmapBlob method is:
3953%
3954% MagickBooleanType UnmapBlob(void *map,const size_t length)
3955%
3956% A description of each parameter follows:
3957%
3958% o map: the address of the binary large object.
3959%
3960% o length: the length of the binary large object.
3961%
3962*/
3963MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3964{
3965#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3966 int
3967 status;
3968
3969 status=munmap(map,length);
3970 return(status == -1 ? MagickFalse : MagickTrue);
3971#else
3972 (void) map;
3973 (void) length;
3974 return(MagickFalse);
3975#endif
3976}
3977
3978/*
3979%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3980% %
3981% %
3982% %
3983+ W r i t e B l o b %
3984% %
3985% %
3986% %
3987%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3988%
3989% WriteBlob() writes data to a blob or image file. It returns the number of
3990% bytes written.
3991%
3992% The format of the WriteBlob method is:
3993%
3994% ssize_t WriteBlob(Image *image,const size_t length,
3995% const unsigned char *data)
3996%
3997% A description of each parameter follows:
3998%
3999% o image: the image.
4000%
4001% o length: Specifies an integer representing the number of bytes to
4002% write to the file.
4003%
4004% o data: The address of the data to write to the blob or file.
4005%
4006*/
4007MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4008 const unsigned char *data)
4009{
4010 int
4011 c;
4012
4013 register const unsigned char
4014 *p;
4015
4016 ssize_t
4017 count;
4018
4019 assert(image != (Image *) NULL);
4020 assert(image->signature == MagickSignature);
4021 assert(data != (const unsigned char *) NULL);
4022 assert(image->blob != (BlobInfo *) NULL);
4023 assert(image->blob->type != UndefinedStream);
4024 if (length == 0)
4025 return(0);
4026 count=0;
4027 p=data;
4028 switch (image->blob->type)
4029 {
4030 case UndefinedStream:
4031 break;
cristy3ed852e2009-09-05 21:47:34 +00004032 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004033 {
4034 count=(ssize_t) write(fileno(image->blob->file_info.file),data,length);
4035 break;
4036 }
4037 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004038 case PipeStream:
4039 {
4040 switch (length)
4041 {
4042 default:
4043 {
4044 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004045 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004046 break;
4047 }
4048 case 2:
4049 {
cristye7b28372012-06-17 13:59:06 +00004050 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004051 if (c == EOF)
4052 break;
4053 count++;
4054 }
4055 case 1:
4056 {
cristye7b28372012-06-17 13:59:06 +00004057 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004058 if (c == EOF)
4059 break;
4060 count++;
4061 }
4062 case 0:
4063 break;
4064 }
4065 break;
4066 }
4067 case ZipStream:
4068 {
4069#if defined(MAGICKCORE_ZLIB_DELEGATE)
4070 switch (length)
4071 {
4072 default:
4073 {
cristye7b28372012-06-17 13:59:06 +00004074 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004075 (unsigned int) length);
4076 break;
4077 }
4078 case 2:
4079 {
cristye7b28372012-06-17 13:59:06 +00004080 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004081 if (c == EOF)
4082 break;
4083 count++;
4084 }
4085 case 1:
4086 {
cristye7b28372012-06-17 13:59:06 +00004087 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004088 if (c == EOF)
4089 break;
4090 count++;
4091 }
4092 case 0:
4093 break;
4094 }
4095#endif
4096 break;
4097 }
4098 case BZipStream:
4099 {
4100#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004101 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004102 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004103#endif
4104 break;
4105 }
4106 case FifoStream:
4107 {
4108 count=(ssize_t) image->blob->stream(image,data,length);
4109 break;
4110 }
4111 case BlobStream:
4112 {
4113 register unsigned char
4114 *q;
4115
4116 if ((image->blob->offset+(MagickOffsetType) length) >=
4117 (MagickOffsetType) image->blob->extent)
4118 {
4119 if (image->blob->mapped != MagickFalse)
4120 return(0);
4121 image->blob->quantum<<=1;
4122 image->blob->extent+=length+image->blob->quantum;
4123 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4124 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4125 (void) SyncBlob(image);
4126 if (image->blob->data == (unsigned char *) NULL)
4127 {
4128 (void) DetachBlob(image->blob);
4129 return(0);
4130 }
4131 }
4132 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004133 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004134 image->blob->offset+=length;
4135 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4136 image->blob->length=(size_t) image->blob->offset;
4137 count=(ssize_t) length;
4138 }
4139 }
4140 return(count);
4141}
4142
4143/*
4144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4145% %
4146% %
4147% %
4148+ W r i t e B l o b B y t e %
4149% %
4150% %
4151% %
4152%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4153%
4154% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4155% written (either 0 or 1);
4156%
4157% The format of the WriteBlobByte method is:
4158%
4159% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4160%
4161% A description of each parameter follows.
4162%
4163% o image: the image.
4164%
4165% o value: Specifies the value to write.
4166%
4167*/
4168MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4169{
4170 assert(image != (Image *) NULL);
4171 assert(image->signature == MagickSignature);
4172 return(WriteBlobStream(image,1,&value));
4173}
4174
4175/*
4176%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4177% %
4178% %
4179% %
4180+ W r i t e B l o b F l o a t %
4181% %
4182% %
4183% %
4184%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4185%
4186% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4187% specified by the endian member of the image structure.
4188%
4189% The format of the WriteBlobFloat method is:
4190%
4191% ssize_t WriteBlobFloat(Image *image,const float value)
4192%
4193% A description of each parameter follows.
4194%
4195% o image: the image.
4196%
4197% o value: Specifies the value to write.
4198%
4199*/
4200MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4201{
4202 union
4203 {
4204 unsigned int
4205 unsigned_value;
4206
4207 float
4208 float_value;
4209 } quantum;
4210
4211 quantum.unsigned_value=0U;
4212 quantum.float_value=value;
4213 return(WriteBlobLong(image,quantum.unsigned_value));
4214}
4215
4216/*
4217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4218% %
4219% %
4220% %
4221+ W r i t e B l o b L o n g %
4222% %
4223% %
4224% %
4225%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4226%
cristybb503372010-05-27 20:51:26 +00004227% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004228% specified by the endian member of the image structure.
4229%
4230% The format of the WriteBlobLong method is:
4231%
4232% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4233%
4234% A description of each parameter follows.
4235%
4236% o image: the image.
4237%
4238% o value: Specifies the value to write.
4239%
4240*/
4241MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4242{
4243 unsigned char
4244 buffer[4];
4245
4246 assert(image != (Image *) NULL);
4247 assert(image->signature == MagickSignature);
4248 if (image->endian == LSBEndian)
4249 {
4250 buffer[0]=(unsigned char) value;
4251 buffer[1]=(unsigned char) (value >> 8);
4252 buffer[2]=(unsigned char) (value >> 16);
4253 buffer[3]=(unsigned char) (value >> 24);
4254 return(WriteBlobStream(image,4,buffer));
4255 }
4256 buffer[0]=(unsigned char) (value >> 24);
4257 buffer[1]=(unsigned char) (value >> 16);
4258 buffer[2]=(unsigned char) (value >> 8);
4259 buffer[3]=(unsigned char) value;
4260 return(WriteBlobStream(image,4,buffer));
4261}
4262
4263/*
4264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4265% %
4266% %
4267% %
4268+ W r i t e B l o b S h o r t %
4269% %
4270% %
4271% %
4272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4273%
4274% WriteBlobShort() writes a short value as a 16-bit quantity in the
4275% byte-order specified by the endian member of the image structure.
4276%
4277% The format of the WriteBlobShort method is:
4278%
4279% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4280%
4281% A description of each parameter follows.
4282%
4283% o image: the image.
4284%
4285% o value: Specifies the value to write.
4286%
4287*/
4288MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4289{
4290 unsigned char
4291 buffer[2];
4292
4293 assert(image != (Image *) NULL);
4294 assert(image->signature == MagickSignature);
4295 if (image->endian == LSBEndian)
4296 {
4297 buffer[0]=(unsigned char) value;
4298 buffer[1]=(unsigned char) (value >> 8);
4299 return(WriteBlobStream(image,2,buffer));
4300 }
4301 buffer[0]=(unsigned char) (value >> 8);
4302 buffer[1]=(unsigned char) value;
4303 return(WriteBlobStream(image,2,buffer));
4304}
4305
4306/*
4307%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4308% %
4309% %
4310% %
4311+ W r i t e B l o b L S B L o n g %
4312% %
4313% %
4314% %
4315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4316%
cristybb503372010-05-27 20:51:26 +00004317% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004318% least-significant byte first order.
4319%
4320% The format of the WriteBlobLSBLong method is:
4321%
4322% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4323%
4324% A description of each parameter follows.
4325%
4326% o image: the image.
4327%
4328% o value: Specifies the value to write.
4329%
4330*/
4331MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4332{
4333 unsigned char
4334 buffer[4];
4335
4336 assert(image != (Image *) NULL);
4337 assert(image->signature == MagickSignature);
4338 buffer[0]=(unsigned char) value;
4339 buffer[1]=(unsigned char) (value >> 8);
4340 buffer[2]=(unsigned char) (value >> 16);
4341 buffer[3]=(unsigned char) (value >> 24);
4342 return(WriteBlobStream(image,4,buffer));
4343}
4344
4345/*
4346%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4347% %
4348% %
4349% %
4350+ W r i t e B l o b L S B S h o r t %
4351% %
4352% %
4353% %
4354%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4355%
cristybb503372010-05-27 20:51:26 +00004356% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004357% least-significant byte first order.
4358%
4359% The format of the WriteBlobLSBShort method is:
4360%
4361% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4362%
4363% A description of each parameter follows.
4364%
4365% o image: the image.
4366%
4367% o value: Specifies the value to write.
4368%
4369*/
4370MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4371{
4372 unsigned char
4373 buffer[2];
4374
4375 assert(image != (Image *) NULL);
4376 assert(image->signature == MagickSignature);
4377 buffer[0]=(unsigned char) value;
4378 buffer[1]=(unsigned char) (value >> 8);
4379 return(WriteBlobStream(image,2,buffer));
4380}
4381
4382/*
4383%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4384% %
4385% %
4386% %
4387+ W r i t e B l o b M S B L o n g %
4388% %
4389% %
4390% %
4391%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4392%
cristybb503372010-05-27 20:51:26 +00004393% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004394% most-significant byte first order.
4395%
4396% The format of the WriteBlobMSBLong method is:
4397%
4398% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4399%
4400% A description of each parameter follows.
4401%
4402% o value: Specifies the value to write.
4403%
4404% o image: the image.
4405%
4406*/
4407MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4408{
4409 unsigned char
4410 buffer[4];
4411
4412 assert(image != (Image *) NULL);
4413 assert(image->signature == MagickSignature);
4414 buffer[0]=(unsigned char) (value >> 24);
4415 buffer[1]=(unsigned char) (value >> 16);
4416 buffer[2]=(unsigned char) (value >> 8);
4417 buffer[3]=(unsigned char) value;
4418 return(WriteBlobStream(image,4,buffer));
4419}
4420
4421/*
4422%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4423% %
4424% %
4425% %
cristy2ca49922010-03-06 02:54:01 +00004426+ W r i t e B l o b M S B L o n g L o n g %
4427% %
4428% %
4429% %
4430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4431%
4432% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4433% most-significant byte first order.
4434%
4435% The format of the WriteBlobMSBLongLong method is:
4436%
4437% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4438%
4439% A description of each parameter follows.
4440%
4441% o value: Specifies the value to write.
4442%
4443% o image: the image.
4444%
4445*/
4446MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4447 const MagickSizeType value)
4448{
4449 unsigned char
4450 buffer[8];
4451
4452 assert(image != (Image *) NULL);
4453 assert(image->signature == MagickSignature);
4454 buffer[0]=(unsigned char) (value >> 56);
4455 buffer[1]=(unsigned char) (value >> 48);
4456 buffer[2]=(unsigned char) (value >> 40);
4457 buffer[3]=(unsigned char) (value >> 32);
4458 buffer[4]=(unsigned char) (value >> 24);
4459 buffer[5]=(unsigned char) (value >> 16);
4460 buffer[6]=(unsigned char) (value >> 8);
4461 buffer[7]=(unsigned char) value;
4462 return(WriteBlobStream(image,8,buffer));
4463}
4464
4465/*
4466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4467% %
4468% %
4469% %
cristy3ed852e2009-09-05 21:47:34 +00004470+ W r i t e B l o b M S B S h o r t %
4471% %
4472% %
4473% %
4474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4475%
cristybb503372010-05-27 20:51:26 +00004476% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004477% most-significant byte first order.
4478%
4479% The format of the WriteBlobMSBShort method is:
4480%
4481% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4482%
4483% A description of each parameter follows.
4484%
4485% o value: Specifies the value to write.
4486%
4487% o file: Specifies the file to write the data to.
4488%
4489*/
4490MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4491{
4492 unsigned char
4493 buffer[2];
4494
4495 assert(image != (Image *) NULL);
4496 assert(image->signature == MagickSignature);
4497 buffer[0]=(unsigned char) (value >> 8);
4498 buffer[1]=(unsigned char) value;
4499 return(WriteBlobStream(image,2,buffer));
4500}
4501
4502/*
4503%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4504% %
4505% %
4506% %
4507+ W r i t e B l o b S t r i n g %
4508% %
4509% %
4510% %
4511%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4512%
4513% WriteBlobString() write a string to a blob. It returns the number of
4514% characters written.
4515%
4516% The format of the WriteBlobString method is:
4517%
4518% ssize_t WriteBlobString(Image *image,const char *string)
4519%
4520% A description of each parameter follows.
4521%
4522% o image: the image.
4523%
4524% o string: Specifies the string to write.
4525%
4526*/
4527MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4528{
4529 assert(image != (Image *) NULL);
4530 assert(image->signature == MagickSignature);
4531 assert(string != (const char *) NULL);
4532 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4533}