blob: 91d04cb51922334c026d11bfd9982ca18a28887f [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 {
cristye7b28372012-06-17 13:59:06 +00003605 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003606 return(-1);
3607 image->blob->offset=TellBlob(image);
3608 break;
3609 }
cristy3ed852e2009-09-05 21:47:34 +00003610 case PipeStream:
3611 case ZipStream:
3612 {
3613#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003614 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003615 return(-1);
3616#endif
3617 image->blob->offset=TellBlob(image);
3618 break;
3619 }
3620 case BZipStream:
3621 return(-1);
3622 case FifoStream:
3623 return(-1);
3624 case BlobStream:
3625 {
3626 switch (whence)
3627 {
3628 case SEEK_SET:
3629 default:
3630 {
3631 if (offset < 0)
3632 return(-1);
3633 image->blob->offset=offset;
3634 break;
3635 }
3636 case SEEK_CUR:
3637 {
3638 if ((image->blob->offset+offset) < 0)
3639 return(-1);
3640 image->blob->offset+=offset;
3641 break;
3642 }
3643 case SEEK_END:
3644 {
3645 if (((MagickOffsetType) image->blob->length+offset) < 0)
3646 return(-1);
3647 image->blob->offset=image->blob->length+offset;
3648 break;
3649 }
3650 }
3651 if (image->blob->offset <= (MagickOffsetType)
3652 ((off_t) image->blob->length))
3653 image->blob->eof=MagickFalse;
3654 else
3655 if (image->blob->mapped != MagickFalse)
3656 return(-1);
3657 else
3658 {
3659 image->blob->extent=(size_t) (image->blob->offset+
3660 image->blob->quantum);
cristyff368632014-01-27 13:01:38 +00003661 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00003662 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3663 image->blob->data,image->blob->extent+1,
3664 sizeof(*image->blob->data));
3665 (void) SyncBlob(image);
3666 if (image->blob->data == (unsigned char *) NULL)
3667 {
3668 (void) DetachBlob(image->blob);
3669 return(-1);
3670 }
3671 }
3672 break;
3673 }
3674 }
3675 return(image->blob->offset);
3676}
3677
3678/*
3679%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3680% %
3681% %
3682% %
3683+ S e t B l o b E x e m p t %
3684% %
3685% %
3686% %
3687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3688%
3689% SetBlobExempt() sets the blob exempt status.
3690%
3691% The format of the SetBlobExempt method is:
3692%
3693% MagickBooleanType SetBlobExempt(const Image *image,
3694% const MagickBooleanType exempt)
3695%
3696% A description of each parameter follows:
3697%
3698% o image: the image.
3699%
3700% o exempt: Set to true if this blob is exempt from being closed.
3701%
3702*/
cristy7832dc22011-09-05 01:21:53 +00003703MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003704{
3705 assert(image != (const Image *) NULL);
3706 assert(image->signature == MagickSignature);
3707 if (image->debug != MagickFalse)
3708 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3709 image->blob->exempt=exempt;
3710}
3711
3712/*
3713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3714% %
3715% %
3716% %
3717+ S e t B l o b E x t e n t %
3718% %
3719% %
3720% %
3721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3722%
3723% SetBlobExtent() ensures enough space is allocated for the blob. If the
3724% method is successful, subsequent writes to bytes in the specified range are
3725% guaranteed not to fail.
3726%
3727% The format of the SetBlobExtent method is:
3728%
3729% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3730%
3731% A description of each parameter follows:
3732%
3733% o image: the image.
3734%
3735% o extent: the blob maximum extent.
3736%
3737*/
cristy7832dc22011-09-05 01:21:53 +00003738MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003739 const MagickSizeType extent)
3740{
3741 assert(image != (Image *) NULL);
3742 assert(image->signature == MagickSignature);
3743 if (image->debug != MagickFalse)
3744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3745 assert(image->blob != (BlobInfo *) NULL);
3746 assert(image->blob->type != UndefinedStream);
3747 switch (image->blob->type)
3748 {
3749 case UndefinedStream:
3750 break;
cristybc20d112012-07-29 20:27:00 +00003751 case StandardStream:
3752 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003753 case FileStream:
3754 {
cristy38e35f42012-12-18 21:12:17 +00003755 MagickOffsetType
3756 offset;
3757
3758 ssize_t
3759 count;
3760
cristy3ed852e2009-09-05 21:47:34 +00003761 if (extent != (MagickSizeType) ((off_t) extent))
3762 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003763 offset=SeekBlob(image,0,SEEK_END);
3764 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003765 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003766 if ((MagickSizeType) offset >= extent)
3767 break;
3768 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003769 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3770 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003771#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3772 if (image->blob->synchronize != MagickFalse)
3773 {
3774 int
3775 status;
3776
3777 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3778 extent-offset);
3779 if (status != 0)
3780 return(MagickFalse);
3781 }
3782#endif
cristy38e35f42012-12-18 21:12:17 +00003783 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003784 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003785 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003786 break;
3787 }
cristy3ed852e2009-09-05 21:47:34 +00003788 case PipeStream:
3789 case ZipStream:
3790 return(MagickFalse);
3791 case BZipStream:
3792 return(MagickFalse);
3793 case FifoStream:
3794 return(MagickFalse);
3795 case BlobStream:
3796 {
cristy38e35f42012-12-18 21:12:17 +00003797 if (extent != (MagickSizeType) ((size_t) extent))
3798 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003799 if (image->blob->mapped != MagickFalse)
3800 {
cristy38e35f42012-12-18 21:12:17 +00003801 MagickOffsetType
3802 offset;
3803
3804 ssize_t
3805 count;
3806
cristy3ed852e2009-09-05 21:47:34 +00003807 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy18aba912013-06-14 19:48:08 +00003808 RelinquishMagickResource(MapResource,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003809 if (extent != (MagickSizeType) ((off_t) extent))
3810 return(MagickFalse);
3811 offset=SeekBlob(image,0,SEEK_END);
3812 if (offset < 0)
3813 return(MagickFalse);
3814 if ((MagickSizeType) offset >= extent)
3815 break;
3816 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003817 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003818 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003819#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3820 if (image->blob->synchronize != MagickFalse)
3821 {
3822 int
3823 status;
3824
3825 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3826 extent-offset);
3827 if (status != 0)
3828 return(MagickFalse);
3829 }
3830#endif
cristy38e35f42012-12-18 21:12:17 +00003831 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003832 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003833 return(MagickFalse);
cristyac1caa22013-06-15 00:41:21 +00003834 (void) AcquireMagickResource(MapResource,extent);
cristy95888612012-04-04 21:56:52 +00003835 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003836 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003837 image->blob->extent=(size_t) extent;
3838 image->blob->length=(size_t) extent;
3839 (void) SyncBlob(image);
3840 break;
cristy3ed852e2009-09-05 21:47:34 +00003841 }
cristy3ed852e2009-09-05 21:47:34 +00003842 image->blob->extent=(size_t) extent;
3843 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3844 image->blob->extent+1,sizeof(*image->blob->data));
3845 (void) SyncBlob(image);
3846 if (image->blob->data == (unsigned char *) NULL)
3847 {
3848 (void) DetachBlob(image->blob);
3849 return(MagickFalse);
3850 }
3851 break;
3852 }
3853 }
3854 return(MagickTrue);
3855}
3856
3857/*
3858%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3859% %
3860% %
3861% %
3862+ S y n c B l o b %
3863% %
3864% %
3865% %
3866%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3867%
3868% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3869% attributes if it is an blob.
3870%
3871% The format of the SyncBlob method is:
3872%
3873% int SyncBlob(Image *image)
3874%
3875% A description of each parameter follows:
3876%
3877% o image: the image.
3878%
3879*/
3880static int SyncBlob(Image *image)
3881{
3882 int
3883 status;
3884
3885 assert(image != (Image *) NULL);
3886 assert(image->signature == MagickSignature);
3887 if (image->debug != MagickFalse)
3888 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3889 assert(image->blob != (BlobInfo *) NULL);
3890 assert(image->blob->type != UndefinedStream);
3891 status=0;
3892 switch (image->blob->type)
3893 {
3894 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003895 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003896 break;
3897 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003898 case PipeStream:
3899 {
cristye7b28372012-06-17 13:59:06 +00003900 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003901 break;
3902 }
3903 case ZipStream:
3904 {
3905#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003906 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003907#endif
3908 break;
3909 }
3910 case BZipStream:
3911 {
3912#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003913 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003914#endif
3915 break;
3916 }
3917 case FifoStream:
3918 break;
3919 case BlobStream:
cristy3ed852e2009-09-05 21:47:34 +00003920 break;
cristy3ed852e2009-09-05 21:47:34 +00003921 }
3922 return(status);
3923}
3924
3925/*
3926%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3927% %
3928% %
3929% %
3930+ T e l l B l o b %
3931% %
3932% %
3933% %
3934%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3935%
3936% TellBlob() obtains the current value of the blob or file position.
3937%
3938% The format of the TellBlob method is:
3939%
3940% MagickOffsetType TellBlob(const Image *image)
3941%
3942% A description of each parameter follows:
3943%
3944% o image: the image.
3945%
3946*/
3947MagickExport MagickOffsetType TellBlob(const Image *image)
3948{
3949 MagickOffsetType
3950 offset;
3951
3952 assert(image != (Image *) NULL);
3953 assert(image->signature == MagickSignature);
3954 if (image->debug != MagickFalse)
3955 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3956 assert(image->blob != (BlobInfo *) NULL);
3957 assert(image->blob->type != UndefinedStream);
3958 offset=(-1);
3959 switch (image->blob->type)
3960 {
3961 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003962 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003963 break;
3964 case FileStream:
3965 {
cristye7b28372012-06-17 13:59:06 +00003966 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003967 break;
3968 }
cristy3ed852e2009-09-05 21:47:34 +00003969 case PipeStream:
3970 break;
3971 case ZipStream:
3972 {
3973#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003974 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003975#endif
3976 break;
3977 }
3978 case BZipStream:
3979 break;
3980 case FifoStream:
3981 break;
3982 case BlobStream:
3983 {
3984 offset=image->blob->offset;
3985 break;
3986 }
3987 }
3988 return(offset);
3989}
3990
3991/*
3992%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3993% %
3994% %
3995% %
3996+ U n m a p B l o b %
3997% %
3998% %
3999% %
4000%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4001%
4002% UnmapBlob() deallocates the binary large object previously allocated with
4003% the MapBlob method.
4004%
4005% The format of the UnmapBlob method is:
4006%
4007% MagickBooleanType UnmapBlob(void *map,const size_t length)
4008%
4009% A description of each parameter follows:
4010%
4011% o map: the address of the binary large object.
4012%
4013% o length: the length of the binary large object.
4014%
4015*/
4016MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4017{
cristydc8ea8e2013-07-28 20:10:44 +00004018#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00004019 int
4020 status;
4021
4022 status=munmap(map,length);
4023 return(status == -1 ? MagickFalse : MagickTrue);
4024#else
4025 (void) map;
4026 (void) length;
4027 return(MagickFalse);
4028#endif
4029}
4030
4031/*
4032%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4033% %
4034% %
4035% %
4036+ W r i t e B l o b %
4037% %
4038% %
4039% %
4040%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4041%
4042% WriteBlob() writes data to a blob or image file. It returns the number of
4043% bytes written.
4044%
4045% The format of the WriteBlob method is:
4046%
4047% ssize_t WriteBlob(Image *image,const size_t length,
4048% const unsigned char *data)
4049%
4050% A description of each parameter follows:
4051%
4052% o image: the image.
4053%
4054% o length: Specifies an integer representing the number of bytes to
4055% write to the file.
4056%
4057% o data: The address of the data to write to the blob or file.
4058%
4059*/
4060MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4061 const unsigned char *data)
4062{
4063 int
4064 c;
4065
4066 register const unsigned char
4067 *p;
4068
4069 ssize_t
4070 count;
4071
4072 assert(image != (Image *) NULL);
4073 assert(image->signature == MagickSignature);
4074 assert(data != (const unsigned char *) NULL);
4075 assert(image->blob != (BlobInfo *) NULL);
4076 assert(image->blob->type != UndefinedStream);
4077 if (length == 0)
4078 return(0);
4079 count=0;
4080 p=data;
4081 switch (image->blob->type)
4082 {
4083 case UndefinedStream:
4084 break;
cristy3ed852e2009-09-05 21:47:34 +00004085 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004086 {
cristy5f3d2752013-01-05 18:53:38 +00004087 count=write(fileno(image->blob->file_info.file),data,length);
cristybc20d112012-07-29 20:27:00 +00004088 break;
4089 }
4090 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004091 case PipeStream:
4092 {
4093 switch (length)
4094 {
4095 default:
4096 {
4097 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004098 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004099 break;
4100 }
4101 case 2:
4102 {
cristye7b28372012-06-17 13:59:06 +00004103 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004104 if (c == EOF)
4105 break;
4106 count++;
4107 }
4108 case 1:
4109 {
cristye7b28372012-06-17 13:59:06 +00004110 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004111 if (c == EOF)
4112 break;
4113 count++;
4114 }
4115 case 0:
4116 break;
4117 }
4118 break;
4119 }
4120 case ZipStream:
4121 {
4122#if defined(MAGICKCORE_ZLIB_DELEGATE)
4123 switch (length)
4124 {
4125 default:
4126 {
cristye7b28372012-06-17 13:59:06 +00004127 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004128 (unsigned int) length);
4129 break;
4130 }
4131 case 2:
4132 {
cristye7b28372012-06-17 13:59:06 +00004133 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004134 if (c == EOF)
4135 break;
4136 count++;
4137 }
4138 case 1:
4139 {
cristye7b28372012-06-17 13:59:06 +00004140 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004141 if (c == EOF)
4142 break;
4143 count++;
4144 }
4145 case 0:
4146 break;
4147 }
4148#endif
4149 break;
4150 }
4151 case BZipStream:
4152 {
4153#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004154 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004155 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004156#endif
4157 break;
4158 }
4159 case FifoStream:
4160 {
4161 count=(ssize_t) image->blob->stream(image,data,length);
4162 break;
4163 }
4164 case BlobStream:
4165 {
4166 register unsigned char
4167 *q;
4168
4169 if ((image->blob->offset+(MagickOffsetType) length) >=
4170 (MagickOffsetType) image->blob->extent)
4171 {
4172 if (image->blob->mapped != MagickFalse)
4173 return(0);
cristy3ed852e2009-09-05 21:47:34 +00004174 image->blob->extent+=length+image->blob->quantum;
cristyff368632014-01-27 13:01:38 +00004175 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00004176 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4177 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4178 (void) SyncBlob(image);
4179 if (image->blob->data == (unsigned char *) NULL)
4180 {
4181 (void) DetachBlob(image->blob);
4182 return(0);
4183 }
4184 }
4185 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004186 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004187 image->blob->offset+=length;
4188 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4189 image->blob->length=(size_t) image->blob->offset;
4190 count=(ssize_t) length;
4191 }
4192 }
4193 return(count);
4194}
4195
4196/*
4197%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4198% %
4199% %
4200% %
4201+ W r i t e B l o b B y t e %
4202% %
4203% %
4204% %
4205%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4206%
4207% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4208% written (either 0 or 1);
4209%
4210% The format of the WriteBlobByte method is:
4211%
4212% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4213%
4214% A description of each parameter follows.
4215%
4216% o image: the image.
4217%
4218% o value: Specifies the value to write.
4219%
4220*/
4221MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4222{
4223 assert(image != (Image *) NULL);
4224 assert(image->signature == MagickSignature);
4225 return(WriteBlobStream(image,1,&value));
4226}
4227
4228/*
4229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4230% %
4231% %
4232% %
4233+ W r i t e B l o b F l o a t %
4234% %
4235% %
4236% %
4237%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4238%
4239% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4240% specified by the endian member of the image structure.
4241%
4242% The format of the WriteBlobFloat method is:
4243%
4244% ssize_t WriteBlobFloat(Image *image,const float value)
4245%
4246% A description of each parameter follows.
4247%
4248% o image: the image.
4249%
4250% o value: Specifies the value to write.
4251%
4252*/
4253MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4254{
4255 union
4256 {
4257 unsigned int
4258 unsigned_value;
4259
4260 float
4261 float_value;
4262 } quantum;
4263
4264 quantum.unsigned_value=0U;
4265 quantum.float_value=value;
4266 return(WriteBlobLong(image,quantum.unsigned_value));
4267}
4268
4269/*
4270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4271% %
4272% %
4273% %
4274+ W r i t e B l o b L o n g %
4275% %
4276% %
4277% %
4278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4279%
cristybb503372010-05-27 20:51:26 +00004280% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004281% specified by the endian member of the image structure.
4282%
4283% The format of the WriteBlobLong method is:
4284%
4285% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4286%
4287% A description of each parameter follows.
4288%
4289% o image: the image.
4290%
4291% o value: Specifies the value to write.
4292%
4293*/
4294MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4295{
4296 unsigned char
4297 buffer[4];
4298
4299 assert(image != (Image *) NULL);
4300 assert(image->signature == MagickSignature);
4301 if (image->endian == LSBEndian)
4302 {
4303 buffer[0]=(unsigned char) value;
4304 buffer[1]=(unsigned char) (value >> 8);
4305 buffer[2]=(unsigned char) (value >> 16);
4306 buffer[3]=(unsigned char) (value >> 24);
4307 return(WriteBlobStream(image,4,buffer));
4308 }
4309 buffer[0]=(unsigned char) (value >> 24);
4310 buffer[1]=(unsigned char) (value >> 16);
4311 buffer[2]=(unsigned char) (value >> 8);
4312 buffer[3]=(unsigned char) value;
4313 return(WriteBlobStream(image,4,buffer));
4314}
4315
4316/*
4317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4318% %
4319% %
4320% %
4321+ W r i t e B l o b S h o r t %
4322% %
4323% %
4324% %
4325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4326%
4327% WriteBlobShort() writes a short value as a 16-bit quantity in the
4328% byte-order specified by the endian member of the image structure.
4329%
4330% The format of the WriteBlobShort method is:
4331%
4332% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4333%
4334% A description of each parameter follows.
4335%
4336% o image: the image.
4337%
4338% o value: Specifies the value to write.
4339%
4340*/
4341MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4342{
4343 unsigned char
4344 buffer[2];
4345
4346 assert(image != (Image *) NULL);
4347 assert(image->signature == MagickSignature);
4348 if (image->endian == LSBEndian)
4349 {
4350 buffer[0]=(unsigned char) value;
4351 buffer[1]=(unsigned char) (value >> 8);
4352 return(WriteBlobStream(image,2,buffer));
4353 }
4354 buffer[0]=(unsigned char) (value >> 8);
4355 buffer[1]=(unsigned char) value;
4356 return(WriteBlobStream(image,2,buffer));
4357}
4358
4359/*
4360%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4361% %
4362% %
4363% %
4364+ W r i t e B l o b L S B L o n g %
4365% %
4366% %
4367% %
4368%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4369%
cristybb503372010-05-27 20:51:26 +00004370% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004371% least-significant byte first order.
4372%
4373% The format of the WriteBlobLSBLong method is:
4374%
4375% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4376%
4377% A description of each parameter follows.
4378%
4379% o image: the image.
4380%
4381% o value: Specifies the value to write.
4382%
4383*/
4384MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4385{
4386 unsigned char
4387 buffer[4];
4388
4389 assert(image != (Image *) NULL);
4390 assert(image->signature == MagickSignature);
4391 buffer[0]=(unsigned char) value;
4392 buffer[1]=(unsigned char) (value >> 8);
4393 buffer[2]=(unsigned char) (value >> 16);
4394 buffer[3]=(unsigned char) (value >> 24);
4395 return(WriteBlobStream(image,4,buffer));
4396}
4397
4398/*
4399%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4400% %
4401% %
4402% %
4403+ W r i t e B l o b L S B S h o r t %
4404% %
4405% %
4406% %
4407%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4408%
cristybb503372010-05-27 20:51:26 +00004409% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004410% least-significant byte first order.
4411%
4412% The format of the WriteBlobLSBShort method is:
4413%
4414% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4415%
4416% A description of each parameter follows.
4417%
4418% o image: the image.
4419%
4420% o value: Specifies the value to write.
4421%
4422*/
4423MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4424{
4425 unsigned char
4426 buffer[2];
4427
4428 assert(image != (Image *) NULL);
4429 assert(image->signature == MagickSignature);
4430 buffer[0]=(unsigned char) value;
4431 buffer[1]=(unsigned char) (value >> 8);
4432 return(WriteBlobStream(image,2,buffer));
4433}
4434
4435/*
4436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4437% %
4438% %
4439% %
4440+ W r i t e B l o b M S B L o n g %
4441% %
4442% %
4443% %
4444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4445%
cristybb503372010-05-27 20:51:26 +00004446% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004447% most-significant byte first order.
4448%
4449% The format of the WriteBlobMSBLong method is:
4450%
4451% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4452%
4453% A description of each parameter follows.
4454%
4455% o value: Specifies the value to write.
4456%
4457% o image: the image.
4458%
4459*/
4460MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4461{
4462 unsigned char
4463 buffer[4];
4464
4465 assert(image != (Image *) NULL);
4466 assert(image->signature == MagickSignature);
4467 buffer[0]=(unsigned char) (value >> 24);
4468 buffer[1]=(unsigned char) (value >> 16);
4469 buffer[2]=(unsigned char) (value >> 8);
4470 buffer[3]=(unsigned char) value;
4471 return(WriteBlobStream(image,4,buffer));
4472}
4473
4474/*
4475%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4476% %
4477% %
4478% %
cristy2ca49922010-03-06 02:54:01 +00004479+ W r i t e B l o b M S B L o n g L o n g %
4480% %
4481% %
4482% %
4483%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4484%
4485% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4486% most-significant byte first order.
4487%
4488% The format of the WriteBlobMSBLongLong method is:
4489%
4490% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4491%
4492% A description of each parameter follows.
4493%
4494% o value: Specifies the value to write.
4495%
4496% o image: the image.
4497%
4498*/
4499MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4500 const MagickSizeType value)
4501{
4502 unsigned char
4503 buffer[8];
4504
4505 assert(image != (Image *) NULL);
4506 assert(image->signature == MagickSignature);
4507 buffer[0]=(unsigned char) (value >> 56);
4508 buffer[1]=(unsigned char) (value >> 48);
4509 buffer[2]=(unsigned char) (value >> 40);
4510 buffer[3]=(unsigned char) (value >> 32);
4511 buffer[4]=(unsigned char) (value >> 24);
4512 buffer[5]=(unsigned char) (value >> 16);
4513 buffer[6]=(unsigned char) (value >> 8);
4514 buffer[7]=(unsigned char) value;
4515 return(WriteBlobStream(image,8,buffer));
4516}
4517
4518/*
4519%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4520% %
4521% %
4522% %
cristy3ed852e2009-09-05 21:47:34 +00004523+ W r i t e B l o b M S B S h o r t %
4524% %
4525% %
4526% %
4527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4528%
cristybb503372010-05-27 20:51:26 +00004529% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004530% most-significant byte first order.
4531%
4532% The format of the WriteBlobMSBShort method is:
4533%
4534% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4535%
4536% A description of each parameter follows.
4537%
4538% o value: Specifies the value to write.
4539%
4540% o file: Specifies the file to write the data to.
4541%
4542*/
4543MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4544{
4545 unsigned char
4546 buffer[2];
4547
4548 assert(image != (Image *) NULL);
4549 assert(image->signature == MagickSignature);
4550 buffer[0]=(unsigned char) (value >> 8);
4551 buffer[1]=(unsigned char) value;
4552 return(WriteBlobStream(image,2,buffer));
4553}
4554
4555/*
4556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4557% %
4558% %
4559% %
4560+ W r i t e B l o b S t r i n g %
4561% %
4562% %
4563% %
4564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4565%
4566% WriteBlobString() write a string to a blob. It returns the number of
4567% characters written.
4568%
4569% The format of the WriteBlobString method is:
4570%
4571% ssize_t WriteBlobString(Image *image,const char *string)
4572%
4573% A description of each parameter follows.
4574%
4575% o image: the image.
4576%
4577% o string: Specifies the string to write.
4578%
4579*/
4580MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4581{
4582 assert(image != (Image *) NULL);
4583 assert(image->signature == MagickSignature);
4584 assert(string != (const char *) NULL);
4585 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4586}