blob: 1083f0baef1b746c046f07b75bf07977a074fce9 [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 %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 1999 %
18% %
19% %
cristyfe676ee2013-11-18 13:03:38 +000020% Copyright 1999-2014 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"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/client.h"
48#include "MagickCore/constitute.h"
49#include "MagickCore/delegate.h"
50#include "MagickCore/exception.h"
51#include "MagickCore/exception-private.h"
52#include "MagickCore/image-private.h"
53#include "MagickCore/list.h"
54#include "MagickCore/locale_.h"
55#include "MagickCore/log.h"
56#include "MagickCore/magick.h"
57#include "MagickCore/memory_.h"
cristy9f3b4fc2014-02-08 14:56:20 +000058#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000059#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)
cristy3d162a92014-02-16 14:05:06 +0000655 RelinquishSemaphoreInfo(&image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000656 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;
cristyd1f55c12014-01-24 00:40:57 +0000967 if ((file == fileno(stdin)) || (offset < 0) ||
968 (offset != (MagickOffsetType) ((ssize_t) offset)))
cristy3ed852e2009-09-05 21:47:34 +0000969 {
970 size_t
971 quantum;
972
973 struct stat
cristye7b28372012-06-17 13:59:06 +0000974 file_stats;
cristy3ed852e2009-09-05 21:47:34 +0000975
976 /*
977 Stream is not seekable.
978 */
cristyd1561652014-01-24 11:13:48 +0000979 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +0000980 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +0000981 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
982 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +0000983 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +0000984 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
985 for (i=0; blob != (unsigned char *) NULL; i+=count)
986 {
cristy65d11e42013-06-14 20:06:25 +0000987 count=read(file,blob+i,quantum);
cristy3ed852e2009-09-05 21:47:34 +0000988 if (count <= 0)
989 {
990 count=0;
991 if (errno != EINTR)
992 break;
993 }
cristy9c66d8c2012-08-10 11:05:36 +0000994 if (~((size_t) i) < (quantum+1))
cristy3ed852e2009-09-05 21:47:34 +0000995 {
996 blob=(unsigned char *) RelinquishMagickMemory(blob);
997 break;
998 }
999 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1000 sizeof(*blob));
1001 if ((size_t) (i+count) >= extent)
1002 break;
1003 }
cristy54439632010-07-15 00:43:34 +00001004 if (LocaleCompare(filename,"-") != 0)
1005 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001006 if (blob == (unsigned char *) NULL)
1007 {
1008 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001009 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001010 return((unsigned char *) NULL);
1011 }
cristya7cb4312010-06-26 00:47:03 +00001012 if (file == -1)
1013 {
1014 blob=(unsigned char *) RelinquishMagickMemory(blob);
1015 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1016 return((unsigned char *) NULL);
1017 }
cristy7753b2a2011-02-19 18:36:52 +00001018 *length=(size_t) MagickMin(i+count,extent);
cristy3ed852e2009-09-05 21:47:34 +00001019 blob[*length]='\0';
1020 return(blob);
1021 }
cristy7753b2a2011-02-19 18:36:52 +00001022 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
cristy3ed852e2009-09-05 21:47:34 +00001023 blob=(unsigned char *) NULL;
cristy37e0b382011-06-07 13:31:21 +00001024 if (~(*length) >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +00001025 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1026 sizeof(*blob));
1027 if (blob == (unsigned char *) NULL)
1028 {
cristy54439632010-07-15 00:43:34 +00001029 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001030 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001031 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001032 return((unsigned char *) NULL);
1033 }
1034 map=MapBlob(file,ReadMode,0,*length);
1035 if (map != (unsigned char *) NULL)
1036 {
cristy54aad5e2010-09-03 16:02:04 +00001037 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +00001038 (void) UnmapBlob(map,*length);
1039 }
1040 else
1041 {
cristy7f317702011-02-18 20:40:28 +00001042 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001043 for (i=0; i < *length; i+=count)
1044 {
cristy65d11e42013-06-14 20:06:25 +00001045 count=read(file,blob+i,(size_t) MagickMin(*length-i,(MagickSizeType)
1046 SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001047 if (count <= 0)
1048 {
1049 count=0;
1050 if (errno != EINTR)
1051 break;
1052 }
1053 }
1054 if (i < *length)
1055 {
1056 file=close(file)-1;
1057 blob=(unsigned char *) RelinquishMagickMemory(blob);
1058 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1059 return((unsigned char *) NULL);
1060 }
1061 }
cristy3ed852e2009-09-05 21:47:34 +00001062 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001063 if (LocaleCompare(filename,"-") != 0)
1064 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001065 if (file == -1)
1066 {
1067 blob=(unsigned char *) RelinquishMagickMemory(blob);
1068 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1069 }
cristy3ed852e2009-09-05 21:47:34 +00001070 return(blob);
1071}
1072
1073/*
1074%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1075% %
1076% %
1077% %
1078% F i l e T o I m a g e %
1079% %
1080% %
1081% %
1082%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1083%
1084% FileToImage() write the contents of a file to an image.
1085%
1086% The format of the FileToImage method is:
1087%
1088% MagickBooleanType FileToImage(Image *,const char *filename)
1089%
1090% A description of each parameter follows:
1091%
1092% o image: the image.
1093%
1094% o filename: the filename.
1095%
1096*/
1097
1098static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1099 const unsigned char *data)
1100{
1101 MagickSizeType
1102 extent;
1103
1104 register unsigned char
1105 *q;
1106
1107 assert(image->blob != (BlobInfo *) NULL);
1108 if (image->blob->type != BlobStream)
1109 return(WriteBlob(image,length,data));
1110 assert(image->blob->type != UndefinedStream);
1111 assert(data != (void *) NULL);
1112 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1113 if (extent >= image->blob->extent)
1114 {
cristy3ed852e2009-09-05 21:47:34 +00001115 extent=image->blob->extent+image->blob->quantum+length;
cristyff368632014-01-27 13:01:38 +00001116 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00001117 if (SetBlobExtent(image,extent) == MagickFalse)
1118 return(0);
1119 }
1120 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001121 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001122 image->blob->offset+=length;
1123 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1124 image->blob->length=(size_t) image->blob->offset;
1125 return((ssize_t) length);
1126}
1127
cristyc82a27b2011-10-21 01:07:16 +00001128MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1129 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001130{
1131 int
1132 file;
1133
1134 size_t
1135 length,
1136 quantum;
1137
1138 ssize_t
1139 count;
1140
1141 struct stat
cristye7b28372012-06-17 13:59:06 +00001142 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001143
1144 unsigned char
1145 *blob;
1146
1147 assert(image != (const Image *) NULL);
1148 assert(image->signature == MagickSignature);
1149 assert(filename != (const char *) NULL);
1150 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
cristyd45808f2012-12-14 21:30:35 +00001151 file=fileno(stdin);
1152 if (LocaleCompare(filename,"-") != 0)
1153 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001154 if (file == -1)
1155 {
cristyc82a27b2011-10-21 01:07:16 +00001156 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001157 return(MagickFalse);
1158 }
1159 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001160 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1161 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001162 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1163 if (blob == (unsigned char *) NULL)
1164 {
cristyc82a27b2011-10-21 01:07:16 +00001165 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1166 filename);
cristy3ed852e2009-09-05 21:47:34 +00001167 return(MagickFalse);
1168 }
1169 for ( ; ; )
1170 {
cristy65d11e42013-06-14 20:06:25 +00001171 count=read(file,blob,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001172 if (count <= 0)
1173 {
1174 count=0;
1175 if (errno != EINTR)
1176 break;
1177 }
1178 length=(size_t) count;
1179 count=WriteBlobStream(image,length,blob);
1180 if (count != (ssize_t) length)
1181 {
cristyc82a27b2011-10-21 01:07:16 +00001182 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001183 break;
1184 }
1185 }
cristya7cb4312010-06-26 00:47:03 +00001186 file=close(file);
1187 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001188 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001189 blob=(unsigned char *) RelinquishMagickMemory(blob);
1190 return(MagickTrue);
1191}
1192
1193/*
1194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1195% %
1196% %
1197% %
1198+ G e t B l o b E r r o r %
1199% %
1200% %
1201% %
1202%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1203%
1204% GetBlobError() returns MagickTrue if the blob associated with the specified
1205% image encountered an error.
1206%
1207% The format of the GetBlobError method is:
1208%
1209% MagickBooleanType GetBlobError(const Image *image)
1210%
1211% A description of each parameter follows:
1212%
1213% o image: the image.
1214%
1215*/
cristy7832dc22011-09-05 01:21:53 +00001216MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001217{
1218 assert(image != (const Image *) NULL);
1219 assert(image->signature == MagickSignature);
1220 if (image->debug != MagickFalse)
1221 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1222 return(image->blob->status);
1223}
1224
1225/*
1226%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1227% %
1228% %
1229% %
1230+ G e t B l o b F i l e H a n d l e %
1231% %
1232% %
1233% %
1234%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1235%
1236% GetBlobFileHandle() returns the file handle associated with the image blob.
1237%
1238% The format of the GetBlobFile method is:
1239%
1240% FILE *GetBlobFileHandle(const Image *image)
1241%
1242% A description of each parameter follows:
1243%
1244% o image: the image.
1245%
1246*/
1247MagickExport FILE *GetBlobFileHandle(const Image *image)
1248{
1249 assert(image != (const Image *) NULL);
1250 assert(image->signature == MagickSignature);
cristye7b28372012-06-17 13:59:06 +00001251 return(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001252}
1253
1254/*
1255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1256% %
1257% %
1258% %
1259+ G e t B l o b I n f o %
1260% %
1261% %
1262% %
1263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1264%
1265% GetBlobInfo() initializes the BlobInfo structure.
1266%
1267% The format of the GetBlobInfo method is:
1268%
1269% void GetBlobInfo(BlobInfo *blob_info)
1270%
1271% A description of each parameter follows:
1272%
1273% o blob_info: Specifies a pointer to a BlobInfo structure.
1274%
1275*/
cristy7832dc22011-09-05 01:21:53 +00001276MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001277{
1278 assert(blob_info != (BlobInfo *) NULL);
1279 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1280 blob_info->type=UndefinedStream;
1281 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1282 blob_info->properties.st_mtime=time((time_t *) NULL);
1283 blob_info->properties.st_ctime=time((time_t *) NULL);
1284 blob_info->debug=IsEventLogging();
1285 blob_info->reference_count=1;
cristy3d162a92014-02-16 14:05:06 +00001286 blob_info->semaphore=AcquireSemaphoreInfo();
cristy3ed852e2009-09-05 21:47:34 +00001287 blob_info->signature=MagickSignature;
1288}
1289
1290/*
1291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1292% %
1293% %
1294% %
1295% G e t B l o b P r o p e r t i e s %
1296% %
1297% %
1298% %
1299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1300%
1301% GetBlobProperties() returns information about an image blob.
1302%
1303% The format of the GetBlobProperties method is:
1304%
1305% const struct stat *GetBlobProperties(const Image *image)
1306%
1307% A description of each parameter follows:
1308%
1309% o image: the image.
1310%
1311*/
cristy7832dc22011-09-05 01:21:53 +00001312MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001313{
1314 assert(image != (Image *) NULL);
1315 assert(image->signature == MagickSignature);
1316 if (image->debug != MagickFalse)
1317 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1318 return(&image->blob->properties);
1319}
1320
1321/*
1322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1323% %
1324% %
1325% %
1326+ G e t B l o b S i z e %
1327% %
1328% %
1329% %
1330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1331%
1332% GetBlobSize() returns the current length of the image file or blob; zero is
1333% returned if the size cannot be determined.
1334%
1335% The format of the GetBlobSize method is:
1336%
1337% MagickSizeType GetBlobSize(const Image *image)
1338%
1339% A description of each parameter follows:
1340%
1341% o image: the image.
1342%
1343*/
1344MagickExport MagickSizeType GetBlobSize(const Image *image)
1345{
1346 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001347 extent;
cristy3ed852e2009-09-05 21:47:34 +00001348
1349 assert(image != (Image *) NULL);
1350 assert(image->signature == MagickSignature);
1351 if (image->debug != MagickFalse)
1352 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1353 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001354 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001355 switch (image->blob->type)
1356 {
1357 case UndefinedStream:
1358 {
cristy81b8ce52010-02-05 01:53:17 +00001359 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001360 break;
1361 }
cristybc20d112012-07-29 20:27:00 +00001362 case StandardStream:
1363 {
1364 extent=image->blob->size;
1365 break;
1366 }
cristy3ed852e2009-09-05 21:47:34 +00001367 case FileStream:
1368 {
cristye7b28372012-06-17 13:59:06 +00001369 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001370 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001371 break;
1372 }
cristy3ed852e2009-09-05 21:47:34 +00001373 case PipeStream:
1374 {
cristy81b8ce52010-02-05 01:53:17 +00001375 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001376 break;
1377 }
1378 case ZipStream:
1379 case BZipStream:
1380 {
1381 MagickBooleanType
1382 status;
1383
1384 status=GetPathAttributes(image->filename,&image->blob->properties);
1385 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001386 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001387 break;
1388 }
1389 case FifoStream:
1390 break;
1391 case BlobStream:
1392 {
cristy891dc792010-03-04 01:47:16 +00001393 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001394 break;
1395 }
1396 }
cristy81b8ce52010-02-05 01:53:17 +00001397 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001398}
1399
1400/*
1401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1402% %
1403% %
1404% %
1405+ G e t B l o b S t r e a m D a t a %
1406% %
1407% %
1408% %
1409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1410%
1411% GetBlobStreamData() returns the stream data for the image.
1412%
1413% The format of the GetBlobStreamData method is:
1414%
1415% unsigned char *GetBlobStreamData(const Image *image)
1416%
1417% A description of each parameter follows:
1418%
1419% o image: the image.
1420%
1421*/
1422MagickExport unsigned char *GetBlobStreamData(const Image *image)
1423{
1424 assert(image != (const Image *) NULL);
1425 assert(image->signature == MagickSignature);
1426 return(image->blob->data);
1427}
1428
1429/*
1430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1431% %
1432% %
1433% %
1434+ G e t B l o b S t r e a m H a n d l e r %
1435% %
1436% %
1437% %
1438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1439%
1440% GetBlobStreamHandler() returns the stream handler for the image.
1441%
1442% The format of the GetBlobStreamHandler method is:
1443%
1444% StreamHandler GetBlobStreamHandler(const Image *image)
1445%
1446% A description of each parameter follows:
1447%
1448% o image: the image.
1449%
1450*/
cristy7832dc22011-09-05 01:21:53 +00001451MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001452{
1453 assert(image != (const Image *) NULL);
1454 assert(image->signature == MagickSignature);
1455 if (image->debug != MagickFalse)
1456 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1457 return(image->blob->stream);
1458}
1459
1460/*
1461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1462% %
1463% %
1464% %
1465% I m a g e T o B l o b %
1466% %
1467% %
1468% %
1469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1470%
1471% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001472% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001473% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001474% etc.). This method is the equivalent of WriteImage(), but writes the
1475% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001476%
1477% The format of the ImageToBlob method is:
1478%
1479% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1480% size_t *length,ExceptionInfo *exception)
1481%
1482% A description of each parameter follows:
1483%
1484% o image_info: the image info.
1485%
1486% o image: the image.
1487%
cristyd7dc7df2014-01-26 13:52:14 +00001488% o length: return the actual length of the blob.
cristy3ed852e2009-09-05 21:47:34 +00001489%
1490% o exception: return any errors or warnings in this structure.
1491%
1492*/
1493MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1494 Image *image,size_t *length,ExceptionInfo *exception)
1495{
1496 const MagickInfo
1497 *magick_info;
1498
1499 ImageInfo
1500 *blob_info;
1501
1502 MagickBooleanType
1503 status;
1504
1505 unsigned char
1506 *blob;
1507
1508 assert(image_info != (const ImageInfo *) NULL);
1509 assert(image_info->signature == MagickSignature);
1510 if (image_info->debug != MagickFalse)
1511 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1512 image_info->filename);
1513 assert(image != (Image *) NULL);
1514 assert(image->signature == MagickSignature);
1515 assert(exception != (ExceptionInfo *) NULL);
1516 *length=0;
1517 blob=(unsigned char *) NULL;
1518 blob_info=CloneImageInfo(image_info);
1519 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001520 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001521 if (*blob_info->magick != '\0')
1522 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1523 magick_info=GetMagickInfo(image->magick,exception);
1524 if (magick_info == (const MagickInfo *) NULL)
1525 {
1526 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001527 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001528 image->filename);
1529 return(blob);
1530 }
1531 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1532 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1533 {
1534 /*
1535 Native blob support for this image format.
1536 */
cristy5facf772014-01-26 14:42:57 +00001537 blob_info->length=0;
1538 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1539 sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001540 if (blob_info->blob == (void *) NULL)
1541 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001542 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001543 else
1544 {
1545 (void) CloseBlob(image);
1546 image->blob->exempt=MagickTrue;
1547 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001548 status=WriteImage(blob_info,image,exception);
cristy5facf772014-01-26 14:42:57 +00001549 *length=image->blob->length;
cristyc42554f2012-08-22 12:00:43 +00001550 blob=DetachBlob(image->blob);
cristy6e50f9e2012-08-22 16:30:29 +00001551 if (status == MagickFalse)
1552 blob=(unsigned char *) RelinquishMagickMemory(blob);
1553 else
cristy7a7eb372014-01-25 23:09:10 +00001554 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1555 sizeof(*blob));
cristy3ed852e2009-09-05 21:47:34 +00001556 }
1557 }
1558 else
1559 {
1560 char
1561 unique[MaxTextExtent];
1562
1563 int
1564 file;
1565
1566 /*
1567 Write file to disk in blob image format.
1568 */
1569 file=AcquireUniqueFileResource(unique);
1570 if (file == -1)
1571 {
1572 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1573 image_info->filename);
1574 }
1575 else
1576 {
1577 blob_info->file=fdopen(file,"wb");
1578 if (blob_info->file != (FILE *) NULL)
1579 {
cristyb51dff52011-05-19 16:55:47 +00001580 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001581 image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001582 status=WriteImage(blob_info,image,exception);
dirk607010e2014-03-01 19:08:11 +00001583 (void) CloseBlob(image);
1584 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001585 if (status != MagickFalse)
cristy2c1b6e02014-01-26 15:03:02 +00001586 blob=FileToBlob(unique,~0UL,length,exception);
cristy3ed852e2009-09-05 21:47:34 +00001587 }
1588 (void) RelinquishUniqueFileResource(unique);
1589 }
1590 }
1591 blob_info=DestroyImageInfo(blob_info);
1592 return(blob);
1593}
1594
1595/*
1596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1597% %
1598% %
1599% %
1600% I m a g e T o F i l e %
1601% %
1602% %
1603% %
1604%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1605%
1606% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1607% occurs otherwise MagickTrue.
1608%
1609% The format of the ImageToFile method is:
1610%
1611% MagickBooleanType ImageToFile(Image *image,char *filename,
1612% ExceptionInfo *exception)
1613%
1614% A description of each parameter follows:
1615%
1616% o image: the image.
1617%
1618% o filename: Write the image to this file.
1619%
1620% o exception: return any errors or warnings in this structure.
1621%
1622*/
cristy3ed852e2009-09-05 21:47:34 +00001623MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1624 ExceptionInfo *exception)
1625{
1626 int
1627 file;
1628
1629 register const unsigned char
1630 *p;
1631
1632 register size_t
1633 i;
1634
1635 size_t
1636 length,
1637 quantum;
1638
1639 ssize_t
1640 count;
1641
1642 struct stat
cristye7b28372012-06-17 13:59:06 +00001643 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001644
1645 unsigned char
1646 *buffer;
1647
1648 assert(image != (Image *) NULL);
1649 assert(image->signature == MagickSignature);
1650 assert(image->blob != (BlobInfo *) NULL);
1651 assert(image->blob->type != UndefinedStream);
1652 if (image->debug != MagickFalse)
1653 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1654 assert(filename != (const char *) NULL);
1655 if (*filename == '\0')
1656 file=AcquireUniqueFileResource(filename);
1657 else
1658 if (LocaleCompare(filename,"-") == 0)
1659 file=fileno(stdout);
1660 else
cristyb70aab92012-01-31 15:04:04 +00001661 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001662 if (file == -1)
1663 {
1664 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1665 return(MagickFalse);
1666 }
1667 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001668 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1669 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001670 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001671 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1672 if (buffer == (unsigned char *) NULL)
1673 {
1674 file=close(file)-1;
1675 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001676 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001677 return(MagickFalse);
1678 }
1679 length=0;
1680 p=ReadBlobStream(image,quantum,buffer,&count);
1681 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1682 {
1683 length=(size_t) count;
1684 for (i=0; i < length; i+=count)
1685 {
1686 count=write(file,p+i,(size_t) (length-i));
1687 if (count <= 0)
1688 {
1689 count=0;
1690 if (errno != EINTR)
1691 break;
1692 }
1693 }
1694 if (i < length)
1695 break;
1696 }
cristy54439632010-07-15 00:43:34 +00001697 if (LocaleCompare(filename,"-") != 0)
1698 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001699 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001700 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001701 {
1702 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1703 return(MagickFalse);
1704 }
1705 return(MagickTrue);
1706}
1707
1708/*
1709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1710% %
1711% %
1712% %
1713% I m a g e s T o B l o b %
1714% %
1715% %
1716% %
1717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1718%
1719% ImagesToBlob() implements direct to memory image formats. It returns the
1720% image sequence as a blob and its length. The magick member of the ImageInfo
1721% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1722%
1723% Note, some image formats do not permit multiple images to the same image
1724% stream (e.g. JPEG). in this instance, just the first image of the
1725% sequence is returned as a blob.
1726%
1727% The format of the ImagesToBlob method is:
1728%
1729% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1730% size_t *length,ExceptionInfo *exception)
1731%
1732% A description of each parameter follows:
1733%
1734% o image_info: the image info.
1735%
1736% o images: the image list.
1737%
cristybb85d6a2014-01-26 13:51:09 +00001738% o length: return the actual length of the blob.
cristy3ed852e2009-09-05 21:47:34 +00001739%
1740% o exception: return any errors or warnings in this structure.
1741%
1742*/
1743MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1744 Image *images,size_t *length,ExceptionInfo *exception)
1745{
1746 const MagickInfo
1747 *magick_info;
1748
1749 ImageInfo
1750 *blob_info;
1751
1752 MagickBooleanType
1753 status;
1754
1755 unsigned char
1756 *blob;
1757
1758 assert(image_info != (const ImageInfo *) NULL);
1759 assert(image_info->signature == MagickSignature);
1760 if (image_info->debug != MagickFalse)
1761 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1762 image_info->filename);
1763 assert(images != (Image *) NULL);
1764 assert(images->signature == MagickSignature);
1765 assert(exception != (ExceptionInfo *) NULL);
1766 *length=0;
1767 blob=(unsigned char *) NULL;
1768 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001769 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1770 exception);
cristy3ed852e2009-09-05 21:47:34 +00001771 if (*blob_info->magick != '\0')
1772 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00001773 magick_info=GetMagickInfo(images->magick,exception);
1774 if (magick_info == (const MagickInfo *) NULL)
1775 {
1776 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001777 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001778 images->filename);
1779 return(blob);
1780 }
cristy4f1f3e82014-01-26 15:25:52 +00001781 if (GetMagickAdjoin(magick_info) == MagickFalse)
1782 {
1783 blob_info=DestroyImageInfo(blob_info);
1784 return(ImageToBlob(image_info,images,length,exception));
1785 }
cristy3ed852e2009-09-05 21:47:34 +00001786 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1787 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1788 {
1789 /*
1790 Native blob support for this images format.
1791 */
cristy5facf772014-01-26 14:42:57 +00001792 blob_info->length=0;
1793 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1794 sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001795 if (blob_info->blob == (void *) NULL)
1796 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001797 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
cristy3ed852e2009-09-05 21:47:34 +00001798 else
1799 {
cristy7a4b8c52014-01-25 22:48:06 +00001800 (void) CloseBlob(images);
cristy3ed852e2009-09-05 21:47:34 +00001801 images->blob->exempt=MagickTrue;
1802 *images->filename='\0';
1803 status=WriteImages(blob_info,images,images->filename,exception);
cristy5facf772014-01-26 14:42:57 +00001804 *length=images->blob->length;
cristy7a4b8c52014-01-25 22:48:06 +00001805 blob=DetachBlob(images->blob);
1806 if (status == MagickFalse)
1807 blob=(unsigned char *) RelinquishMagickMemory(blob);
1808 else
cristy7a7eb372014-01-25 23:09:10 +00001809 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1810 sizeof(*blob));
cristy3ed852e2009-09-05 21:47:34 +00001811 }
1812 }
1813 else
1814 {
1815 char
1816 filename[MaxTextExtent],
1817 unique[MaxTextExtent];
1818
1819 int
1820 file;
1821
1822 /*
1823 Write file to disk in blob images format.
1824 */
1825 file=AcquireUniqueFileResource(unique);
1826 if (file == -1)
1827 {
1828 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1829 image_info->filename);
1830 }
1831 else
1832 {
1833 blob_info->file=fdopen(file,"wb");
1834 if (blob_info->file != (FILE *) NULL)
1835 {
cristyb51dff52011-05-19 16:55:47 +00001836 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001837 images->magick,unique);
1838 status=WriteImages(blob_info,images,filename,exception);
dirk607010e2014-03-01 19:08:11 +00001839 (void) CloseBlob(images);
cristya94f31b2014-03-01 13:25:42 +00001840 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001841 if (status != MagickFalse)
cristy2c1b6e02014-01-26 15:03:02 +00001842 blob=FileToBlob(unique,~0UL,length,exception);
cristy3ed852e2009-09-05 21:47:34 +00001843 }
1844 (void) RelinquishUniqueFileResource(unique);
1845 }
1846 }
1847 blob_info=DestroyImageInfo(blob_info);
1848 return(blob);
1849}
1850/*
1851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1852% %
1853% %
1854% %
1855% I n j e c t I m a g e B l o b %
1856% %
1857% %
1858% %
1859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1860%
1861% InjectImageBlob() injects the image with a copy of itself in the specified
1862% format (e.g. inject JPEG into a PDF image).
1863%
1864% The format of the InjectImageBlob method is:
1865%
1866% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1867% Image *image,Image *inject_image,const char *format,
1868% ExceptionInfo *exception)
1869%
1870% A description of each parameter follows:
1871%
1872% o image_info: the image info..
1873%
1874% o image: the image.
1875%
1876% o inject_image: inject into the image stream.
1877%
1878% o format: the image format.
1879%
1880% o exception: return any errors or warnings in this structure.
1881%
1882*/
1883MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1884 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1885{
1886 char
1887 filename[MaxTextExtent];
1888
1889 FILE
1890 *unique_file;
1891
1892 Image
1893 *byte_image;
1894
1895 ImageInfo
1896 *write_info;
1897
1898 int
1899 file;
1900
1901 MagickBooleanType
1902 status;
1903
cristybb503372010-05-27 20:51:26 +00001904 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001905 i;
1906
1907 size_t
1908 quantum;
1909
1910 ssize_t
1911 count;
1912
1913 struct stat
cristye7b28372012-06-17 13:59:06 +00001914 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001915
1916 unsigned char
1917 *buffer;
1918
1919 /*
1920 Write inject image to a temporary file.
1921 */
1922 assert(image_info != (ImageInfo *) NULL);
1923 assert(image_info->signature == MagickSignature);
1924 assert(image != (Image *) NULL);
1925 assert(image->signature == MagickSignature);
1926 if (image->debug != MagickFalse)
1927 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1928 assert(inject_image != (Image *) NULL);
1929 assert(inject_image->signature == MagickSignature);
1930 assert(exception != (ExceptionInfo *) NULL);
1931 unique_file=(FILE *) NULL;
1932 file=AcquireUniqueFileResource(filename);
1933 if (file != -1)
1934 unique_file=fdopen(file,"wb");
1935 if ((file == -1) || (unique_file == (FILE *) NULL))
1936 {
1937 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1938 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1939 image->filename);
1940 return(MagickFalse);
1941 }
1942 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1943 if (byte_image == (Image *) NULL)
1944 {
1945 (void) fclose(unique_file);
1946 (void) RelinquishUniqueFileResource(filename);
1947 return(MagickFalse);
1948 }
cristyb51dff52011-05-19 16:55:47 +00001949 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001950 filename);
1951 DestroyBlob(byte_image);
1952 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1953 write_info=CloneImageInfo(image_info);
1954 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001955 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001956 write_info=DestroyImageInfo(write_info);
1957 byte_image=DestroyImage(byte_image);
1958 (void) fclose(unique_file);
1959 if (status == MagickFalse)
1960 {
1961 (void) RelinquishUniqueFileResource(filename);
1962 return(MagickFalse);
1963 }
1964 /*
1965 Inject into image stream.
1966 */
cristy18c6c272011-09-23 14:40:37 +00001967 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001968 if (file == -1)
1969 {
1970 (void) RelinquishUniqueFileResource(filename);
1971 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1972 image_info->filename);
1973 return(MagickFalse);
1974 }
1975 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001976 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1977 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001978 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1979 if (buffer == (unsigned char *) NULL)
1980 {
1981 (void) RelinquishUniqueFileResource(filename);
1982 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1983 image->filename);
1984 }
1985 for (i=0; ; i+=count)
1986 {
cristy65d11e42013-06-14 20:06:25 +00001987 count=read(file,buffer,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001988 if (count <= 0)
1989 {
1990 count=0;
1991 if (errno != EINTR)
1992 break;
1993 }
1994 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1995 MagickFalse;
1996 }
cristya7cb4312010-06-26 00:47:03 +00001997 file=close(file);
1998 if (file == -1)
1999 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00002000 (void) RelinquishUniqueFileResource(filename);
2001 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2002 return(status);
2003}
2004
2005/*
2006%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2007% %
2008% %
2009% %
2010+ I s B l o b E x e m p t %
2011% %
2012% %
2013% %
2014%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2015%
2016% IsBlobExempt() returns true if the blob is exempt.
2017%
2018% The format of the IsBlobExempt method is:
2019%
2020% MagickBooleanType IsBlobExempt(const Image *image)
2021%
2022% A description of each parameter follows:
2023%
2024% o image: the image.
2025%
2026*/
cristy7832dc22011-09-05 01:21:53 +00002027MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002028{
2029 assert(image != (const Image *) NULL);
2030 assert(image->signature == MagickSignature);
2031 if (image->debug != MagickFalse)
2032 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2033 return(image->blob->exempt);
2034}
2035
2036/*
2037%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2038% %
2039% %
2040% %
2041+ I s B l o b S e e k a b l e %
2042% %
2043% %
2044% %
2045%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2046%
2047% IsBlobSeekable() returns true if the blob is seekable.
2048%
2049% The format of the IsBlobSeekable method is:
2050%
2051% MagickBooleanType IsBlobSeekable(const Image *image)
2052%
2053% A description of each parameter follows:
2054%
2055% o image: the image.
2056%
2057*/
cristy7832dc22011-09-05 01:21:53 +00002058MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002059{
2060 MagickBooleanType
2061 seekable;
2062
2063 assert(image != (const Image *) NULL);
2064 assert(image->signature == MagickSignature);
2065 if (image->debug != MagickFalse)
2066 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002067 switch (image->blob->type)
2068 {
2069 case FileStream:
2070 case BlobStream:
2071 case ZipStream:
2072 {
2073 seekable=MagickTrue;
2074 break;
2075 }
2076 default:
2077 {
2078 seekable=MagickFalse;
2079 break;
2080 }
2081 }
cristy3ed852e2009-09-05 21:47:34 +00002082 return(seekable);
2083}
2084
2085/*
2086%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2087% %
2088% %
2089% %
2090+ I s B l o b T e m p o r a r y %
2091% %
2092% %
2093% %
2094%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2095%
2096% IsBlobTemporary() returns true if the blob is temporary.
2097%
2098% The format of the IsBlobTemporary method is:
2099%
2100% MagickBooleanType IsBlobTemporary(const Image *image)
2101%
2102% A description of each parameter follows:
2103%
2104% o image: the image.
2105%
2106*/
cristy7832dc22011-09-05 01:21:53 +00002107MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002108{
2109 assert(image != (const Image *) NULL);
2110 assert(image->signature == MagickSignature);
2111 if (image->debug != MagickFalse)
2112 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2113 return(image->blob->temporary);
2114}
2115
2116/*
2117%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2118% %
2119% %
2120% %
2121+ M a p B l o b %
2122% %
2123% %
2124% %
2125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2126%
2127% MapBlob() creates a mapping from a file to a binary large object.
2128%
2129% The format of the MapBlob method is:
2130%
2131% unsigned char *MapBlob(int file,const MapMode mode,
2132% const MagickOffsetType offset,const size_t length)
2133%
2134% A description of each parameter follows:
2135%
2136% o file: map this file descriptor.
2137%
2138% o mode: ReadMode, WriteMode, or IOMode.
2139%
2140% o offset: starting at this offset within the file.
2141%
2142% o length: the length of the mapping is returned in this pointer.
2143%
2144*/
2145MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2146 const MagickOffsetType offset,const size_t length)
2147{
cristydc8ea8e2013-07-28 20:10:44 +00002148#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00002149 int
2150 flags,
2151 protection;
2152
2153 unsigned char
2154 *map;
2155
2156 /*
2157 Map file.
2158 */
2159 flags=0;
2160 if (file == -1)
2161#if defined(MAP_ANONYMOUS)
2162 flags|=MAP_ANONYMOUS;
2163#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;
cristy3ed852e2009-09-05 21:47:34 +00002173 break;
2174 }
2175 case WriteMode:
2176 {
2177 protection=PROT_WRITE;
2178 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002179 break;
2180 }
2181 case IOMode:
2182 {
2183 protection=PROT_READ | PROT_WRITE;
2184 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002185 break;
2186 }
2187 }
cristy56a0dbe2013-07-09 15:27:09 +00002188#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2189 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2190 (off_t) offset);
2191#else
cristy7a4b8c52014-01-25 22:48:06 +00002192 map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
cristy56a0dbe2013-07-09 15:27:09 +00002193 MAP_HUGETLB,file,(off_t) offset);
2194 if (map == (unsigned char *) MAP_FAILED)
2195 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2196 (off_t) offset);
2197#endif
cristy3ed852e2009-09-05 21:47:34 +00002198 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)
cristycd8b3312013-12-22 01:51:11 +00002458 if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
cristy3ed852e2009-09-05 21:47:34 +00002459 {
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);
cristyff368632014-01-27 13:01:38 +00003649 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00003650 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3651 image->blob->data,image->blob->extent+1,
3652 sizeof(*image->blob->data));
3653 (void) SyncBlob(image);
3654 if (image->blob->data == (unsigned char *) NULL)
3655 {
3656 (void) DetachBlob(image->blob);
3657 return(-1);
3658 }
3659 }
3660 break;
3661 }
3662 }
3663 return(image->blob->offset);
3664}
3665
3666/*
3667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3668% %
3669% %
3670% %
3671+ S e t B l o b E x e m p t %
3672% %
3673% %
3674% %
3675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3676%
3677% SetBlobExempt() sets the blob exempt status.
3678%
3679% The format of the SetBlobExempt method is:
3680%
3681% MagickBooleanType SetBlobExempt(const Image *image,
3682% const MagickBooleanType exempt)
3683%
3684% A description of each parameter follows:
3685%
3686% o image: the image.
3687%
3688% o exempt: Set to true if this blob is exempt from being closed.
3689%
3690*/
cristy7832dc22011-09-05 01:21:53 +00003691MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003692{
3693 assert(image != (const Image *) NULL);
3694 assert(image->signature == MagickSignature);
3695 if (image->debug != MagickFalse)
3696 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3697 image->blob->exempt=exempt;
3698}
3699
3700/*
3701%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3702% %
3703% %
3704% %
3705+ S e t B l o b E x t e n t %
3706% %
3707% %
3708% %
3709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3710%
3711% SetBlobExtent() ensures enough space is allocated for the blob. If the
3712% method is successful, subsequent writes to bytes in the specified range are
3713% guaranteed not to fail.
3714%
3715% The format of the SetBlobExtent method is:
3716%
3717% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3718%
3719% A description of each parameter follows:
3720%
3721% o image: the image.
3722%
3723% o extent: the blob maximum extent.
3724%
3725*/
cristy7832dc22011-09-05 01:21:53 +00003726MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003727 const MagickSizeType extent)
3728{
3729 assert(image != (Image *) NULL);
3730 assert(image->signature == MagickSignature);
3731 if (image->debug != MagickFalse)
3732 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3733 assert(image->blob != (BlobInfo *) NULL);
3734 assert(image->blob->type != UndefinedStream);
3735 switch (image->blob->type)
3736 {
3737 case UndefinedStream:
3738 break;
cristybc20d112012-07-29 20:27:00 +00003739 case StandardStream:
3740 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003741 case FileStream:
3742 {
cristy38e35f42012-12-18 21:12:17 +00003743 MagickOffsetType
3744 offset;
3745
3746 ssize_t
3747 count;
3748
cristy3ed852e2009-09-05 21:47:34 +00003749 if (extent != (MagickSizeType) ((off_t) extent))
3750 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003751 offset=SeekBlob(image,0,SEEK_END);
3752 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003753 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003754 if ((MagickSizeType) offset >= extent)
3755 break;
3756 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003757 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3758 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003759#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3760 if (image->blob->synchronize != MagickFalse)
3761 {
3762 int
3763 status;
3764
3765 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3766 extent-offset);
3767 if (status != 0)
3768 return(MagickFalse);
3769 }
3770#endif
cristy38e35f42012-12-18 21:12:17 +00003771 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003772 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003773 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003774 break;
3775 }
cristy3ed852e2009-09-05 21:47:34 +00003776 case PipeStream:
3777 case ZipStream:
3778 return(MagickFalse);
3779 case BZipStream:
3780 return(MagickFalse);
3781 case FifoStream:
3782 return(MagickFalse);
3783 case BlobStream:
3784 {
cristy38e35f42012-12-18 21:12:17 +00003785 if (extent != (MagickSizeType) ((size_t) extent))
3786 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003787 if (image->blob->mapped != MagickFalse)
3788 {
cristy38e35f42012-12-18 21:12:17 +00003789 MagickOffsetType
3790 offset;
3791
3792 ssize_t
3793 count;
3794
cristy3ed852e2009-09-05 21:47:34 +00003795 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy18aba912013-06-14 19:48:08 +00003796 RelinquishMagickResource(MapResource,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003797 if (extent != (MagickSizeType) ((off_t) extent))
3798 return(MagickFalse);
3799 offset=SeekBlob(image,0,SEEK_END);
3800 if (offset < 0)
3801 return(MagickFalse);
3802 if ((MagickSizeType) offset >= extent)
3803 break;
3804 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003805 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003806 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003807#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3808 if (image->blob->synchronize != MagickFalse)
3809 {
3810 int
3811 status;
3812
3813 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3814 extent-offset);
3815 if (status != 0)
3816 return(MagickFalse);
3817 }
3818#endif
cristy38e35f42012-12-18 21:12:17 +00003819 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003820 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003821 return(MagickFalse);
cristyac1caa22013-06-15 00:41:21 +00003822 (void) AcquireMagickResource(MapResource,extent);
cristy95888612012-04-04 21:56:52 +00003823 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003824 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003825 image->blob->extent=(size_t) extent;
3826 image->blob->length=(size_t) extent;
3827 (void) SyncBlob(image);
3828 break;
cristy3ed852e2009-09-05 21:47:34 +00003829 }
cristy3ed852e2009-09-05 21:47:34 +00003830 image->blob->extent=(size_t) extent;
3831 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3832 image->blob->extent+1,sizeof(*image->blob->data));
3833 (void) SyncBlob(image);
3834 if (image->blob->data == (unsigned char *) NULL)
3835 {
3836 (void) DetachBlob(image->blob);
3837 return(MagickFalse);
3838 }
3839 break;
3840 }
3841 }
3842 return(MagickTrue);
3843}
3844
3845/*
3846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3847% %
3848% %
3849% %
3850+ S y n c B l o b %
3851% %
3852% %
3853% %
3854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3855%
3856% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3857% attributes if it is an blob.
3858%
3859% The format of the SyncBlob method is:
3860%
3861% int SyncBlob(Image *image)
3862%
3863% A description of each parameter follows:
3864%
3865% o image: the image.
3866%
3867*/
3868static int SyncBlob(Image *image)
3869{
3870 int
3871 status;
3872
3873 assert(image != (Image *) NULL);
3874 assert(image->signature == MagickSignature);
3875 if (image->debug != MagickFalse)
3876 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3877 assert(image->blob != (BlobInfo *) NULL);
3878 assert(image->blob->type != UndefinedStream);
3879 status=0;
3880 switch (image->blob->type)
3881 {
3882 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003883 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003884 break;
3885 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003886 case PipeStream:
3887 {
cristye7b28372012-06-17 13:59:06 +00003888 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003889 break;
3890 }
3891 case ZipStream:
3892 {
3893#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003894 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003895#endif
3896 break;
3897 }
3898 case BZipStream:
3899 {
3900#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003901 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003902#endif
3903 break;
3904 }
3905 case FifoStream:
3906 break;
3907 case BlobStream:
cristy3ed852e2009-09-05 21:47:34 +00003908 break;
cristy3ed852e2009-09-05 21:47:34 +00003909 }
3910 return(status);
3911}
3912
3913/*
3914%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3915% %
3916% %
3917% %
3918+ T e l l B l o b %
3919% %
3920% %
3921% %
3922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3923%
3924% TellBlob() obtains the current value of the blob or file position.
3925%
3926% The format of the TellBlob method is:
3927%
3928% MagickOffsetType TellBlob(const Image *image)
3929%
3930% A description of each parameter follows:
3931%
3932% o image: the image.
3933%
3934*/
3935MagickExport MagickOffsetType TellBlob(const Image *image)
3936{
3937 MagickOffsetType
3938 offset;
3939
3940 assert(image != (Image *) NULL);
3941 assert(image->signature == MagickSignature);
3942 if (image->debug != MagickFalse)
3943 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3944 assert(image->blob != (BlobInfo *) NULL);
3945 assert(image->blob->type != UndefinedStream);
3946 offset=(-1);
3947 switch (image->blob->type)
3948 {
3949 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003950 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003951 break;
3952 case FileStream:
3953 {
cristye7b28372012-06-17 13:59:06 +00003954 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003955 break;
3956 }
cristy3ed852e2009-09-05 21:47:34 +00003957 case PipeStream:
3958 break;
3959 case ZipStream:
3960 {
3961#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003962 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003963#endif
3964 break;
3965 }
3966 case BZipStream:
3967 break;
3968 case FifoStream:
3969 break;
3970 case BlobStream:
3971 {
3972 offset=image->blob->offset;
3973 break;
3974 }
3975 }
3976 return(offset);
3977}
3978
3979/*
3980%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3981% %
3982% %
3983% %
3984+ U n m a p B l o b %
3985% %
3986% %
3987% %
3988%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3989%
3990% UnmapBlob() deallocates the binary large object previously allocated with
3991% the MapBlob method.
3992%
3993% The format of the UnmapBlob method is:
3994%
3995% MagickBooleanType UnmapBlob(void *map,const size_t length)
3996%
3997% A description of each parameter follows:
3998%
3999% o map: the address of the binary large object.
4000%
4001% o length: the length of the binary large object.
4002%
4003*/
4004MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4005{
cristydc8ea8e2013-07-28 20:10:44 +00004006#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00004007 int
4008 status;
4009
4010 status=munmap(map,length);
4011 return(status == -1 ? MagickFalse : MagickTrue);
4012#else
4013 (void) map;
4014 (void) length;
4015 return(MagickFalse);
4016#endif
4017}
4018
4019/*
4020%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4021% %
4022% %
4023% %
4024+ W r i t e B l o b %
4025% %
4026% %
4027% %
4028%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4029%
4030% WriteBlob() writes data to a blob or image file. It returns the number of
4031% bytes written.
4032%
4033% The format of the WriteBlob method is:
4034%
4035% ssize_t WriteBlob(Image *image,const size_t length,
4036% const unsigned char *data)
4037%
4038% A description of each parameter follows:
4039%
4040% o image: the image.
4041%
4042% o length: Specifies an integer representing the number of bytes to
4043% write to the file.
4044%
4045% o data: The address of the data to write to the blob or file.
4046%
4047*/
4048MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4049 const unsigned char *data)
4050{
4051 int
4052 c;
4053
4054 register const unsigned char
4055 *p;
4056
4057 ssize_t
4058 count;
4059
4060 assert(image != (Image *) NULL);
4061 assert(image->signature == MagickSignature);
4062 assert(data != (const unsigned char *) NULL);
4063 assert(image->blob != (BlobInfo *) NULL);
4064 assert(image->blob->type != UndefinedStream);
4065 if (length == 0)
4066 return(0);
4067 count=0;
4068 p=data;
4069 switch (image->blob->type)
4070 {
4071 case UndefinedStream:
4072 break;
cristy3ed852e2009-09-05 21:47:34 +00004073 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004074 {
cristy5f3d2752013-01-05 18:53:38 +00004075 count=write(fileno(image->blob->file_info.file),data,length);
cristybc20d112012-07-29 20:27:00 +00004076 break;
4077 }
4078 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004079 case PipeStream:
4080 {
4081 switch (length)
4082 {
4083 default:
4084 {
4085 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004086 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004087 break;
4088 }
4089 case 2:
4090 {
cristye7b28372012-06-17 13:59:06 +00004091 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004092 if (c == EOF)
4093 break;
4094 count++;
4095 }
4096 case 1:
4097 {
cristye7b28372012-06-17 13:59:06 +00004098 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004099 if (c == EOF)
4100 break;
4101 count++;
4102 }
4103 case 0:
4104 break;
4105 }
4106 break;
4107 }
4108 case ZipStream:
4109 {
4110#if defined(MAGICKCORE_ZLIB_DELEGATE)
4111 switch (length)
4112 {
4113 default:
4114 {
cristye7b28372012-06-17 13:59:06 +00004115 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004116 (unsigned int) length);
4117 break;
4118 }
4119 case 2:
4120 {
cristye7b28372012-06-17 13:59:06 +00004121 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004122 if (c == EOF)
4123 break;
4124 count++;
4125 }
4126 case 1:
4127 {
cristye7b28372012-06-17 13:59:06 +00004128 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004129 if (c == EOF)
4130 break;
4131 count++;
4132 }
4133 case 0:
4134 break;
4135 }
4136#endif
4137 break;
4138 }
4139 case BZipStream:
4140 {
4141#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004142 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004143 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004144#endif
4145 break;
4146 }
4147 case FifoStream:
4148 {
4149 count=(ssize_t) image->blob->stream(image,data,length);
4150 break;
4151 }
4152 case BlobStream:
4153 {
4154 register unsigned char
4155 *q;
4156
4157 if ((image->blob->offset+(MagickOffsetType) length) >=
4158 (MagickOffsetType) image->blob->extent)
4159 {
4160 if (image->blob->mapped != MagickFalse)
4161 return(0);
cristy3ed852e2009-09-05 21:47:34 +00004162 image->blob->extent+=length+image->blob->quantum;
cristyff368632014-01-27 13:01:38 +00004163 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00004164 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4165 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4166 (void) SyncBlob(image);
4167 if (image->blob->data == (unsigned char *) NULL)
4168 {
4169 (void) DetachBlob(image->blob);
4170 return(0);
4171 }
4172 }
4173 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004174 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004175 image->blob->offset+=length;
4176 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4177 image->blob->length=(size_t) image->blob->offset;
4178 count=(ssize_t) length;
4179 }
4180 }
4181 return(count);
4182}
4183
4184/*
4185%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4186% %
4187% %
4188% %
4189+ W r i t e B l o b B y t e %
4190% %
4191% %
4192% %
4193%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4194%
4195% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4196% written (either 0 or 1);
4197%
4198% The format of the WriteBlobByte method is:
4199%
4200% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4201%
4202% A description of each parameter follows.
4203%
4204% o image: the image.
4205%
4206% o value: Specifies the value to write.
4207%
4208*/
4209MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4210{
4211 assert(image != (Image *) NULL);
4212 assert(image->signature == MagickSignature);
4213 return(WriteBlobStream(image,1,&value));
4214}
4215
4216/*
4217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4218% %
4219% %
4220% %
4221+ W r i t e B l o b F l o a t %
4222% %
4223% %
4224% %
4225%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4226%
4227% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4228% specified by the endian member of the image structure.
4229%
4230% The format of the WriteBlobFloat method is:
4231%
4232% ssize_t WriteBlobFloat(Image *image,const float value)
4233%
4234% A description of each parameter follows.
4235%
4236% o image: the image.
4237%
4238% o value: Specifies the value to write.
4239%
4240*/
4241MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4242{
4243 union
4244 {
4245 unsigned int
4246 unsigned_value;
4247
4248 float
4249 float_value;
4250 } quantum;
4251
4252 quantum.unsigned_value=0U;
4253 quantum.float_value=value;
4254 return(WriteBlobLong(image,quantum.unsigned_value));
4255}
4256
4257/*
4258%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4259% %
4260% %
4261% %
4262+ W r i t e B l o b L o n g %
4263% %
4264% %
4265% %
4266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4267%
cristybb503372010-05-27 20:51:26 +00004268% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004269% specified by the endian member of the image structure.
4270%
4271% The format of the WriteBlobLong method is:
4272%
4273% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4274%
4275% A description of each parameter follows.
4276%
4277% o image: the image.
4278%
4279% o value: Specifies the value to write.
4280%
4281*/
4282MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4283{
4284 unsigned char
4285 buffer[4];
4286
4287 assert(image != (Image *) NULL);
4288 assert(image->signature == MagickSignature);
4289 if (image->endian == LSBEndian)
4290 {
4291 buffer[0]=(unsigned char) value;
4292 buffer[1]=(unsigned char) (value >> 8);
4293 buffer[2]=(unsigned char) (value >> 16);
4294 buffer[3]=(unsigned char) (value >> 24);
4295 return(WriteBlobStream(image,4,buffer));
4296 }
4297 buffer[0]=(unsigned char) (value >> 24);
4298 buffer[1]=(unsigned char) (value >> 16);
4299 buffer[2]=(unsigned char) (value >> 8);
4300 buffer[3]=(unsigned char) value;
4301 return(WriteBlobStream(image,4,buffer));
4302}
4303
4304/*
4305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4306% %
4307% %
4308% %
4309+ W r i t e B l o b S h o r t %
4310% %
4311% %
4312% %
4313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4314%
4315% WriteBlobShort() writes a short value as a 16-bit quantity in the
4316% byte-order specified by the endian member of the image structure.
4317%
4318% The format of the WriteBlobShort method is:
4319%
4320% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4321%
4322% A description of each parameter follows.
4323%
4324% o image: the image.
4325%
4326% o value: Specifies the value to write.
4327%
4328*/
4329MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4330{
4331 unsigned char
4332 buffer[2];
4333
4334 assert(image != (Image *) NULL);
4335 assert(image->signature == MagickSignature);
4336 if (image->endian == LSBEndian)
4337 {
4338 buffer[0]=(unsigned char) value;
4339 buffer[1]=(unsigned char) (value >> 8);
4340 return(WriteBlobStream(image,2,buffer));
4341 }
4342 buffer[0]=(unsigned char) (value >> 8);
4343 buffer[1]=(unsigned char) value;
4344 return(WriteBlobStream(image,2,buffer));
4345}
4346
4347/*
4348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4349% %
4350% %
4351% %
4352+ W r i t e B l o b L S B L o n g %
4353% %
4354% %
4355% %
4356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4357%
cristybb503372010-05-27 20:51:26 +00004358% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004359% least-significant byte first order.
4360%
4361% The format of the WriteBlobLSBLong method is:
4362%
4363% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4364%
4365% A description of each parameter follows.
4366%
4367% o image: the image.
4368%
4369% o value: Specifies the value to write.
4370%
4371*/
4372MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4373{
4374 unsigned char
4375 buffer[4];
4376
4377 assert(image != (Image *) NULL);
4378 assert(image->signature == MagickSignature);
4379 buffer[0]=(unsigned char) value;
4380 buffer[1]=(unsigned char) (value >> 8);
4381 buffer[2]=(unsigned char) (value >> 16);
4382 buffer[3]=(unsigned char) (value >> 24);
4383 return(WriteBlobStream(image,4,buffer));
4384}
4385
4386/*
4387%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4388% %
4389% %
4390% %
4391+ W r i t e B l o b L S B S h o r t %
4392% %
4393% %
4394% %
4395%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4396%
cristybb503372010-05-27 20:51:26 +00004397% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004398% least-significant byte first order.
4399%
4400% The format of the WriteBlobLSBShort method is:
4401%
4402% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4403%
4404% A description of each parameter follows.
4405%
4406% o image: the image.
4407%
4408% o value: Specifies the value to write.
4409%
4410*/
4411MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4412{
4413 unsigned char
4414 buffer[2];
4415
4416 assert(image != (Image *) NULL);
4417 assert(image->signature == MagickSignature);
4418 buffer[0]=(unsigned char) value;
4419 buffer[1]=(unsigned char) (value >> 8);
4420 return(WriteBlobStream(image,2,buffer));
4421}
4422
4423/*
4424%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4425% %
4426% %
4427% %
4428+ W r i t e B l o b M S B L o n g %
4429% %
4430% %
4431% %
4432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4433%
cristybb503372010-05-27 20:51:26 +00004434% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004435% most-significant byte first order.
4436%
4437% The format of the WriteBlobMSBLong method is:
4438%
4439% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4440%
4441% A description of each parameter follows.
4442%
4443% o value: Specifies the value to write.
4444%
4445% o image: the image.
4446%
4447*/
4448MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4449{
4450 unsigned char
4451 buffer[4];
4452
4453 assert(image != (Image *) NULL);
4454 assert(image->signature == MagickSignature);
4455 buffer[0]=(unsigned char) (value >> 24);
4456 buffer[1]=(unsigned char) (value >> 16);
4457 buffer[2]=(unsigned char) (value >> 8);
4458 buffer[3]=(unsigned char) value;
4459 return(WriteBlobStream(image,4,buffer));
4460}
4461
4462/*
4463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4464% %
4465% %
4466% %
cristy2ca49922010-03-06 02:54:01 +00004467+ W r i t e B l o b M S B L o n g L o n g %
4468% %
4469% %
4470% %
4471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4472%
4473% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4474% most-significant byte first order.
4475%
4476% The format of the WriteBlobMSBLongLong method is:
4477%
4478% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4479%
4480% A description of each parameter follows.
4481%
4482% o value: Specifies the value to write.
4483%
4484% o image: the image.
4485%
4486*/
4487MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4488 const MagickSizeType value)
4489{
4490 unsigned char
4491 buffer[8];
4492
4493 assert(image != (Image *) NULL);
4494 assert(image->signature == MagickSignature);
4495 buffer[0]=(unsigned char) (value >> 56);
4496 buffer[1]=(unsigned char) (value >> 48);
4497 buffer[2]=(unsigned char) (value >> 40);
4498 buffer[3]=(unsigned char) (value >> 32);
4499 buffer[4]=(unsigned char) (value >> 24);
4500 buffer[5]=(unsigned char) (value >> 16);
4501 buffer[6]=(unsigned char) (value >> 8);
4502 buffer[7]=(unsigned char) value;
4503 return(WriteBlobStream(image,8,buffer));
4504}
4505
4506/*
4507%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4508% %
4509% %
4510% %
cristy3ed852e2009-09-05 21:47:34 +00004511+ W r i t e B l o b M S B S h o r t %
4512% %
4513% %
4514% %
4515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4516%
cristybb503372010-05-27 20:51:26 +00004517% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004518% most-significant byte first order.
4519%
4520% The format of the WriteBlobMSBShort method is:
4521%
4522% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4523%
4524% A description of each parameter follows.
4525%
4526% o value: Specifies the value to write.
4527%
4528% o file: Specifies the file to write the data to.
4529%
4530*/
4531MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4532{
4533 unsigned char
4534 buffer[2];
4535
4536 assert(image != (Image *) NULL);
4537 assert(image->signature == MagickSignature);
4538 buffer[0]=(unsigned char) (value >> 8);
4539 buffer[1]=(unsigned char) value;
4540 return(WriteBlobStream(image,2,buffer));
4541}
4542
4543/*
4544%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4545% %
4546% %
4547% %
4548+ W r i t e B l o b S t r i n g %
4549% %
4550% %
4551% %
4552%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4553%
4554% WriteBlobString() write a string to a blob. It returns the number of
4555% characters written.
4556%
4557% The format of the WriteBlobString method is:
4558%
4559% ssize_t WriteBlobString(Image *image,const char *string)
4560%
4561% A description of each parameter follows.
4562%
4563% o image: the image.
4564%
4565% o string: Specifies the string to write.
4566%
4567*/
4568MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4569{
4570 assert(image != (Image *) NULL);
4571 assert(image->signature == MagickSignature);
4572 assert(string != (const char *) NULL);
4573 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4574}