blob: 9751155ff00b16e265bf2995d7d8f28b86bae4f5 [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% %
cristy45ef08f2012-12-07 13:13:34 +000020% Copyright 1999-2013 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"
cristy3ed852e2009-09-05 21:47:34 +000067#if defined(MAGICKCORE_ZLIB_DELEGATE)
68#include "zlib.h"
69#endif
70#if defined(MAGICKCORE_BZLIB_DELEGATE)
71#include "bzlib.h"
72#endif
73
74/*
75 Define declarations.
76*/
77#define MagickMaxBlobExtent 65541
cristy3ed852e2009-09-05 21:47:34 +000078#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
79# define MAP_ANONYMOUS MAP_ANON
80#endif
81#if !defined(MAP_FAILED)
82#define MAP_FAILED ((void *) -1)
83#endif
cristy3ed852e2009-09-05 21:47:34 +000084#if defined(__OS2__)
85#include <io.h>
86#define _O_BINARY O_BINARY
87#endif
88
89/*
90 Typedef declarations.
91*/
cristye7b28372012-06-17 13:59:06 +000092typedef union FileInfo
93{
94 FILE
95 *file;
96
97#if defined(MAGICKCORE_ZLIB_DELEGATE)
98 gzFile
99 gzfile;
100#endif
101
102#if defined(MAGICKCORE_BZLIB_DELEGATE)
103 BZFILE
104 *bzfile;
105#endif
106} FileInfo;
107
cristy3ed852e2009-09-05 21:47:34 +0000108struct _BlobInfo
109{
110 size_t
111 length,
112 extent,
113 quantum;
114
115 MagickBooleanType
116 mapped,
117 eof;
118
119 MagickOffsetType
120 offset;
121
122 MagickSizeType
123 size;
124
125 MagickBooleanType
126 exempt,
127 synchronize,
128 status,
129 temporary;
130
131 StreamType
132 type;
133
cristye7b28372012-06-17 13:59:06 +0000134 FileInfo
135 file_info;
cristy3ed852e2009-09-05 21:47:34 +0000136
137 struct stat
138 properties;
139
140 StreamHandler
141 stream;
142
143 unsigned char
144 *data;
145
146 MagickBooleanType
147 debug;
148
149 SemaphoreInfo
150 *semaphore;
151
cristybb503372010-05-27 20:51:26 +0000152 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000153 reference_count;
154
cristybb503372010-05-27 20:51:26 +0000155 size_t
cristy3ed852e2009-09-05 21:47:34 +0000156 signature;
157};
158
159/*
160 Forward declarations.
161*/
162static int
163 SyncBlob(Image *);
164
165/*
166%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
167% %
168% %
169% %
170+ A t t a c h B l o b %
171% %
172% %
173% %
174%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175%
176% AttachBlob() attaches a blob to the BlobInfo structure.
177%
178% The format of the AttachBlob method is:
179%
180% void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
181%
182% A description of each parameter follows:
183%
184% o blob_info: Specifies a pointer to a BlobInfo structure.
185%
186% o blob: the address of a character stream in one of the image formats
187% understood by ImageMagick.
188%
189% o length: This size_t integer reflects the length in bytes of the blob.
190%
191*/
192MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
193 const size_t length)
194{
195 assert(blob_info != (BlobInfo *) NULL);
196 if (blob_info->debug != MagickFalse)
197 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
198 blob_info->length=length;
199 blob_info->extent=length;
200 blob_info->quantum=(size_t) MagickMaxBlobExtent;
201 blob_info->offset=0;
202 blob_info->type=BlobStream;
cristye7b28372012-06-17 13:59:06 +0000203 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000204 blob_info->data=(unsigned char *) blob;
205 blob_info->mapped=MagickFalse;
206}
207
208/*
209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210% %
211% %
212% %
213+ B l o b T o F i l e %
214% %
215% %
216% %
217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218%
219% BlobToFile() writes a blob to a file. It returns MagickFalse if an error
220% occurs otherwise MagickTrue.
221%
222% The format of the BlobToFile method is:
223%
224% MagickBooleanType BlobToFile(char *filename,const void *blob,
225% const size_t length,ExceptionInfo *exception)
226%
227% A description of each parameter follows:
228%
229% o filename: Write the blob to this file.
230%
231% o blob: the address of a blob.
232%
233% o length: This length in bytes of the blob.
234%
235% o exception: return any errors or warnings in this structure.
236%
237*/
238
cristy7753b2a2011-02-19 18:36:52 +0000239static inline MagickSizeType MagickMin(const MagickSizeType x,
240 const MagickSizeType y)
cristy3ed852e2009-09-05 21:47:34 +0000241{
242 if (x < y)
243 return(x);
244 return(y);
245}
246
247MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
248 const size_t length,ExceptionInfo *exception)
249{
250 int
251 file;
252
253 register size_t
254 i;
255
256 ssize_t
257 count;
258
259 assert(filename != (const char *) NULL);
260 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
261 assert(blob != (const void *) NULL);
262 if (*filename == '\0')
263 file=AcquireUniqueFileResource(filename);
264 else
cristy18c6c272011-09-23 14:40:37 +0000265 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +0000266 if (file == -1)
267 {
268 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
269 return(MagickFalse);
270 }
271 for (i=0; i < length; i+=count)
272 {
cristy65d11e42013-06-14 20:06:25 +0000273 count=write(file,(const char *) blob+i,(size_t) MagickMin(length-i,
274 (MagickSizeType) SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +0000275 if (count <= 0)
276 {
277 count=0;
278 if (errno != EINTR)
279 break;
280 }
281 }
cristya7cb4312010-06-26 00:47:03 +0000282 file=close(file);
283 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +0000284 {
285 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
286 return(MagickFalse);
287 }
288 return(MagickTrue);
289}
290
291/*
292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293% %
294% %
295% %
296% B l o b T o I m a g e %
297% %
298% %
299% %
300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301%
302% BlobToImage() implements direct to memory image formats. It returns the
303% blob as an image.
304%
305% The format of the BlobToImage method is:
306%
307% Image *BlobToImage(const ImageInfo *image_info,const void *blob,
308% const size_t length,ExceptionInfo *exception)
309%
310% A description of each parameter follows:
311%
312% o image_info: the image info.
313%
314% o blob: the address of a character stream in one of the image formats
315% understood by ImageMagick.
316%
317% o length: This size_t integer reflects the length in bytes of the blob.
318%
319% o exception: return any errors or warnings in this structure.
320%
321*/
322MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
323 const size_t length,ExceptionInfo *exception)
324{
325 const MagickInfo
326 *magick_info;
327
328 Image
329 *image;
330
331 ImageInfo
332 *blob_info,
333 *clone_info;
334
335 MagickBooleanType
336 status;
337
338 assert(image_info != (ImageInfo *) NULL);
339 assert(image_info->signature == MagickSignature);
340 if (image_info->debug != MagickFalse)
341 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
342 image_info->filename);
343 assert(exception != (ExceptionInfo *) NULL);
344 if ((blob == (const void *) NULL) || (length == 0))
345 {
346 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +0000347 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +0000348 return((Image *) NULL);
349 }
350 blob_info=CloneImageInfo(image_info);
351 blob_info->blob=(void *) blob;
352 blob_info->length=length;
353 if (*blob_info->magick == '\0')
cristyd965a422010-03-03 17:47:35 +0000354 (void) SetImageInfo(blob_info,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000355 magick_info=GetMagickInfo(blob_info->magick,exception);
356 if (magick_info == (const MagickInfo *) NULL)
357 {
358 blob_info=DestroyImageInfo(blob_info);
359 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +0000360 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +0000361 image_info->filename);
362 return((Image *) NULL);
363 }
364 if (GetMagickBlobSupport(magick_info) != MagickFalse)
365 {
366 /*
367 Native blob support for this image format.
368 */
369 (void) CopyMagickString(blob_info->filename,image_info->filename,
370 MaxTextExtent);
371 (void) CopyMagickString(blob_info->magick,image_info->magick,
372 MaxTextExtent);
373 image=ReadImage(blob_info,exception);
374 if (image != (Image *) NULL)
375 (void) DetachBlob(image->blob);
376 blob_info=DestroyImageInfo(blob_info);
377 return(image);
378 }
379 /*
380 Write blob to a temporary file on disk.
381 */
382 blob_info->blob=(void *) NULL;
383 blob_info->length=0;
384 *blob_info->filename='\0';
385 status=BlobToFile(blob_info->filename,blob,length,exception);
386 if (status == MagickFalse)
387 {
388 (void) RelinquishUniqueFileResource(blob_info->filename);
389 blob_info=DestroyImageInfo(blob_info);
390 return((Image *) NULL);
391 }
392 clone_info=CloneImageInfo(blob_info);
cristyb51dff52011-05-19 16:55:47 +0000393 (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +0000394 blob_info->magick,blob_info->filename);
395 image=ReadImage(clone_info,exception);
cristy540a22c2012-06-10 15:22:16 +0000396 if (image != (Image *) NULL)
397 {
398 Image
399 *images;
400
401 /*
402 Restore original filenames.
403 */
404 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
405 {
cristy540a22c2012-06-10 15:22:16 +0000406 (void) CopyMagickMemory(images->filename,image_info->filename,
407 sizeof(images->filename));
cristybe674a62012-08-14 12:38:33 +0000408 (void) CopyMagickMemory(images->magick_filename,image_info->filename,
409 sizeof(images->magick_filename));
cristy540a22c2012-06-10 15:22:16 +0000410 images=GetNextImageInList(images);
411 }
412 }
cristy3ed852e2009-09-05 21:47:34 +0000413 clone_info=DestroyImageInfo(clone_info);
414 (void) RelinquishUniqueFileResource(blob_info->filename);
415 blob_info=DestroyImageInfo(blob_info);
416 return(image);
417}
418
419/*
420%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
421% %
422% %
423% %
424+ C l o n e B l o b I n f o %
425% %
426% %
427% %
428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429%
430% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
431% blob info is NULL, a new one.
432%
433% The format of the CloneBlobInfo method is:
434%
435% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
436%
437% A description of each parameter follows:
438%
439% o blob_info: the blob info.
440%
441*/
442MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
443{
444 BlobInfo
445 *clone_info;
446
cristy73bd4a52010-10-05 11:24:23 +0000447 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
cristy3ed852e2009-09-05 21:47:34 +0000448 if (clone_info == (BlobInfo *) NULL)
449 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
450 GetBlobInfo(clone_info);
451 if (blob_info == (BlobInfo *) NULL)
452 return(clone_info);
453 clone_info->length=blob_info->length;
454 clone_info->extent=blob_info->extent;
455 clone_info->synchronize=blob_info->synchronize;
456 clone_info->quantum=blob_info->quantum;
457 clone_info->mapped=blob_info->mapped;
458 clone_info->eof=blob_info->eof;
459 clone_info->offset=blob_info->offset;
460 clone_info->size=blob_info->size;
461 clone_info->exempt=blob_info->exempt;
462 clone_info->status=blob_info->status;
463 clone_info->temporary=blob_info->temporary;
464 clone_info->type=blob_info->type;
cristye7b28372012-06-17 13:59:06 +0000465 clone_info->file_info.file=blob_info->file_info.file;
cristy3ed852e2009-09-05 21:47:34 +0000466 clone_info->properties=blob_info->properties;
467 clone_info->stream=blob_info->stream;
468 clone_info->data=blob_info->data;
469 clone_info->debug=IsEventLogging();
470 clone_info->reference_count=1;
471 return(clone_info);
472}
473
474/*
475%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
476% %
477% %
478% %
479+ C l o s e B l o b %
480% %
481% %
482% %
483%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484%
485% CloseBlob() closes a stream associated with the image.
486%
487% The format of the CloseBlob method is:
488%
489% MagickBooleanType CloseBlob(Image *image)
490%
491% A description of each parameter follows:
492%
493% o image: the image.
494%
495*/
496MagickExport MagickBooleanType CloseBlob(Image *image)
497{
498 int
499 status;
500
501 /*
502 Close image file.
503 */
504 assert(image != (Image *) NULL);
505 assert(image->signature == MagickSignature);
506 if (image->debug != MagickFalse)
507 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
508 assert(image->blob != (BlobInfo *) NULL);
509 if (image->blob->type == UndefinedStream)
510 return(MagickTrue);
cristy7e2a7c72012-12-27 00:56:47 +0000511 status=SyncBlob(image);
cristy3ed852e2009-09-05 21:47:34 +0000512 switch (image->blob->type)
513 {
514 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000515 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000516 break;
517 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000518 case PipeStream:
519 {
cristy02ce8cc2012-12-27 00:35:49 +0000520 if (image->blob->synchronize != MagickFalse)
521 status=fsync(fileno(image->blob->file_info.file));
cristye7b28372012-06-17 13:59:06 +0000522 status=ferror(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000523 break;
524 }
525 case ZipStream:
526 {
527#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000528 (void) gzerror(image->blob->file_info.gzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000529#endif
530 break;
531 }
532 case BZipStream:
533 {
534#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000535 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000536#endif
537 break;
538 }
539 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000540 break;
cristy02ce8cc2012-12-27 00:35:49 +0000541 case BlobStream:
542 {
543 if ((image->blob->file_info.file != (FILE *) NULL) &&
544 (image->blob->synchronize != MagickFalse))
cristy5678acd2012-12-27 00:41:55 +0000545 {
546 (void) fsync(fileno(image->blob->file_info.file));
547 status=ferror(image->blob->file_info.file);
548 }
cristy02ce8cc2012-12-27 00:35:49 +0000549 break;
550 }
cristy3ed852e2009-09-05 21:47:34 +0000551 }
552 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
cristycd9e6322012-12-27 00:29:00 +0000553 image->blob->size=GetBlobSize(image);
554 image->extent=image->blob->size;
555 image->blob->eof=MagickFalse;
cristybae22e42012-12-27 00:25:59 +0000556 if (image->blob->exempt != MagickFalse)
557 {
558 image->blob->type=UndefinedStream;
559 return(image->blob->status);
560 }
cristy3ed852e2009-09-05 21:47:34 +0000561 switch (image->blob->type)
562 {
563 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000564 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000565 break;
566 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000567 {
cristye7b28372012-06-17 13:59:06 +0000568 status=fclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000569 break;
570 }
571 case PipeStream:
572 {
573#if defined(MAGICKCORE_HAVE_PCLOSE)
cristye7b28372012-06-17 13:59:06 +0000574 status=pclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000575#endif
576 break;
577 }
578 case ZipStream:
579 {
580#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000581 status=gzclose(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +0000582#endif
583 break;
584 }
585 case BZipStream:
586 {
587#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000588 BZ2_bzclose(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +0000589#endif
590 break;
591 }
592 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000593 break;
cristyff483372010-10-16 17:00:58 +0000594 case BlobStream:
595 {
cristye7b28372012-06-17 13:59:06 +0000596 if (image->blob->file_info.file != (FILE *) NULL)
cristy02ce8cc2012-12-27 00:35:49 +0000597 status=fclose(image->blob->file_info.file);
cristyff483372010-10-16 17:00:58 +0000598 break;
599 }
cristy3ed852e2009-09-05 21:47:34 +0000600 }
601 (void) DetachBlob(image->blob);
602 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
603 return(image->blob->status);
604}
605
606/*
607%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608% %
609% %
610% %
611+ D e s t r o y B l o b %
612% %
613% %
614% %
615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616%
617% DestroyBlob() deallocates memory associated with a blob.
618%
619% The format of the DestroyBlob method is:
620%
621% void DestroyBlob(Image *image)
622%
623% A description of each parameter follows:
624%
625% o image: the image.
626%
627*/
628MagickExport void DestroyBlob(Image *image)
629{
630 MagickBooleanType
631 destroy;
632
633 assert(image != (Image *) NULL);
634 assert(image->signature == MagickSignature);
635 if (image->debug != MagickFalse)
636 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
637 assert(image->blob != (BlobInfo *) NULL);
638 assert(image->blob->signature == MagickSignature);
639 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000640 LockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000641 image->blob->reference_count--;
642 assert(image->blob->reference_count >= 0);
643 if (image->blob->reference_count == 0)
644 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000645 UnlockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000646 if (destroy == MagickFalse)
647 return;
648 (void) CloseBlob(image);
649 if (image->blob->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000650 {
651 (void) UnmapBlob(image->blob->data,image->blob->length);
652 RelinquishMagickResource(MapResource,image->blob->length);
653 }
cristy3ed852e2009-09-05 21:47:34 +0000654 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
655 DestroySemaphoreInfo(&image->blob->semaphore);
656 image->blob->signature=(~MagickSignature);
657 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
658}
659
660/*
661%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
662% %
663% %
664% %
665+ D e t a c h B l o b %
666% %
667% %
668% %
669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670%
671% DetachBlob() detaches a blob from the BlobInfo structure.
672%
673% The format of the DetachBlob method is:
674%
675% unsigned char *DetachBlob(BlobInfo *blob_info)
676%
677% A description of each parameter follows:
678%
679% o blob_info: Specifies a pointer to a BlobInfo structure.
680%
681*/
682MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
683{
684 unsigned char
685 *data;
686
687 assert(blob_info != (BlobInfo *) NULL);
688 if (blob_info->debug != MagickFalse)
689 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
690 if (blob_info->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000691 {
692 (void) UnmapBlob(blob_info->data,blob_info->length);
693 RelinquishMagickResource(MapResource,blob_info->length);
694 }
cristy3ed852e2009-09-05 21:47:34 +0000695 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 {
cristy65d11e42013-06-14 20:06:25 +0000985 count=read(file,blob+i,quantum);
cristy3ed852e2009-09-05 21:47:34 +0000986 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(),
cristyefe601c2013-01-05 17:51:12 +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(),
cristyefe601c2013-01-05 17:51:12 +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 {
cristy65d11e42013-06-14 20:06:25 +00001043 count=read(file,blob+i,(size_t) MagickMin(*length-i,(MagickSizeType)
1044 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);
cristyd45808f2012-12-14 21:30:35 +00001149 file=fileno(stdin);
1150 if (LocaleCompare(filename,"-") != 0)
1151 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001152 if (file == -1)
1153 {
cristyc82a27b2011-10-21 01:07:16 +00001154 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001155 return(MagickFalse);
1156 }
1157 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001158 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1159 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001160 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1161 if (blob == (unsigned char *) NULL)
1162 {
cristyc82a27b2011-10-21 01:07:16 +00001163 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1164 filename);
cristy3ed852e2009-09-05 21:47:34 +00001165 return(MagickFalse);
1166 }
1167 for ( ; ; )
1168 {
cristy65d11e42013-06-14 20:06:25 +00001169 count=read(file,blob,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001170 if (count <= 0)
1171 {
1172 count=0;
1173 if (errno != EINTR)
1174 break;
1175 }
1176 length=(size_t) count;
1177 count=WriteBlobStream(image,length,blob);
1178 if (count != (ssize_t) length)
1179 {
cristyc82a27b2011-10-21 01:07:16 +00001180 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001181 break;
1182 }
1183 }
cristya7cb4312010-06-26 00:47:03 +00001184 file=close(file);
1185 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001186 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001187 blob=(unsigned char *) RelinquishMagickMemory(blob);
1188 return(MagickTrue);
1189}
1190
1191/*
1192%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1193% %
1194% %
1195% %
1196+ G e t B l o b E r r o r %
1197% %
1198% %
1199% %
1200%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1201%
1202% GetBlobError() returns MagickTrue if the blob associated with the specified
1203% image encountered an error.
1204%
1205% The format of the GetBlobError method is:
1206%
1207% MagickBooleanType GetBlobError(const Image *image)
1208%
1209% A description of each parameter follows:
1210%
1211% o image: the image.
1212%
1213*/
cristy7832dc22011-09-05 01:21:53 +00001214MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001215{
1216 assert(image != (const Image *) NULL);
1217 assert(image->signature == MagickSignature);
1218 if (image->debug != MagickFalse)
1219 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1220 return(image->blob->status);
1221}
1222
1223/*
1224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1225% %
1226% %
1227% %
1228+ G e t B l o b F i l e H a n d l e %
1229% %
1230% %
1231% %
1232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1233%
1234% GetBlobFileHandle() returns the file handle associated with the image blob.
1235%
1236% The format of the GetBlobFile method is:
1237%
1238% FILE *GetBlobFileHandle(const Image *image)
1239%
1240% A description of each parameter follows:
1241%
1242% o image: the image.
1243%
1244*/
1245MagickExport FILE *GetBlobFileHandle(const Image *image)
1246{
1247 assert(image != (const Image *) NULL);
1248 assert(image->signature == MagickSignature);
cristye7b28372012-06-17 13:59:06 +00001249 return(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001250}
1251
1252/*
1253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1254% %
1255% %
1256% %
1257+ G e t B l o b I n f o %
1258% %
1259% %
1260% %
1261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1262%
1263% GetBlobInfo() initializes the BlobInfo structure.
1264%
1265% The format of the GetBlobInfo method is:
1266%
1267% void GetBlobInfo(BlobInfo *blob_info)
1268%
1269% A description of each parameter follows:
1270%
1271% o blob_info: Specifies a pointer to a BlobInfo structure.
1272%
1273*/
cristy7832dc22011-09-05 01:21:53 +00001274MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001275{
1276 assert(blob_info != (BlobInfo *) NULL);
1277 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1278 blob_info->type=UndefinedStream;
1279 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1280 blob_info->properties.st_mtime=time((time_t *) NULL);
1281 blob_info->properties.st_ctime=time((time_t *) NULL);
1282 blob_info->debug=IsEventLogging();
1283 blob_info->reference_count=1;
1284 blob_info->semaphore=AllocateSemaphoreInfo();
1285 blob_info->signature=MagickSignature;
1286}
1287
1288/*
1289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1290% %
1291% %
1292% %
1293% G e t B l o b P r o p e r t i e s %
1294% %
1295% %
1296% %
1297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1298%
1299% GetBlobProperties() returns information about an image blob.
1300%
1301% The format of the GetBlobProperties method is:
1302%
1303% const struct stat *GetBlobProperties(const Image *image)
1304%
1305% A description of each parameter follows:
1306%
1307% o image: the image.
1308%
1309*/
cristy7832dc22011-09-05 01:21:53 +00001310MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001311{
1312 assert(image != (Image *) NULL);
1313 assert(image->signature == MagickSignature);
1314 if (image->debug != MagickFalse)
1315 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1316 return(&image->blob->properties);
1317}
1318
1319/*
1320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1321% %
1322% %
1323% %
1324+ G e t B l o b S i z e %
1325% %
1326% %
1327% %
1328%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1329%
1330% GetBlobSize() returns the current length of the image file or blob; zero is
1331% returned if the size cannot be determined.
1332%
1333% The format of the GetBlobSize method is:
1334%
1335% MagickSizeType GetBlobSize(const Image *image)
1336%
1337% A description of each parameter follows:
1338%
1339% o image: the image.
1340%
1341*/
1342MagickExport MagickSizeType GetBlobSize(const Image *image)
1343{
1344 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001345 extent;
cristy3ed852e2009-09-05 21:47:34 +00001346
1347 assert(image != (Image *) NULL);
1348 assert(image->signature == MagickSignature);
1349 if (image->debug != MagickFalse)
1350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1351 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001352 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001353 switch (image->blob->type)
1354 {
1355 case UndefinedStream:
1356 {
cristy81b8ce52010-02-05 01:53:17 +00001357 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001358 break;
1359 }
cristybc20d112012-07-29 20:27:00 +00001360 case StandardStream:
1361 {
1362 extent=image->blob->size;
1363 break;
1364 }
cristy3ed852e2009-09-05 21:47:34 +00001365 case FileStream:
1366 {
cristye7b28372012-06-17 13:59:06 +00001367 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001368 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001369 break;
1370 }
cristy3ed852e2009-09-05 21:47:34 +00001371 case PipeStream:
1372 {
cristy81b8ce52010-02-05 01:53:17 +00001373 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001374 break;
1375 }
1376 case ZipStream:
1377 case BZipStream:
1378 {
1379 MagickBooleanType
1380 status;
1381
1382 status=GetPathAttributes(image->filename,&image->blob->properties);
1383 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001384 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001385 break;
1386 }
1387 case FifoStream:
1388 break;
1389 case BlobStream:
1390 {
cristy891dc792010-03-04 01:47:16 +00001391 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001392 break;
1393 }
1394 }
cristy81b8ce52010-02-05 01:53:17 +00001395 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001396}
1397
1398/*
1399%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1400% %
1401% %
1402% %
1403+ G e t B l o b S t r e a m D a t a %
1404% %
1405% %
1406% %
1407%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1408%
1409% GetBlobStreamData() returns the stream data for the image.
1410%
1411% The format of the GetBlobStreamData method is:
1412%
1413% unsigned char *GetBlobStreamData(const Image *image)
1414%
1415% A description of each parameter follows:
1416%
1417% o image: the image.
1418%
1419*/
1420MagickExport unsigned char *GetBlobStreamData(const Image *image)
1421{
1422 assert(image != (const Image *) NULL);
1423 assert(image->signature == MagickSignature);
1424 return(image->blob->data);
1425}
1426
1427/*
1428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1429% %
1430% %
1431% %
1432+ G e t B l o b S t r e a m H a n d l e r %
1433% %
1434% %
1435% %
1436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1437%
1438% GetBlobStreamHandler() returns the stream handler for the image.
1439%
1440% The format of the GetBlobStreamHandler method is:
1441%
1442% StreamHandler GetBlobStreamHandler(const Image *image)
1443%
1444% A description of each parameter follows:
1445%
1446% o image: the image.
1447%
1448*/
cristy7832dc22011-09-05 01:21:53 +00001449MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001450{
1451 assert(image != (const Image *) NULL);
1452 assert(image->signature == MagickSignature);
1453 if (image->debug != MagickFalse)
1454 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1455 return(image->blob->stream);
1456}
1457
1458/*
1459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1460% %
1461% %
1462% %
1463% I m a g e T o B l o b %
1464% %
1465% %
1466% %
1467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1468%
1469% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001470% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001471% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001472% etc.). This method is the equivalent of WriteImage(), but writes the
1473% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001474%
1475% The format of the ImageToBlob method is:
1476%
1477% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1478% size_t *length,ExceptionInfo *exception)
1479%
1480% A description of each parameter follows:
1481%
1482% o image_info: the image info.
1483%
1484% o image: the image.
1485%
1486% o length: This pointer to a size_t integer sets the initial length of the
1487% blob. On return, it reflects the actual length of the blob.
1488%
1489% o exception: return any errors or warnings in this structure.
1490%
1491*/
1492MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1493 Image *image,size_t *length,ExceptionInfo *exception)
1494{
1495 const MagickInfo
1496 *magick_info;
1497
1498 ImageInfo
1499 *blob_info;
1500
1501 MagickBooleanType
1502 status;
1503
1504 unsigned char
1505 *blob;
1506
1507 assert(image_info != (const ImageInfo *) NULL);
1508 assert(image_info->signature == MagickSignature);
1509 if (image_info->debug != MagickFalse)
1510 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1511 image_info->filename);
1512 assert(image != (Image *) NULL);
1513 assert(image->signature == MagickSignature);
1514 assert(exception != (ExceptionInfo *) NULL);
1515 *length=0;
1516 blob=(unsigned char *) NULL;
1517 blob_info=CloneImageInfo(image_info);
1518 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001519 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001520 if (*blob_info->magick != '\0')
1521 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1522 magick_info=GetMagickInfo(image->magick,exception);
1523 if (magick_info == (const MagickInfo *) NULL)
1524 {
1525 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001526 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001527 image->filename);
1528 return(blob);
1529 }
1530 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1531 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1532 {
1533 /*
1534 Native blob support for this image format.
1535 */
1536 blob_info->length=0;
1537 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1538 sizeof(unsigned char));
1539 if (blob_info->blob == (void *) NULL)
1540 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001541 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001542 else
1543 {
1544 (void) CloseBlob(image);
1545 image->blob->exempt=MagickTrue;
1546 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001547 status=WriteImage(blob_info,image,exception);
cristyc42554f2012-08-22 12:00:43 +00001548 *length=image->blob->length;
1549 blob=DetachBlob(image->blob);
cristy6e50f9e2012-08-22 16:30:29 +00001550 if (status == MagickFalse)
1551 blob=(unsigned char *) RelinquishMagickMemory(blob);
1552 else
1553 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1554 sizeof(*blob));
cristy3ed852e2009-09-05 21:47:34 +00001555 }
1556 }
1557 else
1558 {
1559 char
1560 unique[MaxTextExtent];
1561
1562 int
1563 file;
1564
1565 /*
1566 Write file to disk in blob image format.
1567 */
1568 file=AcquireUniqueFileResource(unique);
1569 if (file == -1)
1570 {
1571 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1572 image_info->filename);
1573 }
1574 else
1575 {
1576 blob_info->file=fdopen(file,"wb");
1577 if (blob_info->file != (FILE *) NULL)
1578 {
cristyb51dff52011-05-19 16:55:47 +00001579 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001580 image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001581 status=WriteImage(blob_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001582 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001583 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001584 blob=FileToBlob(image->filename,~0UL,length,exception);
1585 }
1586 (void) RelinquishUniqueFileResource(unique);
1587 }
1588 }
1589 blob_info=DestroyImageInfo(blob_info);
1590 return(blob);
1591}
1592
1593/*
1594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1595% %
1596% %
1597% %
1598% I m a g e T o F i l e %
1599% %
1600% %
1601% %
1602%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1603%
1604% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1605% occurs otherwise MagickTrue.
1606%
1607% The format of the ImageToFile method is:
1608%
1609% MagickBooleanType ImageToFile(Image *image,char *filename,
1610% ExceptionInfo *exception)
1611%
1612% A description of each parameter follows:
1613%
1614% o image: the image.
1615%
1616% o filename: Write the image to this file.
1617%
1618% o exception: return any errors or warnings in this structure.
1619%
1620*/
cristy3ed852e2009-09-05 21:47:34 +00001621MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1622 ExceptionInfo *exception)
1623{
1624 int
1625 file;
1626
1627 register const unsigned char
1628 *p;
1629
1630 register size_t
1631 i;
1632
1633 size_t
1634 length,
1635 quantum;
1636
1637 ssize_t
1638 count;
1639
1640 struct stat
cristye7b28372012-06-17 13:59:06 +00001641 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001642
1643 unsigned char
1644 *buffer;
1645
1646 assert(image != (Image *) NULL);
1647 assert(image->signature == MagickSignature);
1648 assert(image->blob != (BlobInfo *) NULL);
1649 assert(image->blob->type != UndefinedStream);
1650 if (image->debug != MagickFalse)
1651 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1652 assert(filename != (const char *) NULL);
1653 if (*filename == '\0')
1654 file=AcquireUniqueFileResource(filename);
1655 else
1656 if (LocaleCompare(filename,"-") == 0)
1657 file=fileno(stdout);
1658 else
cristyb70aab92012-01-31 15:04:04 +00001659 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001660 if (file == -1)
1661 {
1662 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1663 return(MagickFalse);
1664 }
1665 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001666 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1667 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001668 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001669 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1670 if (buffer == (unsigned char *) NULL)
1671 {
1672 file=close(file)-1;
1673 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001674 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001675 return(MagickFalse);
1676 }
1677 length=0;
1678 p=ReadBlobStream(image,quantum,buffer,&count);
1679 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1680 {
1681 length=(size_t) count;
1682 for (i=0; i < length; i+=count)
1683 {
1684 count=write(file,p+i,(size_t) (length-i));
1685 if (count <= 0)
1686 {
1687 count=0;
1688 if (errno != EINTR)
1689 break;
1690 }
1691 }
1692 if (i < length)
1693 break;
1694 }
cristy54439632010-07-15 00:43:34 +00001695 if (LocaleCompare(filename,"-") != 0)
1696 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001697 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001698 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001699 {
1700 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1701 return(MagickFalse);
1702 }
1703 return(MagickTrue);
1704}
1705
1706/*
1707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1708% %
1709% %
1710% %
1711% I m a g e s T o B l o b %
1712% %
1713% %
1714% %
1715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1716%
1717% ImagesToBlob() implements direct to memory image formats. It returns the
1718% image sequence as a blob and its length. The magick member of the ImageInfo
1719% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1720%
1721% Note, some image formats do not permit multiple images to the same image
1722% stream (e.g. JPEG). in this instance, just the first image of the
1723% sequence is returned as a blob.
1724%
1725% The format of the ImagesToBlob method is:
1726%
1727% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1728% size_t *length,ExceptionInfo *exception)
1729%
1730% A description of each parameter follows:
1731%
1732% o image_info: the image info.
1733%
1734% o images: the image list.
1735%
1736% o length: This pointer to a size_t integer sets the initial length of the
1737% blob. On return, it reflects the actual length of the blob.
1738%
1739% o exception: return any errors or warnings in this structure.
1740%
1741*/
1742MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1743 Image *images,size_t *length,ExceptionInfo *exception)
1744{
1745 const MagickInfo
1746 *magick_info;
1747
1748 ImageInfo
1749 *blob_info;
1750
1751 MagickBooleanType
1752 status;
1753
1754 unsigned char
1755 *blob;
1756
1757 assert(image_info != (const ImageInfo *) NULL);
1758 assert(image_info->signature == MagickSignature);
1759 if (image_info->debug != MagickFalse)
1760 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1761 image_info->filename);
1762 assert(images != (Image *) NULL);
1763 assert(images->signature == MagickSignature);
1764 assert(exception != (ExceptionInfo *) NULL);
1765 *length=0;
1766 blob=(unsigned char *) NULL;
1767 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001768 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1769 exception);
cristy3ed852e2009-09-05 21:47:34 +00001770 if (*blob_info->magick != '\0')
1771 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1772 if (blob_info->adjoin == MagickFalse)
1773 {
1774 blob_info=DestroyImageInfo(blob_info);
1775 return(ImageToBlob(image_info,images,length,exception));
1776 }
1777 magick_info=GetMagickInfo(images->magick,exception);
1778 if (magick_info == (const MagickInfo *) NULL)
1779 {
1780 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001781 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001782 images->filename);
1783 return(blob);
1784 }
1785 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1786 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1787 {
1788 /*
1789 Native blob support for this images format.
1790 */
1791 blob_info->length=0;
1792 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1793 sizeof(unsigned char));
1794 if (blob_info->blob == (void *) NULL)
1795 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001796 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
cristy3ed852e2009-09-05 21:47:34 +00001797 else
1798 {
1799 images->blob->exempt=MagickTrue;
1800 *images->filename='\0';
1801 status=WriteImages(blob_info,images,images->filename,exception);
cristyb24e2402011-10-07 00:48:39 +00001802 if ((status != MagickFalse) && (images->blob->length != 0))
cristy3ed852e2009-09-05 21:47:34 +00001803 {
1804 *length=images->blob->length;
1805 blob=DetachBlob(images->blob);
1806 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1807 sizeof(*blob));
1808 }
1809 }
1810 }
1811 else
1812 {
1813 char
1814 filename[MaxTextExtent],
1815 unique[MaxTextExtent];
1816
1817 int
1818 file;
1819
1820 /*
1821 Write file to disk in blob images format.
1822 */
1823 file=AcquireUniqueFileResource(unique);
1824 if (file == -1)
1825 {
1826 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1827 image_info->filename);
1828 }
1829 else
1830 {
1831 blob_info->file=fdopen(file,"wb");
1832 if (blob_info->file != (FILE *) NULL)
1833 {
cristyb51dff52011-05-19 16:55:47 +00001834 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001835 images->magick,unique);
1836 status=WriteImages(blob_info,images,filename,exception);
1837 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001838 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001839 blob=FileToBlob(images->filename,~0UL,length,exception);
1840 }
1841 (void) RelinquishUniqueFileResource(unique);
1842 }
1843 }
1844 blob_info=DestroyImageInfo(blob_info);
1845 return(blob);
1846}
1847/*
1848%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1849% %
1850% %
1851% %
1852% I n j e c t I m a g e B l o b %
1853% %
1854% %
1855% %
1856%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1857%
1858% InjectImageBlob() injects the image with a copy of itself in the specified
1859% format (e.g. inject JPEG into a PDF image).
1860%
1861% The format of the InjectImageBlob method is:
1862%
1863% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1864% Image *image,Image *inject_image,const char *format,
1865% ExceptionInfo *exception)
1866%
1867% A description of each parameter follows:
1868%
1869% o image_info: the image info..
1870%
1871% o image: the image.
1872%
1873% o inject_image: inject into the image stream.
1874%
1875% o format: the image format.
1876%
1877% o exception: return any errors or warnings in this structure.
1878%
1879*/
1880MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1881 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1882{
1883 char
1884 filename[MaxTextExtent];
1885
1886 FILE
1887 *unique_file;
1888
1889 Image
1890 *byte_image;
1891
1892 ImageInfo
1893 *write_info;
1894
1895 int
1896 file;
1897
1898 MagickBooleanType
1899 status;
1900
cristybb503372010-05-27 20:51:26 +00001901 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001902 i;
1903
1904 size_t
1905 quantum;
1906
1907 ssize_t
1908 count;
1909
1910 struct stat
cristye7b28372012-06-17 13:59:06 +00001911 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001912
1913 unsigned char
1914 *buffer;
1915
1916 /*
1917 Write inject image to a temporary file.
1918 */
1919 assert(image_info != (ImageInfo *) NULL);
1920 assert(image_info->signature == MagickSignature);
1921 assert(image != (Image *) NULL);
1922 assert(image->signature == MagickSignature);
1923 if (image->debug != MagickFalse)
1924 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1925 assert(inject_image != (Image *) NULL);
1926 assert(inject_image->signature == MagickSignature);
1927 assert(exception != (ExceptionInfo *) NULL);
1928 unique_file=(FILE *) NULL;
1929 file=AcquireUniqueFileResource(filename);
1930 if (file != -1)
1931 unique_file=fdopen(file,"wb");
1932 if ((file == -1) || (unique_file == (FILE *) NULL))
1933 {
1934 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1935 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1936 image->filename);
1937 return(MagickFalse);
1938 }
1939 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1940 if (byte_image == (Image *) NULL)
1941 {
1942 (void) fclose(unique_file);
1943 (void) RelinquishUniqueFileResource(filename);
1944 return(MagickFalse);
1945 }
cristyb51dff52011-05-19 16:55:47 +00001946 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001947 filename);
1948 DestroyBlob(byte_image);
1949 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1950 write_info=CloneImageInfo(image_info);
1951 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001952 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001953 write_info=DestroyImageInfo(write_info);
1954 byte_image=DestroyImage(byte_image);
1955 (void) fclose(unique_file);
1956 if (status == MagickFalse)
1957 {
1958 (void) RelinquishUniqueFileResource(filename);
1959 return(MagickFalse);
1960 }
1961 /*
1962 Inject into image stream.
1963 */
cristy18c6c272011-09-23 14:40:37 +00001964 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001965 if (file == -1)
1966 {
1967 (void) RelinquishUniqueFileResource(filename);
1968 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1969 image_info->filename);
1970 return(MagickFalse);
1971 }
1972 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001973 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1974 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001975 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1976 if (buffer == (unsigned char *) NULL)
1977 {
1978 (void) RelinquishUniqueFileResource(filename);
1979 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1980 image->filename);
1981 }
1982 for (i=0; ; i+=count)
1983 {
cristy65d11e42013-06-14 20:06:25 +00001984 count=read(file,buffer,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001985 if (count <= 0)
1986 {
1987 count=0;
1988 if (errno != EINTR)
1989 break;
1990 }
1991 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1992 MagickFalse;
1993 }
cristya7cb4312010-06-26 00:47:03 +00001994 file=close(file);
1995 if (file == -1)
1996 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001997 (void) RelinquishUniqueFileResource(filename);
1998 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1999 return(status);
2000}
2001
2002/*
2003%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2004% %
2005% %
2006% %
2007+ I s B l o b E x e m p t %
2008% %
2009% %
2010% %
2011%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2012%
2013% IsBlobExempt() returns true if the blob is exempt.
2014%
2015% The format of the IsBlobExempt method is:
2016%
2017% MagickBooleanType IsBlobExempt(const Image *image)
2018%
2019% A description of each parameter follows:
2020%
2021% o image: the image.
2022%
2023*/
cristy7832dc22011-09-05 01:21:53 +00002024MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002025{
2026 assert(image != (const Image *) NULL);
2027 assert(image->signature == MagickSignature);
2028 if (image->debug != MagickFalse)
2029 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2030 return(image->blob->exempt);
2031}
2032
2033/*
2034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2035% %
2036% %
2037% %
2038+ I s B l o b S e e k a b l e %
2039% %
2040% %
2041% %
2042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2043%
2044% IsBlobSeekable() returns true if the blob is seekable.
2045%
2046% The format of the IsBlobSeekable method is:
2047%
2048% MagickBooleanType IsBlobSeekable(const Image *image)
2049%
2050% A description of each parameter follows:
2051%
2052% o image: the image.
2053%
2054*/
cristy7832dc22011-09-05 01:21:53 +00002055MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002056{
2057 MagickBooleanType
2058 seekable;
2059
2060 assert(image != (const Image *) NULL);
2061 assert(image->signature == MagickSignature);
2062 if (image->debug != MagickFalse)
2063 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002064 switch (image->blob->type)
2065 {
2066 case FileStream:
2067 case BlobStream:
2068 case ZipStream:
2069 {
2070 seekable=MagickTrue;
2071 break;
2072 }
2073 default:
2074 {
2075 seekable=MagickFalse;
2076 break;
2077 }
2078 }
cristy3ed852e2009-09-05 21:47:34 +00002079 return(seekable);
2080}
2081
2082/*
2083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2084% %
2085% %
2086% %
2087+ I s B l o b T e m p o r a r y %
2088% %
2089% %
2090% %
2091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2092%
2093% IsBlobTemporary() returns true if the blob is temporary.
2094%
2095% The format of the IsBlobTemporary method is:
2096%
2097% MagickBooleanType IsBlobTemporary(const Image *image)
2098%
2099% A description of each parameter follows:
2100%
2101% o image: the image.
2102%
2103*/
cristy7832dc22011-09-05 01:21:53 +00002104MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002105{
2106 assert(image != (const Image *) NULL);
2107 assert(image->signature == MagickSignature);
2108 if (image->debug != MagickFalse)
2109 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2110 return(image->blob->temporary);
2111}
2112
2113/*
2114%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2115% %
2116% %
2117% %
2118+ M a p B l o b %
2119% %
2120% %
2121% %
2122%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2123%
2124% MapBlob() creates a mapping from a file to a binary large object.
2125%
2126% The format of the MapBlob method is:
2127%
2128% unsigned char *MapBlob(int file,const MapMode mode,
2129% const MagickOffsetType offset,const size_t length)
2130%
2131% A description of each parameter follows:
2132%
2133% o file: map this file descriptor.
2134%
2135% o mode: ReadMode, WriteMode, or IOMode.
2136%
2137% o offset: starting at this offset within the file.
2138%
2139% o length: the length of the mapping is returned in this pointer.
2140%
2141*/
2142MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2143 const MagickOffsetType offset,const size_t length)
2144{
2145#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
2146 int
2147 flags,
2148 protection;
2149
2150 unsigned char
2151 *map;
2152
2153 /*
2154 Map file.
2155 */
2156 flags=0;
2157 if (file == -1)
2158#if defined(MAP_ANONYMOUS)
2159 flags|=MAP_ANONYMOUS;
cristy6dac2da2013-04-16 19:10:51 +00002160#if defined(MAGICKCORE_HAVE_HUGEPAGES) && defined(MAP_HUGETLB)
2161 flags|=MAP_HUGETLB;
2162#endif
cristy3ed852e2009-09-05 21:47:34 +00002163#else
2164 return((unsigned char *) NULL);
2165#endif
2166 switch (mode)
2167 {
2168 case ReadMode:
2169 default:
2170 {
2171 protection=PROT_READ;
2172 flags|=MAP_PRIVATE;
2173 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2174 (off_t) offset);
2175 break;
2176 }
2177 case WriteMode:
2178 {
2179 protection=PROT_WRITE;
2180 flags|=MAP_SHARED;
2181 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2182 (off_t) offset);
cristy2a9e7cb2010-03-05 02:15:05 +00002183#if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
2184 (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
2185 POSIX_MADV_WILLNEED);
2186#endif
cristy3ed852e2009-09-05 21:47:34 +00002187 break;
2188 }
2189 case IOMode:
2190 {
2191 protection=PROT_READ | PROT_WRITE;
2192 flags|=MAP_SHARED;
2193 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2194 (off_t) offset);
2195 break;
2196 }
2197 }
2198 if (map == (unsigned char *) MAP_FAILED)
2199 return((unsigned char *) NULL);
2200 return(map);
2201#else
2202 (void) file;
2203 (void) mode;
2204 (void) offset;
2205 (void) length;
2206 return((unsigned char *) NULL);
2207#endif
2208}
2209
2210/*
2211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2212% %
2213% %
2214% %
2215+ M S B O r d e r L o n g %
2216% %
2217% %
2218% %
2219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2220%
2221% MSBOrderLong() converts a least-significant byte first buffer of integers to
2222% most-significant byte first.
2223%
2224% The format of the MSBOrderLong method is:
2225%
2226% void MSBOrderLong(unsigned char *buffer,const size_t length)
2227%
2228% A description of each parameter follows.
2229%
2230% o buffer: Specifies a pointer to a buffer of integers.
2231%
2232% o length: Specifies the length of the buffer.
2233%
2234*/
2235MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2236{
2237 int
2238 c;
2239
2240 register unsigned char
2241 *p,
2242 *q;
2243
2244 assert(buffer != (unsigned char *) NULL);
2245 q=buffer+length;
2246 while (buffer < q)
2247 {
2248 p=buffer+3;
2249 c=(int) (*p);
2250 *p=(*buffer);
2251 *buffer++=(unsigned char) c;
2252 p=buffer+1;
2253 c=(int) (*p);
2254 *p=(*buffer);
2255 *buffer++=(unsigned char) c;
2256 buffer+=2;
2257 }
2258}
2259
2260/*
2261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2262% %
2263% %
2264% %
2265+ M S B O r d e r S h o r t %
2266% %
2267% %
2268% %
2269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2270%
2271% MSBOrderShort() converts a least-significant byte first buffer of integers
2272% to most-significant byte first.
2273%
2274% The format of the MSBOrderShort method is:
2275%
2276% void MSBOrderShort(unsigned char *p,const size_t length)
2277%
2278% A description of each parameter follows.
2279%
2280% o p: Specifies a pointer to a buffer of integers.
2281%
2282% o length: Specifies the length of the buffer.
2283%
2284*/
2285MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2286{
2287 int
2288 c;
2289
2290 register unsigned char
2291 *q;
2292
2293 assert(p != (unsigned char *) NULL);
2294 q=p+length;
2295 while (p < q)
2296 {
2297 c=(int) (*p);
2298 *p=(*(p+1));
2299 p++;
2300 *p++=(unsigned char) c;
2301 }
2302}
2303
2304/*
2305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2306% %
2307% %
2308% %
2309+ O p e n B l o b %
2310% %
2311% %
2312% %
2313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2314%
2315% OpenBlob() opens a file associated with the image. A file name of '-' sets
2316% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2317% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2318% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2319% from a system command.
2320%
2321% The format of the OpenBlob method is:
2322%
2323% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2324% const BlobMode mode,ExceptionInfo *exception)
2325%
2326% A description of each parameter follows:
2327%
2328% o image_info: the image info.
2329%
2330% o image: the image.
2331%
2332% o mode: the mode for opening the file.
2333%
2334*/
2335MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2336 Image *image,const BlobMode mode,ExceptionInfo *exception)
2337{
2338 char
cristybf6a7092010-06-11 02:12:15 +00002339 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002340 filename[MaxTextExtent];
2341
2342 const char
2343 *type;
2344
2345 MagickBooleanType
2346 status;
2347
2348 PolicyRights
2349 rights;
2350
2351 assert(image_info != (ImageInfo *) NULL);
2352 assert(image_info->signature == MagickSignature);
2353 if (image_info->debug != MagickFalse)
2354 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2355 image_info->filename);
2356 assert(image != (Image *) NULL);
2357 assert(image->signature == MagickSignature);
2358 if (image_info->blob != (void *) NULL)
2359 {
2360 if (image_info->stream != (StreamHandler) NULL)
2361 image->blob->stream=(StreamHandler) image_info->stream;
2362 AttachBlob(image->blob,image_info->blob,image_info->length);
2363 return(MagickTrue);
2364 }
2365 (void) DetachBlob(image->blob);
2366 switch (mode)
2367 {
2368 default: type="r"; break;
2369 case ReadBlobMode: type="r"; break;
2370 case ReadBinaryBlobMode: type="rb"; break;
2371 case WriteBlobMode: type="w"; break;
2372 case WriteBinaryBlobMode: type="w+b"; break;
2373 case AppendBlobMode: type="a"; break;
2374 case AppendBinaryBlobMode: type="a+b"; break;
2375 }
2376 if (*type != 'r')
2377 image->blob->synchronize=image_info->synchronize;
2378 if (image_info->stream != (StreamHandler) NULL)
2379 {
2380 image->blob->stream=(StreamHandler) image_info->stream;
2381 if (*type == 'w')
2382 {
2383 image->blob->type=FifoStream;
2384 return(MagickTrue);
2385 }
2386 }
2387 /*
2388 Open image file.
2389 */
2390 *filename='\0';
2391 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2392 rights=ReadPolicyRights;
2393 if (*type == 'w')
2394 rights=WritePolicyRights;
2395 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2396 {
cristya9197f62010-01-12 02:23:34 +00002397 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002398 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
cristyefe601c2013-01-05 17:51:12 +00002399 "NotAuthorized","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00002400 return(MagickFalse);
2401 }
2402 if ((LocaleCompare(filename,"-") == 0) ||
2403 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2404 {
cristye7b28372012-06-17 13:59:06 +00002405 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002406#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002407 if (strchr(type,'b') != (char *) NULL)
cristye7b28372012-06-17 13:59:06 +00002408 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002409#endif
2410 image->blob->type=StandardStream;
2411 image->blob->exempt=MagickTrue;
2412 return(MagickTrue);
2413 }
cristybc20d112012-07-29 20:27:00 +00002414 if (LocaleNCompare(filename,"fd:",3) == 0)
2415 {
2416 char
2417 mode[MaxTextExtent];
2418
2419 *mode=(*type);
2420 mode[1]='\0';
2421 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2422#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2423 if (strchr(type,'b') != (char *) NULL)
2424 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2425#endif
2426 image->blob->type=StandardStream;
2427 image->blob->exempt=MagickTrue;
2428 return(MagickTrue);
2429 }
cristy3ed852e2009-09-05 21:47:34 +00002430#if defined(MAGICKCORE_HAVE_POPEN)
2431 if (*filename == '|')
2432 {
2433 char
2434 mode[MaxTextExtent];
2435
2436 /*
2437 Pipe image to or from a system command.
2438 */
2439#if defined(SIGPIPE)
2440 if (*type == 'w')
2441 (void) signal(SIGPIPE,SIG_IGN);
2442#endif
2443 *mode=(*type);
2444 mode[1]='\0';
cristye7b28372012-06-17 13:59:06 +00002445 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2446 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002447 {
2448 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2449 return(MagickFalse);
2450 }
2451 image->blob->type=PipeStream;
2452 image->blob->exempt=MagickTrue;
2453 return(MagickTrue);
2454 }
2455#endif
2456 status=GetPathAttributes(filename,&image->blob->properties);
2457#if defined(S_ISFIFO)
2458 if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2459 {
cristye7b28372012-06-17 13:59:06 +00002460 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2461 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002462 {
2463 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2464 return(MagickFalse);
2465 }
2466 image->blob->type=FileStream;
2467 image->blob->exempt=MagickTrue;
2468 return(MagickTrue);
2469 }
2470#endif
cristybf6a7092010-06-11 02:12:15 +00002471 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002472 if (*type == 'w')
2473 {
cristye8939e72010-02-03 17:05:25 +00002474 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002475 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002476 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002477 {
2478 /*
2479 Form filename for multi-part images.
2480 */
2481 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002482 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002483 if ((LocaleCompare(filename,image->filename) == 0) &&
2484 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2485 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002486 {
cristybf7fa0d2010-02-04 00:51:10 +00002487 char
cristybf7fa0d2010-02-04 00:51:10 +00002488 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002489
cristybf7fa0d2010-02-04 00:51:10 +00002490 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002491 if (*extension == '\0')
cristyb51dff52011-05-19 16:55:47 +00002492 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002493 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002494 else
cristyb51dff52011-05-19 16:55:47 +00002495 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002496 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002497 }
2498 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002499#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002500 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002501#endif
cristye8939e72010-02-03 17:05:25 +00002502 }
cristy3ed852e2009-09-05 21:47:34 +00002503 }
cristybf6a7092010-06-11 02:12:15 +00002504 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002505 {
cristye7b28372012-06-17 13:59:06 +00002506 image->blob->file_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002507 image->blob->type=FileStream;
2508 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002509 }
2510 else
cristybf6a7092010-06-11 02:12:15 +00002511 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002512 {
cristye7b28372012-06-17 13:59:06 +00002513 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2514 if (image->blob->file_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002515 {
2516 size_t
cristybf6a7092010-06-11 02:12:15 +00002517 count;
cristy3ed852e2009-09-05 21:47:34 +00002518
cristybf6a7092010-06-11 02:12:15 +00002519 unsigned char
2520 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002521
cristybf6a7092010-06-11 02:12:15 +00002522 image->blob->type=FileStream;
2523#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002524 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2525 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002526#endif
2527 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristye7b28372012-06-17 13:59:06 +00002528 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
cristyae958042013-01-05 15:48:19 +00002529 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
cristy79fe6932012-12-25 00:31:30 +00002530 (void) fflush(image->blob->file_info.file);
cristybf6a7092010-06-11 02:12:15 +00002531 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2532 " read %.20g magic header bytes",(double) count);
2533#if defined(MAGICKCORE_ZLIB_DELEGATE)
2534 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2535 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002536 {
cristye7b28372012-06-17 13:59:06 +00002537 (void) fclose(image->blob->file_info.file);
2538 image->blob->file_info.gzfile=gzopen(filename,type);
2539 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002540 image->blob->type=ZipStream;
2541 }
2542#endif
2543#if defined(MAGICKCORE_BZLIB_DELEGATE)
2544 if (strncmp((char *) magick,"BZh",3) == 0)
2545 {
cristye7b28372012-06-17 13:59:06 +00002546 (void) fclose(image->blob->file_info.file);
2547 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2548 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002549 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002550 }
cristybf6a7092010-06-11 02:12:15 +00002551#endif
cristyc6c589d2010-07-06 01:34:57 +00002552 if (image->blob->type == FileStream)
2553 {
2554 const MagickInfo
2555 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002556
cristyc6c589d2010-07-06 01:34:57 +00002557 ExceptionInfo
2558 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002559
cristy18aba912013-06-14 19:48:08 +00002560 size_t
2561 length;
2562
cristyc6c589d2010-07-06 01:34:57 +00002563 sans_exception=AcquireExceptionInfo();
2564 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2565 sans_exception=DestroyExceptionInfo(sans_exception);
cristy2eddb3d2013-06-16 14:10:08 +00002566 length=(size_t) image->blob->properties.st_size;
cristyc6c589d2010-07-06 01:34:57 +00002567 if ((magick_info != (const MagickInfo *) NULL) &&
2568 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
cristy7c242ea2013-06-21 17:19:53 +00002569 (length <= MagickMaxBufferExtent) &&
cristy18aba912013-06-14 19:48:08 +00002570 (AcquireMagickResource(MapResource,length) != MagickFalse))
cristyc6c589d2010-07-06 01:34:57 +00002571 {
cristyc6c589d2010-07-06 01:34:57 +00002572 void
2573 *blob;
cristybf6a7092010-06-11 02:12:15 +00002574
cristyfe00ebf2013-06-16 14:17:53 +00002575 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2576 length);
cristy18aba912013-06-14 19:48:08 +00002577 if (blob == (void *) NULL)
2578 RelinquishMagickResource(MapResource,length);
2579 else
cristyc6c589d2010-07-06 01:34:57 +00002580 {
2581 /*
2582 Format supports blobs-- use memory-mapped I/O.
2583 */
2584 if (image_info->file != (FILE *) NULL)
2585 image->blob->exempt=MagickFalse;
2586 else
2587 {
cristye7b28372012-06-17 13:59:06 +00002588 (void) fclose(image->blob->file_info.file);
2589 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002590 }
2591 AttachBlob(image->blob,blob,length);
2592 image->blob->mapped=MagickTrue;
2593 }
2594 }
2595 }
cristy3ed852e2009-09-05 21:47:34 +00002596 }
cristybf6a7092010-06-11 02:12:15 +00002597 }
2598 else
2599#if defined(MAGICKCORE_ZLIB_DELEGATE)
2600 if ((LocaleCompare(extension,"Z") == 0) ||
2601 (LocaleCompare(extension,"gz") == 0) ||
2602 (LocaleCompare(extension,"wmz") == 0) ||
2603 (LocaleCompare(extension,"svgz") == 0))
2604 {
2605 if (mode == WriteBinaryBlobMode)
2606 type="wb";
cristye7b28372012-06-17 13:59:06 +00002607 image->blob->file_info.gzfile=gzopen(filename,type);
2608 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002609 image->blob->type=ZipStream;
2610 }
2611 else
2612#endif
2613#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002614 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002615 {
cristye7b28372012-06-17 13:59:06 +00002616 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2617 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002618 image->blob->type=BZipStream;
2619 }
2620 else
2621#endif
2622 {
cristye7b28372012-06-17 13:59:06 +00002623 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2624 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002625 {
2626 image->blob->type=FileStream;
2627#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002628 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2629 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002630#endif
2631 }
2632 }
cristy3ed852e2009-09-05 21:47:34 +00002633 image->blob->status=MagickFalse;
2634 if (image->blob->type != UndefinedStream)
2635 image->blob->size=GetBlobSize(image);
2636 else
2637 {
2638 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2639 return(MagickFalse);
2640 }
2641 return(MagickTrue);
2642}
2643
2644/*
2645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2646% %
2647% %
2648% %
2649+ P i n g B l o b %
2650% %
2651% %
2652% %
2653%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2654%
2655% PingBlob() returns all the attributes of an image or image sequence except
2656% for the pixels. It is much faster and consumes far less memory than
2657% BlobToImage(). On failure, a NULL image is returned and exception
2658% describes the reason for the failure.
2659%
2660% The format of the PingBlob method is:
2661%
2662% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2663% const size_t length,ExceptionInfo *exception)
2664%
2665% A description of each parameter follows:
2666%
2667% o image_info: the image info.
2668%
2669% o blob: the address of a character stream in one of the image formats
2670% understood by ImageMagick.
2671%
2672% o length: This size_t integer reflects the length in bytes of the blob.
2673%
2674% o exception: return any errors or warnings in this structure.
2675%
2676*/
2677
2678#if defined(__cplusplus) || defined(c_plusplus)
2679extern "C" {
2680#endif
2681
2682static size_t PingStream(const Image *magick_unused(image),
2683 const void *magick_unused(pixels),const size_t columns)
2684{
2685 return(columns);
2686}
2687
2688#if defined(__cplusplus) || defined(c_plusplus)
2689}
2690#endif
2691
2692MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2693 const size_t length,ExceptionInfo *exception)
2694{
2695 Image
2696 *image;
2697
2698 ImageInfo
2699 *ping_info;
2700
2701 assert(image_info != (ImageInfo *) NULL);
2702 assert(image_info->signature == MagickSignature);
2703 if (image_info->debug != MagickFalse)
2704 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2705 image_info->filename);
2706 assert(exception != (ExceptionInfo *) NULL);
2707 if ((blob == (const void *) NULL) || (length == 0))
2708 {
2709 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +00002710 "UnrecognizedImageFormat","`%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002711 return((Image *) NULL);
2712 }
2713 ping_info=CloneImageInfo(image_info);
2714 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2715 if (ping_info->blob == (const void *) NULL)
2716 {
2717 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00002718 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002719 return((Image *) NULL);
2720 }
cristy54aad5e2010-09-03 16:02:04 +00002721 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002722 ping_info->length=length;
2723 ping_info->ping=MagickTrue;
2724 image=ReadStream(ping_info,&PingStream,exception);
2725 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2726 ping_info=DestroyImageInfo(ping_info);
2727 return(image);
2728}
2729
2730/*
2731%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2732% %
2733% %
2734% %
2735+ R e a d B l o b %
2736% %
2737% %
2738% %
2739%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2740%
2741% ReadBlob() reads data from the blob or image file and returns it. It
cristy5f3d2752013-01-05 18:53:38 +00002742% returns the number of bytes read. If length is zero, ReadBlob() returns
2743% zero and has no other results. If length is greater than SSIZE_MAX, the
2744% result is unspecified.
cristy3ed852e2009-09-05 21:47:34 +00002745%
2746% The format of the ReadBlob method is:
2747%
2748% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2749%
2750% A description of each parameter follows:
2751%
2752% o image: the image.
2753%
2754% o length: Specifies an integer representing the number of bytes to read
2755% from the file.
2756%
2757% o data: Specifies an area to place the information requested from the
2758% file.
2759%
2760*/
2761MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2762 unsigned char *data)
2763{
2764 int
2765 c;
2766
2767 register unsigned char
2768 *q;
2769
2770 ssize_t
2771 count;
2772
2773 assert(image != (Image *) NULL);
2774 assert(image->signature == MagickSignature);
2775 assert(image->blob != (BlobInfo *) NULL);
2776 assert(image->blob->type != UndefinedStream);
2777 if (length == 0)
2778 return(0);
2779 assert(data != (void *) NULL);
2780 count=0;
2781 q=data;
2782 switch (image->blob->type)
2783 {
2784 case UndefinedStream:
2785 break;
cristy3ed852e2009-09-05 21:47:34 +00002786 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002787 {
cristy8faec1e2013-04-25 19:41:22 +00002788 register ssize_t
2789 i;
2790
2791 for (i=0; i < (ssize_t) length; i+=count)
2792 {
cristy7c242ea2013-06-21 17:19:53 +00002793 count=read(fileno(image->blob->file_info.file),q+i,(size_t)
cristy8faec1e2013-04-25 19:41:22 +00002794 MagickMin(length-i,(MagickSizeType) SSIZE_MAX));
2795 if (count <= 0)
2796 {
2797 count=0;
2798 if (errno != EINTR)
2799 break;
2800 }
2801 }
2802 count=i;
cristybc20d112012-07-29 20:27:00 +00002803 break;
2804 }
2805 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002806 case PipeStream:
2807 {
2808 switch (length)
2809 {
2810 default:
2811 {
cristye7b28372012-06-17 13:59:06 +00002812 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002813 break;
2814 }
2815 case 2:
2816 {
cristye7b28372012-06-17 13:59:06 +00002817 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002818 if (c == EOF)
2819 break;
2820 *q++=(unsigned char) c;
2821 count++;
2822 }
2823 case 1:
2824 {
cristye7b28372012-06-17 13:59:06 +00002825 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002826 if (c == EOF)
2827 break;
2828 *q++=(unsigned char) c;
2829 count++;
2830 }
2831 case 0:
2832 break;
2833 }
2834 break;
2835 }
2836 case ZipStream:
2837 {
2838#if defined(MAGICKCORE_ZLIB_DELEGATE)
2839 switch (length)
2840 {
2841 default:
2842 {
cristye7b28372012-06-17 13:59:06 +00002843 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002844 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002845 break;
2846 }
2847 case 2:
2848 {
cristye7b28372012-06-17 13:59:06 +00002849 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002850 if (c == EOF)
2851 break;
2852 *q++=(unsigned char) c;
2853 count++;
2854 }
2855 case 1:
2856 {
cristye7b28372012-06-17 13:59:06 +00002857 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002858 if (c == EOF)
2859 break;
2860 *q++=(unsigned char) c;
2861 count++;
2862 }
2863 case 0:
2864 break;
2865 }
2866#endif
2867 break;
2868 }
2869 case BZipStream:
2870 {
2871#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy5f3d2752013-01-05 18:53:38 +00002872 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
cristy3ed852e2009-09-05 21:47:34 +00002873#endif
2874 break;
2875 }
2876 case FifoStream:
2877 break;
2878 case BlobStream:
2879 {
2880 register const unsigned char
2881 *p;
2882
2883 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2884 {
2885 image->blob->eof=MagickTrue;
2886 break;
2887 }
2888 p=image->blob->data+image->blob->offset;
cristye7b28372012-06-17 13:59:06 +00002889 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2890 image->blob->offset));
cristy3ed852e2009-09-05 21:47:34 +00002891 image->blob->offset+=count;
2892 if (count != (ssize_t) length)
2893 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002894 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002895 break;
2896 }
2897 }
2898 return(count);
2899}
2900
2901/*
2902%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2903% %
2904% %
2905% %
2906+ R e a d B l o b B y t e %
2907% %
2908% %
2909% %
2910%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2911%
2912% ReadBlobByte() reads a single byte from the image file and returns it.
2913%
2914% The format of the ReadBlobByte method is:
2915%
2916% int ReadBlobByte(Image *image)
2917%
2918% A description of each parameter follows.
2919%
2920% o image: the image.
2921%
2922*/
2923MagickExport int ReadBlobByte(Image *image)
2924{
2925 register const unsigned char
2926 *p;
2927
2928 ssize_t
2929 count;
2930
2931 unsigned char
2932 buffer[1];
2933
2934 assert(image != (Image *) NULL);
2935 assert(image->signature == MagickSignature);
2936 p=ReadBlobStream(image,1,buffer,&count);
2937 if (count != 1)
2938 return(EOF);
2939 return((int) (*p));
2940}
2941
2942/*
2943%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2944% %
2945% %
2946% %
2947+ R e a d B l o b D o u b l e %
2948% %
2949% %
2950% %
2951%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2952%
2953% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2954% specified by the endian member of the image structure.
2955%
2956% The format of the ReadBlobDouble method is:
2957%
2958% double ReadBlobDouble(Image *image)
2959%
2960% A description of each parameter follows.
2961%
2962% o image: the image.
2963%
2964*/
2965MagickExport double ReadBlobDouble(Image *image)
2966{
2967 union
2968 {
2969 MagickSizeType
2970 unsigned_value;
2971
2972 double
2973 double_value;
2974 } quantum;
2975
2976 quantum.double_value=0.0;
2977 quantum.unsigned_value=ReadBlobLongLong(image);
2978 return(quantum.double_value);
2979}
2980
2981/*
2982%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2983% %
2984% %
2985% %
2986+ R e a d B l o b F l o a t %
2987% %
2988% %
2989% %
2990%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2991%
2992% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2993% specified by the endian member of the image structure.
2994%
2995% The format of the ReadBlobFloat method is:
2996%
2997% float ReadBlobFloat(Image *image)
2998%
2999% A description of each parameter follows.
3000%
3001% o image: the image.
3002%
3003*/
3004MagickExport float ReadBlobFloat(Image *image)
3005{
3006 union
3007 {
3008 unsigned int
3009 unsigned_value;
3010
3011 float
3012 float_value;
3013 } quantum;
3014
3015 quantum.float_value=0.0;
3016 quantum.unsigned_value=ReadBlobLong(image);
3017 return(quantum.float_value);
3018}
3019
3020/*
3021%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3022% %
3023% %
3024% %
3025+ R e a d B l o b L o n g %
3026% %
3027% %
3028% %
3029%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3030%
cristybb503372010-05-27 20:51:26 +00003031% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003032% specified by the endian member of the image structure.
3033%
3034% The format of the ReadBlobLong method is:
3035%
3036% unsigned int ReadBlobLong(Image *image)
3037%
3038% A description of each parameter follows.
3039%
3040% o image: the image.
3041%
3042*/
3043MagickExport unsigned int ReadBlobLong(Image *image)
3044{
3045 register const unsigned char
3046 *p;
3047
3048 ssize_t
3049 count;
3050
3051 unsigned char
3052 buffer[4];
3053
3054 unsigned int
3055 value;
3056
3057 assert(image != (Image *) NULL);
3058 assert(image->signature == MagickSignature);
3059 *buffer='\0';
3060 p=ReadBlobStream(image,4,buffer,&count);
3061 if (count != 4)
3062 return(0UL);
3063 if (image->endian == LSBEndian)
3064 {
3065 value=(unsigned int) (*p++);
3066 value|=((unsigned int) (*p++)) << 8;
3067 value|=((unsigned int) (*p++)) << 16;
3068 value|=((unsigned int) (*p++)) << 24;
3069 return(value);
3070 }
3071 value=((unsigned int) (*p++)) << 24;
3072 value|=((unsigned int) (*p++)) << 16;
3073 value|=((unsigned int) (*p++)) << 8;
3074 value|=((unsigned int) (*p++));
3075 return(value);
3076}
3077
3078/*
3079%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3080% %
3081% %
3082% %
3083+ R e a d B l o b L o n g L o n g %
3084% %
3085% %
3086% %
3087%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3088%
cristy4cb162a2010-05-30 03:04:47 +00003089% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3090% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003091%
cristy4cb162a2010-05-30 03:04:47 +00003092% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003093%
cristy4cb162a2010-05-30 03:04:47 +00003094% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003095%
3096% A description of each parameter follows.
3097%
3098% o image: the image.
3099%
3100*/
3101MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3102{
cristy0286d852010-10-12 18:38:07 +00003103 MagickSizeType
3104 value;
3105
cristy3ed852e2009-09-05 21:47:34 +00003106 register const unsigned char
3107 *p;
3108
3109 ssize_t
3110 count;
3111
3112 unsigned char
3113 buffer[8];
3114
cristy3ed852e2009-09-05 21:47:34 +00003115 assert(image != (Image *) NULL);
3116 assert(image->signature == MagickSignature);
3117 *buffer='\0';
3118 p=ReadBlobStream(image,8,buffer,&count);
3119 if (count != 8)
3120 return(MagickULLConstant(0));
3121 if (image->endian == LSBEndian)
3122 {
3123 value=(MagickSizeType) (*p++);
3124 value|=((MagickSizeType) (*p++)) << 8;
3125 value|=((MagickSizeType) (*p++)) << 16;
3126 value|=((MagickSizeType) (*p++)) << 24;
3127 value|=((MagickSizeType) (*p++)) << 32;
3128 value|=((MagickSizeType) (*p++)) << 40;
3129 value|=((MagickSizeType) (*p++)) << 48;
3130 value|=((MagickSizeType) (*p++)) << 56;
3131 return(value & MagickULLConstant(0xffffffffffffffff));
3132 }
3133 value=((MagickSizeType) (*p++)) << 56;
3134 value|=((MagickSizeType) (*p++)) << 48;
3135 value|=((MagickSizeType) (*p++)) << 40;
3136 value|=((MagickSizeType) (*p++)) << 32;
3137 value|=((MagickSizeType) (*p++)) << 24;
3138 value|=((MagickSizeType) (*p++)) << 16;
3139 value|=((MagickSizeType) (*p++)) << 8;
3140 value|=((MagickSizeType) (*p++));
3141 return(value & MagickULLConstant(0xffffffffffffffff));
3142}
3143
3144/*
3145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3146% %
3147% %
3148% %
3149+ R e a d B l o b S h o r t %
3150% %
3151% %
3152% %
3153%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3154%
3155% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3156% specified by the endian member of the image structure.
3157%
3158% The format of the ReadBlobShort method is:
3159%
3160% unsigned short ReadBlobShort(Image *image)
3161%
3162% A description of each parameter follows.
3163%
3164% o image: the image.
3165%
3166*/
3167MagickExport unsigned short ReadBlobShort(Image *image)
3168{
3169 register const unsigned char
3170 *p;
3171
3172 register unsigned int
3173 value;
3174
3175 ssize_t
3176 count;
3177
3178 unsigned char
3179 buffer[2];
3180
3181 assert(image != (Image *) NULL);
3182 assert(image->signature == MagickSignature);
3183 *buffer='\0';
3184 p=ReadBlobStream(image,2,buffer,&count);
3185 if (count != 2)
3186 return((unsigned short) 0U);
3187 if (image->endian == LSBEndian)
3188 {
3189 value=(unsigned int) (*p++);
3190 value|=((unsigned int) (*p++)) << 8;
3191 return((unsigned short) (value & 0xffff));
3192 }
3193 value=(unsigned int) ((*p++) << 8);
3194 value|=(unsigned int) (*p++);
3195 return((unsigned short) (value & 0xffff));
3196}
3197
3198/*
3199%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3200% %
3201% %
3202% %
3203+ R e a d B l o b L S B L o n g %
3204% %
3205% %
3206% %
3207%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3208%
cristybb503372010-05-27 20:51:26 +00003209% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003210% least-significant byte first order.
3211%
3212% The format of the ReadBlobLSBLong method is:
3213%
3214% unsigned int ReadBlobLSBLong(Image *image)
3215%
3216% A description of each parameter follows.
3217%
3218% o image: the image.
3219%
3220*/
3221MagickExport unsigned int ReadBlobLSBLong(Image *image)
3222{
3223 register const unsigned char
3224 *p;
3225
3226 register unsigned int
3227 value;
3228
3229 ssize_t
3230 count;
3231
3232 unsigned char
3233 buffer[4];
3234
3235 assert(image != (Image *) NULL);
3236 assert(image->signature == MagickSignature);
3237 *buffer='\0';
3238 p=ReadBlobStream(image,4,buffer,&count);
3239 if (count != 4)
3240 return(0U);
3241 value=(unsigned int) (*p++);
3242 value|=((unsigned int) (*p++)) << 8;
3243 value|=((unsigned int) (*p++)) << 16;
3244 value|=((unsigned int) (*p++)) << 24;
3245 return(value);
3246}
3247
3248/*
3249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3250% %
3251% %
3252% %
3253+ R e a d B l o b L S B S h o r t %
3254% %
3255% %
3256% %
3257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3258%
3259% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3260% least-significant byte first order.
3261%
3262% The format of the ReadBlobLSBShort method is:
3263%
3264% unsigned short ReadBlobLSBShort(Image *image)
3265%
3266% A description of each parameter follows.
3267%
3268% o image: the image.
3269%
3270*/
3271MagickExport unsigned short ReadBlobLSBShort(Image *image)
3272{
3273 register const unsigned char
3274 *p;
3275
3276 register unsigned int
3277 value;
3278
3279 ssize_t
3280 count;
3281
3282 unsigned char
3283 buffer[2];
3284
3285 assert(image != (Image *) NULL);
3286 assert(image->signature == MagickSignature);
3287 *buffer='\0';
3288 p=ReadBlobStream(image,2,buffer,&count);
3289 if (count != 2)
3290 return((unsigned short) 0U);
3291 value=(unsigned int) (*p++);
3292 value|=((unsigned int) ((*p++)) << 8);
3293 return((unsigned short) (value & 0xffff));
3294}
3295
3296/*
3297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3298% %
3299% %
3300% %
3301+ R e a d B l o b M S B L o n g %
3302% %
3303% %
3304% %
3305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3306%
cristybb503372010-05-27 20:51:26 +00003307% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003308% most-significant byte first order.
3309%
3310% The format of the ReadBlobMSBLong method is:
3311%
3312% unsigned int ReadBlobMSBLong(Image *image)
3313%
3314% A description of each parameter follows.
3315%
3316% o image: the image.
3317%
3318*/
3319MagickExport unsigned int ReadBlobMSBLong(Image *image)
3320{
3321 register const unsigned char
3322 *p;
3323
3324 register unsigned int
3325 value;
3326
3327 ssize_t
3328 count;
3329
3330 unsigned char
3331 buffer[4];
3332
3333 assert(image != (Image *) NULL);
3334 assert(image->signature == MagickSignature);
3335 *buffer='\0';
3336 p=ReadBlobStream(image,4,buffer,&count);
3337 if (count != 4)
3338 return(0UL);
3339 value=((unsigned int) (*p++) << 24);
3340 value|=((unsigned int) (*p++) << 16);
3341 value|=((unsigned int) (*p++) << 8);
3342 value|=(unsigned int) (*p++);
3343 return(value);
3344}
3345
3346/*
3347%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3348% %
3349% %
3350% %
cristy2d3d87f2010-03-01 00:23:08 +00003351+ R e a d B l o b M S B L o n g L o n g %
3352% %
3353% %
3354% %
3355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3356%
cristybb503372010-05-27 20:51:26 +00003357% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003358% most-significant byte first order.
3359%
3360% The format of the ReadBlobMSBLongLong method is:
3361%
3362% unsigned int ReadBlobMSBLongLong(Image *image)
3363%
3364% A description of each parameter follows.
3365%
3366% o image: the image.
3367%
3368*/
3369MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3370{
3371 register const unsigned char
3372 *p;
3373
3374 register MagickSizeType
3375 value;
3376
3377 ssize_t
3378 count;
3379
3380 unsigned char
cristy0286d852010-10-12 18:38:07 +00003381 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003382
3383 assert(image != (Image *) NULL);
3384 assert(image->signature == MagickSignature);
3385 *buffer='\0';
3386 p=ReadBlobStream(image,8,buffer,&count);
3387 if (count != 8)
3388 return(MagickULLConstant(0));
3389 value=((MagickSizeType) (*p++)) << 56;
3390 value|=((MagickSizeType) (*p++)) << 48;
3391 value|=((MagickSizeType) (*p++)) << 40;
3392 value|=((MagickSizeType) (*p++)) << 32;
3393 value|=((MagickSizeType) (*p++)) << 24;
3394 value|=((MagickSizeType) (*p++)) << 16;
3395 value|=((MagickSizeType) (*p++)) << 8;
3396 value|=((MagickSizeType) (*p++));
3397 return(value & MagickULLConstant(0xffffffffffffffff));
3398}
3399
3400/*
3401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3402% %
3403% %
3404% %
cristy3ed852e2009-09-05 21:47:34 +00003405+ R e a d B l o b M S B S h o r t %
3406% %
3407% %
3408% %
3409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3410%
3411% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3412% most-significant byte first order.
3413%
3414% The format of the ReadBlobMSBShort method is:
3415%
3416% unsigned short ReadBlobMSBShort(Image *image)
3417%
3418% A description of each parameter follows.
3419%
3420% o image: the image.
3421%
3422*/
3423MagickExport unsigned short ReadBlobMSBShort(Image *image)
3424{
3425 register const unsigned char
3426 *p;
3427
3428 register unsigned int
3429 value;
3430
3431 ssize_t
3432 count;
3433
3434 unsigned char
3435 buffer[2];
3436
3437 assert(image != (Image *) NULL);
3438 assert(image->signature == MagickSignature);
3439 *buffer='\0';
3440 p=ReadBlobStream(image,2,buffer,&count);
3441 if (count != 2)
3442 return((unsigned short) 0U);
3443 value=(unsigned int) ((*p++) << 8);
3444 value|=(unsigned int) (*p++);
3445 return((unsigned short) (value & 0xffff));
3446}
3447
3448/*
3449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3450% %
3451% %
3452% %
3453+ R e a d B l o b S t r i n g %
3454% %
3455% %
3456% %
3457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3458%
3459% ReadBlobString() reads characters from a blob or file until a newline
3460% character is read or an end-of-file condition is encountered.
3461%
3462% The format of the ReadBlobString method is:
3463%
3464% char *ReadBlobString(Image *image,char *string)
3465%
3466% A description of each parameter follows:
3467%
3468% o image: the image.
3469%
3470% o string: the address of a character buffer.
3471%
3472*/
3473MagickExport char *ReadBlobString(Image *image,char *string)
3474{
3475 register const unsigned char
3476 *p;
3477
cristybb503372010-05-27 20:51:26 +00003478 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003479 i;
3480
3481 ssize_t
3482 count;
3483
3484 unsigned char
3485 buffer[1];
3486
3487 assert(image != (Image *) NULL);
3488 assert(image->signature == MagickSignature);
3489 for (i=0; i < (MaxTextExtent-1L); i++)
3490 {
3491 p=ReadBlobStream(image,1,buffer,&count);
3492 if (count != 1)
3493 {
3494 if (i == 0)
3495 return((char *) NULL);
3496 break;
3497 }
3498 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003499 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003500 break;
3501 }
cristy2b5db102010-06-09 01:07:28 +00003502 if (string[i] == '\r')
3503 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003504 string[i]='\0';
3505 return(string);
3506}
3507
3508/*
3509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3510% %
3511% %
3512% %
3513+ R e f e r e n c e B l o b %
3514% %
3515% %
3516% %
3517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3518%
3519% ReferenceBlob() increments the reference count associated with the pixel
3520% blob returning a pointer to the blob.
3521%
3522% The format of the ReferenceBlob method is:
3523%
3524% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3525%
3526% A description of each parameter follows:
3527%
3528% o blob_info: the blob_info.
3529%
3530*/
3531MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3532{
3533 assert(blob != (BlobInfo *) NULL);
3534 assert(blob->signature == MagickSignature);
3535 if (blob->debug != MagickFalse)
3536 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003537 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003538 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003539 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003540 return(blob);
3541}
3542
3543/*
3544%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3545% %
3546% %
3547% %
3548+ S e e k B l o b %
3549% %
3550% %
3551% %
3552%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3553%
3554% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3555% and returns the resulting offset.
3556%
3557% The format of the SeekBlob method is:
3558%
3559% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3560% const int whence)
3561%
3562% A description of each parameter follows:
3563%
3564% o image: the image.
3565%
3566% o offset: Specifies an integer representing the offset in bytes.
3567%
3568% o whence: Specifies an integer representing how the offset is
3569% treated relative to the beginning of the blob as follows:
3570%
3571% SEEK_SET Set position equal to offset bytes.
3572% SEEK_CUR Set position to current location plus offset.
3573% SEEK_END Set position to EOF plus offset.
3574%
3575*/
3576MagickExport MagickOffsetType SeekBlob(Image *image,
3577 const MagickOffsetType offset,const int whence)
3578{
3579 assert(image != (Image *) NULL);
3580 assert(image->signature == MagickSignature);
3581 if (image->debug != MagickFalse)
3582 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3583 assert(image->blob != (BlobInfo *) NULL);
3584 assert(image->blob->type != UndefinedStream);
3585 switch (image->blob->type)
3586 {
3587 case UndefinedStream:
3588 break;
cristybc20d112012-07-29 20:27:00 +00003589 case StandardStream:
3590 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003591 case FileStream:
3592 {
cristye7b28372012-06-17 13:59:06 +00003593 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003594 return(-1);
3595 image->blob->offset=TellBlob(image);
3596 break;
3597 }
cristy3ed852e2009-09-05 21:47:34 +00003598 case PipeStream:
3599 case ZipStream:
3600 {
3601#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003602 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003603 return(-1);
3604#endif
3605 image->blob->offset=TellBlob(image);
3606 break;
3607 }
3608 case BZipStream:
3609 return(-1);
3610 case FifoStream:
3611 return(-1);
3612 case BlobStream:
3613 {
3614 switch (whence)
3615 {
3616 case SEEK_SET:
3617 default:
3618 {
3619 if (offset < 0)
3620 return(-1);
3621 image->blob->offset=offset;
3622 break;
3623 }
3624 case SEEK_CUR:
3625 {
3626 if ((image->blob->offset+offset) < 0)
3627 return(-1);
3628 image->blob->offset+=offset;
3629 break;
3630 }
3631 case SEEK_END:
3632 {
3633 if (((MagickOffsetType) image->blob->length+offset) < 0)
3634 return(-1);
3635 image->blob->offset=image->blob->length+offset;
3636 break;
3637 }
3638 }
3639 if (image->blob->offset <= (MagickOffsetType)
3640 ((off_t) image->blob->length))
3641 image->blob->eof=MagickFalse;
3642 else
3643 if (image->blob->mapped != MagickFalse)
3644 return(-1);
3645 else
3646 {
3647 image->blob->extent=(size_t) (image->blob->offset+
3648 image->blob->quantum);
3649 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3650 image->blob->data,image->blob->extent+1,
3651 sizeof(*image->blob->data));
3652 (void) SyncBlob(image);
3653 if (image->blob->data == (unsigned char *) NULL)
3654 {
3655 (void) DetachBlob(image->blob);
3656 return(-1);
3657 }
3658 }
3659 break;
3660 }
3661 }
3662 return(image->blob->offset);
3663}
3664
3665/*
3666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3667% %
3668% %
3669% %
3670+ S e t B l o b E x e m p t %
3671% %
3672% %
3673% %
3674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3675%
3676% SetBlobExempt() sets the blob exempt status.
3677%
3678% The format of the SetBlobExempt method is:
3679%
3680% MagickBooleanType SetBlobExempt(const Image *image,
3681% const MagickBooleanType exempt)
3682%
3683% A description of each parameter follows:
3684%
3685% o image: the image.
3686%
3687% o exempt: Set to true if this blob is exempt from being closed.
3688%
3689*/
cristy7832dc22011-09-05 01:21:53 +00003690MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003691{
3692 assert(image != (const Image *) NULL);
3693 assert(image->signature == MagickSignature);
3694 if (image->debug != MagickFalse)
3695 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3696 image->blob->exempt=exempt;
3697}
3698
3699/*
3700%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3701% %
3702% %
3703% %
3704+ S e t B l o b E x t e n t %
3705% %
3706% %
3707% %
3708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3709%
3710% SetBlobExtent() ensures enough space is allocated for the blob. If the
3711% method is successful, subsequent writes to bytes in the specified range are
3712% guaranteed not to fail.
3713%
3714% The format of the SetBlobExtent method is:
3715%
3716% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3717%
3718% A description of each parameter follows:
3719%
3720% o image: the image.
3721%
3722% o extent: the blob maximum extent.
3723%
3724*/
cristy7832dc22011-09-05 01:21:53 +00003725MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003726 const MagickSizeType extent)
3727{
3728 assert(image != (Image *) NULL);
3729 assert(image->signature == MagickSignature);
3730 if (image->debug != MagickFalse)
3731 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3732 assert(image->blob != (BlobInfo *) NULL);
3733 assert(image->blob->type != UndefinedStream);
3734 switch (image->blob->type)
3735 {
3736 case UndefinedStream:
3737 break;
cristybc20d112012-07-29 20:27:00 +00003738 case StandardStream:
3739 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003740 case FileStream:
3741 {
cristy38e35f42012-12-18 21:12:17 +00003742 MagickOffsetType
3743 offset;
3744
3745 ssize_t
3746 count;
3747
cristy3ed852e2009-09-05 21:47:34 +00003748 if (extent != (MagickSizeType) ((off_t) extent))
3749 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003750 offset=SeekBlob(image,0,SEEK_END);
3751 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003752 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003753 if ((MagickSizeType) offset >= extent)
3754 break;
3755 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003756 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3757 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003758#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3759 if (image->blob->synchronize != MagickFalse)
3760 {
3761 int
3762 status;
3763
3764 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3765 extent-offset);
3766 if (status != 0)
3767 return(MagickFalse);
3768 }
3769#endif
cristy38e35f42012-12-18 21:12:17 +00003770 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003771 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003772 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003773 break;
3774 }
cristy3ed852e2009-09-05 21:47:34 +00003775 case PipeStream:
3776 case ZipStream:
3777 return(MagickFalse);
3778 case BZipStream:
3779 return(MagickFalse);
3780 case FifoStream:
3781 return(MagickFalse);
3782 case BlobStream:
3783 {
cristy38e35f42012-12-18 21:12:17 +00003784 if (extent != (MagickSizeType) ((size_t) extent))
3785 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003786 if (image->blob->mapped != MagickFalse)
3787 {
cristy38e35f42012-12-18 21:12:17 +00003788 MagickOffsetType
3789 offset;
3790
3791 ssize_t
3792 count;
3793
cristy3ed852e2009-09-05 21:47:34 +00003794 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy18aba912013-06-14 19:48:08 +00003795 RelinquishMagickResource(MapResource,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003796 if (extent != (MagickSizeType) ((off_t) extent))
3797 return(MagickFalse);
3798 offset=SeekBlob(image,0,SEEK_END);
3799 if (offset < 0)
3800 return(MagickFalse);
3801 if ((MagickSizeType) offset >= extent)
3802 break;
3803 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003804 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003805 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003806#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3807 if (image->blob->synchronize != MagickFalse)
3808 {
3809 int
3810 status;
3811
3812 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3813 extent-offset);
3814 if (status != 0)
3815 return(MagickFalse);
3816 }
3817#endif
cristy38e35f42012-12-18 21:12:17 +00003818 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003819 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003820 return(MagickFalse);
cristyac1caa22013-06-15 00:41:21 +00003821 (void) AcquireMagickResource(MapResource,extent);
cristy95888612012-04-04 21:56:52 +00003822 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003823 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003824 image->blob->extent=(size_t) extent;
3825 image->blob->length=(size_t) extent;
3826 (void) SyncBlob(image);
3827 break;
cristy3ed852e2009-09-05 21:47:34 +00003828 }
cristy3ed852e2009-09-05 21:47:34 +00003829 image->blob->extent=(size_t) extent;
3830 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3831 image->blob->extent+1,sizeof(*image->blob->data));
3832 (void) SyncBlob(image);
3833 if (image->blob->data == (unsigned char *) NULL)
3834 {
3835 (void) DetachBlob(image->blob);
3836 return(MagickFalse);
3837 }
3838 break;
3839 }
3840 }
3841 return(MagickTrue);
3842}
3843
3844/*
3845%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3846% %
3847% %
3848% %
3849+ S y n c B l o b %
3850% %
3851% %
3852% %
3853%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3854%
3855% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3856% attributes if it is an blob.
3857%
3858% The format of the SyncBlob method is:
3859%
3860% int SyncBlob(Image *image)
3861%
3862% A description of each parameter follows:
3863%
3864% o image: the image.
3865%
3866*/
3867static int SyncBlob(Image *image)
3868{
3869 int
3870 status;
3871
3872 assert(image != (Image *) NULL);
3873 assert(image->signature == MagickSignature);
3874 if (image->debug != MagickFalse)
3875 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3876 assert(image->blob != (BlobInfo *) NULL);
3877 assert(image->blob->type != UndefinedStream);
3878 status=0;
3879 switch (image->blob->type)
3880 {
3881 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003882 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003883 break;
3884 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003885 case PipeStream:
3886 {
cristye7b28372012-06-17 13:59:06 +00003887 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003888 break;
3889 }
3890 case ZipStream:
3891 {
3892#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003893 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003894#endif
3895 break;
3896 }
3897 case BZipStream:
3898 {
3899#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003900 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003901#endif
3902 break;
3903 }
3904 case FifoStream:
3905 break;
3906 case BlobStream:
cristy3ed852e2009-09-05 21:47:34 +00003907 break;
cristy3ed852e2009-09-05 21:47:34 +00003908 }
3909 return(status);
3910}
3911
3912/*
3913%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3914% %
3915% %
3916% %
3917+ T e l l B l o b %
3918% %
3919% %
3920% %
3921%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3922%
3923% TellBlob() obtains the current value of the blob or file position.
3924%
3925% The format of the TellBlob method is:
3926%
3927% MagickOffsetType TellBlob(const Image *image)
3928%
3929% A description of each parameter follows:
3930%
3931% o image: the image.
3932%
3933*/
3934MagickExport MagickOffsetType TellBlob(const Image *image)
3935{
3936 MagickOffsetType
3937 offset;
3938
3939 assert(image != (Image *) NULL);
3940 assert(image->signature == MagickSignature);
3941 if (image->debug != MagickFalse)
3942 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3943 assert(image->blob != (BlobInfo *) NULL);
3944 assert(image->blob->type != UndefinedStream);
3945 offset=(-1);
3946 switch (image->blob->type)
3947 {
3948 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003949 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003950 break;
3951 case FileStream:
3952 {
cristye7b28372012-06-17 13:59:06 +00003953 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003954 break;
3955 }
cristy3ed852e2009-09-05 21:47:34 +00003956 case PipeStream:
3957 break;
3958 case ZipStream:
3959 {
3960#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003961 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003962#endif
3963 break;
3964 }
3965 case BZipStream:
3966 break;
3967 case FifoStream:
3968 break;
3969 case BlobStream:
3970 {
3971 offset=image->blob->offset;
3972 break;
3973 }
3974 }
3975 return(offset);
3976}
3977
3978/*
3979%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3980% %
3981% %
3982% %
3983+ U n m a p B l o b %
3984% %
3985% %
3986% %
3987%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3988%
3989% UnmapBlob() deallocates the binary large object previously allocated with
3990% the MapBlob method.
3991%
3992% The format of the UnmapBlob method is:
3993%
3994% MagickBooleanType UnmapBlob(void *map,const size_t length)
3995%
3996% A description of each parameter follows:
3997%
3998% o map: the address of the binary large object.
3999%
4000% o length: the length of the binary large object.
4001%
4002*/
4003MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4004{
4005#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
4006 int
4007 status;
4008
4009 status=munmap(map,length);
4010 return(status == -1 ? MagickFalse : MagickTrue);
4011#else
4012 (void) map;
4013 (void) length;
4014 return(MagickFalse);
4015#endif
4016}
4017
4018/*
4019%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4020% %
4021% %
4022% %
4023+ W r i t e B l o b %
4024% %
4025% %
4026% %
4027%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4028%
4029% WriteBlob() writes data to a blob or image file. It returns the number of
4030% bytes written.
4031%
4032% The format of the WriteBlob method is:
4033%
4034% ssize_t WriteBlob(Image *image,const size_t length,
4035% const unsigned char *data)
4036%
4037% A description of each parameter follows:
4038%
4039% o image: the image.
4040%
4041% o length: Specifies an integer representing the number of bytes to
4042% write to the file.
4043%
4044% o data: The address of the data to write to the blob or file.
4045%
4046*/
4047MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4048 const unsigned char *data)
4049{
4050 int
4051 c;
4052
4053 register const unsigned char
4054 *p;
4055
4056 ssize_t
4057 count;
4058
4059 assert(image != (Image *) NULL);
4060 assert(image->signature == MagickSignature);
4061 assert(data != (const unsigned char *) NULL);
4062 assert(image->blob != (BlobInfo *) NULL);
4063 assert(image->blob->type != UndefinedStream);
4064 if (length == 0)
4065 return(0);
4066 count=0;
4067 p=data;
4068 switch (image->blob->type)
4069 {
4070 case UndefinedStream:
4071 break;
cristy3ed852e2009-09-05 21:47:34 +00004072 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004073 {
cristy5f3d2752013-01-05 18:53:38 +00004074 count=write(fileno(image->blob->file_info.file),data,length);
cristybc20d112012-07-29 20:27:00 +00004075 break;
4076 }
4077 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004078 case PipeStream:
4079 {
4080 switch (length)
4081 {
4082 default:
4083 {
4084 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004085 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004086 break;
4087 }
4088 case 2:
4089 {
cristye7b28372012-06-17 13:59:06 +00004090 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004091 if (c == EOF)
4092 break;
4093 count++;
4094 }
4095 case 1:
4096 {
cristye7b28372012-06-17 13:59:06 +00004097 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004098 if (c == EOF)
4099 break;
4100 count++;
4101 }
4102 case 0:
4103 break;
4104 }
4105 break;
4106 }
4107 case ZipStream:
4108 {
4109#if defined(MAGICKCORE_ZLIB_DELEGATE)
4110 switch (length)
4111 {
4112 default:
4113 {
cristye7b28372012-06-17 13:59:06 +00004114 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004115 (unsigned int) length);
4116 break;
4117 }
4118 case 2:
4119 {
cristye7b28372012-06-17 13:59:06 +00004120 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004121 if (c == EOF)
4122 break;
4123 count++;
4124 }
4125 case 1:
4126 {
cristye7b28372012-06-17 13:59:06 +00004127 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004128 if (c == EOF)
4129 break;
4130 count++;
4131 }
4132 case 0:
4133 break;
4134 }
4135#endif
4136 break;
4137 }
4138 case BZipStream:
4139 {
4140#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004141 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004142 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004143#endif
4144 break;
4145 }
4146 case FifoStream:
4147 {
4148 count=(ssize_t) image->blob->stream(image,data,length);
4149 break;
4150 }
4151 case BlobStream:
4152 {
4153 register unsigned char
4154 *q;
4155
4156 if ((image->blob->offset+(MagickOffsetType) length) >=
4157 (MagickOffsetType) image->blob->extent)
4158 {
4159 if (image->blob->mapped != MagickFalse)
4160 return(0);
4161 image->blob->quantum<<=1;
4162 image->blob->extent+=length+image->blob->quantum;
4163 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4164 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4165 (void) SyncBlob(image);
4166 if (image->blob->data == (unsigned char *) NULL)
4167 {
4168 (void) DetachBlob(image->blob);
4169 return(0);
4170 }
4171 }
4172 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004173 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004174 image->blob->offset+=length;
4175 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4176 image->blob->length=(size_t) image->blob->offset;
4177 count=(ssize_t) length;
4178 }
4179 }
4180 return(count);
4181}
4182
4183/*
4184%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4185% %
4186% %
4187% %
4188+ W r i t e B l o b B y t e %
4189% %
4190% %
4191% %
4192%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4193%
4194% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4195% written (either 0 or 1);
4196%
4197% The format of the WriteBlobByte method is:
4198%
4199% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4200%
4201% A description of each parameter follows.
4202%
4203% o image: the image.
4204%
4205% o value: Specifies the value to write.
4206%
4207*/
4208MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4209{
4210 assert(image != (Image *) NULL);
4211 assert(image->signature == MagickSignature);
4212 return(WriteBlobStream(image,1,&value));
4213}
4214
4215/*
4216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4217% %
4218% %
4219% %
4220+ W r i t e B l o b F l o a t %
4221% %
4222% %
4223% %
4224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4225%
4226% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4227% specified by the endian member of the image structure.
4228%
4229% The format of the WriteBlobFloat method is:
4230%
4231% ssize_t WriteBlobFloat(Image *image,const float value)
4232%
4233% A description of each parameter follows.
4234%
4235% o image: the image.
4236%
4237% o value: Specifies the value to write.
4238%
4239*/
4240MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4241{
4242 union
4243 {
4244 unsigned int
4245 unsigned_value;
4246
4247 float
4248 float_value;
4249 } quantum;
4250
4251 quantum.unsigned_value=0U;
4252 quantum.float_value=value;
4253 return(WriteBlobLong(image,quantum.unsigned_value));
4254}
4255
4256/*
4257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4258% %
4259% %
4260% %
4261+ W r i t e B l o b L o n g %
4262% %
4263% %
4264% %
4265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4266%
cristybb503372010-05-27 20:51:26 +00004267% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004268% specified by the endian member of the image structure.
4269%
4270% The format of the WriteBlobLong method is:
4271%
4272% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4273%
4274% A description of each parameter follows.
4275%
4276% o image: the image.
4277%
4278% o value: Specifies the value to write.
4279%
4280*/
4281MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4282{
4283 unsigned char
4284 buffer[4];
4285
4286 assert(image != (Image *) NULL);
4287 assert(image->signature == MagickSignature);
4288 if (image->endian == LSBEndian)
4289 {
4290 buffer[0]=(unsigned char) value;
4291 buffer[1]=(unsigned char) (value >> 8);
4292 buffer[2]=(unsigned char) (value >> 16);
4293 buffer[3]=(unsigned char) (value >> 24);
4294 return(WriteBlobStream(image,4,buffer));
4295 }
4296 buffer[0]=(unsigned char) (value >> 24);
4297 buffer[1]=(unsigned char) (value >> 16);
4298 buffer[2]=(unsigned char) (value >> 8);
4299 buffer[3]=(unsigned char) value;
4300 return(WriteBlobStream(image,4,buffer));
4301}
4302
4303/*
4304%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4305% %
4306% %
4307% %
4308+ W r i t e B l o b S h o r t %
4309% %
4310% %
4311% %
4312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4313%
4314% WriteBlobShort() writes a short value as a 16-bit quantity in the
4315% byte-order specified by the endian member of the image structure.
4316%
4317% The format of the WriteBlobShort method is:
4318%
4319% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4320%
4321% A description of each parameter follows.
4322%
4323% o image: the image.
4324%
4325% o value: Specifies the value to write.
4326%
4327*/
4328MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4329{
4330 unsigned char
4331 buffer[2];
4332
4333 assert(image != (Image *) NULL);
4334 assert(image->signature == MagickSignature);
4335 if (image->endian == LSBEndian)
4336 {
4337 buffer[0]=(unsigned char) value;
4338 buffer[1]=(unsigned char) (value >> 8);
4339 return(WriteBlobStream(image,2,buffer));
4340 }
4341 buffer[0]=(unsigned char) (value >> 8);
4342 buffer[1]=(unsigned char) value;
4343 return(WriteBlobStream(image,2,buffer));
4344}
4345
4346/*
4347%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4348% %
4349% %
4350% %
4351+ W r i t e B l o b L S B L o n g %
4352% %
4353% %
4354% %
4355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4356%
cristybb503372010-05-27 20:51:26 +00004357% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004358% least-significant byte first order.
4359%
4360% The format of the WriteBlobLSBLong method is:
4361%
4362% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4363%
4364% A description of each parameter follows.
4365%
4366% o image: the image.
4367%
4368% o value: Specifies the value to write.
4369%
4370*/
4371MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4372{
4373 unsigned char
4374 buffer[4];
4375
4376 assert(image != (Image *) NULL);
4377 assert(image->signature == MagickSignature);
4378 buffer[0]=(unsigned char) value;
4379 buffer[1]=(unsigned char) (value >> 8);
4380 buffer[2]=(unsigned char) (value >> 16);
4381 buffer[3]=(unsigned char) (value >> 24);
4382 return(WriteBlobStream(image,4,buffer));
4383}
4384
4385/*
4386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4387% %
4388% %
4389% %
4390+ W r i t e B l o b L S B S h o r t %
4391% %
4392% %
4393% %
4394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4395%
cristybb503372010-05-27 20:51:26 +00004396% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004397% least-significant byte first order.
4398%
4399% The format of the WriteBlobLSBShort method is:
4400%
4401% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4402%
4403% A description of each parameter follows.
4404%
4405% o image: the image.
4406%
4407% o value: Specifies the value to write.
4408%
4409*/
4410MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4411{
4412 unsigned char
4413 buffer[2];
4414
4415 assert(image != (Image *) NULL);
4416 assert(image->signature == MagickSignature);
4417 buffer[0]=(unsigned char) value;
4418 buffer[1]=(unsigned char) (value >> 8);
4419 return(WriteBlobStream(image,2,buffer));
4420}
4421
4422/*
4423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4424% %
4425% %
4426% %
4427+ W r i t e B l o b M S B L o n g %
4428% %
4429% %
4430% %
4431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4432%
cristybb503372010-05-27 20:51:26 +00004433% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004434% most-significant byte first order.
4435%
4436% The format of the WriteBlobMSBLong method is:
4437%
4438% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4439%
4440% A description of each parameter follows.
4441%
4442% o value: Specifies the value to write.
4443%
4444% o image: the image.
4445%
4446*/
4447MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4448{
4449 unsigned char
4450 buffer[4];
4451
4452 assert(image != (Image *) NULL);
4453 assert(image->signature == MagickSignature);
4454 buffer[0]=(unsigned char) (value >> 24);
4455 buffer[1]=(unsigned char) (value >> 16);
4456 buffer[2]=(unsigned char) (value >> 8);
4457 buffer[3]=(unsigned char) value;
4458 return(WriteBlobStream(image,4,buffer));
4459}
4460
4461/*
4462%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4463% %
4464% %
4465% %
cristy2ca49922010-03-06 02:54:01 +00004466+ W r i t e B l o b M S B L o n g L o n g %
4467% %
4468% %
4469% %
4470%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4471%
4472% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4473% most-significant byte first order.
4474%
4475% The format of the WriteBlobMSBLongLong method is:
4476%
4477% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4478%
4479% A description of each parameter follows.
4480%
4481% o value: Specifies the value to write.
4482%
4483% o image: the image.
4484%
4485*/
4486MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4487 const MagickSizeType value)
4488{
4489 unsigned char
4490 buffer[8];
4491
4492 assert(image != (Image *) NULL);
4493 assert(image->signature == MagickSignature);
4494 buffer[0]=(unsigned char) (value >> 56);
4495 buffer[1]=(unsigned char) (value >> 48);
4496 buffer[2]=(unsigned char) (value >> 40);
4497 buffer[3]=(unsigned char) (value >> 32);
4498 buffer[4]=(unsigned char) (value >> 24);
4499 buffer[5]=(unsigned char) (value >> 16);
4500 buffer[6]=(unsigned char) (value >> 8);
4501 buffer[7]=(unsigned char) value;
4502 return(WriteBlobStream(image,8,buffer));
4503}
4504
4505/*
4506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4507% %
4508% %
4509% %
cristy3ed852e2009-09-05 21:47:34 +00004510+ W r i t e B l o b M S B S h o r t %
4511% %
4512% %
4513% %
4514%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4515%
cristybb503372010-05-27 20:51:26 +00004516% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004517% most-significant byte first order.
4518%
4519% The format of the WriteBlobMSBShort method is:
4520%
4521% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4522%
4523% A description of each parameter follows.
4524%
4525% o value: Specifies the value to write.
4526%
4527% o file: Specifies the file to write the data to.
4528%
4529*/
4530MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4531{
4532 unsigned char
4533 buffer[2];
4534
4535 assert(image != (Image *) NULL);
4536 assert(image->signature == MagickSignature);
4537 buffer[0]=(unsigned char) (value >> 8);
4538 buffer[1]=(unsigned char) value;
4539 return(WriteBlobStream(image,2,buffer));
4540}
4541
4542/*
4543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4544% %
4545% %
4546% %
4547+ W r i t e B l o b S t r i n g %
4548% %
4549% %
4550% %
4551%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4552%
4553% WriteBlobString() write a string to a blob. It returns the number of
4554% characters written.
4555%
4556% The format of the WriteBlobString method is:
4557%
4558% ssize_t WriteBlobString(Image *image,const char *string)
4559%
4560% A description of each parameter follows.
4561%
4562% o image: the image.
4563%
4564% o string: Specifies the string to write.
4565%
4566*/
4567MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4568{
4569 assert(image != (Image *) NULL);
4570 assert(image->signature == MagickSignature);
4571 assert(string != (const char *) NULL);
4572 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4573}