blob: cbcae1bd5063ffeb1e453b86999f59a78472d9ef [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 {
cristy3ed852e2009-09-05 21:47:34 +0000358 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +0000359 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +0000360 blob_info->magick);
361 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +0000362 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 /*
dirk7fcec532014-04-24 18:52:40 +0000402 Restore original filenames and image format.
cristy540a22c2012-06-10 15:22:16 +0000403 */
404 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
405 {
dirk7fcec532014-04-24 18:52:40 +0000406 (void) CopyMagickString(images->filename,image_info->filename,
407 MaxTextExtent);
408 (void) CopyMagickString(images->magick_filename,image_info->filename,
409 MaxTextExtent);
410 (void) CopyMagickString(images->magick,magick_info->name,
411 MaxTextExtent);
cristy540a22c2012-06-10 15:22:16 +0000412 images=GetNextImageInList(images);
413 }
414 }
cristy3ed852e2009-09-05 21:47:34 +0000415 clone_info=DestroyImageInfo(clone_info);
416 (void) RelinquishUniqueFileResource(blob_info->filename);
417 blob_info=DestroyImageInfo(blob_info);
418 return(image);
419}
420
421/*
422%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423% %
424% %
425% %
426+ C l o n e B l o b I n f o %
427% %
428% %
429% %
430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431%
432% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
433% blob info is NULL, a new one.
434%
435% The format of the CloneBlobInfo method is:
436%
437% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
438%
439% A description of each parameter follows:
440%
441% o blob_info: the blob info.
442%
443*/
444MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
445{
446 BlobInfo
447 *clone_info;
448
cristy73bd4a52010-10-05 11:24:23 +0000449 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
cristy3ed852e2009-09-05 21:47:34 +0000450 if (clone_info == (BlobInfo *) NULL)
451 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
452 GetBlobInfo(clone_info);
453 if (blob_info == (BlobInfo *) NULL)
454 return(clone_info);
455 clone_info->length=blob_info->length;
456 clone_info->extent=blob_info->extent;
457 clone_info->synchronize=blob_info->synchronize;
458 clone_info->quantum=blob_info->quantum;
459 clone_info->mapped=blob_info->mapped;
460 clone_info->eof=blob_info->eof;
461 clone_info->offset=blob_info->offset;
462 clone_info->size=blob_info->size;
463 clone_info->exempt=blob_info->exempt;
464 clone_info->status=blob_info->status;
465 clone_info->temporary=blob_info->temporary;
466 clone_info->type=blob_info->type;
cristye7b28372012-06-17 13:59:06 +0000467 clone_info->file_info.file=blob_info->file_info.file;
cristy3ed852e2009-09-05 21:47:34 +0000468 clone_info->properties=blob_info->properties;
469 clone_info->stream=blob_info->stream;
470 clone_info->data=blob_info->data;
471 clone_info->debug=IsEventLogging();
472 clone_info->reference_count=1;
473 return(clone_info);
474}
475
476/*
477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
478% %
479% %
480% %
481+ C l o s e B l o b %
482% %
483% %
484% %
485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486%
487% CloseBlob() closes a stream associated with the image.
488%
489% The format of the CloseBlob method is:
490%
491% MagickBooleanType CloseBlob(Image *image)
492%
493% A description of each parameter follows:
494%
495% o image: the image.
496%
497*/
498MagickExport MagickBooleanType CloseBlob(Image *image)
499{
500 int
501 status;
502
503 /*
504 Close image file.
505 */
506 assert(image != (Image *) NULL);
507 assert(image->signature == MagickSignature);
508 if (image->debug != MagickFalse)
509 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
510 assert(image->blob != (BlobInfo *) NULL);
511 if (image->blob->type == UndefinedStream)
512 return(MagickTrue);
cristy7e2a7c72012-12-27 00:56:47 +0000513 status=SyncBlob(image);
cristy3ed852e2009-09-05 21:47:34 +0000514 switch (image->blob->type)
515 {
516 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000517 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000518 break;
519 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000520 case PipeStream:
521 {
cristy02ce8cc2012-12-27 00:35:49 +0000522 if (image->blob->synchronize != MagickFalse)
523 status=fsync(fileno(image->blob->file_info.file));
cristye7b28372012-06-17 13:59:06 +0000524 status=ferror(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000525 break;
526 }
527 case ZipStream:
528 {
529#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000530 (void) gzerror(image->blob->file_info.gzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000531#endif
532 break;
533 }
534 case BZipStream:
535 {
536#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000537 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000538#endif
539 break;
540 }
541 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000542 break;
cristy02ce8cc2012-12-27 00:35:49 +0000543 case BlobStream:
544 {
545 if ((image->blob->file_info.file != (FILE *) NULL) &&
546 (image->blob->synchronize != MagickFalse))
cristy5678acd2012-12-27 00:41:55 +0000547 {
548 (void) fsync(fileno(image->blob->file_info.file));
549 status=ferror(image->blob->file_info.file);
550 }
cristy02ce8cc2012-12-27 00:35:49 +0000551 break;
552 }
cristy3ed852e2009-09-05 21:47:34 +0000553 }
554 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
cristycd9e6322012-12-27 00:29:00 +0000555 image->blob->size=GetBlobSize(image);
556 image->extent=image->blob->size;
557 image->blob->eof=MagickFalse;
cristybae22e42012-12-27 00:25:59 +0000558 if (image->blob->exempt != MagickFalse)
559 {
560 image->blob->type=UndefinedStream;
561 return(image->blob->status);
562 }
cristy3ed852e2009-09-05 21:47:34 +0000563 switch (image->blob->type)
564 {
565 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000566 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000567 break;
568 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000569 {
cristye7b28372012-06-17 13:59:06 +0000570 status=fclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000571 break;
572 }
573 case PipeStream:
574 {
575#if defined(MAGICKCORE_HAVE_PCLOSE)
cristye7b28372012-06-17 13:59:06 +0000576 status=pclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000577#endif
578 break;
579 }
580 case ZipStream:
581 {
582#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000583 status=gzclose(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +0000584#endif
585 break;
586 }
587 case BZipStream:
588 {
589#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000590 BZ2_bzclose(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +0000591#endif
592 break;
593 }
594 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000595 break;
cristyff483372010-10-16 17:00:58 +0000596 case BlobStream:
597 {
cristye7b28372012-06-17 13:59:06 +0000598 if (image->blob->file_info.file != (FILE *) NULL)
cristy02ce8cc2012-12-27 00:35:49 +0000599 status=fclose(image->blob->file_info.file);
cristyff483372010-10-16 17:00:58 +0000600 break;
601 }
cristy3ed852e2009-09-05 21:47:34 +0000602 }
603 (void) DetachBlob(image->blob);
604 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
605 return(image->blob->status);
606}
607
608/*
609%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610% %
611% %
612% %
613+ D e s t r o y B l o b %
614% %
615% %
616% %
617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
618%
619% DestroyBlob() deallocates memory associated with a blob.
620%
621% The format of the DestroyBlob method is:
622%
623% void DestroyBlob(Image *image)
624%
625% A description of each parameter follows:
626%
627% o image: the image.
628%
629*/
630MagickExport void DestroyBlob(Image *image)
631{
632 MagickBooleanType
633 destroy;
634
635 assert(image != (Image *) NULL);
636 assert(image->signature == MagickSignature);
637 if (image->debug != MagickFalse)
638 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
639 assert(image->blob != (BlobInfo *) NULL);
640 assert(image->blob->signature == MagickSignature);
641 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000642 LockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000643 image->blob->reference_count--;
644 assert(image->blob->reference_count >= 0);
645 if (image->blob->reference_count == 0)
646 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000647 UnlockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000648 if (destroy == MagickFalse)
649 return;
650 (void) CloseBlob(image);
651 if (image->blob->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000652 {
653 (void) UnmapBlob(image->blob->data,image->blob->length);
654 RelinquishMagickResource(MapResource,image->blob->length);
655 }
cristy3ed852e2009-09-05 21:47:34 +0000656 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
cristy3d162a92014-02-16 14:05:06 +0000657 RelinquishSemaphoreInfo(&image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000658 image->blob->signature=(~MagickSignature);
659 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
660}
661
662/*
663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
664% %
665% %
666% %
667+ D e t a c h B l o b %
668% %
669% %
670% %
671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
672%
673% DetachBlob() detaches a blob from the BlobInfo structure.
674%
675% The format of the DetachBlob method is:
676%
677% unsigned char *DetachBlob(BlobInfo *blob_info)
678%
679% A description of each parameter follows:
680%
681% o blob_info: Specifies a pointer to a BlobInfo structure.
682%
683*/
684MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
685{
686 unsigned char
687 *data;
688
689 assert(blob_info != (BlobInfo *) NULL);
690 if (blob_info->debug != MagickFalse)
691 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
692 if (blob_info->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000693 {
694 (void) UnmapBlob(blob_info->data,blob_info->length);
cristy100a0562014-04-18 01:27:37 +0000695 blob_info->data=(unsigned char *) NULL;
cristy18aba912013-06-14 19:48:08 +0000696 RelinquishMagickResource(MapResource,blob_info->length);
697 }
cristy3ed852e2009-09-05 21:47:34 +0000698 blob_info->mapped=MagickFalse;
699 blob_info->length=0;
700 blob_info->offset=0;
701 blob_info->eof=MagickFalse;
702 blob_info->exempt=MagickFalse;
703 blob_info->type=UndefinedStream;
cristye7b28372012-06-17 13:59:06 +0000704 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000705 data=blob_info->data;
706 blob_info->data=(unsigned char *) NULL;
707 blob_info->stream=(StreamHandler) NULL;
708 return(data);
709}
710
711/*
712%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
713% %
714% %
715% %
cristyc1af14f2010-09-16 20:01:21 +0000716+ D i s c a r d B l o b B y t e s %
717% %
718% %
719% %
720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721%
722% DiscardBlobBytes() discards bytes in a blob.
723%
724% The format of the DiscardBlobBytes method is:
725%
726% MagickBooleanType DiscardBlobBytes(Image *image,const size_t length)
727%
728% A description of each parameter follows.
729%
730% o image: the image.
731%
732% o length: the number of bytes to skip.
733%
734*/
735
736static inline const unsigned char *ReadBlobStream(Image *image,
737 const size_t length,unsigned char *data,ssize_t *count)
738{
739 assert(count != (ssize_t *) NULL);
740 assert(image->blob != (BlobInfo *) NULL);
741 if (image->blob->type != BlobStream)
742 {
743 *count=ReadBlob(image,length,data);
744 return(data);
745 }
746 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
747 {
748 *count=0;
749 image->blob->eof=MagickTrue;
750 return(data);
751 }
752 data=image->blob->data+image->blob->offset;
cristy7753b2a2011-02-19 18:36:52 +0000753 *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
cristyc1af14f2010-09-16 20:01:21 +0000754 image->blob->offset));
755 image->blob->offset+=(*count);
756 if (*count != (ssize_t) length)
757 image->blob->eof=MagickTrue;
758 return(data);
759}
760
761MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
cristy7753b2a2011-02-19 18:36:52 +0000762 const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000763{
cristy7753b2a2011-02-19 18:36:52 +0000764 register MagickOffsetType
cristyc1af14f2010-09-16 20:01:21 +0000765 i;
766
767 size_t
768 quantum;
769
770 ssize_t
771 count;
772
773 unsigned char
cristyf55846d2010-09-17 19:01:10 +0000774 buffer[16384];
cristyc1af14f2010-09-16 20:01:21 +0000775
776 assert(image != (Image *) NULL);
777 assert(image->signature == MagickSignature);
778 count=0;
cristy7753b2a2011-02-19 18:36:52 +0000779 for (i=0; i < (MagickOffsetType) length; i+=count)
cristyc1af14f2010-09-16 20:01:21 +0000780 {
cristy7753b2a2011-02-19 18:36:52 +0000781 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
cristyc1af14f2010-09-16 20:01:21 +0000782 (void) ReadBlobStream(image,quantum,buffer,&count);
783 if (count <= 0)
784 {
785 count=0;
786 if (errno != EINTR)
787 break;
788 }
789 }
cristy7753b2a2011-02-19 18:36:52 +0000790 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
cristyc1af14f2010-09-16 20:01:21 +0000791}
792
793/*
794%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795% %
796% %
797% %
cristy3ed852e2009-09-05 21:47:34 +0000798+ D u p l i c a t e s B l o b %
799% %
800% %
801% %
802%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
803%
804% DuplicateBlob() duplicates a blob descriptor.
805%
806% The format of the DuplicateBlob method is:
807%
808% void DuplicateBlob(Image *image,const Image *duplicate)
809%
810% A description of each parameter follows:
811%
812% o image: the image.
813%
814% o duplicate: the duplicate image.
815%
816*/
817MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
818{
819 assert(image != (Image *) NULL);
820 assert(image->signature == MagickSignature);
821 if (image->debug != MagickFalse)
822 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
823 assert(duplicate != (Image *) NULL);
824 assert(duplicate->signature == MagickSignature);
825 DestroyBlob(image);
826 image->blob=ReferenceBlob(duplicate->blob);
827}
828
829/*
830%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
831% %
832% %
833% %
834+ E O F B l o b %
835% %
836% %
837% %
838%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
839%
840% EOFBlob() returns a non-zero value when EOF has been detected reading from
841% a blob or file.
842%
843% The format of the EOFBlob method is:
844%
845% int EOFBlob(const Image *image)
846%
847% A description of each parameter follows:
848%
849% o image: the image.
850%
851*/
852MagickExport int EOFBlob(const Image *image)
853{
854 assert(image != (Image *) NULL);
855 assert(image->signature == MagickSignature);
856 if (image->debug != MagickFalse)
857 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
858 assert(image->blob != (BlobInfo *) NULL);
859 assert(image->blob->type != UndefinedStream);
860 switch (image->blob->type)
861 {
862 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000863 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000864 break;
865 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000866 case PipeStream:
867 {
cristye7b28372012-06-17 13:59:06 +0000868 image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
cristy95888612012-04-04 21:56:52 +0000869 MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000870 break;
871 }
872 case ZipStream:
873 {
874 image->blob->eof=MagickFalse;
875 break;
876 }
877 case BZipStream:
878 {
879#if defined(MAGICKCORE_BZLIB_DELEGATE)
880 int
881 status;
882
883 status=0;
cristye7b28372012-06-17 13:59:06 +0000884 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000885 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
886#endif
887 break;
888 }
889 case FifoStream:
890 {
891 image->blob->eof=MagickFalse;
892 break;
893 }
894 case BlobStream:
895 break;
896 }
897 return((int) image->blob->eof);
898}
899
900/*
901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902% %
903% %
904% %
905+ F i l e T o B l o b %
906% %
907% %
908% %
909%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
910%
cristy178edaf2011-01-23 03:42:39 +0000911% FileToBlob() returns the contents of a file as a buffer terminated with
912% the '\0' character. The length of the buffer (not including the extra
913% terminating '\0' character) is returned via the 'length' parameter. Free
914% the buffer with RelinquishMagickMemory().
cristy3ed852e2009-09-05 21:47:34 +0000915%
916% The format of the FileToBlob method is:
917%
918% unsigned char *FileToBlob(const char *filename,const size_t extent,
919% size_t *length,ExceptionInfo *exception)
920%
921% A description of each parameter follows:
922%
923% o blob: FileToBlob() returns the contents of a file as a blob. If
924% an error occurs NULL is returned.
925%
926% o filename: the filename.
927%
928% o extent: The maximum length of the blob.
929%
930% o length: On return, this reflects the actual length of the blob.
931%
932% o exception: return any errors or warnings in this structure.
933%
934*/
935MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
936 size_t *length,ExceptionInfo *exception)
937{
938 int
939 file;
940
941 MagickOffsetType
942 offset;
943
944 register size_t
945 i;
946
947 ssize_t
948 count;
949
950 unsigned char
951 *blob;
952
953 void
954 *map;
955
956 assert(filename != (const char *) NULL);
957 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
958 assert(exception != (ExceptionInfo *) NULL);
959 *length=0;
960 file=fileno(stdin);
961 if (LocaleCompare(filename,"-") != 0)
cristy18c6c272011-09-23 14:40:37 +0000962 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +0000963 if (file == -1)
964 {
965 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
966 return((unsigned char *) NULL);
967 }
cristy7f317702011-02-18 20:40:28 +0000968 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
cristy3ed852e2009-09-05 21:47:34 +0000969 count=0;
cristyd1f55c12014-01-24 00:40:57 +0000970 if ((file == fileno(stdin)) || (offset < 0) ||
971 (offset != (MagickOffsetType) ((ssize_t) offset)))
cristy3ed852e2009-09-05 21:47:34 +0000972 {
973 size_t
974 quantum;
975
976 struct stat
cristye7b28372012-06-17 13:59:06 +0000977 file_stats;
cristy3ed852e2009-09-05 21:47:34 +0000978
979 /*
980 Stream is not seekable.
981 */
cristyd1561652014-01-24 11:13:48 +0000982 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +0000983 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +0000984 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
985 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +0000986 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +0000987 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
988 for (i=0; blob != (unsigned char *) NULL; i+=count)
989 {
cristy65d11e42013-06-14 20:06:25 +0000990 count=read(file,blob+i,quantum);
cristy3ed852e2009-09-05 21:47:34 +0000991 if (count <= 0)
992 {
993 count=0;
994 if (errno != EINTR)
995 break;
996 }
cristy9c66d8c2012-08-10 11:05:36 +0000997 if (~((size_t) i) < (quantum+1))
cristy3ed852e2009-09-05 21:47:34 +0000998 {
999 blob=(unsigned char *) RelinquishMagickMemory(blob);
1000 break;
1001 }
1002 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1003 sizeof(*blob));
1004 if ((size_t) (i+count) >= extent)
1005 break;
1006 }
cristy54439632010-07-15 00:43:34 +00001007 if (LocaleCompare(filename,"-") != 0)
1008 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001009 if (blob == (unsigned char *) NULL)
1010 {
1011 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001012 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001013 return((unsigned char *) NULL);
1014 }
cristya7cb4312010-06-26 00:47:03 +00001015 if (file == -1)
1016 {
1017 blob=(unsigned char *) RelinquishMagickMemory(blob);
1018 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1019 return((unsigned char *) NULL);
1020 }
cristy7753b2a2011-02-19 18:36:52 +00001021 *length=(size_t) MagickMin(i+count,extent);
cristy3ed852e2009-09-05 21:47:34 +00001022 blob[*length]='\0';
1023 return(blob);
1024 }
cristy7753b2a2011-02-19 18:36:52 +00001025 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
cristy3ed852e2009-09-05 21:47:34 +00001026 blob=(unsigned char *) NULL;
cristy37e0b382011-06-07 13:31:21 +00001027 if (~(*length) >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +00001028 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1029 sizeof(*blob));
1030 if (blob == (unsigned char *) NULL)
1031 {
cristy54439632010-07-15 00:43:34 +00001032 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001033 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001034 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001035 return((unsigned char *) NULL);
1036 }
1037 map=MapBlob(file,ReadMode,0,*length);
1038 if (map != (unsigned char *) NULL)
1039 {
cristy54aad5e2010-09-03 16:02:04 +00001040 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +00001041 (void) UnmapBlob(map,*length);
1042 }
1043 else
1044 {
cristy7f317702011-02-18 20:40:28 +00001045 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001046 for (i=0; i < *length; i+=count)
1047 {
cristy65d11e42013-06-14 20:06:25 +00001048 count=read(file,blob+i,(size_t) MagickMin(*length-i,(MagickSizeType)
1049 SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001050 if (count <= 0)
1051 {
1052 count=0;
1053 if (errno != EINTR)
1054 break;
1055 }
1056 }
1057 if (i < *length)
1058 {
1059 file=close(file)-1;
1060 blob=(unsigned char *) RelinquishMagickMemory(blob);
1061 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1062 return((unsigned char *) NULL);
1063 }
1064 }
cristy3ed852e2009-09-05 21:47:34 +00001065 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001066 if (LocaleCompare(filename,"-") != 0)
1067 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001068 if (file == -1)
1069 {
1070 blob=(unsigned char *) RelinquishMagickMemory(blob);
1071 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1072 }
cristy3ed852e2009-09-05 21:47:34 +00001073 return(blob);
1074}
1075
1076/*
1077%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1078% %
1079% %
1080% %
1081% F i l e T o I m a g e %
1082% %
1083% %
1084% %
1085%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1086%
1087% FileToImage() write the contents of a file to an image.
1088%
1089% The format of the FileToImage method is:
1090%
1091% MagickBooleanType FileToImage(Image *,const char *filename)
1092%
1093% A description of each parameter follows:
1094%
1095% o image: the image.
1096%
1097% o filename: the filename.
1098%
1099*/
1100
1101static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1102 const unsigned char *data)
1103{
1104 MagickSizeType
1105 extent;
1106
1107 register unsigned char
1108 *q;
1109
1110 assert(image->blob != (BlobInfo *) NULL);
1111 if (image->blob->type != BlobStream)
1112 return(WriteBlob(image,length,data));
1113 assert(image->blob->type != UndefinedStream);
1114 assert(data != (void *) NULL);
1115 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1116 if (extent >= image->blob->extent)
1117 {
cristy3ed852e2009-09-05 21:47:34 +00001118 extent=image->blob->extent+image->blob->quantum+length;
cristyff368632014-01-27 13:01:38 +00001119 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00001120 if (SetBlobExtent(image,extent) == MagickFalse)
1121 return(0);
1122 }
1123 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001124 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001125 image->blob->offset+=length;
1126 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1127 image->blob->length=(size_t) image->blob->offset;
1128 return((ssize_t) length);
1129}
1130
cristyc82a27b2011-10-21 01:07:16 +00001131MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1132 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001133{
1134 int
1135 file;
1136
1137 size_t
1138 length,
1139 quantum;
1140
1141 ssize_t
1142 count;
1143
1144 struct stat
cristye7b28372012-06-17 13:59:06 +00001145 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001146
1147 unsigned char
1148 *blob;
1149
1150 assert(image != (const Image *) NULL);
1151 assert(image->signature == MagickSignature);
1152 assert(filename != (const char *) NULL);
1153 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
cristyd45808f2012-12-14 21:30:35 +00001154 file=fileno(stdin);
1155 if (LocaleCompare(filename,"-") != 0)
1156 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001157 if (file == -1)
1158 {
cristyc82a27b2011-10-21 01:07:16 +00001159 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001160 return(MagickFalse);
1161 }
1162 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001163 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1164 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001165 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1166 if (blob == (unsigned char *) NULL)
1167 {
cristy100a0562014-04-18 01:27:37 +00001168 file=close(file);
cristyc82a27b2011-10-21 01:07:16 +00001169 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1170 filename);
cristy3ed852e2009-09-05 21:47:34 +00001171 return(MagickFalse);
1172 }
1173 for ( ; ; )
1174 {
cristy65d11e42013-06-14 20:06:25 +00001175 count=read(file,blob,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001176 if (count <= 0)
1177 {
1178 count=0;
1179 if (errno != EINTR)
1180 break;
1181 }
1182 length=(size_t) count;
1183 count=WriteBlobStream(image,length,blob);
1184 if (count != (ssize_t) length)
1185 {
cristyc82a27b2011-10-21 01:07:16 +00001186 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001187 break;
1188 }
1189 }
cristya7cb4312010-06-26 00:47:03 +00001190 file=close(file);
1191 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001192 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001193 blob=(unsigned char *) RelinquishMagickMemory(blob);
1194 return(MagickTrue);
1195}
1196
1197/*
1198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1199% %
1200% %
1201% %
1202+ G e t B l o b E r r o r %
1203% %
1204% %
1205% %
1206%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1207%
1208% GetBlobError() returns MagickTrue if the blob associated with the specified
1209% image encountered an error.
1210%
1211% The format of the GetBlobError method is:
1212%
1213% MagickBooleanType GetBlobError(const Image *image)
1214%
1215% A description of each parameter follows:
1216%
1217% o image: the image.
1218%
1219*/
cristy7832dc22011-09-05 01:21:53 +00001220MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001221{
1222 assert(image != (const Image *) NULL);
1223 assert(image->signature == MagickSignature);
1224 if (image->debug != MagickFalse)
1225 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1226 return(image->blob->status);
1227}
1228
1229/*
1230%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1231% %
1232% %
1233% %
1234+ G e t B l o b F i l e H a n d l e %
1235% %
1236% %
1237% %
1238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1239%
1240% GetBlobFileHandle() returns the file handle associated with the image blob.
1241%
1242% The format of the GetBlobFile method is:
1243%
1244% FILE *GetBlobFileHandle(const Image *image)
1245%
1246% A description of each parameter follows:
1247%
1248% o image: the image.
1249%
1250*/
1251MagickExport FILE *GetBlobFileHandle(const Image *image)
1252{
1253 assert(image != (const Image *) NULL);
1254 assert(image->signature == MagickSignature);
cristye7b28372012-06-17 13:59:06 +00001255 return(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001256}
1257
1258/*
1259%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1260% %
1261% %
1262% %
1263+ G e t B l o b I n f o %
1264% %
1265% %
1266% %
1267%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1268%
1269% GetBlobInfo() initializes the BlobInfo structure.
1270%
1271% The format of the GetBlobInfo method is:
1272%
1273% void GetBlobInfo(BlobInfo *blob_info)
1274%
1275% A description of each parameter follows:
1276%
1277% o blob_info: Specifies a pointer to a BlobInfo structure.
1278%
1279*/
cristy7832dc22011-09-05 01:21:53 +00001280MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001281{
1282 assert(blob_info != (BlobInfo *) NULL);
1283 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1284 blob_info->type=UndefinedStream;
1285 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1286 blob_info->properties.st_mtime=time((time_t *) NULL);
1287 blob_info->properties.st_ctime=time((time_t *) NULL);
1288 blob_info->debug=IsEventLogging();
1289 blob_info->reference_count=1;
cristy3d162a92014-02-16 14:05:06 +00001290 blob_info->semaphore=AcquireSemaphoreInfo();
cristy3ed852e2009-09-05 21:47:34 +00001291 blob_info->signature=MagickSignature;
1292}
1293
1294/*
1295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1296% %
1297% %
1298% %
1299% G e t B l o b P r o p e r t i e s %
1300% %
1301% %
1302% %
1303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1304%
1305% GetBlobProperties() returns information about an image blob.
1306%
1307% The format of the GetBlobProperties method is:
1308%
1309% const struct stat *GetBlobProperties(const Image *image)
1310%
1311% A description of each parameter follows:
1312%
1313% o image: the image.
1314%
1315*/
cristy7832dc22011-09-05 01:21:53 +00001316MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001317{
1318 assert(image != (Image *) NULL);
1319 assert(image->signature == MagickSignature);
1320 if (image->debug != MagickFalse)
1321 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1322 return(&image->blob->properties);
1323}
1324
1325/*
1326%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1327% %
1328% %
1329% %
1330+ G e t B l o b S i z e %
1331% %
1332% %
1333% %
1334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1335%
1336% GetBlobSize() returns the current length of the image file or blob; zero is
1337% returned if the size cannot be determined.
1338%
1339% The format of the GetBlobSize method is:
1340%
1341% MagickSizeType GetBlobSize(const Image *image)
1342%
1343% A description of each parameter follows:
1344%
1345% o image: the image.
1346%
1347*/
1348MagickExport MagickSizeType GetBlobSize(const Image *image)
1349{
1350 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001351 extent;
cristy3ed852e2009-09-05 21:47:34 +00001352
1353 assert(image != (Image *) NULL);
1354 assert(image->signature == MagickSignature);
1355 if (image->debug != MagickFalse)
1356 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1357 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001358 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001359 switch (image->blob->type)
1360 {
1361 case UndefinedStream:
1362 {
cristy81b8ce52010-02-05 01:53:17 +00001363 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001364 break;
1365 }
cristybc20d112012-07-29 20:27:00 +00001366 case StandardStream:
1367 {
1368 extent=image->blob->size;
1369 break;
1370 }
cristy3ed852e2009-09-05 21:47:34 +00001371 case FileStream:
1372 {
cristye7b28372012-06-17 13:59:06 +00001373 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001374 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001375 break;
1376 }
cristy3ed852e2009-09-05 21:47:34 +00001377 case PipeStream:
1378 {
cristy81b8ce52010-02-05 01:53:17 +00001379 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001380 break;
1381 }
1382 case ZipStream:
1383 case BZipStream:
1384 {
1385 MagickBooleanType
1386 status;
1387
1388 status=GetPathAttributes(image->filename,&image->blob->properties);
1389 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001390 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001391 break;
1392 }
1393 case FifoStream:
1394 break;
1395 case BlobStream:
1396 {
cristy891dc792010-03-04 01:47:16 +00001397 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001398 break;
1399 }
1400 }
cristy81b8ce52010-02-05 01:53:17 +00001401 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001402}
1403
1404/*
1405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1406% %
1407% %
1408% %
1409+ G e t B l o b S t r e a m D a t a %
1410% %
1411% %
1412% %
1413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1414%
1415% GetBlobStreamData() returns the stream data for the image.
1416%
1417% The format of the GetBlobStreamData method is:
1418%
1419% unsigned char *GetBlobStreamData(const Image *image)
1420%
1421% A description of each parameter follows:
1422%
1423% o image: the image.
1424%
1425*/
1426MagickExport unsigned char *GetBlobStreamData(const Image *image)
1427{
1428 assert(image != (const Image *) NULL);
1429 assert(image->signature == MagickSignature);
1430 return(image->blob->data);
1431}
1432
1433/*
1434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1435% %
1436% %
1437% %
1438+ G e t B l o b S t r e a m H a n d l e r %
1439% %
1440% %
1441% %
1442%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1443%
1444% GetBlobStreamHandler() returns the stream handler for the image.
1445%
1446% The format of the GetBlobStreamHandler method is:
1447%
1448% StreamHandler GetBlobStreamHandler(const Image *image)
1449%
1450% A description of each parameter follows:
1451%
1452% o image: the image.
1453%
1454*/
cristy7832dc22011-09-05 01:21:53 +00001455MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001456{
1457 assert(image != (const Image *) NULL);
1458 assert(image->signature == MagickSignature);
1459 if (image->debug != MagickFalse)
1460 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1461 return(image->blob->stream);
1462}
1463
1464/*
1465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1466% %
1467% %
1468% %
1469% I m a g e T o B l o b %
1470% %
1471% %
1472% %
1473%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1474%
1475% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001476% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001477% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001478% etc.). This method is the equivalent of WriteImage(), but writes the
1479% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001480%
1481% The format of the ImageToBlob method is:
1482%
1483% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1484% size_t *length,ExceptionInfo *exception)
1485%
1486% A description of each parameter follows:
1487%
1488% o image_info: the image info.
1489%
1490% o image: the image.
1491%
cristyd7dc7df2014-01-26 13:52:14 +00001492% o length: return the actual length of the blob.
cristy3ed852e2009-09-05 21:47:34 +00001493%
1494% o exception: return any errors or warnings in this structure.
1495%
1496*/
1497MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1498 Image *image,size_t *length,ExceptionInfo *exception)
1499{
1500 const MagickInfo
1501 *magick_info;
1502
1503 ImageInfo
1504 *blob_info;
1505
1506 MagickBooleanType
1507 status;
1508
1509 unsigned char
1510 *blob;
1511
1512 assert(image_info != (const ImageInfo *) NULL);
1513 assert(image_info->signature == MagickSignature);
1514 if (image_info->debug != MagickFalse)
1515 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1516 image_info->filename);
1517 assert(image != (Image *) NULL);
1518 assert(image->signature == MagickSignature);
1519 assert(exception != (ExceptionInfo *) NULL);
1520 *length=0;
1521 blob=(unsigned char *) NULL;
1522 blob_info=CloneImageInfo(image_info);
1523 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001524 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001525 if (*blob_info->magick != '\0')
1526 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1527 magick_info=GetMagickInfo(image->magick,exception);
1528 if (magick_info == (const MagickInfo *) NULL)
1529 {
1530 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001531 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +00001532 image->magick);
1533 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +00001534 return(blob);
1535 }
1536 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1537 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1538 {
1539 /*
1540 Native blob support for this image format.
1541 */
cristy5facf772014-01-26 14:42:57 +00001542 blob_info->length=0;
1543 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1544 sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001545 if (blob_info->blob == (void *) NULL)
1546 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001547 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001548 else
1549 {
1550 (void) CloseBlob(image);
1551 image->blob->exempt=MagickTrue;
1552 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001553 status=WriteImage(blob_info,image,exception);
cristy5facf772014-01-26 14:42:57 +00001554 *length=image->blob->length;
cristyc42554f2012-08-22 12:00:43 +00001555 blob=DetachBlob(image->blob);
cristy6e50f9e2012-08-22 16:30:29 +00001556 if (status == MagickFalse)
1557 blob=(unsigned char *) RelinquishMagickMemory(blob);
1558 else
cristy7a7eb372014-01-25 23:09:10 +00001559 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1560 sizeof(*blob));
cristy3ed852e2009-09-05 21:47:34 +00001561 }
1562 }
1563 else
1564 {
1565 char
1566 unique[MaxTextExtent];
1567
1568 int
1569 file;
1570
1571 /*
1572 Write file to disk in blob image format.
1573 */
1574 file=AcquireUniqueFileResource(unique);
1575 if (file == -1)
1576 {
1577 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1578 image_info->filename);
1579 }
1580 else
1581 {
1582 blob_info->file=fdopen(file,"wb");
1583 if (blob_info->file != (FILE *) NULL)
1584 {
cristyb51dff52011-05-19 16:55:47 +00001585 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001586 image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001587 status=WriteImage(blob_info,image,exception);
dirk607010e2014-03-01 19:08:11 +00001588 (void) CloseBlob(image);
1589 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001590 if (status != MagickFalse)
cristy2c1b6e02014-01-26 15:03:02 +00001591 blob=FileToBlob(unique,~0UL,length,exception);
cristy3ed852e2009-09-05 21:47:34 +00001592 }
1593 (void) RelinquishUniqueFileResource(unique);
1594 }
1595 }
1596 blob_info=DestroyImageInfo(blob_info);
1597 return(blob);
1598}
1599
1600/*
1601%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1602% %
1603% %
1604% %
1605% I m a g e T o F i l e %
1606% %
1607% %
1608% %
1609%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1610%
1611% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1612% occurs otherwise MagickTrue.
1613%
1614% The format of the ImageToFile method is:
1615%
1616% MagickBooleanType ImageToFile(Image *image,char *filename,
1617% ExceptionInfo *exception)
1618%
1619% A description of each parameter follows:
1620%
1621% o image: the image.
1622%
1623% o filename: Write the image to this file.
1624%
1625% o exception: return any errors or warnings in this structure.
1626%
1627*/
cristy3ed852e2009-09-05 21:47:34 +00001628MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1629 ExceptionInfo *exception)
1630{
1631 int
1632 file;
1633
1634 register const unsigned char
1635 *p;
1636
1637 register size_t
1638 i;
1639
1640 size_t
1641 length,
1642 quantum;
1643
1644 ssize_t
1645 count;
1646
1647 struct stat
cristye7b28372012-06-17 13:59:06 +00001648 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001649
1650 unsigned char
1651 *buffer;
1652
1653 assert(image != (Image *) NULL);
1654 assert(image->signature == MagickSignature);
1655 assert(image->blob != (BlobInfo *) NULL);
1656 assert(image->blob->type != UndefinedStream);
1657 if (image->debug != MagickFalse)
1658 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1659 assert(filename != (const char *) NULL);
1660 if (*filename == '\0')
1661 file=AcquireUniqueFileResource(filename);
1662 else
1663 if (LocaleCompare(filename,"-") == 0)
1664 file=fileno(stdout);
1665 else
cristyb70aab92012-01-31 15:04:04 +00001666 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001667 if (file == -1)
1668 {
1669 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1670 return(MagickFalse);
1671 }
1672 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001673 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1674 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001675 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001676 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1677 if (buffer == (unsigned char *) NULL)
1678 {
1679 file=close(file)-1;
1680 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001681 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001682 return(MagickFalse);
1683 }
1684 length=0;
1685 p=ReadBlobStream(image,quantum,buffer,&count);
1686 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1687 {
1688 length=(size_t) count;
1689 for (i=0; i < length; i+=count)
1690 {
1691 count=write(file,p+i,(size_t) (length-i));
1692 if (count <= 0)
1693 {
1694 count=0;
1695 if (errno != EINTR)
1696 break;
1697 }
1698 }
1699 if (i < length)
1700 break;
1701 }
cristy54439632010-07-15 00:43:34 +00001702 if (LocaleCompare(filename,"-") != 0)
1703 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001704 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001705 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001706 {
cristye3216eb2014-04-18 17:10:21 +00001707 if (file != -1)
cristy100a0562014-04-18 01:27:37 +00001708 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001709 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1710 return(MagickFalse);
1711 }
1712 return(MagickTrue);
1713}
1714
1715/*
1716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1717% %
1718% %
1719% %
1720% I m a g e s T o B l o b %
1721% %
1722% %
1723% %
1724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725%
1726% ImagesToBlob() implements direct to memory image formats. It returns the
1727% image sequence as a blob and its length. The magick member of the ImageInfo
1728% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1729%
1730% Note, some image formats do not permit multiple images to the same image
1731% stream (e.g. JPEG). in this instance, just the first image of the
1732% sequence is returned as a blob.
1733%
1734% The format of the ImagesToBlob method is:
1735%
1736% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1737% size_t *length,ExceptionInfo *exception)
1738%
1739% A description of each parameter follows:
1740%
1741% o image_info: the image info.
1742%
1743% o images: the image list.
1744%
cristybb85d6a2014-01-26 13:51:09 +00001745% o length: return the actual length of the blob.
cristy3ed852e2009-09-05 21:47:34 +00001746%
1747% o exception: return any errors or warnings in this structure.
1748%
1749*/
1750MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1751 Image *images,size_t *length,ExceptionInfo *exception)
1752{
1753 const MagickInfo
1754 *magick_info;
1755
1756 ImageInfo
1757 *blob_info;
1758
1759 MagickBooleanType
1760 status;
1761
1762 unsigned char
1763 *blob;
1764
1765 assert(image_info != (const ImageInfo *) NULL);
1766 assert(image_info->signature == MagickSignature);
1767 if (image_info->debug != MagickFalse)
1768 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1769 image_info->filename);
1770 assert(images != (Image *) NULL);
1771 assert(images->signature == MagickSignature);
1772 assert(exception != (ExceptionInfo *) NULL);
1773 *length=0;
1774 blob=(unsigned char *) NULL;
1775 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001776 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1777 exception);
cristy3ed852e2009-09-05 21:47:34 +00001778 if (*blob_info->magick != '\0')
1779 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00001780 magick_info=GetMagickInfo(images->magick,exception);
1781 if (magick_info == (const MagickInfo *) NULL)
1782 {
1783 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001784 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +00001785 images->magick);
1786 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +00001787 return(blob);
1788 }
cristy4f1f3e82014-01-26 15:25:52 +00001789 if (GetMagickAdjoin(magick_info) == MagickFalse)
1790 {
1791 blob_info=DestroyImageInfo(blob_info);
1792 return(ImageToBlob(image_info,images,length,exception));
1793 }
cristy3ed852e2009-09-05 21:47:34 +00001794 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1795 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1796 {
1797 /*
1798 Native blob support for this images format.
1799 */
cristy5facf772014-01-26 14:42:57 +00001800 blob_info->length=0;
1801 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1802 sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001803 if (blob_info->blob == (void *) NULL)
1804 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001805 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
cristy3ed852e2009-09-05 21:47:34 +00001806 else
1807 {
cristy7a4b8c52014-01-25 22:48:06 +00001808 (void) CloseBlob(images);
cristy3ed852e2009-09-05 21:47:34 +00001809 images->blob->exempt=MagickTrue;
1810 *images->filename='\0';
1811 status=WriteImages(blob_info,images,images->filename,exception);
cristy5facf772014-01-26 14:42:57 +00001812 *length=images->blob->length;
cristy7a4b8c52014-01-25 22:48:06 +00001813 blob=DetachBlob(images->blob);
1814 if (status == MagickFalse)
1815 blob=(unsigned char *) RelinquishMagickMemory(blob);
1816 else
cristy7a7eb372014-01-25 23:09:10 +00001817 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1818 sizeof(*blob));
cristy3ed852e2009-09-05 21:47:34 +00001819 }
1820 }
1821 else
1822 {
1823 char
1824 filename[MaxTextExtent],
1825 unique[MaxTextExtent];
1826
1827 int
1828 file;
1829
1830 /*
1831 Write file to disk in blob images format.
1832 */
1833 file=AcquireUniqueFileResource(unique);
1834 if (file == -1)
1835 {
1836 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1837 image_info->filename);
1838 }
1839 else
1840 {
1841 blob_info->file=fdopen(file,"wb");
1842 if (blob_info->file != (FILE *) NULL)
1843 {
cristyb51dff52011-05-19 16:55:47 +00001844 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001845 images->magick,unique);
1846 status=WriteImages(blob_info,images,filename,exception);
dirk607010e2014-03-01 19:08:11 +00001847 (void) CloseBlob(images);
cristya94f31b2014-03-01 13:25:42 +00001848 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001849 if (status != MagickFalse)
cristy2c1b6e02014-01-26 15:03:02 +00001850 blob=FileToBlob(unique,~0UL,length,exception);
cristy3ed852e2009-09-05 21:47:34 +00001851 }
1852 (void) RelinquishUniqueFileResource(unique);
1853 }
1854 }
1855 blob_info=DestroyImageInfo(blob_info);
1856 return(blob);
1857}
1858/*
1859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1860% %
1861% %
1862% %
1863% I n j e c t I m a g e B l o b %
1864% %
1865% %
1866% %
1867%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1868%
1869% InjectImageBlob() injects the image with a copy of itself in the specified
1870% format (e.g. inject JPEG into a PDF image).
1871%
1872% The format of the InjectImageBlob method is:
1873%
1874% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1875% Image *image,Image *inject_image,const char *format,
1876% ExceptionInfo *exception)
1877%
1878% A description of each parameter follows:
1879%
1880% o image_info: the image info..
1881%
1882% o image: the image.
1883%
1884% o inject_image: inject into the image stream.
1885%
1886% o format: the image format.
1887%
1888% o exception: return any errors or warnings in this structure.
1889%
1890*/
1891MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1892 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1893{
1894 char
1895 filename[MaxTextExtent];
1896
1897 FILE
1898 *unique_file;
1899
1900 Image
1901 *byte_image;
1902
1903 ImageInfo
1904 *write_info;
1905
1906 int
1907 file;
1908
1909 MagickBooleanType
1910 status;
1911
cristybb503372010-05-27 20:51:26 +00001912 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001913 i;
1914
1915 size_t
1916 quantum;
1917
1918 ssize_t
1919 count;
1920
1921 struct stat
cristye7b28372012-06-17 13:59:06 +00001922 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001923
1924 unsigned char
1925 *buffer;
1926
1927 /*
1928 Write inject image to a temporary file.
1929 */
1930 assert(image_info != (ImageInfo *) NULL);
1931 assert(image_info->signature == MagickSignature);
1932 assert(image != (Image *) NULL);
1933 assert(image->signature == MagickSignature);
1934 if (image->debug != MagickFalse)
1935 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1936 assert(inject_image != (Image *) NULL);
1937 assert(inject_image->signature == MagickSignature);
1938 assert(exception != (ExceptionInfo *) NULL);
1939 unique_file=(FILE *) NULL;
1940 file=AcquireUniqueFileResource(filename);
1941 if (file != -1)
1942 unique_file=fdopen(file,"wb");
1943 if ((file == -1) || (unique_file == (FILE *) NULL))
1944 {
1945 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1946 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1947 image->filename);
1948 return(MagickFalse);
1949 }
1950 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1951 if (byte_image == (Image *) NULL)
1952 {
1953 (void) fclose(unique_file);
1954 (void) RelinquishUniqueFileResource(filename);
1955 return(MagickFalse);
1956 }
cristyb51dff52011-05-19 16:55:47 +00001957 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001958 filename);
1959 DestroyBlob(byte_image);
1960 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1961 write_info=CloneImageInfo(image_info);
1962 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001963 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001964 write_info=DestroyImageInfo(write_info);
1965 byte_image=DestroyImage(byte_image);
1966 (void) fclose(unique_file);
1967 if (status == MagickFalse)
1968 {
1969 (void) RelinquishUniqueFileResource(filename);
1970 return(MagickFalse);
1971 }
1972 /*
1973 Inject into image stream.
1974 */
cristy18c6c272011-09-23 14:40:37 +00001975 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001976 if (file == -1)
1977 {
1978 (void) RelinquishUniqueFileResource(filename);
1979 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1980 image_info->filename);
1981 return(MagickFalse);
1982 }
1983 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001984 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1985 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001986 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1987 if (buffer == (unsigned char *) NULL)
1988 {
1989 (void) RelinquishUniqueFileResource(filename);
1990 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1991 image->filename);
1992 }
1993 for (i=0; ; i+=count)
1994 {
cristy65d11e42013-06-14 20:06:25 +00001995 count=read(file,buffer,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001996 if (count <= 0)
1997 {
1998 count=0;
1999 if (errno != EINTR)
2000 break;
2001 }
2002 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2003 MagickFalse;
2004 }
cristya7cb4312010-06-26 00:47:03 +00002005 file=close(file);
2006 if (file == -1)
2007 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00002008 (void) RelinquishUniqueFileResource(filename);
2009 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2010 return(status);
2011}
2012
2013/*
2014%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2015% %
2016% %
2017% %
2018+ I s B l o b E x e m p t %
2019% %
2020% %
2021% %
2022%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2023%
2024% IsBlobExempt() returns true if the blob is exempt.
2025%
2026% The format of the IsBlobExempt method is:
2027%
2028% MagickBooleanType IsBlobExempt(const Image *image)
2029%
2030% A description of each parameter follows:
2031%
2032% o image: the image.
2033%
2034*/
cristy7832dc22011-09-05 01:21:53 +00002035MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002036{
2037 assert(image != (const Image *) NULL);
2038 assert(image->signature == MagickSignature);
2039 if (image->debug != MagickFalse)
2040 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2041 return(image->blob->exempt);
2042}
2043
2044/*
2045%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2046% %
2047% %
2048% %
2049+ I s B l o b S e e k a b l e %
2050% %
2051% %
2052% %
2053%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2054%
2055% IsBlobSeekable() returns true if the blob is seekable.
2056%
2057% The format of the IsBlobSeekable method is:
2058%
2059% MagickBooleanType IsBlobSeekable(const Image *image)
2060%
2061% A description of each parameter follows:
2062%
2063% o image: the image.
2064%
2065*/
cristy7832dc22011-09-05 01:21:53 +00002066MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002067{
2068 MagickBooleanType
2069 seekable;
2070
2071 assert(image != (const Image *) NULL);
2072 assert(image->signature == MagickSignature);
2073 if (image->debug != MagickFalse)
2074 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002075 switch (image->blob->type)
2076 {
2077 case FileStream:
2078 case BlobStream:
2079 case ZipStream:
2080 {
2081 seekable=MagickTrue;
2082 break;
2083 }
2084 default:
2085 {
2086 seekable=MagickFalse;
2087 break;
2088 }
2089 }
cristy3ed852e2009-09-05 21:47:34 +00002090 return(seekable);
2091}
2092
2093/*
2094%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2095% %
2096% %
2097% %
2098+ I s B l o b T e m p o r a r y %
2099% %
2100% %
2101% %
2102%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2103%
2104% IsBlobTemporary() returns true if the blob is temporary.
2105%
2106% The format of the IsBlobTemporary method is:
2107%
2108% MagickBooleanType IsBlobTemporary(const Image *image)
2109%
2110% A description of each parameter follows:
2111%
2112% o image: the image.
2113%
2114*/
cristy7832dc22011-09-05 01:21:53 +00002115MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002116{
2117 assert(image != (const Image *) NULL);
2118 assert(image->signature == MagickSignature);
2119 if (image->debug != MagickFalse)
2120 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2121 return(image->blob->temporary);
2122}
2123
2124/*
2125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2126% %
2127% %
2128% %
2129+ M a p B l o b %
2130% %
2131% %
2132% %
2133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2134%
2135% MapBlob() creates a mapping from a file to a binary large object.
2136%
2137% The format of the MapBlob method is:
2138%
2139% unsigned char *MapBlob(int file,const MapMode mode,
2140% const MagickOffsetType offset,const size_t length)
2141%
2142% A description of each parameter follows:
2143%
2144% o file: map this file descriptor.
2145%
2146% o mode: ReadMode, WriteMode, or IOMode.
2147%
2148% o offset: starting at this offset within the file.
2149%
2150% o length: the length of the mapping is returned in this pointer.
2151%
2152*/
2153MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2154 const MagickOffsetType offset,const size_t length)
2155{
cristydc8ea8e2013-07-28 20:10:44 +00002156#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00002157 int
2158 flags,
2159 protection;
2160
2161 unsigned char
2162 *map;
2163
2164 /*
2165 Map file.
2166 */
2167 flags=0;
2168 if (file == -1)
2169#if defined(MAP_ANONYMOUS)
2170 flags|=MAP_ANONYMOUS;
2171#else
2172 return((unsigned char *) NULL);
2173#endif
2174 switch (mode)
2175 {
2176 case ReadMode:
2177 default:
2178 {
2179 protection=PROT_READ;
2180 flags|=MAP_PRIVATE;
cristy3ed852e2009-09-05 21:47:34 +00002181 break;
2182 }
2183 case WriteMode:
2184 {
2185 protection=PROT_WRITE;
2186 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002187 break;
2188 }
2189 case IOMode:
2190 {
2191 protection=PROT_READ | PROT_WRITE;
2192 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002193 break;
2194 }
2195 }
cristy56a0dbe2013-07-09 15:27:09 +00002196#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2197 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2198 (off_t) offset);
2199#else
cristy7a4b8c52014-01-25 22:48:06 +00002200 map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
cristy56a0dbe2013-07-09 15:27:09 +00002201 MAP_HUGETLB,file,(off_t) offset);
2202 if (map == (unsigned char *) MAP_FAILED)
2203 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2204 (off_t) offset);
2205#endif
cristy3ed852e2009-09-05 21:47:34 +00002206 if (map == (unsigned char *) MAP_FAILED)
2207 return((unsigned char *) NULL);
2208 return(map);
2209#else
2210 (void) file;
2211 (void) mode;
2212 (void) offset;
2213 (void) length;
2214 return((unsigned char *) NULL);
2215#endif
2216}
2217
2218/*
2219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2220% %
2221% %
2222% %
2223+ M S B O r d e r L o n g %
2224% %
2225% %
2226% %
2227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2228%
2229% MSBOrderLong() converts a least-significant byte first buffer of integers to
2230% most-significant byte first.
2231%
2232% The format of the MSBOrderLong method is:
2233%
2234% void MSBOrderLong(unsigned char *buffer,const size_t length)
2235%
2236% A description of each parameter follows.
2237%
2238% o buffer: Specifies a pointer to a buffer of integers.
2239%
2240% o length: Specifies the length of the buffer.
2241%
2242*/
2243MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2244{
2245 int
2246 c;
2247
2248 register unsigned char
2249 *p,
2250 *q;
2251
2252 assert(buffer != (unsigned char *) NULL);
2253 q=buffer+length;
2254 while (buffer < q)
2255 {
2256 p=buffer+3;
2257 c=(int) (*p);
2258 *p=(*buffer);
2259 *buffer++=(unsigned char) c;
2260 p=buffer+1;
2261 c=(int) (*p);
2262 *p=(*buffer);
2263 *buffer++=(unsigned char) c;
2264 buffer+=2;
2265 }
2266}
2267
2268/*
2269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2270% %
2271% %
2272% %
2273+ M S B O r d e r S h o r t %
2274% %
2275% %
2276% %
2277%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2278%
2279% MSBOrderShort() converts a least-significant byte first buffer of integers
2280% to most-significant byte first.
2281%
2282% The format of the MSBOrderShort method is:
2283%
2284% void MSBOrderShort(unsigned char *p,const size_t length)
2285%
2286% A description of each parameter follows.
2287%
2288% o p: Specifies a pointer to a buffer of integers.
2289%
2290% o length: Specifies the length of the buffer.
2291%
2292*/
2293MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2294{
2295 int
2296 c;
2297
2298 register unsigned char
2299 *q;
2300
2301 assert(p != (unsigned char *) NULL);
2302 q=p+length;
2303 while (p < q)
2304 {
2305 c=(int) (*p);
2306 *p=(*(p+1));
2307 p++;
2308 *p++=(unsigned char) c;
2309 }
2310}
2311
2312/*
2313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2314% %
2315% %
2316% %
2317+ O p e n B l o b %
2318% %
2319% %
2320% %
2321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2322%
2323% OpenBlob() opens a file associated with the image. A file name of '-' sets
2324% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2325% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2326% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2327% from a system command.
2328%
2329% The format of the OpenBlob method is:
2330%
2331% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2332% const BlobMode mode,ExceptionInfo *exception)
2333%
2334% A description of each parameter follows:
2335%
2336% o image_info: the image info.
2337%
2338% o image: the image.
2339%
2340% o mode: the mode for opening the file.
2341%
2342*/
2343MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2344 Image *image,const BlobMode mode,ExceptionInfo *exception)
2345{
2346 char
cristybf6a7092010-06-11 02:12:15 +00002347 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002348 filename[MaxTextExtent];
2349
2350 const char
2351 *type;
2352
2353 MagickBooleanType
2354 status;
2355
2356 PolicyRights
2357 rights;
2358
2359 assert(image_info != (ImageInfo *) NULL);
2360 assert(image_info->signature == MagickSignature);
2361 if (image_info->debug != MagickFalse)
2362 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2363 image_info->filename);
2364 assert(image != (Image *) NULL);
2365 assert(image->signature == MagickSignature);
2366 if (image_info->blob != (void *) NULL)
2367 {
2368 if (image_info->stream != (StreamHandler) NULL)
2369 image->blob->stream=(StreamHandler) image_info->stream;
2370 AttachBlob(image->blob,image_info->blob,image_info->length);
2371 return(MagickTrue);
2372 }
2373 (void) DetachBlob(image->blob);
2374 switch (mode)
2375 {
2376 default: type="r"; break;
2377 case ReadBlobMode: type="r"; break;
2378 case ReadBinaryBlobMode: type="rb"; break;
2379 case WriteBlobMode: type="w"; break;
2380 case WriteBinaryBlobMode: type="w+b"; break;
2381 case AppendBlobMode: type="a"; break;
2382 case AppendBinaryBlobMode: type="a+b"; break;
2383 }
2384 if (*type != 'r')
2385 image->blob->synchronize=image_info->synchronize;
2386 if (image_info->stream != (StreamHandler) NULL)
2387 {
2388 image->blob->stream=(StreamHandler) image_info->stream;
2389 if (*type == 'w')
2390 {
2391 image->blob->type=FifoStream;
2392 return(MagickTrue);
2393 }
2394 }
2395 /*
2396 Open image file.
2397 */
2398 *filename='\0';
2399 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2400 rights=ReadPolicyRights;
2401 if (*type == 'w')
2402 rights=WritePolicyRights;
2403 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2404 {
cristya9197f62010-01-12 02:23:34 +00002405 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002406 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
cristyefe601c2013-01-05 17:51:12 +00002407 "NotAuthorized","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00002408 return(MagickFalse);
2409 }
2410 if ((LocaleCompare(filename,"-") == 0) ||
2411 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2412 {
cristye7b28372012-06-17 13:59:06 +00002413 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002414#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002415 if (strchr(type,'b') != (char *) NULL)
cristye7b28372012-06-17 13:59:06 +00002416 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002417#endif
2418 image->blob->type=StandardStream;
2419 image->blob->exempt=MagickTrue;
2420 return(MagickTrue);
2421 }
cristybc20d112012-07-29 20:27:00 +00002422 if (LocaleNCompare(filename,"fd:",3) == 0)
2423 {
2424 char
2425 mode[MaxTextExtent];
2426
2427 *mode=(*type);
2428 mode[1]='\0';
2429 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2430#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2431 if (strchr(type,'b') != (char *) NULL)
2432 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2433#endif
2434 image->blob->type=StandardStream;
2435 image->blob->exempt=MagickTrue;
2436 return(MagickTrue);
2437 }
cristy3ed852e2009-09-05 21:47:34 +00002438#if defined(MAGICKCORE_HAVE_POPEN)
2439 if (*filename == '|')
2440 {
2441 char
2442 mode[MaxTextExtent];
2443
2444 /*
2445 Pipe image to or from a system command.
2446 */
2447#if defined(SIGPIPE)
2448 if (*type == 'w')
2449 (void) signal(SIGPIPE,SIG_IGN);
2450#endif
2451 *mode=(*type);
2452 mode[1]='\0';
cristye7b28372012-06-17 13:59:06 +00002453 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2454 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002455 {
2456 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2457 return(MagickFalse);
2458 }
2459 image->blob->type=PipeStream;
2460 image->blob->exempt=MagickTrue;
2461 return(MagickTrue);
2462 }
2463#endif
2464 status=GetPathAttributes(filename,&image->blob->properties);
2465#if defined(S_ISFIFO)
cristycd8b3312013-12-22 01:51:11 +00002466 if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
cristy3ed852e2009-09-05 21:47:34 +00002467 {
cristye7b28372012-06-17 13:59:06 +00002468 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2469 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002470 {
2471 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2472 return(MagickFalse);
2473 }
2474 image->blob->type=FileStream;
2475 image->blob->exempt=MagickTrue;
2476 return(MagickTrue);
2477 }
2478#endif
cristybf6a7092010-06-11 02:12:15 +00002479 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002480 if (*type == 'w')
2481 {
cristye8939e72010-02-03 17:05:25 +00002482 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002483 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002484 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002485 {
2486 /*
2487 Form filename for multi-part images.
2488 */
2489 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002490 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002491 if ((LocaleCompare(filename,image->filename) == 0) &&
2492 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2493 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002494 {
cristybf7fa0d2010-02-04 00:51:10 +00002495 char
cristybf7fa0d2010-02-04 00:51:10 +00002496 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002497
cristybf7fa0d2010-02-04 00:51:10 +00002498 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002499 if (*extension == '\0')
cristyb51dff52011-05-19 16:55:47 +00002500 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002501 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002502 else
cristyb51dff52011-05-19 16:55:47 +00002503 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002504 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002505 }
2506 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002507#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002508 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002509#endif
cristye8939e72010-02-03 17:05:25 +00002510 }
cristy3ed852e2009-09-05 21:47:34 +00002511 }
cristybf6a7092010-06-11 02:12:15 +00002512 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002513 {
cristye7b28372012-06-17 13:59:06 +00002514 image->blob->file_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002515 image->blob->type=FileStream;
2516 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002517 }
2518 else
cristybf6a7092010-06-11 02:12:15 +00002519 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002520 {
cristye7b28372012-06-17 13:59:06 +00002521 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2522 if (image->blob->file_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002523 {
2524 size_t
cristybf6a7092010-06-11 02:12:15 +00002525 count;
cristy3ed852e2009-09-05 21:47:34 +00002526
cristybf6a7092010-06-11 02:12:15 +00002527 unsigned char
2528 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002529
cristybf6a7092010-06-11 02:12:15 +00002530 image->blob->type=FileStream;
2531#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002532 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2533 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002534#endif
2535 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristye7b28372012-06-17 13:59:06 +00002536 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
cristyae958042013-01-05 15:48:19 +00002537 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
cristy79fe6932012-12-25 00:31:30 +00002538 (void) fflush(image->blob->file_info.file);
cristybf6a7092010-06-11 02:12:15 +00002539 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2540 " read %.20g magic header bytes",(double) count);
2541#if defined(MAGICKCORE_ZLIB_DELEGATE)
2542 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2543 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002544 {
cristy98677002014-04-27 19:33:02 +00002545 if (image->blob->file_info.file != (FILE *) NULL)
2546 (void) fclose(image->blob->file_info.file);
2547 image->blob->file_info.file=(FILE *) NULL;
cristye7b28372012-06-17 13:59:06 +00002548 image->blob->file_info.gzfile=gzopen(filename,type);
2549 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002550 image->blob->type=ZipStream;
2551 }
2552#endif
2553#if defined(MAGICKCORE_BZLIB_DELEGATE)
2554 if (strncmp((char *) magick,"BZh",3) == 0)
2555 {
cristy98677002014-04-27 19:33:02 +00002556 if (image->blob->file_info.file != (FILE *) NULL)
2557 (void) fclose(image->blob->file_info.file);
2558 image->blob->file_info.file=(FILE *) NULL;
cristye7b28372012-06-17 13:59:06 +00002559 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2560 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002561 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002562 }
cristybf6a7092010-06-11 02:12:15 +00002563#endif
cristyc6c589d2010-07-06 01:34:57 +00002564 if (image->blob->type == FileStream)
2565 {
2566 const MagickInfo
2567 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002568
cristyc6c589d2010-07-06 01:34:57 +00002569 ExceptionInfo
2570 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002571
cristy18aba912013-06-14 19:48:08 +00002572 size_t
2573 length;
2574
cristyc6c589d2010-07-06 01:34:57 +00002575 sans_exception=AcquireExceptionInfo();
2576 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2577 sans_exception=DestroyExceptionInfo(sans_exception);
cristy2eddb3d2013-06-16 14:10:08 +00002578 length=(size_t) image->blob->properties.st_size;
cristyc6c589d2010-07-06 01:34:57 +00002579 if ((magick_info != (const MagickInfo *) NULL) &&
2580 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
cristy7c242ea2013-06-21 17:19:53 +00002581 (length <= MagickMaxBufferExtent) &&
cristy18aba912013-06-14 19:48:08 +00002582 (AcquireMagickResource(MapResource,length) != MagickFalse))
cristyc6c589d2010-07-06 01:34:57 +00002583 {
cristyc6c589d2010-07-06 01:34:57 +00002584 void
2585 *blob;
cristybf6a7092010-06-11 02:12:15 +00002586
cristyfe00ebf2013-06-16 14:17:53 +00002587 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2588 length);
cristy18aba912013-06-14 19:48:08 +00002589 if (blob == (void *) NULL)
2590 RelinquishMagickResource(MapResource,length);
2591 else
cristyc6c589d2010-07-06 01:34:57 +00002592 {
2593 /*
2594 Format supports blobs-- use memory-mapped I/O.
2595 */
2596 if (image_info->file != (FILE *) NULL)
2597 image->blob->exempt=MagickFalse;
2598 else
2599 {
cristye7b28372012-06-17 13:59:06 +00002600 (void) fclose(image->blob->file_info.file);
2601 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002602 }
2603 AttachBlob(image->blob,blob,length);
2604 image->blob->mapped=MagickTrue;
2605 }
2606 }
2607 }
cristy3ed852e2009-09-05 21:47:34 +00002608 }
cristybf6a7092010-06-11 02:12:15 +00002609 }
2610 else
2611#if defined(MAGICKCORE_ZLIB_DELEGATE)
2612 if ((LocaleCompare(extension,"Z") == 0) ||
2613 (LocaleCompare(extension,"gz") == 0) ||
2614 (LocaleCompare(extension,"wmz") == 0) ||
2615 (LocaleCompare(extension,"svgz") == 0))
2616 {
2617 if (mode == WriteBinaryBlobMode)
2618 type="wb";
cristye7b28372012-06-17 13:59:06 +00002619 image->blob->file_info.gzfile=gzopen(filename,type);
2620 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002621 image->blob->type=ZipStream;
2622 }
2623 else
2624#endif
2625#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002626 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002627 {
cristye7b28372012-06-17 13:59:06 +00002628 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2629 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002630 image->blob->type=BZipStream;
2631 }
2632 else
2633#endif
2634 {
cristye7b28372012-06-17 13:59:06 +00002635 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2636 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002637 {
2638 image->blob->type=FileStream;
2639#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002640 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2641 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002642#endif
2643 }
2644 }
cristy3ed852e2009-09-05 21:47:34 +00002645 image->blob->status=MagickFalse;
2646 if (image->blob->type != UndefinedStream)
2647 image->blob->size=GetBlobSize(image);
2648 else
2649 {
2650 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2651 return(MagickFalse);
2652 }
2653 return(MagickTrue);
2654}
2655
2656/*
2657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2658% %
2659% %
2660% %
2661+ P i n g B l o b %
2662% %
2663% %
2664% %
2665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2666%
2667% PingBlob() returns all the attributes of an image or image sequence except
2668% for the pixels. It is much faster and consumes far less memory than
2669% BlobToImage(). On failure, a NULL image is returned and exception
2670% describes the reason for the failure.
2671%
2672% The format of the PingBlob method is:
2673%
2674% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2675% const size_t length,ExceptionInfo *exception)
2676%
2677% A description of each parameter follows:
2678%
2679% o image_info: the image info.
2680%
2681% o blob: the address of a character stream in one of the image formats
2682% understood by ImageMagick.
2683%
2684% o length: This size_t integer reflects the length in bytes of the blob.
2685%
2686% o exception: return any errors or warnings in this structure.
2687%
2688*/
2689
2690#if defined(__cplusplus) || defined(c_plusplus)
2691extern "C" {
2692#endif
2693
2694static size_t PingStream(const Image *magick_unused(image),
2695 const void *magick_unused(pixels),const size_t columns)
2696{
2697 return(columns);
2698}
2699
2700#if defined(__cplusplus) || defined(c_plusplus)
2701}
2702#endif
2703
2704MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2705 const size_t length,ExceptionInfo *exception)
2706{
2707 Image
2708 *image;
2709
2710 ImageInfo
2711 *ping_info;
2712
2713 assert(image_info != (ImageInfo *) NULL);
2714 assert(image_info->signature == MagickSignature);
2715 if (image_info->debug != MagickFalse)
2716 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2717 image_info->filename);
2718 assert(exception != (ExceptionInfo *) NULL);
2719 if ((blob == (const void *) NULL) || (length == 0))
2720 {
2721 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +00002722 "UnrecognizedImageFormat","`%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002723 return((Image *) NULL);
2724 }
2725 ping_info=CloneImageInfo(image_info);
2726 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2727 if (ping_info->blob == (const void *) NULL)
2728 {
2729 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00002730 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002731 return((Image *) NULL);
2732 }
cristy54aad5e2010-09-03 16:02:04 +00002733 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002734 ping_info->length=length;
2735 ping_info->ping=MagickTrue;
2736 image=ReadStream(ping_info,&PingStream,exception);
2737 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2738 ping_info=DestroyImageInfo(ping_info);
2739 return(image);
2740}
2741
2742/*
2743%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2744% %
2745% %
2746% %
2747+ R e a d B l o b %
2748% %
2749% %
2750% %
2751%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2752%
2753% ReadBlob() reads data from the blob or image file and returns it. It
cristy5f3d2752013-01-05 18:53:38 +00002754% returns the number of bytes read. If length is zero, ReadBlob() returns
2755% zero and has no other results. If length is greater than SSIZE_MAX, the
2756% result is unspecified.
cristy3ed852e2009-09-05 21:47:34 +00002757%
2758% The format of the ReadBlob method is:
2759%
2760% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2761%
2762% A description of each parameter follows:
2763%
2764% o image: the image.
2765%
2766% o length: Specifies an integer representing the number of bytes to read
2767% from the file.
2768%
2769% o data: Specifies an area to place the information requested from the
2770% file.
2771%
2772*/
2773MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2774 unsigned char *data)
2775{
2776 int
2777 c;
2778
2779 register unsigned char
2780 *q;
2781
2782 ssize_t
2783 count;
2784
2785 assert(image != (Image *) NULL);
2786 assert(image->signature == MagickSignature);
2787 assert(image->blob != (BlobInfo *) NULL);
2788 assert(image->blob->type != UndefinedStream);
2789 if (length == 0)
2790 return(0);
2791 assert(data != (void *) NULL);
2792 count=0;
2793 q=data;
2794 switch (image->blob->type)
2795 {
2796 case UndefinedStream:
2797 break;
cristy3ed852e2009-09-05 21:47:34 +00002798 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002799 {
cristy8faec1e2013-04-25 19:41:22 +00002800 register ssize_t
2801 i;
2802
2803 for (i=0; i < (ssize_t) length; i+=count)
2804 {
cristy7c242ea2013-06-21 17:19:53 +00002805 count=read(fileno(image->blob->file_info.file),q+i,(size_t)
cristy8faec1e2013-04-25 19:41:22 +00002806 MagickMin(length-i,(MagickSizeType) SSIZE_MAX));
2807 if (count <= 0)
2808 {
2809 count=0;
2810 if (errno != EINTR)
2811 break;
2812 }
2813 }
2814 count=i;
cristybc20d112012-07-29 20:27:00 +00002815 break;
2816 }
2817 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002818 case PipeStream:
2819 {
2820 switch (length)
2821 {
2822 default:
2823 {
cristye7b28372012-06-17 13:59:06 +00002824 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002825 break;
2826 }
2827 case 2:
2828 {
cristye7b28372012-06-17 13:59:06 +00002829 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002830 if (c == EOF)
2831 break;
2832 *q++=(unsigned char) c;
2833 count++;
2834 }
2835 case 1:
2836 {
cristye7b28372012-06-17 13:59:06 +00002837 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002838 if (c == EOF)
2839 break;
2840 *q++=(unsigned char) c;
2841 count++;
2842 }
2843 case 0:
2844 break;
2845 }
2846 break;
2847 }
2848 case ZipStream:
2849 {
2850#if defined(MAGICKCORE_ZLIB_DELEGATE)
2851 switch (length)
2852 {
2853 default:
2854 {
cristye7b28372012-06-17 13:59:06 +00002855 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002856 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002857 break;
2858 }
2859 case 2:
2860 {
cristye7b28372012-06-17 13:59:06 +00002861 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002862 if (c == EOF)
2863 break;
2864 *q++=(unsigned char) c;
2865 count++;
2866 }
2867 case 1:
2868 {
cristye7b28372012-06-17 13:59:06 +00002869 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002870 if (c == EOF)
2871 break;
2872 *q++=(unsigned char) c;
2873 count++;
2874 }
2875 case 0:
2876 break;
2877 }
2878#endif
2879 break;
2880 }
2881 case BZipStream:
2882 {
2883#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy5f3d2752013-01-05 18:53:38 +00002884 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
cristy3ed852e2009-09-05 21:47:34 +00002885#endif
2886 break;
2887 }
2888 case FifoStream:
2889 break;
2890 case BlobStream:
2891 {
2892 register const unsigned char
2893 *p;
2894
2895 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2896 {
2897 image->blob->eof=MagickTrue;
2898 break;
2899 }
2900 p=image->blob->data+image->blob->offset;
cristye7b28372012-06-17 13:59:06 +00002901 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2902 image->blob->offset));
cristy3ed852e2009-09-05 21:47:34 +00002903 image->blob->offset+=count;
2904 if (count != (ssize_t) length)
2905 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002906 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002907 break;
2908 }
2909 }
2910 return(count);
2911}
2912
2913/*
2914%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2915% %
2916% %
2917% %
2918+ R e a d B l o b B y t e %
2919% %
2920% %
2921% %
2922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2923%
2924% ReadBlobByte() reads a single byte from the image file and returns it.
2925%
2926% The format of the ReadBlobByte method is:
2927%
2928% int ReadBlobByte(Image *image)
2929%
2930% A description of each parameter follows.
2931%
2932% o image: the image.
2933%
2934*/
2935MagickExport int ReadBlobByte(Image *image)
2936{
2937 register const unsigned char
2938 *p;
2939
2940 ssize_t
2941 count;
2942
2943 unsigned char
2944 buffer[1];
2945
2946 assert(image != (Image *) NULL);
2947 assert(image->signature == MagickSignature);
2948 p=ReadBlobStream(image,1,buffer,&count);
2949 if (count != 1)
2950 return(EOF);
2951 return((int) (*p));
2952}
2953
2954/*
2955%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2956% %
2957% %
2958% %
2959+ R e a d B l o b D o u b l e %
2960% %
2961% %
2962% %
2963%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2964%
2965% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2966% specified by the endian member of the image structure.
2967%
2968% The format of the ReadBlobDouble method is:
2969%
2970% double ReadBlobDouble(Image *image)
2971%
2972% A description of each parameter follows.
2973%
2974% o image: the image.
2975%
2976*/
2977MagickExport double ReadBlobDouble(Image *image)
2978{
2979 union
2980 {
2981 MagickSizeType
2982 unsigned_value;
2983
2984 double
2985 double_value;
2986 } quantum;
2987
2988 quantum.double_value=0.0;
2989 quantum.unsigned_value=ReadBlobLongLong(image);
2990 return(quantum.double_value);
2991}
2992
2993/*
2994%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2995% %
2996% %
2997% %
2998+ R e a d B l o b F l o a t %
2999% %
3000% %
3001% %
3002%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3003%
3004% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3005% specified by the endian member of the image structure.
3006%
3007% The format of the ReadBlobFloat method is:
3008%
3009% float ReadBlobFloat(Image *image)
3010%
3011% A description of each parameter follows.
3012%
3013% o image: the image.
3014%
3015*/
3016MagickExport float ReadBlobFloat(Image *image)
3017{
3018 union
3019 {
3020 unsigned int
3021 unsigned_value;
3022
3023 float
3024 float_value;
3025 } quantum;
3026
3027 quantum.float_value=0.0;
3028 quantum.unsigned_value=ReadBlobLong(image);
3029 return(quantum.float_value);
3030}
3031
3032/*
3033%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3034% %
3035% %
3036% %
3037+ R e a d B l o b L o n g %
3038% %
3039% %
3040% %
3041%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3042%
cristybb503372010-05-27 20:51:26 +00003043% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003044% specified by the endian member of the image structure.
3045%
3046% The format of the ReadBlobLong method is:
3047%
3048% unsigned int ReadBlobLong(Image *image)
3049%
3050% A description of each parameter follows.
3051%
3052% o image: the image.
3053%
3054*/
3055MagickExport unsigned int ReadBlobLong(Image *image)
3056{
3057 register const unsigned char
3058 *p;
3059
3060 ssize_t
3061 count;
3062
3063 unsigned char
3064 buffer[4];
3065
3066 unsigned int
3067 value;
3068
3069 assert(image != (Image *) NULL);
3070 assert(image->signature == MagickSignature);
3071 *buffer='\0';
3072 p=ReadBlobStream(image,4,buffer,&count);
3073 if (count != 4)
3074 return(0UL);
3075 if (image->endian == LSBEndian)
3076 {
3077 value=(unsigned int) (*p++);
3078 value|=((unsigned int) (*p++)) << 8;
3079 value|=((unsigned int) (*p++)) << 16;
3080 value|=((unsigned int) (*p++)) << 24;
3081 return(value);
3082 }
3083 value=((unsigned int) (*p++)) << 24;
3084 value|=((unsigned int) (*p++)) << 16;
3085 value|=((unsigned int) (*p++)) << 8;
3086 value|=((unsigned int) (*p++));
3087 return(value);
3088}
3089
3090/*
3091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3092% %
3093% %
3094% %
3095+ R e a d B l o b L o n g L o n g %
3096% %
3097% %
3098% %
3099%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3100%
cristy4cb162a2010-05-30 03:04:47 +00003101% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3102% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003103%
cristy4cb162a2010-05-30 03:04:47 +00003104% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003105%
cristy4cb162a2010-05-30 03:04:47 +00003106% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003107%
3108% A description of each parameter follows.
3109%
3110% o image: the image.
3111%
3112*/
3113MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3114{
cristy0286d852010-10-12 18:38:07 +00003115 MagickSizeType
3116 value;
3117
cristy3ed852e2009-09-05 21:47:34 +00003118 register const unsigned char
3119 *p;
3120
3121 ssize_t
3122 count;
3123
3124 unsigned char
3125 buffer[8];
3126
cristy3ed852e2009-09-05 21:47:34 +00003127 assert(image != (Image *) NULL);
3128 assert(image->signature == MagickSignature);
3129 *buffer='\0';
3130 p=ReadBlobStream(image,8,buffer,&count);
3131 if (count != 8)
3132 return(MagickULLConstant(0));
3133 if (image->endian == LSBEndian)
3134 {
3135 value=(MagickSizeType) (*p++);
3136 value|=((MagickSizeType) (*p++)) << 8;
3137 value|=((MagickSizeType) (*p++)) << 16;
3138 value|=((MagickSizeType) (*p++)) << 24;
3139 value|=((MagickSizeType) (*p++)) << 32;
3140 value|=((MagickSizeType) (*p++)) << 40;
3141 value|=((MagickSizeType) (*p++)) << 48;
3142 value|=((MagickSizeType) (*p++)) << 56;
3143 return(value & MagickULLConstant(0xffffffffffffffff));
3144 }
3145 value=((MagickSizeType) (*p++)) << 56;
3146 value|=((MagickSizeType) (*p++)) << 48;
3147 value|=((MagickSizeType) (*p++)) << 40;
3148 value|=((MagickSizeType) (*p++)) << 32;
3149 value|=((MagickSizeType) (*p++)) << 24;
3150 value|=((MagickSizeType) (*p++)) << 16;
3151 value|=((MagickSizeType) (*p++)) << 8;
3152 value|=((MagickSizeType) (*p++));
3153 return(value & MagickULLConstant(0xffffffffffffffff));
3154}
3155
3156/*
3157%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3158% %
3159% %
3160% %
3161+ R e a d B l o b S h o r t %
3162% %
3163% %
3164% %
3165%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3166%
3167% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3168% specified by the endian member of the image structure.
3169%
3170% The format of the ReadBlobShort method is:
3171%
3172% unsigned short ReadBlobShort(Image *image)
3173%
3174% A description of each parameter follows.
3175%
3176% o image: the image.
3177%
3178*/
3179MagickExport unsigned short ReadBlobShort(Image *image)
3180{
3181 register const unsigned char
3182 *p;
3183
3184 register unsigned int
3185 value;
3186
3187 ssize_t
3188 count;
3189
3190 unsigned char
3191 buffer[2];
3192
3193 assert(image != (Image *) NULL);
3194 assert(image->signature == MagickSignature);
3195 *buffer='\0';
3196 p=ReadBlobStream(image,2,buffer,&count);
3197 if (count != 2)
3198 return((unsigned short) 0U);
3199 if (image->endian == LSBEndian)
3200 {
3201 value=(unsigned int) (*p++);
3202 value|=((unsigned int) (*p++)) << 8;
3203 return((unsigned short) (value & 0xffff));
3204 }
3205 value=(unsigned int) ((*p++) << 8);
3206 value|=(unsigned int) (*p++);
3207 return((unsigned short) (value & 0xffff));
3208}
3209
3210/*
3211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3212% %
3213% %
3214% %
3215+ R e a d B l o b L S B L o n g %
3216% %
3217% %
3218% %
3219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3220%
cristybb503372010-05-27 20:51:26 +00003221% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003222% least-significant byte first order.
3223%
3224% The format of the ReadBlobLSBLong method is:
3225%
3226% unsigned int ReadBlobLSBLong(Image *image)
3227%
3228% A description of each parameter follows.
3229%
3230% o image: the image.
3231%
3232*/
3233MagickExport unsigned int ReadBlobLSBLong(Image *image)
3234{
3235 register const unsigned char
3236 *p;
3237
3238 register unsigned int
3239 value;
3240
3241 ssize_t
3242 count;
3243
3244 unsigned char
3245 buffer[4];
3246
3247 assert(image != (Image *) NULL);
3248 assert(image->signature == MagickSignature);
3249 *buffer='\0';
3250 p=ReadBlobStream(image,4,buffer,&count);
3251 if (count != 4)
3252 return(0U);
3253 value=(unsigned int) (*p++);
3254 value|=((unsigned int) (*p++)) << 8;
3255 value|=((unsigned int) (*p++)) << 16;
3256 value|=((unsigned int) (*p++)) << 24;
3257 return(value);
3258}
3259
3260/*
3261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3262% %
3263% %
3264% %
3265+ R e a d B l o b L S B S h o r t %
3266% %
3267% %
3268% %
3269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3270%
3271% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3272% least-significant byte first order.
3273%
3274% The format of the ReadBlobLSBShort method is:
3275%
3276% unsigned short ReadBlobLSBShort(Image *image)
3277%
3278% A description of each parameter follows.
3279%
3280% o image: the image.
3281%
3282*/
3283MagickExport unsigned short ReadBlobLSBShort(Image *image)
3284{
3285 register const unsigned char
3286 *p;
3287
3288 register unsigned int
3289 value;
3290
3291 ssize_t
3292 count;
3293
3294 unsigned char
3295 buffer[2];
3296
3297 assert(image != (Image *) NULL);
3298 assert(image->signature == MagickSignature);
3299 *buffer='\0';
3300 p=ReadBlobStream(image,2,buffer,&count);
3301 if (count != 2)
3302 return((unsigned short) 0U);
3303 value=(unsigned int) (*p++);
3304 value|=((unsigned int) ((*p++)) << 8);
3305 return((unsigned short) (value & 0xffff));
3306}
3307
3308/*
3309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3310% %
3311% %
3312% %
3313+ R e a d B l o b M S B L o n g %
3314% %
3315% %
3316% %
3317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3318%
cristybb503372010-05-27 20:51:26 +00003319% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003320% most-significant byte first order.
3321%
3322% The format of the ReadBlobMSBLong method is:
3323%
3324% unsigned int ReadBlobMSBLong(Image *image)
3325%
3326% A description of each parameter follows.
3327%
3328% o image: the image.
3329%
3330*/
3331MagickExport unsigned int ReadBlobMSBLong(Image *image)
3332{
3333 register const unsigned char
3334 *p;
3335
3336 register unsigned int
3337 value;
3338
3339 ssize_t
3340 count;
3341
3342 unsigned char
3343 buffer[4];
3344
3345 assert(image != (Image *) NULL);
3346 assert(image->signature == MagickSignature);
3347 *buffer='\0';
3348 p=ReadBlobStream(image,4,buffer,&count);
3349 if (count != 4)
3350 return(0UL);
3351 value=((unsigned int) (*p++) << 24);
3352 value|=((unsigned int) (*p++) << 16);
3353 value|=((unsigned int) (*p++) << 8);
3354 value|=(unsigned int) (*p++);
3355 return(value);
3356}
3357
3358/*
3359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3360% %
3361% %
3362% %
cristy2d3d87f2010-03-01 00:23:08 +00003363+ R e a d B l o b M S B L o n g L o n g %
3364% %
3365% %
3366% %
3367%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3368%
cristybb503372010-05-27 20:51:26 +00003369% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003370% most-significant byte first order.
3371%
3372% The format of the ReadBlobMSBLongLong method is:
3373%
3374% unsigned int ReadBlobMSBLongLong(Image *image)
3375%
3376% A description of each parameter follows.
3377%
3378% o image: the image.
3379%
3380*/
3381MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3382{
3383 register const unsigned char
3384 *p;
3385
3386 register MagickSizeType
3387 value;
3388
3389 ssize_t
3390 count;
3391
3392 unsigned char
cristy0286d852010-10-12 18:38:07 +00003393 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003394
3395 assert(image != (Image *) NULL);
3396 assert(image->signature == MagickSignature);
3397 *buffer='\0';
3398 p=ReadBlobStream(image,8,buffer,&count);
3399 if (count != 8)
3400 return(MagickULLConstant(0));
3401 value=((MagickSizeType) (*p++)) << 56;
3402 value|=((MagickSizeType) (*p++)) << 48;
3403 value|=((MagickSizeType) (*p++)) << 40;
3404 value|=((MagickSizeType) (*p++)) << 32;
3405 value|=((MagickSizeType) (*p++)) << 24;
3406 value|=((MagickSizeType) (*p++)) << 16;
3407 value|=((MagickSizeType) (*p++)) << 8;
3408 value|=((MagickSizeType) (*p++));
3409 return(value & MagickULLConstant(0xffffffffffffffff));
3410}
3411
3412/*
3413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3414% %
3415% %
3416% %
cristy3ed852e2009-09-05 21:47:34 +00003417+ R e a d B l o b M S B S h o r t %
3418% %
3419% %
3420% %
3421%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3422%
3423% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3424% most-significant byte first order.
3425%
3426% The format of the ReadBlobMSBShort method is:
3427%
3428% unsigned short ReadBlobMSBShort(Image *image)
3429%
3430% A description of each parameter follows.
3431%
3432% o image: the image.
3433%
3434*/
3435MagickExport unsigned short ReadBlobMSBShort(Image *image)
3436{
3437 register const unsigned char
3438 *p;
3439
3440 register unsigned int
3441 value;
3442
3443 ssize_t
3444 count;
3445
3446 unsigned char
3447 buffer[2];
3448
3449 assert(image != (Image *) NULL);
3450 assert(image->signature == MagickSignature);
3451 *buffer='\0';
3452 p=ReadBlobStream(image,2,buffer,&count);
3453 if (count != 2)
3454 return((unsigned short) 0U);
3455 value=(unsigned int) ((*p++) << 8);
3456 value|=(unsigned int) (*p++);
3457 return((unsigned short) (value & 0xffff));
3458}
3459
3460/*
3461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3462% %
3463% %
3464% %
3465+ R e a d B l o b S t r i n g %
3466% %
3467% %
3468% %
3469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3470%
3471% ReadBlobString() reads characters from a blob or file until a newline
3472% character is read or an end-of-file condition is encountered.
3473%
3474% The format of the ReadBlobString method is:
3475%
3476% char *ReadBlobString(Image *image,char *string)
3477%
3478% A description of each parameter follows:
3479%
3480% o image: the image.
3481%
3482% o string: the address of a character buffer.
3483%
3484*/
3485MagickExport char *ReadBlobString(Image *image,char *string)
3486{
3487 register const unsigned char
3488 *p;
3489
cristybb503372010-05-27 20:51:26 +00003490 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003491 i;
3492
3493 ssize_t
3494 count;
3495
3496 unsigned char
3497 buffer[1];
3498
3499 assert(image != (Image *) NULL);
3500 assert(image->signature == MagickSignature);
3501 for (i=0; i < (MaxTextExtent-1L); i++)
3502 {
3503 p=ReadBlobStream(image,1,buffer,&count);
3504 if (count != 1)
3505 {
3506 if (i == 0)
3507 return((char *) NULL);
3508 break;
3509 }
3510 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003511 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003512 break;
3513 }
cristy2b5db102010-06-09 01:07:28 +00003514 if (string[i] == '\r')
3515 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003516 string[i]='\0';
3517 return(string);
3518}
3519
3520/*
3521%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3522% %
3523% %
3524% %
3525+ R e f e r e n c e B l o b %
3526% %
3527% %
3528% %
3529%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3530%
3531% ReferenceBlob() increments the reference count associated with the pixel
3532% blob returning a pointer to the blob.
3533%
3534% The format of the ReferenceBlob method is:
3535%
3536% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3537%
3538% A description of each parameter follows:
3539%
3540% o blob_info: the blob_info.
3541%
3542*/
3543MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3544{
3545 assert(blob != (BlobInfo *) NULL);
3546 assert(blob->signature == MagickSignature);
3547 if (blob->debug != MagickFalse)
3548 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003549 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003550 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003551 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003552 return(blob);
3553}
3554
3555/*
3556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3557% %
3558% %
3559% %
3560+ S e e k B l o b %
3561% %
3562% %
3563% %
3564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3565%
3566% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3567% and returns the resulting offset.
3568%
3569% The format of the SeekBlob method is:
3570%
3571% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3572% const int whence)
3573%
3574% A description of each parameter follows:
3575%
3576% o image: the image.
3577%
3578% o offset: Specifies an integer representing the offset in bytes.
3579%
3580% o whence: Specifies an integer representing how the offset is
3581% treated relative to the beginning of the blob as follows:
3582%
3583% SEEK_SET Set position equal to offset bytes.
3584% SEEK_CUR Set position to current location plus offset.
3585% SEEK_END Set position to EOF plus offset.
3586%
3587*/
3588MagickExport MagickOffsetType SeekBlob(Image *image,
3589 const MagickOffsetType offset,const int whence)
3590{
3591 assert(image != (Image *) NULL);
3592 assert(image->signature == MagickSignature);
3593 if (image->debug != MagickFalse)
3594 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3595 assert(image->blob != (BlobInfo *) NULL);
3596 assert(image->blob->type != UndefinedStream);
3597 switch (image->blob->type)
3598 {
3599 case UndefinedStream:
3600 break;
cristybc20d112012-07-29 20:27:00 +00003601 case StandardStream:
3602 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003603 case FileStream:
3604 {
cristyb7144222014-05-18 21:09:22 +00003605 if ((whence == SEEK_SET) && (offset < 0))
3606 return(-1);
cristye7b28372012-06-17 13:59:06 +00003607 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003608 return(-1);
3609 image->blob->offset=TellBlob(image);
3610 break;
3611 }
cristy3ed852e2009-09-05 21:47:34 +00003612 case PipeStream:
3613 case ZipStream:
3614 {
3615#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003616 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003617 return(-1);
3618#endif
3619 image->blob->offset=TellBlob(image);
3620 break;
3621 }
3622 case BZipStream:
3623 return(-1);
3624 case FifoStream:
3625 return(-1);
3626 case BlobStream:
3627 {
3628 switch (whence)
3629 {
3630 case SEEK_SET:
3631 default:
3632 {
3633 if (offset < 0)
3634 return(-1);
3635 image->blob->offset=offset;
3636 break;
3637 }
3638 case SEEK_CUR:
3639 {
3640 if ((image->blob->offset+offset) < 0)
3641 return(-1);
3642 image->blob->offset+=offset;
3643 break;
3644 }
3645 case SEEK_END:
3646 {
3647 if (((MagickOffsetType) image->blob->length+offset) < 0)
3648 return(-1);
3649 image->blob->offset=image->blob->length+offset;
3650 break;
3651 }
3652 }
3653 if (image->blob->offset <= (MagickOffsetType)
3654 ((off_t) image->blob->length))
3655 image->blob->eof=MagickFalse;
3656 else
3657 if (image->blob->mapped != MagickFalse)
3658 return(-1);
3659 else
3660 {
3661 image->blob->extent=(size_t) (image->blob->offset+
3662 image->blob->quantum);
cristyff368632014-01-27 13:01:38 +00003663 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00003664 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3665 image->blob->data,image->blob->extent+1,
3666 sizeof(*image->blob->data));
3667 (void) SyncBlob(image);
3668 if (image->blob->data == (unsigned char *) NULL)
3669 {
3670 (void) DetachBlob(image->blob);
3671 return(-1);
3672 }
3673 }
3674 break;
3675 }
3676 }
3677 return(image->blob->offset);
3678}
3679
3680/*
3681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3682% %
3683% %
3684% %
3685+ S e t B l o b E x e m p t %
3686% %
3687% %
3688% %
3689%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3690%
3691% SetBlobExempt() sets the blob exempt status.
3692%
3693% The format of the SetBlobExempt method is:
3694%
3695% MagickBooleanType SetBlobExempt(const Image *image,
3696% const MagickBooleanType exempt)
3697%
3698% A description of each parameter follows:
3699%
3700% o image: the image.
3701%
3702% o exempt: Set to true if this blob is exempt from being closed.
3703%
3704*/
cristy7832dc22011-09-05 01:21:53 +00003705MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003706{
3707 assert(image != (const Image *) NULL);
3708 assert(image->signature == MagickSignature);
3709 if (image->debug != MagickFalse)
3710 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3711 image->blob->exempt=exempt;
3712}
3713
3714/*
3715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3716% %
3717% %
3718% %
3719+ S e t B l o b E x t e n t %
3720% %
3721% %
3722% %
3723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3724%
3725% SetBlobExtent() ensures enough space is allocated for the blob. If the
3726% method is successful, subsequent writes to bytes in the specified range are
3727% guaranteed not to fail.
3728%
3729% The format of the SetBlobExtent method is:
3730%
3731% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3732%
3733% A description of each parameter follows:
3734%
3735% o image: the image.
3736%
3737% o extent: the blob maximum extent.
3738%
3739*/
cristy7832dc22011-09-05 01:21:53 +00003740MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003741 const MagickSizeType extent)
3742{
3743 assert(image != (Image *) NULL);
3744 assert(image->signature == MagickSignature);
3745 if (image->debug != MagickFalse)
3746 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3747 assert(image->blob != (BlobInfo *) NULL);
3748 assert(image->blob->type != UndefinedStream);
3749 switch (image->blob->type)
3750 {
3751 case UndefinedStream:
3752 break;
cristybc20d112012-07-29 20:27:00 +00003753 case StandardStream:
3754 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003755 case FileStream:
3756 {
cristy38e35f42012-12-18 21:12:17 +00003757 MagickOffsetType
3758 offset;
3759
3760 ssize_t
3761 count;
3762
cristy3ed852e2009-09-05 21:47:34 +00003763 if (extent != (MagickSizeType) ((off_t) extent))
3764 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003765 offset=SeekBlob(image,0,SEEK_END);
3766 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003767 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003768 if ((MagickSizeType) offset >= extent)
3769 break;
3770 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003771 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3772 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003773#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3774 if (image->blob->synchronize != MagickFalse)
3775 {
3776 int
3777 status;
3778
3779 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3780 extent-offset);
3781 if (status != 0)
3782 return(MagickFalse);
3783 }
3784#endif
cristy38e35f42012-12-18 21:12:17 +00003785 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003786 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003787 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003788 break;
3789 }
cristy3ed852e2009-09-05 21:47:34 +00003790 case PipeStream:
3791 case ZipStream:
3792 return(MagickFalse);
3793 case BZipStream:
3794 return(MagickFalse);
3795 case FifoStream:
3796 return(MagickFalse);
3797 case BlobStream:
3798 {
cristy38e35f42012-12-18 21:12:17 +00003799 if (extent != (MagickSizeType) ((size_t) extent))
3800 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003801 if (image->blob->mapped != MagickFalse)
3802 {
cristy38e35f42012-12-18 21:12:17 +00003803 MagickOffsetType
3804 offset;
3805
3806 ssize_t
3807 count;
3808
cristy3ed852e2009-09-05 21:47:34 +00003809 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy18aba912013-06-14 19:48:08 +00003810 RelinquishMagickResource(MapResource,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003811 if (extent != (MagickSizeType) ((off_t) extent))
3812 return(MagickFalse);
3813 offset=SeekBlob(image,0,SEEK_END);
3814 if (offset < 0)
3815 return(MagickFalse);
3816 if ((MagickSizeType) offset >= extent)
3817 break;
3818 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003819 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003820 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003821#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3822 if (image->blob->synchronize != MagickFalse)
3823 {
3824 int
3825 status;
3826
3827 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3828 extent-offset);
3829 if (status != 0)
3830 return(MagickFalse);
3831 }
3832#endif
cristy38e35f42012-12-18 21:12:17 +00003833 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003834 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003835 return(MagickFalse);
cristyac1caa22013-06-15 00:41:21 +00003836 (void) AcquireMagickResource(MapResource,extent);
cristy95888612012-04-04 21:56:52 +00003837 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003838 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003839 image->blob->extent=(size_t) extent;
3840 image->blob->length=(size_t) extent;
3841 (void) SyncBlob(image);
3842 break;
cristy3ed852e2009-09-05 21:47:34 +00003843 }
cristy3ed852e2009-09-05 21:47:34 +00003844 image->blob->extent=(size_t) extent;
3845 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3846 image->blob->extent+1,sizeof(*image->blob->data));
3847 (void) SyncBlob(image);
3848 if (image->blob->data == (unsigned char *) NULL)
3849 {
3850 (void) DetachBlob(image->blob);
3851 return(MagickFalse);
3852 }
3853 break;
3854 }
3855 }
3856 return(MagickTrue);
3857}
3858
3859/*
3860%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3861% %
3862% %
3863% %
3864+ S y n c B l o b %
3865% %
3866% %
3867% %
3868%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3869%
3870% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3871% attributes if it is an blob.
3872%
3873% The format of the SyncBlob method is:
3874%
3875% int SyncBlob(Image *image)
3876%
3877% A description of each parameter follows:
3878%
3879% o image: the image.
3880%
3881*/
3882static int SyncBlob(Image *image)
3883{
3884 int
3885 status;
3886
3887 assert(image != (Image *) NULL);
3888 assert(image->signature == MagickSignature);
3889 if (image->debug != MagickFalse)
3890 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3891 assert(image->blob != (BlobInfo *) NULL);
3892 assert(image->blob->type != UndefinedStream);
3893 status=0;
3894 switch (image->blob->type)
3895 {
3896 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003897 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003898 break;
3899 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003900 case PipeStream:
3901 {
cristye7b28372012-06-17 13:59:06 +00003902 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003903 break;
3904 }
3905 case ZipStream:
3906 {
3907#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003908 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003909#endif
3910 break;
3911 }
3912 case BZipStream:
3913 {
3914#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003915 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003916#endif
3917 break;
3918 }
3919 case FifoStream:
3920 break;
3921 case BlobStream:
cristy3ed852e2009-09-05 21:47:34 +00003922 break;
cristy3ed852e2009-09-05 21:47:34 +00003923 }
3924 return(status);
3925}
3926
3927/*
3928%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3929% %
3930% %
3931% %
3932+ T e l l B l o b %
3933% %
3934% %
3935% %
3936%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3937%
3938% TellBlob() obtains the current value of the blob or file position.
3939%
3940% The format of the TellBlob method is:
3941%
3942% MagickOffsetType TellBlob(const Image *image)
3943%
3944% A description of each parameter follows:
3945%
3946% o image: the image.
3947%
3948*/
3949MagickExport MagickOffsetType TellBlob(const Image *image)
3950{
3951 MagickOffsetType
3952 offset;
3953
3954 assert(image != (Image *) NULL);
3955 assert(image->signature == MagickSignature);
3956 if (image->debug != MagickFalse)
3957 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3958 assert(image->blob != (BlobInfo *) NULL);
3959 assert(image->blob->type != UndefinedStream);
3960 offset=(-1);
3961 switch (image->blob->type)
3962 {
3963 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003964 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003965 break;
3966 case FileStream:
3967 {
cristye7b28372012-06-17 13:59:06 +00003968 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003969 break;
3970 }
cristy3ed852e2009-09-05 21:47:34 +00003971 case PipeStream:
3972 break;
3973 case ZipStream:
3974 {
3975#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003976 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003977#endif
3978 break;
3979 }
3980 case BZipStream:
3981 break;
3982 case FifoStream:
3983 break;
3984 case BlobStream:
3985 {
3986 offset=image->blob->offset;
3987 break;
3988 }
3989 }
3990 return(offset);
3991}
3992
3993/*
3994%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3995% %
3996% %
3997% %
3998+ U n m a p B l o b %
3999% %
4000% %
4001% %
4002%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4003%
4004% UnmapBlob() deallocates the binary large object previously allocated with
4005% the MapBlob method.
4006%
4007% The format of the UnmapBlob method is:
4008%
4009% MagickBooleanType UnmapBlob(void *map,const size_t length)
4010%
4011% A description of each parameter follows:
4012%
4013% o map: the address of the binary large object.
4014%
4015% o length: the length of the binary large object.
4016%
4017*/
4018MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4019{
cristydc8ea8e2013-07-28 20:10:44 +00004020#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00004021 int
4022 status;
4023
4024 status=munmap(map,length);
4025 return(status == -1 ? MagickFalse : MagickTrue);
4026#else
4027 (void) map;
4028 (void) length;
4029 return(MagickFalse);
4030#endif
4031}
4032
4033/*
4034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4035% %
4036% %
4037% %
4038+ W r i t e B l o b %
4039% %
4040% %
4041% %
4042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4043%
4044% WriteBlob() writes data to a blob or image file. It returns the number of
4045% bytes written.
4046%
4047% The format of the WriteBlob method is:
4048%
4049% ssize_t WriteBlob(Image *image,const size_t length,
4050% const unsigned char *data)
4051%
4052% A description of each parameter follows:
4053%
4054% o image: the image.
4055%
4056% o length: Specifies an integer representing the number of bytes to
4057% write to the file.
4058%
4059% o data: The address of the data to write to the blob or file.
4060%
4061*/
4062MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4063 const unsigned char *data)
4064{
4065 int
4066 c;
4067
4068 register const unsigned char
4069 *p;
4070
4071 ssize_t
4072 count;
4073
4074 assert(image != (Image *) NULL);
4075 assert(image->signature == MagickSignature);
4076 assert(data != (const unsigned char *) NULL);
4077 assert(image->blob != (BlobInfo *) NULL);
4078 assert(image->blob->type != UndefinedStream);
4079 if (length == 0)
4080 return(0);
4081 count=0;
4082 p=data;
4083 switch (image->blob->type)
4084 {
4085 case UndefinedStream:
4086 break;
cristy3ed852e2009-09-05 21:47:34 +00004087 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004088 {
cristy5f3d2752013-01-05 18:53:38 +00004089 count=write(fileno(image->blob->file_info.file),data,length);
cristybc20d112012-07-29 20:27:00 +00004090 break;
4091 }
4092 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004093 case PipeStream:
4094 {
4095 switch (length)
4096 {
4097 default:
4098 {
4099 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004100 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004101 break;
4102 }
4103 case 2:
4104 {
cristye7b28372012-06-17 13:59:06 +00004105 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004106 if (c == EOF)
4107 break;
4108 count++;
4109 }
4110 case 1:
4111 {
cristye7b28372012-06-17 13:59:06 +00004112 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004113 if (c == EOF)
4114 break;
4115 count++;
4116 }
4117 case 0:
4118 break;
4119 }
4120 break;
4121 }
4122 case ZipStream:
4123 {
4124#if defined(MAGICKCORE_ZLIB_DELEGATE)
4125 switch (length)
4126 {
4127 default:
4128 {
cristye7b28372012-06-17 13:59:06 +00004129 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004130 (unsigned int) length);
4131 break;
4132 }
4133 case 2:
4134 {
cristye7b28372012-06-17 13:59:06 +00004135 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004136 if (c == EOF)
4137 break;
4138 count++;
4139 }
4140 case 1:
4141 {
cristye7b28372012-06-17 13:59:06 +00004142 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004143 if (c == EOF)
4144 break;
4145 count++;
4146 }
4147 case 0:
4148 break;
4149 }
4150#endif
4151 break;
4152 }
4153 case BZipStream:
4154 {
4155#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004156 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004157 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004158#endif
4159 break;
4160 }
4161 case FifoStream:
4162 {
4163 count=(ssize_t) image->blob->stream(image,data,length);
4164 break;
4165 }
4166 case BlobStream:
4167 {
4168 register unsigned char
4169 *q;
4170
4171 if ((image->blob->offset+(MagickOffsetType) length) >=
4172 (MagickOffsetType) image->blob->extent)
4173 {
4174 if (image->blob->mapped != MagickFalse)
4175 return(0);
cristy3ed852e2009-09-05 21:47:34 +00004176 image->blob->extent+=length+image->blob->quantum;
cristyff368632014-01-27 13:01:38 +00004177 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00004178 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4179 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4180 (void) SyncBlob(image);
4181 if (image->blob->data == (unsigned char *) NULL)
4182 {
4183 (void) DetachBlob(image->blob);
4184 return(0);
4185 }
4186 }
4187 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004188 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004189 image->blob->offset+=length;
4190 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4191 image->blob->length=(size_t) image->blob->offset;
4192 count=(ssize_t) length;
4193 }
4194 }
4195 return(count);
4196}
4197
4198/*
4199%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4200% %
4201% %
4202% %
4203+ W r i t e B l o b B y t e %
4204% %
4205% %
4206% %
4207%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4208%
4209% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4210% written (either 0 or 1);
4211%
4212% The format of the WriteBlobByte method is:
4213%
4214% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4215%
4216% A description of each parameter follows.
4217%
4218% o image: the image.
4219%
4220% o value: Specifies the value to write.
4221%
4222*/
4223MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4224{
4225 assert(image != (Image *) NULL);
4226 assert(image->signature == MagickSignature);
4227 return(WriteBlobStream(image,1,&value));
4228}
4229
4230/*
4231%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4232% %
4233% %
4234% %
4235+ W r i t e B l o b F l o a t %
4236% %
4237% %
4238% %
4239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4240%
4241% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4242% specified by the endian member of the image structure.
4243%
4244% The format of the WriteBlobFloat method is:
4245%
4246% ssize_t WriteBlobFloat(Image *image,const float value)
4247%
4248% A description of each parameter follows.
4249%
4250% o image: the image.
4251%
4252% o value: Specifies the value to write.
4253%
4254*/
4255MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4256{
4257 union
4258 {
4259 unsigned int
4260 unsigned_value;
4261
4262 float
4263 float_value;
4264 } quantum;
4265
4266 quantum.unsigned_value=0U;
4267 quantum.float_value=value;
4268 return(WriteBlobLong(image,quantum.unsigned_value));
4269}
4270
4271/*
4272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4273% %
4274% %
4275% %
4276+ W r i t e B l o b L o n g %
4277% %
4278% %
4279% %
4280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4281%
cristybb503372010-05-27 20:51:26 +00004282% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004283% specified by the endian member of the image structure.
4284%
4285% The format of the WriteBlobLong method is:
4286%
4287% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4288%
4289% A description of each parameter follows.
4290%
4291% o image: the image.
4292%
4293% o value: Specifies the value to write.
4294%
4295*/
4296MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4297{
4298 unsigned char
4299 buffer[4];
4300
4301 assert(image != (Image *) NULL);
4302 assert(image->signature == MagickSignature);
4303 if (image->endian == LSBEndian)
4304 {
4305 buffer[0]=(unsigned char) value;
4306 buffer[1]=(unsigned char) (value >> 8);
4307 buffer[2]=(unsigned char) (value >> 16);
4308 buffer[3]=(unsigned char) (value >> 24);
4309 return(WriteBlobStream(image,4,buffer));
4310 }
4311 buffer[0]=(unsigned char) (value >> 24);
4312 buffer[1]=(unsigned char) (value >> 16);
4313 buffer[2]=(unsigned char) (value >> 8);
4314 buffer[3]=(unsigned char) value;
4315 return(WriteBlobStream(image,4,buffer));
4316}
4317
4318/*
4319%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4320% %
4321% %
4322% %
4323+ W r i t e B l o b S h o r t %
4324% %
4325% %
4326% %
4327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4328%
4329% WriteBlobShort() writes a short value as a 16-bit quantity in the
4330% byte-order specified by the endian member of the image structure.
4331%
4332% The format of the WriteBlobShort method is:
4333%
4334% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4335%
4336% A description of each parameter follows.
4337%
4338% o image: the image.
4339%
4340% o value: Specifies the value to write.
4341%
4342*/
4343MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4344{
4345 unsigned char
4346 buffer[2];
4347
4348 assert(image != (Image *) NULL);
4349 assert(image->signature == MagickSignature);
4350 if (image->endian == LSBEndian)
4351 {
4352 buffer[0]=(unsigned char) value;
4353 buffer[1]=(unsigned char) (value >> 8);
4354 return(WriteBlobStream(image,2,buffer));
4355 }
4356 buffer[0]=(unsigned char) (value >> 8);
4357 buffer[1]=(unsigned char) value;
4358 return(WriteBlobStream(image,2,buffer));
4359}
4360
4361/*
4362%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4363% %
4364% %
4365% %
4366+ W r i t e B l o b L S B L o n g %
4367% %
4368% %
4369% %
4370%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4371%
cristybb503372010-05-27 20:51:26 +00004372% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004373% least-significant byte first order.
4374%
4375% The format of the WriteBlobLSBLong method is:
4376%
4377% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4378%
4379% A description of each parameter follows.
4380%
4381% o image: the image.
4382%
4383% o value: Specifies the value to write.
4384%
4385*/
4386MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4387{
4388 unsigned char
4389 buffer[4];
4390
4391 assert(image != (Image *) NULL);
4392 assert(image->signature == MagickSignature);
4393 buffer[0]=(unsigned char) value;
4394 buffer[1]=(unsigned char) (value >> 8);
4395 buffer[2]=(unsigned char) (value >> 16);
4396 buffer[3]=(unsigned char) (value >> 24);
4397 return(WriteBlobStream(image,4,buffer));
4398}
4399
4400/*
4401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4402% %
4403% %
4404% %
4405+ W r i t e B l o b L S B S h o r t %
4406% %
4407% %
4408% %
4409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4410%
cristybb503372010-05-27 20:51:26 +00004411% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004412% least-significant byte first order.
4413%
4414% The format of the WriteBlobLSBShort method is:
4415%
4416% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4417%
4418% A description of each parameter follows.
4419%
4420% o image: the image.
4421%
4422% o value: Specifies the value to write.
4423%
4424*/
4425MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4426{
4427 unsigned char
4428 buffer[2];
4429
4430 assert(image != (Image *) NULL);
4431 assert(image->signature == MagickSignature);
4432 buffer[0]=(unsigned char) value;
4433 buffer[1]=(unsigned char) (value >> 8);
4434 return(WriteBlobStream(image,2,buffer));
4435}
4436
4437/*
4438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4439% %
4440% %
4441% %
4442+ W r i t e B l o b M S B L o n g %
4443% %
4444% %
4445% %
4446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4447%
cristybb503372010-05-27 20:51:26 +00004448% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004449% most-significant byte first order.
4450%
4451% The format of the WriteBlobMSBLong method is:
4452%
4453% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4454%
4455% A description of each parameter follows.
4456%
4457% o value: Specifies the value to write.
4458%
4459% o image: the image.
4460%
4461*/
4462MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4463{
4464 unsigned char
4465 buffer[4];
4466
4467 assert(image != (Image *) NULL);
4468 assert(image->signature == MagickSignature);
4469 buffer[0]=(unsigned char) (value >> 24);
4470 buffer[1]=(unsigned char) (value >> 16);
4471 buffer[2]=(unsigned char) (value >> 8);
4472 buffer[3]=(unsigned char) value;
4473 return(WriteBlobStream(image,4,buffer));
4474}
4475
4476/*
4477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4478% %
4479% %
4480% %
cristy2ca49922010-03-06 02:54:01 +00004481+ W r i t e B l o b M S B L o n g L o n g %
4482% %
4483% %
4484% %
4485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4486%
4487% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4488% most-significant byte first order.
4489%
4490% The format of the WriteBlobMSBLongLong method is:
4491%
4492% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4493%
4494% A description of each parameter follows.
4495%
4496% o value: Specifies the value to write.
4497%
4498% o image: the image.
4499%
4500*/
4501MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4502 const MagickSizeType value)
4503{
4504 unsigned char
4505 buffer[8];
4506
4507 assert(image != (Image *) NULL);
4508 assert(image->signature == MagickSignature);
4509 buffer[0]=(unsigned char) (value >> 56);
4510 buffer[1]=(unsigned char) (value >> 48);
4511 buffer[2]=(unsigned char) (value >> 40);
4512 buffer[3]=(unsigned char) (value >> 32);
4513 buffer[4]=(unsigned char) (value >> 24);
4514 buffer[5]=(unsigned char) (value >> 16);
4515 buffer[6]=(unsigned char) (value >> 8);
4516 buffer[7]=(unsigned char) value;
4517 return(WriteBlobStream(image,8,buffer));
4518}
4519
4520/*
4521%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4522% %
4523% %
4524% %
cristy3ed852e2009-09-05 21:47:34 +00004525+ W r i t e B l o b M S B S h o r t %
4526% %
4527% %
4528% %
4529%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4530%
cristybb503372010-05-27 20:51:26 +00004531% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004532% most-significant byte first order.
4533%
4534% The format of the WriteBlobMSBShort method is:
4535%
4536% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4537%
4538% A description of each parameter follows.
4539%
4540% o value: Specifies the value to write.
4541%
4542% o file: Specifies the file to write the data to.
4543%
4544*/
4545MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4546{
4547 unsigned char
4548 buffer[2];
4549
4550 assert(image != (Image *) NULL);
4551 assert(image->signature == MagickSignature);
4552 buffer[0]=(unsigned char) (value >> 8);
4553 buffer[1]=(unsigned char) value;
4554 return(WriteBlobStream(image,2,buffer));
4555}
4556
4557/*
4558%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4559% %
4560% %
4561% %
4562+ W r i t e B l o b S t r i n g %
4563% %
4564% %
4565% %
4566%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4567%
4568% WriteBlobString() write a string to a blob. It returns the number of
4569% characters written.
4570%
4571% The format of the WriteBlobString method is:
4572%
4573% ssize_t WriteBlobString(Image *image,const char *string)
4574%
4575% A description of each parameter follows.
4576%
4577% o image: the image.
4578%
4579% o string: Specifies the string to write.
4580%
4581*/
4582MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4583{
4584 assert(image != (Image *) NULL);
4585 assert(image->signature == MagickSignature);
4586 assert(string != (const char *) NULL);
4587 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4588}