blob: 0955ad8374d82802a780ab113947e1d5dd2253bb [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% %
Cristy7ce65e72015-12-12 18:03:16 -050020% Copyright 1999-2016 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*/
Cristy9125cd52015-09-17 20:16:13 -040043#ifdef __VMS
44#include <types.h>
45#include <mman.h>
46#endif
cristy4c08aed2011-07-01 19:47:50 +000047#include "MagickCore/studio.h"
48#include "MagickCore/blob.h"
49#include "MagickCore/blob-private.h"
50#include "MagickCore/cache.h"
51#include "MagickCore/client.h"
52#include "MagickCore/constitute.h"
53#include "MagickCore/delegate.h"
54#include "MagickCore/exception.h"
55#include "MagickCore/exception-private.h"
56#include "MagickCore/image-private.h"
57#include "MagickCore/list.h"
58#include "MagickCore/locale_.h"
59#include "MagickCore/log.h"
60#include "MagickCore/magick.h"
61#include "MagickCore/memory_.h"
cristy9f3b4fc2014-02-08 14:56:20 +000062#include "MagickCore/nt-base-private.h"
cristyfb348292015-04-12 00:28:54 +000063#include "MagickCore/option.h"
cristy4c08aed2011-07-01 19:47:50 +000064#include "MagickCore/policy.h"
65#include "MagickCore/resource_.h"
66#include "MagickCore/semaphore.h"
67#include "MagickCore/string_.h"
68#include "MagickCore/string-private.h"
69#include "MagickCore/token.h"
70#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000071#include "MagickCore/utility-private.h"
cristy3ed852e2009-09-05 21:47:34 +000072#if defined(MAGICKCORE_ZLIB_DELEGATE)
73#include "zlib.h"
74#endif
75#if defined(MAGICKCORE_BZLIB_DELEGATE)
76#include "bzlib.h"
77#endif
78
79/*
80 Define declarations.
81*/
cristy38c8f5c2015-03-04 14:51:57 +000082#define MagickMaxBlobExtent (8*8192)
cristy3ed852e2009-09-05 21:47:34 +000083#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
84# define MAP_ANONYMOUS MAP_ANON
85#endif
86#if !defined(MAP_FAILED)
87#define MAP_FAILED ((void *) -1)
88#endif
cristy3ed852e2009-09-05 21:47:34 +000089#if defined(__OS2__)
90#include <io.h>
91#define _O_BINARY O_BINARY
92#endif
93
94/*
95 Typedef declarations.
96*/
cristye7b28372012-06-17 13:59:06 +000097typedef union FileInfo
98{
99 FILE
100 *file;
101
102#if defined(MAGICKCORE_ZLIB_DELEGATE)
103 gzFile
104 gzfile;
105#endif
106
107#if defined(MAGICKCORE_BZLIB_DELEGATE)
108 BZFILE
109 *bzfile;
110#endif
111} FileInfo;
112
cristy3ed852e2009-09-05 21:47:34 +0000113struct _BlobInfo
114{
115 size_t
116 length,
117 extent,
118 quantum;
119
120 MagickBooleanType
121 mapped,
122 eof;
123
124 MagickOffsetType
125 offset;
126
127 MagickSizeType
128 size;
129
130 MagickBooleanType
131 exempt,
cristy0779de22015-05-03 12:45:49 +0000132 immutable,
cristy3ed852e2009-09-05 21:47:34 +0000133 synchronize,
134 status,
135 temporary;
136
137 StreamType
138 type;
139
cristye7b28372012-06-17 13:59:06 +0000140 FileInfo
141 file_info;
cristy3ed852e2009-09-05 21:47:34 +0000142
143 struct stat
144 properties;
145
146 StreamHandler
147 stream;
148
cristyf3fe18d2015-01-26 19:57:08 +0000149 unsigned char
cristy3ed852e2009-09-05 21:47:34 +0000150 *data;
151
152 MagickBooleanType
153 debug;
154
155 SemaphoreInfo
156 *semaphore;
157
cristybb503372010-05-27 20:51:26 +0000158 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000159 reference_count;
160
cristybb503372010-05-27 20:51:26 +0000161 size_t
cristy3ed852e2009-09-05 21:47:34 +0000162 signature;
163};
164
165/*
166 Forward declarations.
167*/
168static int
169 SyncBlob(Image *);
170
171/*
172%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173% %
174% %
175% %
176+ A t t a c h B l o b %
177% %
178% %
179% %
180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181%
182% AttachBlob() attaches a blob to the BlobInfo structure.
183%
184% The format of the AttachBlob method is:
185%
186% void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
187%
188% A description of each parameter follows:
189%
190% o blob_info: Specifies a pointer to a BlobInfo structure.
191%
192% o blob: the address of a character stream in one of the image formats
193% understood by ImageMagick.
194%
195% o length: This size_t integer reflects the length in bytes of the blob.
196%
197*/
198MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
199 const size_t length)
200{
201 assert(blob_info != (BlobInfo *) NULL);
202 if (blob_info->debug != MagickFalse)
203 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
204 blob_info->length=length;
205 blob_info->extent=length;
206 blob_info->quantum=(size_t) MagickMaxBlobExtent;
207 blob_info->offset=0;
208 blob_info->type=BlobStream;
cristye7b28372012-06-17 13:59:06 +0000209 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000210 blob_info->data=(unsigned char *) blob;
211 blob_info->mapped=MagickFalse;
cristy0779de22015-05-03 12:45:49 +0000212 blob_info->immutable=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +0000213}
214
215/*
216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
217% %
218% %
219% %
220+ B l o b T o F i l e %
221% %
222% %
223% %
224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225%
226% BlobToFile() writes a blob to a file. It returns MagickFalse if an error
227% occurs otherwise MagickTrue.
228%
229% The format of the BlobToFile method is:
230%
231% MagickBooleanType BlobToFile(char *filename,const void *blob,
232% const size_t length,ExceptionInfo *exception)
233%
234% A description of each parameter follows:
235%
236% o filename: Write the blob to this file.
237%
238% o blob: the address of a blob.
239%
240% o length: This length in bytes of the blob.
241%
242% o exception: return any errors or warnings in this structure.
243%
244*/
cristy3ed852e2009-09-05 21:47:34 +0000245MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
246 const size_t length,ExceptionInfo *exception)
247{
248 int
249 file;
250
251 register size_t
252 i;
253
254 ssize_t
255 count;
256
257 assert(filename != (const char *) NULL);
258 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
259 assert(blob != (const void *) NULL);
260 if (*filename == '\0')
261 file=AcquireUniqueFileResource(filename);
262 else
cristy18c6c272011-09-23 14:40:37 +0000263 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +0000264 if (file == -1)
265 {
266 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
267 return(MagickFalse);
268 }
269 for (i=0; i < length; i+=count)
270 {
cristyf201ba62015-07-05 13:54:28 +0000271 count=write(file,(const char *) blob+i,MagickMin(length-i,SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +0000272 if (count <= 0)
273 {
274 count=0;
275 if (errno != EINTR)
276 break;
277 }
278 }
cristya7cb4312010-06-26 00:47:03 +0000279 file=close(file);
280 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +0000281 {
282 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
283 return(MagickFalse);
284 }
285 return(MagickTrue);
286}
287
288/*
289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290% %
291% %
292% %
293% B l o b T o I m a g e %
294% %
295% %
296% %
297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
298%
299% BlobToImage() implements direct to memory image formats. It returns the
300% blob as an image.
301%
302% The format of the BlobToImage method is:
303%
304% Image *BlobToImage(const ImageInfo *image_info,const void *blob,
305% const size_t length,ExceptionInfo *exception)
306%
307% A description of each parameter follows:
308%
309% o image_info: the image info.
310%
311% o blob: the address of a character stream in one of the image formats
312% understood by ImageMagick.
313%
314% o length: This size_t integer reflects the length in bytes of the blob.
315%
316% o exception: return any errors or warnings in this structure.
317%
318*/
319MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
320 const size_t length,ExceptionInfo *exception)
321{
322 const MagickInfo
323 *magick_info;
324
325 Image
326 *image;
327
328 ImageInfo
329 *blob_info,
330 *clone_info;
331
332 MagickBooleanType
333 status;
334
335 assert(image_info != (ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000336 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000337 if (image_info->debug != MagickFalse)
338 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
339 image_info->filename);
340 assert(exception != (ExceptionInfo *) NULL);
341 if ((blob == (const void *) NULL) || (length == 0))
342 {
343 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +0000344 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +0000345 return((Image *) NULL);
346 }
347 blob_info=CloneImageInfo(image_info);
348 blob_info->blob=(void *) blob;
349 blob_info->length=length;
350 if (*blob_info->magick == '\0')
cristyd965a422010-03-03 17:47:35 +0000351 (void) SetImageInfo(blob_info,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000352 magick_info=GetMagickInfo(blob_info->magick,exception);
353 if (magick_info == (const MagickInfo *) NULL)
354 {
cristy3ed852e2009-09-05 21:47:34 +0000355 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +0000356 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +0000357 blob_info->magick);
358 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +0000359 return((Image *) NULL);
360 }
361 if (GetMagickBlobSupport(magick_info) != MagickFalse)
362 {
363 /*
364 Native blob support for this image format.
365 */
366 (void) CopyMagickString(blob_info->filename,image_info->filename,
cristy151b66d2015-04-15 10:50:31 +0000367 MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000368 (void) CopyMagickString(blob_info->magick,image_info->magick,
cristy151b66d2015-04-15 10:50:31 +0000369 MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000370 image=ReadImage(blob_info,exception);
371 if (image != (Image *) NULL)
372 (void) DetachBlob(image->blob);
373 blob_info=DestroyImageInfo(blob_info);
374 return(image);
375 }
376 /*
377 Write blob to a temporary file on disk.
378 */
379 blob_info->blob=(void *) NULL;
380 blob_info->length=0;
381 *blob_info->filename='\0';
382 status=BlobToFile(blob_info->filename,blob,length,exception);
383 if (status == MagickFalse)
384 {
385 (void) RelinquishUniqueFileResource(blob_info->filename);
386 blob_info=DestroyImageInfo(blob_info);
387 return((Image *) NULL);
388 }
389 clone_info=CloneImageInfo(blob_info);
cristy151b66d2015-04-15 10:50:31 +0000390 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +0000391 blob_info->magick,blob_info->filename);
392 image=ReadImage(clone_info,exception);
cristy540a22c2012-06-10 15:22:16 +0000393 if (image != (Image *) NULL)
394 {
395 Image
396 *images;
397
398 /*
dirk7fcec532014-04-24 18:52:40 +0000399 Restore original filenames and image format.
cristy540a22c2012-06-10 15:22:16 +0000400 */
401 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
402 {
dirk7fcec532014-04-24 18:52:40 +0000403 (void) CopyMagickString(images->filename,image_info->filename,
cristy151b66d2015-04-15 10:50:31 +0000404 MagickPathExtent);
dirk7fcec532014-04-24 18:52:40 +0000405 (void) CopyMagickString(images->magick_filename,image_info->filename,
cristy151b66d2015-04-15 10:50:31 +0000406 MagickPathExtent);
dirk7fcec532014-04-24 18:52:40 +0000407 (void) CopyMagickString(images->magick,magick_info->name,
cristy151b66d2015-04-15 10:50:31 +0000408 MagickPathExtent);
cristy540a22c2012-06-10 15:22:16 +0000409 images=GetNextImageInList(images);
410 }
411 }
cristy3ed852e2009-09-05 21:47:34 +0000412 clone_info=DestroyImageInfo(clone_info);
413 (void) RelinquishUniqueFileResource(blob_info->filename);
414 blob_info=DestroyImageInfo(blob_info);
415 return(image);
416}
417
418/*
419%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420% %
421% %
422% %
423+ C l o n e B l o b I n f o %
424% %
425% %
426% %
427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
428%
429% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
430% blob info is NULL, a new one.
431%
432% The format of the CloneBlobInfo method is:
433%
434% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
435%
436% A description of each parameter follows:
437%
438% o blob_info: the blob info.
439%
440*/
441MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
442{
443 BlobInfo
444 *clone_info;
445
cristy73bd4a52010-10-05 11:24:23 +0000446 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
cristy3ed852e2009-09-05 21:47:34 +0000447 if (clone_info == (BlobInfo *) NULL)
448 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
449 GetBlobInfo(clone_info);
450 if (blob_info == (BlobInfo *) NULL)
451 return(clone_info);
452 clone_info->length=blob_info->length;
453 clone_info->extent=blob_info->extent;
454 clone_info->synchronize=blob_info->synchronize;
455 clone_info->quantum=blob_info->quantum;
456 clone_info->mapped=blob_info->mapped;
457 clone_info->eof=blob_info->eof;
458 clone_info->offset=blob_info->offset;
459 clone_info->size=blob_info->size;
460 clone_info->exempt=blob_info->exempt;
cristy0779de22015-05-03 12:45:49 +0000461 clone_info->immutable=blob_info->immutable;
cristy3ed852e2009-09-05 21:47:34 +0000462 clone_info->status=blob_info->status;
463 clone_info->temporary=blob_info->temporary;
464 clone_info->type=blob_info->type;
cristye7b28372012-06-17 13:59:06 +0000465 clone_info->file_info.file=blob_info->file_info.file;
cristy3ed852e2009-09-05 21:47:34 +0000466 clone_info->properties=blob_info->properties;
467 clone_info->stream=blob_info->stream;
468 clone_info->data=blob_info->data;
469 clone_info->debug=IsEventLogging();
470 clone_info->reference_count=1;
471 return(clone_info);
472}
473
474/*
475%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
476% %
477% %
478% %
479+ C l o s e B l o b %
480% %
481% %
482% %
483%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484%
485% CloseBlob() closes a stream associated with the image.
486%
487% The format of the CloseBlob method is:
488%
489% MagickBooleanType CloseBlob(Image *image)
490%
491% A description of each parameter follows:
492%
493% o image: the image.
494%
495*/
496MagickExport MagickBooleanType CloseBlob(Image *image)
497{
498 int
499 status;
500
501 /*
502 Close image file.
503 */
504 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000505 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000506 if (image->debug != MagickFalse)
507 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
508 assert(image->blob != (BlobInfo *) NULL);
509 if (image->blob->type == UndefinedStream)
510 return(MagickTrue);
cristy7e2a7c72012-12-27 00:56:47 +0000511 status=SyncBlob(image);
cristy3ed852e2009-09-05 21:47:34 +0000512 switch (image->blob->type)
513 {
514 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000515 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000516 break;
517 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000518 case PipeStream:
519 {
cristy02ce8cc2012-12-27 00:35:49 +0000520 if (image->blob->synchronize != MagickFalse)
521 status=fsync(fileno(image->blob->file_info.file));
cristye7b28372012-06-17 13:59:06 +0000522 status=ferror(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000523 break;
524 }
525 case ZipStream:
526 {
527#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000528 (void) gzerror(image->blob->file_info.gzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000529#endif
530 break;
531 }
532 case BZipStream:
533 {
534#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000535 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000536#endif
537 break;
538 }
539 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000540 break;
cristy02ce8cc2012-12-27 00:35:49 +0000541 case BlobStream:
542 {
543 if ((image->blob->file_info.file != (FILE *) NULL) &&
544 (image->blob->synchronize != MagickFalse))
cristy5678acd2012-12-27 00:41:55 +0000545 {
546 (void) fsync(fileno(image->blob->file_info.file));
547 status=ferror(image->blob->file_info.file);
548 }
cristy02ce8cc2012-12-27 00:35:49 +0000549 break;
550 }
cristy3ed852e2009-09-05 21:47:34 +0000551 }
552 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
cristycd9e6322012-12-27 00:29:00 +0000553 image->blob->size=GetBlobSize(image);
554 image->extent=image->blob->size;
555 image->blob->eof=MagickFalse;
cristybae22e42012-12-27 00:25:59 +0000556 if (image->blob->exempt != MagickFalse)
557 {
558 image->blob->type=UndefinedStream;
559 return(image->blob->status);
560 }
cristy3ed852e2009-09-05 21:47:34 +0000561 switch (image->blob->type)
562 {
563 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000564 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000565 break;
566 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000567 {
cristye7b28372012-06-17 13:59:06 +0000568 status=fclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000569 break;
570 }
571 case PipeStream:
572 {
573#if defined(MAGICKCORE_HAVE_PCLOSE)
cristye7b28372012-06-17 13:59:06 +0000574 status=pclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000575#endif
576 break;
577 }
578 case ZipStream:
579 {
580#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000581 status=gzclose(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +0000582#endif
583 break;
584 }
585 case BZipStream:
586 {
587#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000588 BZ2_bzclose(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +0000589#endif
590 break;
591 }
592 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000593 break;
cristyff483372010-10-16 17:00:58 +0000594 case BlobStream:
595 {
cristye7b28372012-06-17 13:59:06 +0000596 if (image->blob->file_info.file != (FILE *) NULL)
cristy02ce8cc2012-12-27 00:35:49 +0000597 status=fclose(image->blob->file_info.file);
cristyff483372010-10-16 17:00:58 +0000598 break;
599 }
cristy3ed852e2009-09-05 21:47:34 +0000600 }
601 (void) DetachBlob(image->blob);
602 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
603 return(image->blob->status);
604}
605
606/*
607%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608% %
609% %
610% %
611+ D e s t r o y B l o b %
612% %
613% %
614% %
615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616%
617% DestroyBlob() deallocates memory associated with a blob.
618%
619% The format of the DestroyBlob method is:
620%
621% void DestroyBlob(Image *image)
622%
623% A description of each parameter follows:
624%
625% o image: the image.
626%
627*/
628MagickExport void DestroyBlob(Image *image)
629{
630 MagickBooleanType
631 destroy;
632
633 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000634 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000635 if (image->debug != MagickFalse)
636 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
637 assert(image->blob != (BlobInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000638 assert(image->blob->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000639 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000640 LockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000641 image->blob->reference_count--;
642 assert(image->blob->reference_count >= 0);
643 if (image->blob->reference_count == 0)
644 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000645 UnlockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000646 if (destroy == MagickFalse)
647 return;
648 (void) CloseBlob(image);
649 if (image->blob->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000650 {
651 (void) UnmapBlob(image->blob->data,image->blob->length);
652 RelinquishMagickResource(MapResource,image->blob->length);
653 }
cristy3ed852e2009-09-05 21:47:34 +0000654 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
cristy3d162a92014-02-16 14:05:06 +0000655 RelinquishSemaphoreInfo(&image->blob->semaphore);
cristye1c94d92015-06-28 12:16:33 +0000656 image->blob->signature=(~MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000657 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
658}
659
660/*
661%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
662% %
663% %
664% %
665+ D e t a c h B l o b %
666% %
667% %
668% %
669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670%
671% DetachBlob() detaches a blob from the BlobInfo structure.
672%
673% The format of the DetachBlob method is:
674%
cristy6586a802015-01-24 15:48:55 +0000675% void *DetachBlob(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +0000676%
677% A description of each parameter follows:
678%
679% o blob_info: Specifies a pointer to a BlobInfo structure.
680%
681*/
cristy6586a802015-01-24 15:48:55 +0000682MagickExport void *DetachBlob(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +0000683{
cristy6586a802015-01-24 15:48:55 +0000684 void
cristy3ed852e2009-09-05 21:47:34 +0000685 *data;
686
687 assert(blob_info != (BlobInfo *) NULL);
688 if (blob_info->debug != MagickFalse)
689 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
690 if (blob_info->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000691 {
692 (void) UnmapBlob(blob_info->data,blob_info->length);
cristyf3fe18d2015-01-26 19:57:08 +0000693 blob_info->data=(unsigned char *) NULL;
cristy18aba912013-06-14 19:48:08 +0000694 RelinquishMagickResource(MapResource,blob_info->length);
695 }
cristy3ed852e2009-09-05 21:47:34 +0000696 blob_info->mapped=MagickFalse;
697 blob_info->length=0;
698 blob_info->offset=0;
699 blob_info->eof=MagickFalse;
700 blob_info->exempt=MagickFalse;
cristy0779de22015-05-03 12:45:49 +0000701 blob_info->immutable=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000702 blob_info->type=UndefinedStream;
cristye7b28372012-06-17 13:59:06 +0000703 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000704 data=blob_info->data;
705 blob_info->data=(unsigned char *) NULL;
706 blob_info->stream=(StreamHandler) NULL;
707 return(data);
708}
709
710/*
711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712% %
713% %
714% %
cristy10f10ec2014-09-20 01:00:50 +0000715+ D i s a s s o c i a t e B l o b %
716% %
717% %
718% %
719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720%
721% DisassociateBlob() disassociates the image stream. It checks if the
722% blob of the specified image is referenced by other images. If the reference
723% count is higher then 1 a new blob is assigned to the specified image.
724%
725% The format of the DisassociateBlob method is:
726%
dirkcfe4c1c2014-09-20 07:38:59 +0000727% void DisassociateBlob(const Image *image)
cristy10f10ec2014-09-20 01:00:50 +0000728%
729% A description of each parameter follows:
730%
731% o image: the image.
732%
733*/
734MagickPrivate void DisassociateBlob(Image *image)
735{
736 BlobInfo
737 *blob;
738
739 MagickBooleanType
740 clone;
741
742 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000743 assert(image->signature == MagickCoreSignature);
cristy10f10ec2014-09-20 01:00:50 +0000744 if (image->debug != MagickFalse)
745 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
746 assert(image->blob != (BlobInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000747 assert(image->blob->signature == MagickCoreSignature);
cristy10f10ec2014-09-20 01:00:50 +0000748 clone=MagickFalse;
749 LockSemaphoreInfo(image->blob->semaphore);
750 assert(image->blob->reference_count >= 0);
751 if (image->blob->reference_count > 1)
752 clone=MagickTrue;
753 UnlockSemaphoreInfo(image->blob->semaphore);
754 if (clone == MagickFalse)
cristy345d8722014-09-24 16:49:02 +0000755 return;
cristy10f10ec2014-09-20 01:00:50 +0000756 blob=CloneBlobInfo(image->blob);
757 DestroyBlob(image);
758 image->blob=blob;
759}
760
761/*
762%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
763% %
764% %
765% %
cristyc1af14f2010-09-16 20:01:21 +0000766+ D i s c a r d B l o b B y t e s %
767% %
768% %
769% %
770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
771%
772% DiscardBlobBytes() discards bytes in a blob.
773%
774% The format of the DiscardBlobBytes method is:
775%
cristy6f008fd2014-05-25 23:27:26 +0000776% MagickBooleanType DiscardBlobBytes(Image *image,
777% const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000778%
779% A description of each parameter follows.
780%
781% o image: the image.
782%
783% o length: the number of bytes to skip.
784%
785*/
cristyc1af14f2010-09-16 20:01:21 +0000786MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
cristy7753b2a2011-02-19 18:36:52 +0000787 const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000788{
cristy7753b2a2011-02-19 18:36:52 +0000789 register MagickOffsetType
cristyc1af14f2010-09-16 20:01:21 +0000790 i;
791
792 size_t
793 quantum;
794
795 ssize_t
796 count;
797
798 unsigned char
cristyf55846d2010-09-17 19:01:10 +0000799 buffer[16384];
cristyc1af14f2010-09-16 20:01:21 +0000800
801 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000802 assert(image->signature == MagickCoreSignature);
cristy908a35b2015-06-14 22:19:29 +0000803 if (length != (MagickSizeType) ((MagickOffsetType) length))
804 return(MagickFalse);
cristyc1af14f2010-09-16 20:01:21 +0000805 count=0;
cristy7753b2a2011-02-19 18:36:52 +0000806 for (i=0; i < (MagickOffsetType) length; i+=count)
cristyc1af14f2010-09-16 20:01:21 +0000807 {
cristy7753b2a2011-02-19 18:36:52 +0000808 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
cristyc1af14f2010-09-16 20:01:21 +0000809 (void) ReadBlobStream(image,quantum,buffer,&count);
810 if (count <= 0)
811 {
812 count=0;
813 if (errno != EINTR)
814 break;
815 }
816 }
cristy7753b2a2011-02-19 18:36:52 +0000817 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
cristyc1af14f2010-09-16 20:01:21 +0000818}
819
820/*
821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822% %
823% %
824% %
cristy3ed852e2009-09-05 21:47:34 +0000825+ D u p l i c a t e s B l o b %
826% %
827% %
828% %
829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830%
831% DuplicateBlob() duplicates a blob descriptor.
832%
833% The format of the DuplicateBlob method is:
834%
835% void DuplicateBlob(Image *image,const Image *duplicate)
836%
837% A description of each parameter follows:
838%
839% o image: the image.
840%
841% o duplicate: the duplicate image.
842%
843*/
844MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
845{
846 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000847 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000848 if (image->debug != MagickFalse)
849 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
850 assert(duplicate != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000851 assert(duplicate->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000852 DestroyBlob(image);
853 image->blob=ReferenceBlob(duplicate->blob);
854}
855
856/*
857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
858% %
859% %
860% %
861+ E O F B l o b %
862% %
863% %
864% %
865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866%
867% EOFBlob() returns a non-zero value when EOF has been detected reading from
868% a blob or file.
869%
870% The format of the EOFBlob method is:
871%
872% int EOFBlob(const Image *image)
873%
874% A description of each parameter follows:
875%
876% o image: the image.
877%
878*/
879MagickExport int EOFBlob(const Image *image)
880{
881 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000882 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000883 if (image->debug != MagickFalse)
884 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
885 assert(image->blob != (BlobInfo *) NULL);
886 assert(image->blob->type != UndefinedStream);
887 switch (image->blob->type)
888 {
889 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000890 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000891 break;
892 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000893 case PipeStream:
894 {
cristye7b28372012-06-17 13:59:06 +0000895 image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
cristy95888612012-04-04 21:56:52 +0000896 MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000897 break;
898 }
899 case ZipStream:
900 {
901 image->blob->eof=MagickFalse;
902 break;
903 }
904 case BZipStream:
905 {
906#if defined(MAGICKCORE_BZLIB_DELEGATE)
907 int
908 status;
909
910 status=0;
cristye7b28372012-06-17 13:59:06 +0000911 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000912 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
913#endif
914 break;
915 }
916 case FifoStream:
917 {
918 image->blob->eof=MagickFalse;
919 break;
920 }
921 case BlobStream:
922 break;
923 }
924 return((int) image->blob->eof);
925}
926
927/*
928%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
929% %
930% %
931% %
932+ F i l e T o B l o b %
933% %
934% %
935% %
936%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
937%
cristy178edaf2011-01-23 03:42:39 +0000938% FileToBlob() returns the contents of a file as a buffer terminated with
939% the '\0' character. The length of the buffer (not including the extra
940% terminating '\0' character) is returned via the 'length' parameter. Free
941% the buffer with RelinquishMagickMemory().
cristy3ed852e2009-09-05 21:47:34 +0000942%
943% The format of the FileToBlob method is:
944%
cristy6586a802015-01-24 15:48:55 +0000945% void *FileToBlob(const char *filename,const size_t extent,
cristy3ed852e2009-09-05 21:47:34 +0000946% size_t *length,ExceptionInfo *exception)
947%
948% A description of each parameter follows:
949%
950% o blob: FileToBlob() returns the contents of a file as a blob. If
951% an error occurs NULL is returned.
952%
953% o filename: the filename.
954%
955% o extent: The maximum length of the blob.
956%
957% o length: On return, this reflects the actual length of the blob.
958%
959% o exception: return any errors or warnings in this structure.
960%
961*/
cristy6586a802015-01-24 15:48:55 +0000962MagickExport void *FileToBlob(const char *filename,const size_t extent,
cristy3ed852e2009-09-05 21:47:34 +0000963 size_t *length,ExceptionInfo *exception)
964{
965 int
966 file;
967
968 MagickOffsetType
969 offset;
970
971 register size_t
972 i;
973
974 ssize_t
975 count;
976
977 unsigned char
978 *blob;
979
980 void
981 *map;
982
983 assert(filename != (const char *) NULL);
984 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
985 assert(exception != (ExceptionInfo *) NULL);
986 *length=0;
987 file=fileno(stdin);
988 if (LocaleCompare(filename,"-") != 0)
cristy18c6c272011-09-23 14:40:37 +0000989 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +0000990 if (file == -1)
991 {
992 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
cristy6586a802015-01-24 15:48:55 +0000993 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +0000994 }
cristy7f317702011-02-18 20:40:28 +0000995 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
cristy3ed852e2009-09-05 21:47:34 +0000996 count=0;
cristyd1f55c12014-01-24 00:40:57 +0000997 if ((file == fileno(stdin)) || (offset < 0) ||
998 (offset != (MagickOffsetType) ((ssize_t) offset)))
cristy3ed852e2009-09-05 21:47:34 +0000999 {
1000 size_t
1001 quantum;
1002
1003 struct stat
cristye7b28372012-06-17 13:59:06 +00001004 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001005
1006 /*
1007 Stream is not seekable.
1008 */
cristyd1561652014-01-24 11:13:48 +00001009 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001010 quantum=(size_t) MagickMaxBufferExtent;
cristyf201ba62015-07-05 13:54:28 +00001011 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1012 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001013 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1014 for (i=0; blob != (unsigned char *) NULL; i+=count)
1015 {
cristy65d11e42013-06-14 20:06:25 +00001016 count=read(file,blob+i,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001017 if (count <= 0)
1018 {
1019 count=0;
1020 if (errno != EINTR)
1021 break;
1022 }
cristy9c66d8c2012-08-10 11:05:36 +00001023 if (~((size_t) i) < (quantum+1))
cristy3ed852e2009-09-05 21:47:34 +00001024 {
1025 blob=(unsigned char *) RelinquishMagickMemory(blob);
1026 break;
1027 }
1028 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1029 sizeof(*blob));
1030 if ((size_t) (i+count) >= extent)
1031 break;
1032 }
cristy54439632010-07-15 00:43:34 +00001033 if (LocaleCompare(filename,"-") != 0)
1034 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001035 if (blob == (unsigned char *) NULL)
1036 {
1037 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001038 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy6586a802015-01-24 15:48:55 +00001039 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00001040 }
cristya7cb4312010-06-26 00:47:03 +00001041 if (file == -1)
1042 {
1043 blob=(unsigned char *) RelinquishMagickMemory(blob);
1044 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
cristy6586a802015-01-24 15:48:55 +00001045 return(NULL);
cristya7cb4312010-06-26 00:47:03 +00001046 }
cristy7753b2a2011-02-19 18:36:52 +00001047 *length=(size_t) MagickMin(i+count,extent);
cristy3ed852e2009-09-05 21:47:34 +00001048 blob[*length]='\0';
1049 return(blob);
1050 }
Cristy6b24c862015-12-19 21:20:23 -05001051 *length=(size_t) MagickMin(offset,(MagickOffsetType)
1052 MagickMin(extent,SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001053 blob=(unsigned char *) NULL;
cristy151b66d2015-04-15 10:50:31 +00001054 if (~(*length) >= (MagickPathExtent-1))
1055 blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
cristy3ed852e2009-09-05 21:47:34 +00001056 sizeof(*blob));
1057 if (blob == (unsigned char *) NULL)
1058 {
cristy54439632010-07-15 00:43:34 +00001059 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001060 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001061 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy6586a802015-01-24 15:48:55 +00001062 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00001063 }
1064 map=MapBlob(file,ReadMode,0,*length);
1065 if (map != (unsigned char *) NULL)
1066 {
cristy54aad5e2010-09-03 16:02:04 +00001067 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +00001068 (void) UnmapBlob(map,*length);
1069 }
1070 else
1071 {
cristy7f317702011-02-18 20:40:28 +00001072 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001073 for (i=0; i < *length; i+=count)
1074 {
cristyf201ba62015-07-05 13:54:28 +00001075 count=read(file,blob+i,(size_t) MagickMin(*length-i,SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001076 if (count <= 0)
1077 {
1078 count=0;
1079 if (errno != EINTR)
1080 break;
1081 }
1082 }
1083 if (i < *length)
1084 {
1085 file=close(file)-1;
1086 blob=(unsigned char *) RelinquishMagickMemory(blob);
1087 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
cristy6586a802015-01-24 15:48:55 +00001088 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00001089 }
1090 }
cristy3ed852e2009-09-05 21:47:34 +00001091 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001092 if (LocaleCompare(filename,"-") != 0)
1093 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001094 if (file == -1)
1095 {
1096 blob=(unsigned char *) RelinquishMagickMemory(blob);
1097 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1098 }
cristy3ed852e2009-09-05 21:47:34 +00001099 return(blob);
1100}
1101
1102/*
1103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1104% %
1105% %
1106% %
1107% F i l e T o I m a g e %
1108% %
1109% %
1110% %
1111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1112%
1113% FileToImage() write the contents of a file to an image.
1114%
1115% The format of the FileToImage method is:
1116%
1117% MagickBooleanType FileToImage(Image *,const char *filename)
1118%
1119% A description of each parameter follows:
1120%
1121% o image: the image.
1122%
1123% o filename: the filename.
1124%
1125*/
1126
1127static inline ssize_t WriteBlobStream(Image *image,const size_t length,
cristye2222cc2015-01-26 20:01:34 +00001128 const void *data)
cristy3ed852e2009-09-05 21:47:34 +00001129{
1130 MagickSizeType
1131 extent;
1132
1133 register unsigned char
1134 *q;
1135
1136 assert(image->blob != (BlobInfo *) NULL);
cristye2222cc2015-01-26 20:01:34 +00001137 assert(image->blob->type != UndefinedStream);
1138 assert(data != NULL);
cristy3ed852e2009-09-05 21:47:34 +00001139 if (image->blob->type != BlobStream)
cristyce0e7b22015-05-18 00:12:46 +00001140 return(WriteBlob(image,length,(const unsigned char *) data));
cristy3ed852e2009-09-05 21:47:34 +00001141 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1142 if (extent >= image->blob->extent)
1143 {
cristy3ed852e2009-09-05 21:47:34 +00001144 extent=image->blob->extent+image->blob->quantum+length;
cristyff368632014-01-27 13:01:38 +00001145 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00001146 if (SetBlobExtent(image,extent) == MagickFalse)
1147 return(0);
1148 }
1149 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001150 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001151 image->blob->offset+=length;
1152 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1153 image->blob->length=(size_t) image->blob->offset;
1154 return((ssize_t) length);
1155}
1156
cristyc82a27b2011-10-21 01:07:16 +00001157MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1158 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001159{
1160 int
1161 file;
1162
1163 size_t
1164 length,
1165 quantum;
1166
1167 ssize_t
1168 count;
1169
1170 struct stat
cristye7b28372012-06-17 13:59:06 +00001171 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001172
1173 unsigned char
1174 *blob;
1175
1176 assert(image != (const Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001177 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001178 assert(filename != (const char *) NULL);
1179 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
cristyd45808f2012-12-14 21:30:35 +00001180 file=fileno(stdin);
1181 if (LocaleCompare(filename,"-") != 0)
1182 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001183 if (file == -1)
1184 {
cristyc82a27b2011-10-21 01:07:16 +00001185 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001186 return(MagickFalse);
1187 }
1188 quantum=(size_t) MagickMaxBufferExtent;
cristyf201ba62015-07-05 13:54:28 +00001189 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
cristye7b28372012-06-17 13:59:06 +00001190 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001191 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1192 if (blob == (unsigned char *) NULL)
1193 {
cristy100a0562014-04-18 01:27:37 +00001194 file=close(file);
cristyc82a27b2011-10-21 01:07:16 +00001195 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1196 filename);
cristy3ed852e2009-09-05 21:47:34 +00001197 return(MagickFalse);
1198 }
1199 for ( ; ; )
1200 {
cristy65d11e42013-06-14 20:06:25 +00001201 count=read(file,blob,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001202 if (count <= 0)
1203 {
1204 count=0;
1205 if (errno != EINTR)
1206 break;
1207 }
1208 length=(size_t) count;
1209 count=WriteBlobStream(image,length,blob);
1210 if (count != (ssize_t) length)
1211 {
cristyc82a27b2011-10-21 01:07:16 +00001212 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001213 break;
1214 }
1215 }
cristya7cb4312010-06-26 00:47:03 +00001216 file=close(file);
1217 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001218 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001219 blob=(unsigned char *) RelinquishMagickMemory(blob);
1220 return(MagickTrue);
1221}
dirk54fae512014-09-19 20:58:22 +00001222
1223
cristy3ed852e2009-09-05 21:47:34 +00001224/*
1225%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1226% %
1227% %
1228% %
1229+ G e t B l o b E r r o r %
1230% %
1231% %
1232% %
1233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1234%
1235% GetBlobError() returns MagickTrue if the blob associated with the specified
1236% image encountered an error.
1237%
1238% The format of the GetBlobError method is:
1239%
1240% MagickBooleanType GetBlobError(const Image *image)
1241%
1242% A description of each parameter follows:
1243%
1244% o image: the image.
1245%
1246*/
cristy7832dc22011-09-05 01:21:53 +00001247MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001248{
1249 assert(image != (const Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001250 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001251 if (image->debug != MagickFalse)
1252 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1253 return(image->blob->status);
1254}
1255
1256/*
1257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1258% %
1259% %
1260% %
1261+ G e t B l o b F i l e H a n d l e %
1262% %
1263% %
1264% %
1265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1266%
1267% GetBlobFileHandle() returns the file handle associated with the image blob.
1268%
1269% The format of the GetBlobFile method is:
1270%
1271% FILE *GetBlobFileHandle(const Image *image)
1272%
1273% A description of each parameter follows:
1274%
1275% o image: the image.
1276%
1277*/
1278MagickExport FILE *GetBlobFileHandle(const Image *image)
1279{
1280 assert(image != (const Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001281 assert(image->signature == MagickCoreSignature);
cristye7b28372012-06-17 13:59:06 +00001282 return(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001283}
1284
1285/*
1286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1287% %
1288% %
1289% %
1290+ G e t B l o b I n f o %
1291% %
1292% %
1293% %
1294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1295%
1296% GetBlobInfo() initializes the BlobInfo structure.
1297%
1298% The format of the GetBlobInfo method is:
1299%
1300% void GetBlobInfo(BlobInfo *blob_info)
1301%
1302% A description of each parameter follows:
1303%
1304% o blob_info: Specifies a pointer to a BlobInfo structure.
1305%
1306*/
cristy7832dc22011-09-05 01:21:53 +00001307MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001308{
1309 assert(blob_info != (BlobInfo *) NULL);
1310 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1311 blob_info->type=UndefinedStream;
1312 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1313 blob_info->properties.st_mtime=time((time_t *) NULL);
1314 blob_info->properties.st_ctime=time((time_t *) NULL);
1315 blob_info->debug=IsEventLogging();
1316 blob_info->reference_count=1;
cristy3d162a92014-02-16 14:05:06 +00001317 blob_info->semaphore=AcquireSemaphoreInfo();
cristye1c94d92015-06-28 12:16:33 +00001318 blob_info->signature=MagickCoreSignature;
cristy3ed852e2009-09-05 21:47:34 +00001319}
1320
1321/*
1322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1323% %
1324% %
1325% %
1326% G e t B l o b P r o p e r t i e s %
1327% %
1328% %
1329% %
1330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1331%
1332% GetBlobProperties() returns information about an image blob.
1333%
1334% The format of the GetBlobProperties method is:
1335%
1336% const struct stat *GetBlobProperties(const Image *image)
1337%
1338% A description of each parameter follows:
1339%
1340% o image: the image.
1341%
1342*/
cristy7832dc22011-09-05 01:21:53 +00001343MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001344{
1345 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001346 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001347 if (image->debug != MagickFalse)
1348 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1349 return(&image->blob->properties);
1350}
1351
1352/*
1353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1354% %
1355% %
1356% %
1357+ G e t B l o b S i z e %
1358% %
1359% %
1360% %
1361%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1362%
1363% GetBlobSize() returns the current length of the image file or blob; zero is
1364% returned if the size cannot be determined.
1365%
1366% The format of the GetBlobSize method is:
1367%
1368% MagickSizeType GetBlobSize(const Image *image)
1369%
1370% A description of each parameter follows:
1371%
1372% o image: the image.
1373%
1374*/
1375MagickExport MagickSizeType GetBlobSize(const Image *image)
1376{
1377 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001378 extent;
cristy3ed852e2009-09-05 21:47:34 +00001379
1380 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001381 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001382 if (image->debug != MagickFalse)
1383 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1384 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001385 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001386 switch (image->blob->type)
1387 {
1388 case UndefinedStream:
1389 {
cristy81b8ce52010-02-05 01:53:17 +00001390 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001391 break;
1392 }
cristybc20d112012-07-29 20:27:00 +00001393 case StandardStream:
1394 {
1395 extent=image->blob->size;
1396 break;
1397 }
cristy3ed852e2009-09-05 21:47:34 +00001398 case FileStream:
1399 {
cristye7b28372012-06-17 13:59:06 +00001400 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001401 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001402 break;
1403 }
cristy3ed852e2009-09-05 21:47:34 +00001404 case PipeStream:
1405 {
cristy81b8ce52010-02-05 01:53:17 +00001406 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001407 break;
1408 }
1409 case ZipStream:
1410 case BZipStream:
1411 {
1412 MagickBooleanType
1413 status;
1414
1415 status=GetPathAttributes(image->filename,&image->blob->properties);
1416 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001417 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001418 break;
1419 }
1420 case FifoStream:
1421 break;
1422 case BlobStream:
1423 {
cristy891dc792010-03-04 01:47:16 +00001424 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001425 break;
1426 }
1427 }
cristy81b8ce52010-02-05 01:53:17 +00001428 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001429}
1430
1431/*
1432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1433% %
1434% %
1435% %
1436+ G e t B l o b S t r e a m D a t a %
1437% %
1438% %
1439% %
1440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1441%
1442% GetBlobStreamData() returns the stream data for the image.
1443%
1444% The format of the GetBlobStreamData method is:
1445%
cristy6586a802015-01-24 15:48:55 +00001446% void *GetBlobStreamData(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001447%
1448% A description of each parameter follows:
1449%
1450% o image: the image.
1451%
1452*/
cristy6586a802015-01-24 15:48:55 +00001453MagickExport void *GetBlobStreamData(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001454{
1455 assert(image != (const Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001456 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001457 return(image->blob->data);
1458}
1459
1460/*
1461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1462% %
1463% %
1464% %
1465+ G e t B l o b S t r e a m H a n d l e r %
1466% %
1467% %
1468% %
1469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1470%
1471% GetBlobStreamHandler() returns the stream handler for the image.
1472%
1473% The format of the GetBlobStreamHandler method is:
1474%
1475% StreamHandler GetBlobStreamHandler(const Image *image)
1476%
1477% A description of each parameter follows:
1478%
1479% o image: the image.
1480%
1481*/
cristy7832dc22011-09-05 01:21:53 +00001482MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001483{
1484 assert(image != (const Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001485 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001486 if (image->debug != MagickFalse)
1487 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1488 return(image->blob->stream);
1489}
1490
1491/*
1492%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1493% %
1494% %
1495% %
1496% I m a g e T o B l o b %
1497% %
1498% %
1499% %
1500%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1501%
1502% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001503% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001504% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001505% etc.). This method is the equivalent of WriteImage(), but writes the
1506% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001507%
1508% The format of the ImageToBlob method is:
1509%
cristy6586a802015-01-24 15:48:55 +00001510% void *ImageToBlob(const ImageInfo *image_info,Image *image,
cristy3ed852e2009-09-05 21:47:34 +00001511% size_t *length,ExceptionInfo *exception)
1512%
1513% A description of each parameter follows:
1514%
1515% o image_info: the image info.
1516%
1517% o image: the image.
1518%
cristyd7dc7df2014-01-26 13:52:14 +00001519% o length: return the actual length of the blob.
cristy3ed852e2009-09-05 21:47:34 +00001520%
1521% o exception: return any errors or warnings in this structure.
1522%
1523*/
cristy6586a802015-01-24 15:48:55 +00001524MagickExport void *ImageToBlob(const ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001525 Image *image,size_t *length,ExceptionInfo *exception)
1526{
1527 const MagickInfo
1528 *magick_info;
1529
1530 ImageInfo
1531 *blob_info;
1532
1533 MagickBooleanType
1534 status;
1535
cristyce0e7b22015-05-18 00:12:46 +00001536 void
cristy3ed852e2009-09-05 21:47:34 +00001537 *blob;
1538
1539 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001540 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001541 if (image_info->debug != MagickFalse)
1542 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1543 image_info->filename);
1544 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001545 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001546 assert(exception != (ExceptionInfo *) NULL);
1547 *length=0;
1548 blob=(unsigned char *) NULL;
1549 blob_info=CloneImageInfo(image_info);
1550 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001551 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001552 if (*blob_info->magick != '\0')
cristy151b66d2015-04-15 10:50:31 +00001553 (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001554 magick_info=GetMagickInfo(image->magick,exception);
1555 if (magick_info == (const MagickInfo *) NULL)
1556 {
1557 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001558 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +00001559 image->magick);
1560 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +00001561 return(blob);
1562 }
cristy151b66d2015-04-15 10:50:31 +00001563 (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001564 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1565 {
1566 /*
1567 Native blob support for this image format.
1568 */
cristy5facf772014-01-26 14:42:57 +00001569 blob_info->length=0;
cristy6586a802015-01-24 15:48:55 +00001570 blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
cristy5facf772014-01-26 14:42:57 +00001571 sizeof(unsigned char));
cristy6586a802015-01-24 15:48:55 +00001572 if (blob_info->blob == NULL)
cristy3ed852e2009-09-05 21:47:34 +00001573 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001574 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001575 else
1576 {
1577 (void) CloseBlob(image);
1578 image->blob->exempt=MagickTrue;
1579 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001580 status=WriteImage(blob_info,image,exception);
cristy5facf772014-01-26 14:42:57 +00001581 *length=image->blob->length;
cristyc42554f2012-08-22 12:00:43 +00001582 blob=DetachBlob(image->blob);
cristy6e50f9e2012-08-22 16:30:29 +00001583 if (status == MagickFalse)
cristyce0e7b22015-05-18 00:12:46 +00001584 blob=RelinquishMagickMemory(blob);
cristy6e50f9e2012-08-22 16:30:29 +00001585 else
cristyce0e7b22015-05-18 00:12:46 +00001586 blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001587 }
1588 }
1589 else
1590 {
1591 char
cristy151b66d2015-04-15 10:50:31 +00001592 unique[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00001593
1594 int
1595 file;
1596
1597 /*
1598 Write file to disk in blob image format.
1599 */
1600 file=AcquireUniqueFileResource(unique);
1601 if (file == -1)
1602 {
1603 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1604 image_info->filename);
1605 }
1606 else
1607 {
1608 blob_info->file=fdopen(file,"wb");
1609 if (blob_info->file != (FILE *) NULL)
1610 {
cristyce0e7b22015-05-18 00:12:46 +00001611 (void) FormatLocaleString(image->filename,MagickPathExtent,
1612 "%s:%s",image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001613 status=WriteImage(blob_info,image,exception);
dirk607010e2014-03-01 19:08:11 +00001614 (void) CloseBlob(image);
1615 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001616 if (status != MagickFalse)
cristy2c1b6e02014-01-26 15:03:02 +00001617 blob=FileToBlob(unique,~0UL,length,exception);
cristy3ed852e2009-09-05 21:47:34 +00001618 }
1619 (void) RelinquishUniqueFileResource(unique);
1620 }
1621 }
1622 blob_info=DestroyImageInfo(blob_info);
1623 return(blob);
1624}
1625
1626/*
1627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1628% %
1629% %
1630% %
1631% I m a g e T o F i l e %
1632% %
1633% %
1634% %
1635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1636%
1637% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1638% occurs otherwise MagickTrue.
1639%
1640% The format of the ImageToFile method is:
1641%
1642% MagickBooleanType ImageToFile(Image *image,char *filename,
1643% ExceptionInfo *exception)
1644%
1645% A description of each parameter follows:
1646%
1647% o image: the image.
1648%
1649% o filename: Write the image to this file.
1650%
1651% o exception: return any errors or warnings in this structure.
1652%
1653*/
cristy3ed852e2009-09-05 21:47:34 +00001654MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1655 ExceptionInfo *exception)
1656{
1657 int
1658 file;
1659
1660 register const unsigned char
1661 *p;
1662
1663 register size_t
1664 i;
1665
1666 size_t
1667 length,
1668 quantum;
1669
1670 ssize_t
1671 count;
1672
1673 struct stat
cristye7b28372012-06-17 13:59:06 +00001674 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001675
1676 unsigned char
1677 *buffer;
1678
1679 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001680 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001681 assert(image->blob != (BlobInfo *) NULL);
1682 assert(image->blob->type != UndefinedStream);
1683 if (image->debug != MagickFalse)
1684 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1685 assert(filename != (const char *) NULL);
1686 if (*filename == '\0')
1687 file=AcquireUniqueFileResource(filename);
1688 else
1689 if (LocaleCompare(filename,"-") == 0)
1690 file=fileno(stdout);
1691 else
cristyb70aab92012-01-31 15:04:04 +00001692 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001693 if (file == -1)
1694 {
1695 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1696 return(MagickFalse);
1697 }
1698 quantum=(size_t) MagickMaxBufferExtent;
cristyf201ba62015-07-05 13:54:28 +00001699 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1700 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001701 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1702 if (buffer == (unsigned char *) NULL)
1703 {
1704 file=close(file)-1;
1705 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001706 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001707 return(MagickFalse);
1708 }
1709 length=0;
cristyce0e7b22015-05-18 00:12:46 +00001710 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
cristyf201ba62015-07-05 13:54:28 +00001711 for (i=0; count > 0; )
cristy3ed852e2009-09-05 21:47:34 +00001712 {
1713 length=(size_t) count;
1714 for (i=0; i < length; i+=count)
1715 {
1716 count=write(file,p+i,(size_t) (length-i));
1717 if (count <= 0)
1718 {
1719 count=0;
1720 if (errno != EINTR)
1721 break;
1722 }
1723 }
1724 if (i < length)
1725 break;
cristyf201ba62015-07-05 13:54:28 +00001726 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00001727 }
cristy54439632010-07-15 00:43:34 +00001728 if (LocaleCompare(filename,"-") != 0)
1729 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001730 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001731 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001732 {
cristye3216eb2014-04-18 17:10:21 +00001733 if (file != -1)
cristy100a0562014-04-18 01:27:37 +00001734 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001735 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1736 return(MagickFalse);
1737 }
1738 return(MagickTrue);
1739}
1740
1741/*
1742%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1743% %
1744% %
1745% %
1746% I m a g e s T o B l o b %
1747% %
1748% %
1749% %
1750%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1751%
1752% ImagesToBlob() implements direct to memory image formats. It returns the
1753% image sequence as a blob and its length. The magick member of the ImageInfo
1754% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1755%
1756% Note, some image formats do not permit multiple images to the same image
1757% stream (e.g. JPEG). in this instance, just the first image of the
1758% sequence is returned as a blob.
1759%
1760% The format of the ImagesToBlob method is:
1761%
cristy6586a802015-01-24 15:48:55 +00001762% void *ImagesToBlob(const ImageInfo *image_info,Image *images,
cristy3ed852e2009-09-05 21:47:34 +00001763% size_t *length,ExceptionInfo *exception)
1764%
1765% A description of each parameter follows:
1766%
1767% o image_info: the image info.
1768%
1769% o images: the image list.
1770%
cristybb85d6a2014-01-26 13:51:09 +00001771% o length: return the actual length of the blob.
cristy3ed852e2009-09-05 21:47:34 +00001772%
1773% o exception: return any errors or warnings in this structure.
1774%
1775*/
cristy6586a802015-01-24 15:48:55 +00001776MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
1777 size_t *length,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001778{
1779 const MagickInfo
1780 *magick_info;
1781
1782 ImageInfo
1783 *blob_info;
1784
1785 MagickBooleanType
1786 status;
1787
cristyce0e7b22015-05-18 00:12:46 +00001788 void
cristy3ed852e2009-09-05 21:47:34 +00001789 *blob;
1790
1791 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001792 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001793 if (image_info->debug != MagickFalse)
1794 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1795 image_info->filename);
1796 assert(images != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001797 assert(images->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001798 assert(exception != (ExceptionInfo *) NULL);
1799 *length=0;
1800 blob=(unsigned char *) NULL;
1801 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001802 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1803 exception);
cristy3ed852e2009-09-05 21:47:34 +00001804 if (*blob_info->magick != '\0')
cristy151b66d2015-04-15 10:50:31 +00001805 (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001806 magick_info=GetMagickInfo(images->magick,exception);
1807 if (magick_info == (const MagickInfo *) NULL)
1808 {
1809 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001810 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +00001811 images->magick);
1812 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +00001813 return(blob);
1814 }
cristy4f1f3e82014-01-26 15:25:52 +00001815 if (GetMagickAdjoin(magick_info) == MagickFalse)
1816 {
1817 blob_info=DestroyImageInfo(blob_info);
1818 return(ImageToBlob(image_info,images,length,exception));
1819 }
cristy151b66d2015-04-15 10:50:31 +00001820 (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001821 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1822 {
1823 /*
1824 Native blob support for this images format.
1825 */
cristy5facf772014-01-26 14:42:57 +00001826 blob_info->length=0;
1827 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1828 sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001829 if (blob_info->blob == (void *) NULL)
1830 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001831 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
cristy3ed852e2009-09-05 21:47:34 +00001832 else
1833 {
cristy7a4b8c52014-01-25 22:48:06 +00001834 (void) CloseBlob(images);
cristy3ed852e2009-09-05 21:47:34 +00001835 images->blob->exempt=MagickTrue;
1836 *images->filename='\0';
1837 status=WriteImages(blob_info,images,images->filename,exception);
cristy5facf772014-01-26 14:42:57 +00001838 *length=images->blob->length;
cristy7a4b8c52014-01-25 22:48:06 +00001839 blob=DetachBlob(images->blob);
1840 if (status == MagickFalse)
cristyce0e7b22015-05-18 00:12:46 +00001841 blob=RelinquishMagickMemory(blob);
cristy7a4b8c52014-01-25 22:48:06 +00001842 else
cristyce0e7b22015-05-18 00:12:46 +00001843 blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001844 }
1845 }
1846 else
1847 {
1848 char
cristy151b66d2015-04-15 10:50:31 +00001849 filename[MagickPathExtent],
1850 unique[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00001851
1852 int
1853 file;
1854
1855 /*
1856 Write file to disk in blob images format.
1857 */
1858 file=AcquireUniqueFileResource(unique);
1859 if (file == -1)
1860 {
1861 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1862 image_info->filename);
1863 }
1864 else
1865 {
1866 blob_info->file=fdopen(file,"wb");
1867 if (blob_info->file != (FILE *) NULL)
1868 {
cristy151b66d2015-04-15 10:50:31 +00001869 (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001870 images->magick,unique);
1871 status=WriteImages(blob_info,images,filename,exception);
dirk607010e2014-03-01 19:08:11 +00001872 (void) CloseBlob(images);
cristya94f31b2014-03-01 13:25:42 +00001873 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001874 if (status != MagickFalse)
cristy2c1b6e02014-01-26 15:03:02 +00001875 blob=FileToBlob(unique,~0UL,length,exception);
cristy3ed852e2009-09-05 21:47:34 +00001876 }
1877 (void) RelinquishUniqueFileResource(unique);
1878 }
1879 }
1880 blob_info=DestroyImageInfo(blob_info);
1881 return(blob);
1882}
1883/*
1884%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1885% %
1886% %
1887% %
1888% I n j e c t I m a g e B l o b %
1889% %
1890% %
1891% %
1892%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1893%
1894% InjectImageBlob() injects the image with a copy of itself in the specified
1895% format (e.g. inject JPEG into a PDF image).
1896%
1897% The format of the InjectImageBlob method is:
1898%
1899% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1900% Image *image,Image *inject_image,const char *format,
1901% ExceptionInfo *exception)
1902%
1903% A description of each parameter follows:
1904%
1905% o image_info: the image info..
1906%
1907% o image: the image.
1908%
1909% o inject_image: inject into the image stream.
1910%
1911% o format: the image format.
1912%
1913% o exception: return any errors or warnings in this structure.
1914%
1915*/
1916MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1917 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1918{
1919 char
cristy151b66d2015-04-15 10:50:31 +00001920 filename[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00001921
1922 FILE
1923 *unique_file;
1924
1925 Image
1926 *byte_image;
1927
1928 ImageInfo
1929 *write_info;
1930
1931 int
1932 file;
1933
1934 MagickBooleanType
1935 status;
1936
cristybb503372010-05-27 20:51:26 +00001937 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001938 i;
1939
1940 size_t
1941 quantum;
1942
1943 ssize_t
1944 count;
1945
1946 struct stat
cristye7b28372012-06-17 13:59:06 +00001947 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001948
1949 unsigned char
1950 *buffer;
1951
1952 /*
1953 Write inject image to a temporary file.
1954 */
1955 assert(image_info != (ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001956 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001957 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001958 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001959 if (image->debug != MagickFalse)
1960 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1961 assert(inject_image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001962 assert(inject_image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001963 assert(exception != (ExceptionInfo *) NULL);
1964 unique_file=(FILE *) NULL;
1965 file=AcquireUniqueFileResource(filename);
1966 if (file != -1)
1967 unique_file=fdopen(file,"wb");
1968 if ((file == -1) || (unique_file == (FILE *) NULL))
1969 {
cristy151b66d2015-04-15 10:50:31 +00001970 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001971 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1972 image->filename);
1973 return(MagickFalse);
1974 }
1975 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1976 if (byte_image == (Image *) NULL)
1977 {
1978 (void) fclose(unique_file);
1979 (void) RelinquishUniqueFileResource(filename);
1980 return(MagickFalse);
1981 }
cristy151b66d2015-04-15 10:50:31 +00001982 (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001983 filename);
1984 DestroyBlob(byte_image);
1985 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1986 write_info=CloneImageInfo(image_info);
1987 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001988 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001989 write_info=DestroyImageInfo(write_info);
1990 byte_image=DestroyImage(byte_image);
1991 (void) fclose(unique_file);
1992 if (status == MagickFalse)
1993 {
1994 (void) RelinquishUniqueFileResource(filename);
1995 return(MagickFalse);
1996 }
1997 /*
1998 Inject into image stream.
1999 */
cristy18c6c272011-09-23 14:40:37 +00002000 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00002001 if (file == -1)
2002 {
2003 (void) RelinquishUniqueFileResource(filename);
2004 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2005 image_info->filename);
2006 return(MagickFalse);
2007 }
2008 quantum=(size_t) MagickMaxBufferExtent;
cristyf201ba62015-07-05 13:54:28 +00002009 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
cristye7b28372012-06-17 13:59:06 +00002010 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00002011 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2012 if (buffer == (unsigned char *) NULL)
2013 {
2014 (void) RelinquishUniqueFileResource(filename);
cristyc658afb2015-01-21 21:45:09 +00002015 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00002016 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2017 image->filename);
2018 }
2019 for (i=0; ; i+=count)
2020 {
cristy65d11e42013-06-14 20:06:25 +00002021 count=read(file,buffer,quantum);
cristy3ed852e2009-09-05 21:47:34 +00002022 if (count <= 0)
2023 {
2024 count=0;
2025 if (errno != EINTR)
2026 break;
2027 }
2028 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2029 MagickFalse;
2030 }
cristya7cb4312010-06-26 00:47:03 +00002031 file=close(file);
2032 if (file == -1)
2033 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00002034 (void) RelinquishUniqueFileResource(filename);
2035 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2036 return(status);
2037}
2038
2039/*
2040%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2041% %
2042% %
2043% %
2044+ I s B l o b E x e m p t %
2045% %
2046% %
2047% %
2048%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2049%
2050% IsBlobExempt() returns true if the blob is exempt.
2051%
2052% The format of the IsBlobExempt method is:
2053%
2054% MagickBooleanType IsBlobExempt(const Image *image)
2055%
2056% A description of each parameter follows:
2057%
2058% o image: the image.
2059%
2060*/
cristy7832dc22011-09-05 01:21:53 +00002061MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002062{
2063 assert(image != (const Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00002064 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00002065 if (image->debug != MagickFalse)
2066 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2067 return(image->blob->exempt);
2068}
2069
2070/*
2071%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2072% %
2073% %
2074% %
2075+ I s B l o b S e e k a b l e %
2076% %
2077% %
2078% %
2079%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2080%
2081% IsBlobSeekable() returns true if the blob is seekable.
2082%
2083% The format of the IsBlobSeekable method is:
2084%
2085% MagickBooleanType IsBlobSeekable(const Image *image)
2086%
2087% A description of each parameter follows:
2088%
2089% o image: the image.
2090%
2091*/
cristy7832dc22011-09-05 01:21:53 +00002092MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002093{
2094 MagickBooleanType
2095 seekable;
2096
2097 assert(image != (const Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00002098 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00002099 if (image->debug != MagickFalse)
2100 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002101 switch (image->blob->type)
2102 {
2103 case FileStream:
2104 case BlobStream:
2105 case ZipStream:
2106 {
2107 seekable=MagickTrue;
2108 break;
2109 }
2110 default:
2111 {
2112 seekable=MagickFalse;
2113 break;
2114 }
2115 }
cristy3ed852e2009-09-05 21:47:34 +00002116 return(seekable);
2117}
2118
2119/*
2120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2121% %
2122% %
2123% %
2124+ I s B l o b T e m p o r a r y %
2125% %
2126% %
2127% %
2128%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2129%
2130% IsBlobTemporary() returns true if the blob is temporary.
2131%
2132% The format of the IsBlobTemporary method is:
2133%
2134% MagickBooleanType IsBlobTemporary(const Image *image)
2135%
2136% A description of each parameter follows:
2137%
2138% o image: the image.
2139%
2140*/
cristy7832dc22011-09-05 01:21:53 +00002141MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002142{
2143 assert(image != (const Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00002144 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00002145 if (image->debug != MagickFalse)
2146 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2147 return(image->blob->temporary);
2148}
2149
2150/*
2151%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2152% %
2153% %
2154% %
2155+ M a p B l o b %
2156% %
2157% %
2158% %
2159%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2160%
2161% MapBlob() creates a mapping from a file to a binary large object.
2162%
2163% The format of the MapBlob method is:
2164%
cristy6586a802015-01-24 15:48:55 +00002165% void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
2166% const size_t length)
cristy3ed852e2009-09-05 21:47:34 +00002167%
2168% A description of each parameter follows:
2169%
2170% o file: map this file descriptor.
2171%
2172% o mode: ReadMode, WriteMode, or IOMode.
2173%
2174% o offset: starting at this offset within the file.
2175%
2176% o length: the length of the mapping is returned in this pointer.
2177%
2178*/
cristy6586a802015-01-24 15:48:55 +00002179MagickExport void *MapBlob(int file,const MapMode mode,
cristy3ed852e2009-09-05 21:47:34 +00002180 const MagickOffsetType offset,const size_t length)
2181{
cristydc8ea8e2013-07-28 20:10:44 +00002182#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00002183 int
2184 flags,
2185 protection;
2186
cristy6586a802015-01-24 15:48:55 +00002187 void
cristy3ed852e2009-09-05 21:47:34 +00002188 *map;
2189
2190 /*
2191 Map file.
2192 */
2193 flags=0;
2194 if (file == -1)
2195#if defined(MAP_ANONYMOUS)
2196 flags|=MAP_ANONYMOUS;
2197#else
cristy6586a802015-01-24 15:48:55 +00002198 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00002199#endif
2200 switch (mode)
2201 {
2202 case ReadMode:
2203 default:
2204 {
2205 protection=PROT_READ;
2206 flags|=MAP_PRIVATE;
cristy3ed852e2009-09-05 21:47:34 +00002207 break;
2208 }
2209 case WriteMode:
2210 {
2211 protection=PROT_WRITE;
2212 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002213 break;
2214 }
2215 case IOMode:
2216 {
2217 protection=PROT_READ | PROT_WRITE;
2218 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002219 break;
2220 }
2221 }
cristy56a0dbe2013-07-09 15:27:09 +00002222#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
cristy6586a802015-01-24 15:48:55 +00002223 map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
cristy56a0dbe2013-07-09 15:27:09 +00002224#else
cristy6586a802015-01-24 15:48:55 +00002225 map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,(off_t)
2226 offset);
2227 if (map == MAP_FAILED)
2228 map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
cristy56a0dbe2013-07-09 15:27:09 +00002229#endif
cristy6586a802015-01-24 15:48:55 +00002230 if (map == MAP_FAILED)
2231 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00002232 return(map);
2233#else
2234 (void) file;
2235 (void) mode;
2236 (void) offset;
2237 (void) length;
cristy6586a802015-01-24 15:48:55 +00002238 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00002239#endif
2240}
2241
2242/*
2243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2244% %
2245% %
2246% %
2247+ M S B O r d e r L o n g %
2248% %
2249% %
2250% %
2251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2252%
2253% MSBOrderLong() converts a least-significant byte first buffer of integers to
2254% most-significant byte first.
2255%
2256% The format of the MSBOrderLong method is:
2257%
2258% void MSBOrderLong(unsigned char *buffer,const size_t length)
2259%
2260% A description of each parameter follows.
2261%
2262% o buffer: Specifies a pointer to a buffer of integers.
2263%
2264% o length: Specifies the length of the buffer.
2265%
2266*/
2267MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2268{
2269 int
2270 c;
2271
2272 register unsigned char
2273 *p,
2274 *q;
2275
2276 assert(buffer != (unsigned char *) NULL);
2277 q=buffer+length;
2278 while (buffer < q)
2279 {
2280 p=buffer+3;
2281 c=(int) (*p);
2282 *p=(*buffer);
2283 *buffer++=(unsigned char) c;
2284 p=buffer+1;
2285 c=(int) (*p);
2286 *p=(*buffer);
2287 *buffer++=(unsigned char) c;
2288 buffer+=2;
2289 }
2290}
2291
2292/*
2293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2294% %
2295% %
2296% %
2297+ M S B O r d e r S h o r t %
2298% %
2299% %
2300% %
2301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2302%
2303% MSBOrderShort() converts a least-significant byte first buffer of integers
2304% to most-significant byte first.
2305%
2306% The format of the MSBOrderShort method is:
2307%
2308% void MSBOrderShort(unsigned char *p,const size_t length)
2309%
2310% A description of each parameter follows.
2311%
2312% o p: Specifies a pointer to a buffer of integers.
2313%
2314% o length: Specifies the length of the buffer.
2315%
2316*/
2317MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2318{
2319 int
2320 c;
2321
2322 register unsigned char
2323 *q;
2324
2325 assert(p != (unsigned char *) NULL);
2326 q=p+length;
2327 while (p < q)
2328 {
2329 c=(int) (*p);
2330 *p=(*(p+1));
2331 p++;
2332 *p++=(unsigned char) c;
2333 }
2334}
2335
2336/*
2337%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2338% %
2339% %
2340% %
2341+ O p e n B l o b %
2342% %
2343% %
2344% %
2345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2346%
2347% OpenBlob() opens a file associated with the image. A file name of '-' sets
2348% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2349% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2350% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2351% from a system command.
2352%
2353% The format of the OpenBlob method is:
2354%
2355% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2356% const BlobMode mode,ExceptionInfo *exception)
2357%
2358% A description of each parameter follows:
2359%
2360% o image_info: the image info.
2361%
2362% o image: the image.
2363%
2364% o mode: the mode for opening the file.
2365%
2366*/
cristyfb348292015-04-12 00:28:54 +00002367
2368static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
2369 Image *image)
2370{
2371 const char
2372 *option;
2373
2374 int
2375 status;
2376
2377 size_t
2378 size;
2379
2380 size=16384;
2381 option=GetImageOption(image_info,"stream:buffer-size");
2382 if (option != (const char *) NULL)
2383 size=StringToUnsignedLong(option);
2384 status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
2385 _IONBF : _IOFBF,size);
2386 return(status == 0 ? MagickTrue : MagickFalse);
2387}
2388
cristy3ed852e2009-09-05 21:47:34 +00002389MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2390 Image *image,const BlobMode mode,ExceptionInfo *exception)
2391{
2392 char
cristy151b66d2015-04-15 10:50:31 +00002393 extension[MagickPathExtent],
2394 filename[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00002395
2396 const char
2397 *type;
2398
2399 MagickBooleanType
2400 status;
2401
2402 PolicyRights
2403 rights;
2404
2405 assert(image_info != (ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00002406 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00002407 if (image_info->debug != MagickFalse)
2408 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2409 image_info->filename);
2410 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00002411 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00002412 if (image_info->blob != (void *) NULL)
2413 {
2414 if (image_info->stream != (StreamHandler) NULL)
2415 image->blob->stream=(StreamHandler) image_info->stream;
2416 AttachBlob(image->blob,image_info->blob,image_info->length);
2417 return(MagickTrue);
2418 }
2419 (void) DetachBlob(image->blob);
2420 switch (mode)
2421 {
2422 default: type="r"; break;
2423 case ReadBlobMode: type="r"; break;
2424 case ReadBinaryBlobMode: type="rb"; break;
2425 case WriteBlobMode: type="w"; break;
2426 case WriteBinaryBlobMode: type="w+b"; break;
2427 case AppendBlobMode: type="a"; break;
2428 case AppendBinaryBlobMode: type="a+b"; break;
2429 }
2430 if (*type != 'r')
2431 image->blob->synchronize=image_info->synchronize;
2432 if (image_info->stream != (StreamHandler) NULL)
2433 {
2434 image->blob->stream=(StreamHandler) image_info->stream;
2435 if (*type == 'w')
2436 {
2437 image->blob->type=FifoStream;
2438 return(MagickTrue);
2439 }
2440 }
2441 /*
2442 Open image file.
2443 */
2444 *filename='\0';
cristy151b66d2015-04-15 10:50:31 +00002445 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00002446 rights=ReadPolicyRights;
2447 if (*type == 'w')
2448 rights=WritePolicyRights;
2449 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2450 {
cristya9197f62010-01-12 02:23:34 +00002451 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002452 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
cristyefe601c2013-01-05 17:51:12 +00002453 "NotAuthorized","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00002454 return(MagickFalse);
2455 }
2456 if ((LocaleCompare(filename,"-") == 0) ||
2457 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2458 {
cristye7b28372012-06-17 13:59:06 +00002459 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002460#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002461 if (strchr(type,'b') != (char *) NULL)
cristye7b28372012-06-17 13:59:06 +00002462 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002463#endif
2464 image->blob->type=StandardStream;
2465 image->blob->exempt=MagickTrue;
cristyfb348292015-04-12 00:28:54 +00002466 return(SetStreamBuffering(image_info,image));
cristy3ed852e2009-09-05 21:47:34 +00002467 }
cristybc20d112012-07-29 20:27:00 +00002468 if (LocaleNCompare(filename,"fd:",3) == 0)
2469 {
2470 char
dirkfa589d62015-09-20 16:59:31 +02002471 fileMode[MagickPathExtent];
cristybc20d112012-07-29 20:27:00 +00002472
dirkfa589d62015-09-20 16:59:31 +02002473 *fileMode =(*type);
2474 fileMode[1]='\0';
2475 image->blob->file_info.file=fdopen(StringToLong(filename+3),fileMode);
cristybc20d112012-07-29 20:27:00 +00002476#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2477 if (strchr(type,'b') != (char *) NULL)
2478 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2479#endif
2480 image->blob->type=StandardStream;
2481 image->blob->exempt=MagickTrue;
cristyfb348292015-04-12 00:28:54 +00002482 return(SetStreamBuffering(image_info,image));
cristybc20d112012-07-29 20:27:00 +00002483 }
cristy3ed852e2009-09-05 21:47:34 +00002484#if defined(MAGICKCORE_HAVE_POPEN)
2485 if (*filename == '|')
2486 {
2487 char
dirkfa589d62015-09-20 16:59:31 +02002488 fileMode[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00002489
2490 /*
2491 Pipe image to or from a system command.
2492 */
2493#if defined(SIGPIPE)
2494 if (*type == 'w')
2495 (void) signal(SIGPIPE,SIG_IGN);
2496#endif
dirkfa589d62015-09-20 16:59:31 +02002497 *fileMode =(*type);
2498 fileMode[1]='\0';
2499 image->blob->file_info.file=(FILE *) popen_utf8(filename+1, fileMode);
cristye7b28372012-06-17 13:59:06 +00002500 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002501 {
2502 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2503 return(MagickFalse);
2504 }
2505 image->blob->type=PipeStream;
2506 image->blob->exempt=MagickTrue;
cristyfb348292015-04-12 00:28:54 +00002507 return(SetStreamBuffering(image_info,image));
cristy3ed852e2009-09-05 21:47:34 +00002508 }
2509#endif
2510 status=GetPathAttributes(filename,&image->blob->properties);
2511#if defined(S_ISFIFO)
cristycd8b3312013-12-22 01:51:11 +00002512 if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
cristy3ed852e2009-09-05 21:47:34 +00002513 {
cristye7b28372012-06-17 13:59:06 +00002514 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2515 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002516 {
2517 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2518 return(MagickFalse);
2519 }
2520 image->blob->type=FileStream;
2521 image->blob->exempt=MagickTrue;
cristyfb348292015-04-12 00:28:54 +00002522 return(SetStreamBuffering(image_info,image));
cristy3ed852e2009-09-05 21:47:34 +00002523 }
2524#endif
cristybf6a7092010-06-11 02:12:15 +00002525 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002526 if (*type == 'w')
2527 {
cristy151b66d2015-04-15 10:50:31 +00002528 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
cristyb9e31362010-04-22 16:38:17 +00002529 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002530 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002531 {
2532 /*
2533 Form filename for multi-part images.
2534 */
2535 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002536 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002537 if ((LocaleCompare(filename,image->filename) == 0) &&
2538 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2539 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002540 {
cristybf7fa0d2010-02-04 00:51:10 +00002541 char
cristy151b66d2015-04-15 10:50:31 +00002542 path[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00002543
cristybf7fa0d2010-02-04 00:51:10 +00002544 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002545 if (*extension == '\0')
cristy151b66d2015-04-15 10:50:31 +00002546 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002547 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002548 else
cristy151b66d2015-04-15 10:50:31 +00002549 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002550 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002551 }
cristy151b66d2015-04-15 10:50:31 +00002552 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00002553#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002554 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002555#endif
cristye8939e72010-02-03 17:05:25 +00002556 }
cristy3ed852e2009-09-05 21:47:34 +00002557 }
cristybf6a7092010-06-11 02:12:15 +00002558 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002559 {
cristye7b28372012-06-17 13:59:06 +00002560 image->blob->file_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002561 image->blob->type=FileStream;
2562 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002563 }
2564 else
cristybf6a7092010-06-11 02:12:15 +00002565 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002566 {
cristye7b28372012-06-17 13:59:06 +00002567 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2568 if (image->blob->file_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002569 {
2570 size_t
cristybf6a7092010-06-11 02:12:15 +00002571 count;
cristy3ed852e2009-09-05 21:47:34 +00002572
cristybf6a7092010-06-11 02:12:15 +00002573 unsigned char
2574 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002575
cristybf6a7092010-06-11 02:12:15 +00002576 image->blob->type=FileStream;
cristyfb348292015-04-12 00:28:54 +00002577 (void) SetStreamBuffering(image_info,image);
cristybf6a7092010-06-11 02:12:15 +00002578 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristye7b28372012-06-17 13:59:06 +00002579 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
cristyae958042013-01-05 15:48:19 +00002580 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
Cristy389502d2015-09-29 08:11:16 -04002581#if defined(MAGICKCORE_POSIX_SUPPORT)
2582 (void) fflush(image->blob->file_info.file);
2583#endif
cristybf6a7092010-06-11 02:12:15 +00002584 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2585 " read %.20g magic header bytes",(double) count);
2586#if defined(MAGICKCORE_ZLIB_DELEGATE)
2587 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2588 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002589 {
cristy98677002014-04-27 19:33:02 +00002590 if (image->blob->file_info.file != (FILE *) NULL)
2591 (void) fclose(image->blob->file_info.file);
2592 image->blob->file_info.file=(FILE *) NULL;
cristye7b28372012-06-17 13:59:06 +00002593 image->blob->file_info.gzfile=gzopen(filename,type);
2594 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002595 image->blob->type=ZipStream;
2596 }
2597#endif
2598#if defined(MAGICKCORE_BZLIB_DELEGATE)
2599 if (strncmp((char *) magick,"BZh",3) == 0)
2600 {
cristy98677002014-04-27 19:33:02 +00002601 if (image->blob->file_info.file != (FILE *) NULL)
2602 (void) fclose(image->blob->file_info.file);
2603 image->blob->file_info.file=(FILE *) NULL;
cristye7b28372012-06-17 13:59:06 +00002604 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2605 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002606 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002607 }
cristybf6a7092010-06-11 02:12:15 +00002608#endif
cristyc6c589d2010-07-06 01:34:57 +00002609 if (image->blob->type == FileStream)
2610 {
2611 const MagickInfo
2612 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002613
cristyc6c589d2010-07-06 01:34:57 +00002614 ExceptionInfo
2615 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002616
cristy18aba912013-06-14 19:48:08 +00002617 size_t
2618 length;
2619
cristyc6c589d2010-07-06 01:34:57 +00002620 sans_exception=AcquireExceptionInfo();
2621 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2622 sans_exception=DestroyExceptionInfo(sans_exception);
cristy2eddb3d2013-06-16 14:10:08 +00002623 length=(size_t) image->blob->properties.st_size;
cristyc6c589d2010-07-06 01:34:57 +00002624 if ((magick_info != (const MagickInfo *) NULL) &&
2625 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
cristybfdec892015-01-24 23:56:26 +00002626 (length > MagickMaxBufferExtent) &&
cristy18aba912013-06-14 19:48:08 +00002627 (AcquireMagickResource(MapResource,length) != MagickFalse))
cristyc6c589d2010-07-06 01:34:57 +00002628 {
cristyc6c589d2010-07-06 01:34:57 +00002629 void
2630 *blob;
cristybf6a7092010-06-11 02:12:15 +00002631
cristyfe00ebf2013-06-16 14:17:53 +00002632 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2633 length);
cristy18aba912013-06-14 19:48:08 +00002634 if (blob == (void *) NULL)
2635 RelinquishMagickResource(MapResource,length);
2636 else
cristyc6c589d2010-07-06 01:34:57 +00002637 {
2638 /*
2639 Format supports blobs-- use memory-mapped I/O.
2640 */
2641 if (image_info->file != (FILE *) NULL)
2642 image->blob->exempt=MagickFalse;
2643 else
2644 {
cristye7b28372012-06-17 13:59:06 +00002645 (void) fclose(image->blob->file_info.file);
2646 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002647 }
2648 AttachBlob(image->blob,blob,length);
2649 image->blob->mapped=MagickTrue;
2650 }
2651 }
2652 }
cristy3ed852e2009-09-05 21:47:34 +00002653 }
cristybf6a7092010-06-11 02:12:15 +00002654 }
2655 else
2656#if defined(MAGICKCORE_ZLIB_DELEGATE)
2657 if ((LocaleCompare(extension,"Z") == 0) ||
2658 (LocaleCompare(extension,"gz") == 0) ||
2659 (LocaleCompare(extension,"wmz") == 0) ||
2660 (LocaleCompare(extension,"svgz") == 0))
2661 {
2662 if (mode == WriteBinaryBlobMode)
2663 type="wb";
cristye7b28372012-06-17 13:59:06 +00002664 image->blob->file_info.gzfile=gzopen(filename,type);
2665 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002666 image->blob->type=ZipStream;
2667 }
2668 else
2669#endif
2670#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002671 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002672 {
cristye7b28372012-06-17 13:59:06 +00002673 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2674 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002675 image->blob->type=BZipStream;
2676 }
2677 else
2678#endif
2679 {
cristye7b28372012-06-17 13:59:06 +00002680 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2681 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002682 {
2683 image->blob->type=FileStream;
cristyfb348292015-04-12 00:28:54 +00002684 (void) SetStreamBuffering(image_info,image);
cristybf6a7092010-06-11 02:12:15 +00002685 }
2686 }
cristy3ed852e2009-09-05 21:47:34 +00002687 image->blob->status=MagickFalse;
2688 if (image->blob->type != UndefinedStream)
2689 image->blob->size=GetBlobSize(image);
2690 else
2691 {
2692 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2693 return(MagickFalse);
2694 }
2695 return(MagickTrue);
2696}
2697
2698/*
2699%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2700% %
2701% %
2702% %
2703+ P i n g B l o b %
2704% %
2705% %
2706% %
2707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2708%
2709% PingBlob() returns all the attributes of an image or image sequence except
2710% for the pixels. It is much faster and consumes far less memory than
2711% BlobToImage(). On failure, a NULL image is returned and exception
2712% describes the reason for the failure.
2713%
2714% The format of the PingBlob method is:
2715%
2716% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2717% const size_t length,ExceptionInfo *exception)
2718%
2719% A description of each parameter follows:
2720%
2721% o image_info: the image info.
2722%
2723% o blob: the address of a character stream in one of the image formats
2724% understood by ImageMagick.
2725%
2726% o length: This size_t integer reflects the length in bytes of the blob.
2727%
2728% o exception: return any errors or warnings in this structure.
2729%
2730*/
2731
2732#if defined(__cplusplus) || defined(c_plusplus)
2733extern "C" {
2734#endif
2735
2736static size_t PingStream(const Image *magick_unused(image),
2737 const void *magick_unused(pixels),const size_t columns)
2738{
2739 return(columns);
2740}
2741
2742#if defined(__cplusplus) || defined(c_plusplus)
2743}
2744#endif
2745
2746MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2747 const size_t length,ExceptionInfo *exception)
2748{
2749 Image
2750 *image;
2751
2752 ImageInfo
2753 *ping_info;
2754
2755 assert(image_info != (ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00002756 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00002757 if (image_info->debug != MagickFalse)
2758 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2759 image_info->filename);
2760 assert(exception != (ExceptionInfo *) NULL);
2761 if ((blob == (const void *) NULL) || (length == 0))
2762 {
2763 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +00002764 "UnrecognizedImageFormat","`%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002765 return((Image *) NULL);
2766 }
2767 ping_info=CloneImageInfo(image_info);
2768 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2769 if (ping_info->blob == (const void *) NULL)
2770 {
2771 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00002772 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002773 return((Image *) NULL);
2774 }
cristy54aad5e2010-09-03 16:02:04 +00002775 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002776 ping_info->length=length;
2777 ping_info->ping=MagickTrue;
2778 image=ReadStream(ping_info,&PingStream,exception);
2779 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2780 ping_info=DestroyImageInfo(ping_info);
2781 return(image);
2782}
2783
2784/*
2785%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2786% %
2787% %
2788% %
2789+ R e a d B l o b %
2790% %
2791% %
2792% %
2793%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2794%
2795% ReadBlob() reads data from the blob or image file and returns it. It
cristy5f3d2752013-01-05 18:53:38 +00002796% returns the number of bytes read. If length is zero, ReadBlob() returns
2797% zero and has no other results. If length is greater than SSIZE_MAX, the
2798% result is unspecified.
cristy3ed852e2009-09-05 21:47:34 +00002799%
2800% The format of the ReadBlob method is:
2801%
cristy6586a802015-01-24 15:48:55 +00002802% ssize_t ReadBlob(Image *image,const size_t length,void *data)
cristy3ed852e2009-09-05 21:47:34 +00002803%
2804% A description of each parameter follows:
2805%
2806% o image: the image.
2807%
2808% o length: Specifies an integer representing the number of bytes to read
2809% from the file.
2810%
2811% o data: Specifies an area to place the information requested from the
2812% file.
2813%
2814*/
cristy6586a802015-01-24 15:48:55 +00002815MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
cristy3ed852e2009-09-05 21:47:34 +00002816{
2817 int
2818 c;
2819
2820 register unsigned char
2821 *q;
2822
2823 ssize_t
2824 count;
2825
2826 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00002827 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00002828 assert(image->blob != (BlobInfo *) NULL);
2829 assert(image->blob->type != UndefinedStream);
2830 if (length == 0)
2831 return(0);
2832 assert(data != (void *) NULL);
2833 count=0;
cristyce0e7b22015-05-18 00:12:46 +00002834 q=(unsigned char *) data;
cristy3ed852e2009-09-05 21:47:34 +00002835 switch (image->blob->type)
2836 {
2837 case UndefinedStream:
2838 break;
cristy3ed852e2009-09-05 21:47:34 +00002839 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002840 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002841 case PipeStream:
2842 {
2843 switch (length)
2844 {
2845 default:
2846 {
cristye7b28372012-06-17 13:59:06 +00002847 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002848 break;
2849 }
cristy28389292015-04-11 12:43:09 +00002850 case 4:
2851 {
2852 c=getc(image->blob->file_info.file);
2853 if (c == EOF)
2854 break;
2855 *q++=(unsigned char) c;
2856 count++;
2857 }
2858 case 3:
2859 {
2860 c=getc(image->blob->file_info.file);
2861 if (c == EOF)
2862 break;
2863 *q++=(unsigned char) c;
2864 count++;
2865 }
cristy3ed852e2009-09-05 21:47:34 +00002866 case 2:
2867 {
cristye7b28372012-06-17 13:59:06 +00002868 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002869 if (c == EOF)
2870 break;
2871 *q++=(unsigned char) c;
2872 count++;
2873 }
2874 case 1:
2875 {
cristye7b28372012-06-17 13:59:06 +00002876 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002877 if (c == EOF)
2878 break;
2879 *q++=(unsigned char) c;
2880 count++;
2881 }
2882 case 0:
2883 break;
2884 }
2885 break;
2886 }
2887 case ZipStream:
2888 {
2889#if defined(MAGICKCORE_ZLIB_DELEGATE)
2890 switch (length)
2891 {
2892 default:
2893 {
cristye7b28372012-06-17 13:59:06 +00002894 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002895 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002896 break;
2897 }
cristy28389292015-04-11 12:43:09 +00002898 case 4:
2899 {
2900 c=gzgetc(image->blob->file_info.gzfile);
2901 if (c == EOF)
2902 break;
2903 *q++=(unsigned char) c;
2904 count++;
2905 }
2906 case 3:
2907 {
2908 c=gzgetc(image->blob->file_info.gzfile);
2909 if (c == EOF)
2910 break;
2911 *q++=(unsigned char) c;
2912 count++;
2913 }
cristy3ed852e2009-09-05 21:47:34 +00002914 case 2:
2915 {
cristye7b28372012-06-17 13:59:06 +00002916 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002917 if (c == EOF)
2918 break;
2919 *q++=(unsigned char) c;
2920 count++;
2921 }
2922 case 1:
2923 {
cristye7b28372012-06-17 13:59:06 +00002924 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002925 if (c == EOF)
2926 break;
2927 *q++=(unsigned char) c;
2928 count++;
2929 }
2930 case 0:
2931 break;
2932 }
2933#endif
2934 break;
2935 }
2936 case BZipStream:
2937 {
2938#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy5f3d2752013-01-05 18:53:38 +00002939 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
cristy3ed852e2009-09-05 21:47:34 +00002940#endif
2941 break;
2942 }
2943 case FifoStream:
2944 break;
2945 case BlobStream:
2946 {
2947 register const unsigned char
2948 *p;
2949
2950 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2951 {
2952 image->blob->eof=MagickTrue;
2953 break;
2954 }
2955 p=image->blob->data+image->blob->offset;
cristyf201ba62015-07-05 13:54:28 +00002956 count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
cristy3ed852e2009-09-05 21:47:34 +00002957 image->blob->offset+=count;
2958 if (count != (ssize_t) length)
2959 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002960 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002961 break;
2962 }
2963 }
2964 return(count);
2965}
2966
2967/*
2968%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2969% %
2970% %
2971% %
2972+ R e a d B l o b B y t e %
2973% %
2974% %
2975% %
2976%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2977%
2978% ReadBlobByte() reads a single byte from the image file and returns it.
2979%
2980% The format of the ReadBlobByte method is:
2981%
2982% int ReadBlobByte(Image *image)
2983%
2984% A description of each parameter follows.
2985%
2986% o image: the image.
2987%
2988*/
2989MagickExport int ReadBlobByte(Image *image)
2990{
2991 register const unsigned char
2992 *p;
2993
2994 ssize_t
2995 count;
2996
2997 unsigned char
2998 buffer[1];
2999
3000 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003001 assert(image->signature == MagickCoreSignature);
cristyce0e7b22015-05-18 00:12:46 +00003002 p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003003 if (count != 1)
3004 return(EOF);
3005 return((int) (*p));
3006}
3007
3008/*
3009%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3010% %
3011% %
3012% %
3013+ R e a d B l o b D o u b l e %
3014% %
3015% %
3016% %
3017%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3018%
3019% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3020% specified by the endian member of the image structure.
3021%
3022% The format of the ReadBlobDouble method is:
3023%
3024% double ReadBlobDouble(Image *image)
3025%
3026% A description of each parameter follows.
3027%
3028% o image: the image.
3029%
3030*/
3031MagickExport double ReadBlobDouble(Image *image)
3032{
3033 union
3034 {
3035 MagickSizeType
3036 unsigned_value;
3037
3038 double
3039 double_value;
3040 } quantum;
3041
3042 quantum.double_value=0.0;
3043 quantum.unsigned_value=ReadBlobLongLong(image);
3044 return(quantum.double_value);
3045}
3046
3047/*
3048%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3049% %
3050% %
3051% %
3052+ R e a d B l o b F l o a t %
3053% %
3054% %
3055% %
3056%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3057%
3058% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3059% specified by the endian member of the image structure.
3060%
3061% The format of the ReadBlobFloat method is:
3062%
3063% float ReadBlobFloat(Image *image)
3064%
3065% A description of each parameter follows.
3066%
3067% o image: the image.
3068%
3069*/
3070MagickExport float ReadBlobFloat(Image *image)
3071{
3072 union
3073 {
3074 unsigned int
3075 unsigned_value;
3076
3077 float
3078 float_value;
3079 } quantum;
3080
3081 quantum.float_value=0.0;
3082 quantum.unsigned_value=ReadBlobLong(image);
3083 return(quantum.float_value);
3084}
3085
3086/*
3087%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3088% %
3089% %
3090% %
3091+ R e a d B l o b L o n g %
3092% %
3093% %
3094% %
3095%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3096%
cristybb503372010-05-27 20:51:26 +00003097% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003098% specified by the endian member of the image structure.
3099%
3100% The format of the ReadBlobLong method is:
3101%
3102% unsigned int ReadBlobLong(Image *image)
3103%
3104% A description of each parameter follows.
3105%
3106% o image: the image.
3107%
3108*/
3109MagickExport unsigned int ReadBlobLong(Image *image)
3110{
3111 register const unsigned char
3112 *p;
3113
3114 ssize_t
3115 count;
3116
3117 unsigned char
3118 buffer[4];
3119
3120 unsigned int
3121 value;
3122
3123 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003124 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00003125 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003126 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003127 if (count != 4)
3128 return(0UL);
3129 if (image->endian == LSBEndian)
3130 {
3131 value=(unsigned int) (*p++);
3132 value|=((unsigned int) (*p++)) << 8;
3133 value|=((unsigned int) (*p++)) << 16;
3134 value|=((unsigned int) (*p++)) << 24;
3135 return(value);
3136 }
3137 value=((unsigned int) (*p++)) << 24;
3138 value|=((unsigned int) (*p++)) << 16;
3139 value|=((unsigned int) (*p++)) << 8;
3140 value|=((unsigned int) (*p++));
3141 return(value);
3142}
3143
3144/*
3145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3146% %
3147% %
3148% %
3149+ R e a d B l o b L o n g L o n g %
3150% %
3151% %
3152% %
3153%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3154%
cristy4cb162a2010-05-30 03:04:47 +00003155% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3156% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003157%
cristy4cb162a2010-05-30 03:04:47 +00003158% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003159%
cristy4cb162a2010-05-30 03:04:47 +00003160% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003161%
3162% A description of each parameter follows.
3163%
3164% o image: the image.
3165%
3166*/
3167MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3168{
cristy0286d852010-10-12 18:38:07 +00003169 MagickSizeType
3170 value;
3171
cristy3ed852e2009-09-05 21:47:34 +00003172 register const unsigned char
3173 *p;
3174
3175 ssize_t
3176 count;
3177
3178 unsigned char
3179 buffer[8];
3180
cristy3ed852e2009-09-05 21:47:34 +00003181 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003182 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00003183 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003184 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003185 if (count != 8)
3186 return(MagickULLConstant(0));
3187 if (image->endian == LSBEndian)
3188 {
3189 value=(MagickSizeType) (*p++);
3190 value|=((MagickSizeType) (*p++)) << 8;
3191 value|=((MagickSizeType) (*p++)) << 16;
3192 value|=((MagickSizeType) (*p++)) << 24;
3193 value|=((MagickSizeType) (*p++)) << 32;
3194 value|=((MagickSizeType) (*p++)) << 40;
3195 value|=((MagickSizeType) (*p++)) << 48;
3196 value|=((MagickSizeType) (*p++)) << 56;
3197 return(value & MagickULLConstant(0xffffffffffffffff));
3198 }
3199 value=((MagickSizeType) (*p++)) << 56;
3200 value|=((MagickSizeType) (*p++)) << 48;
3201 value|=((MagickSizeType) (*p++)) << 40;
3202 value|=((MagickSizeType) (*p++)) << 32;
3203 value|=((MagickSizeType) (*p++)) << 24;
3204 value|=((MagickSizeType) (*p++)) << 16;
3205 value|=((MagickSizeType) (*p++)) << 8;
3206 value|=((MagickSizeType) (*p++));
3207 return(value & MagickULLConstant(0xffffffffffffffff));
3208}
3209
3210/*
3211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3212% %
3213% %
3214% %
3215+ R e a d B l o b S h o r t %
3216% %
3217% %
3218% %
3219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3220%
3221% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3222% specified by the endian member of the image structure.
3223%
3224% The format of the ReadBlobShort method is:
3225%
3226% unsigned short ReadBlobShort(Image *image)
3227%
3228% A description of each parameter follows.
3229%
3230% o image: the image.
3231%
3232*/
3233MagickExport unsigned short ReadBlobShort(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[2];
3246
3247 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003248 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00003249 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003250 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003251 if (count != 2)
3252 return((unsigned short) 0U);
3253 if (image->endian == LSBEndian)
3254 {
3255 value=(unsigned int) (*p++);
3256 value|=((unsigned int) (*p++)) << 8;
3257 return((unsigned short) (value & 0xffff));
3258 }
3259 value=(unsigned int) ((*p++) << 8);
3260 value|=(unsigned int) (*p++);
3261 return((unsigned short) (value & 0xffff));
3262}
3263
3264/*
3265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3266% %
3267% %
3268% %
3269+ R e a d B l o b L S B L o n g %
3270% %
3271% %
3272% %
3273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3274%
cristybb503372010-05-27 20:51:26 +00003275% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003276% least-significant byte first order.
3277%
3278% The format of the ReadBlobLSBLong method is:
3279%
3280% unsigned int ReadBlobLSBLong(Image *image)
3281%
3282% A description of each parameter follows.
3283%
3284% o image: the image.
3285%
3286*/
3287MagickExport unsigned int ReadBlobLSBLong(Image *image)
3288{
3289 register const unsigned char
3290 *p;
3291
3292 register unsigned int
3293 value;
3294
3295 ssize_t
3296 count;
3297
3298 unsigned char
3299 buffer[4];
3300
3301 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003302 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00003303 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003304 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003305 if (count != 4)
3306 return(0U);
3307 value=(unsigned int) (*p++);
3308 value|=((unsigned int) (*p++)) << 8;
3309 value|=((unsigned int) (*p++)) << 16;
3310 value|=((unsigned int) (*p++)) << 24;
3311 return(value);
3312}
3313
3314/*
3315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3316% %
3317% %
3318% %
3319+ R e a d B l o b L S B S h o r t %
3320% %
3321% %
3322% %
3323%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3324%
3325% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3326% least-significant byte first order.
3327%
3328% The format of the ReadBlobLSBShort method is:
3329%
3330% unsigned short ReadBlobLSBShort(Image *image)
3331%
3332% A description of each parameter follows.
3333%
3334% o image: the image.
3335%
3336*/
3337MagickExport unsigned short ReadBlobLSBShort(Image *image)
3338{
3339 register const unsigned char
3340 *p;
3341
3342 register unsigned int
3343 value;
3344
3345 ssize_t
3346 count;
3347
3348 unsigned char
3349 buffer[2];
3350
3351 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003352 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00003353 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003354 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003355 if (count != 2)
3356 return((unsigned short) 0U);
3357 value=(unsigned int) (*p++);
3358 value|=((unsigned int) ((*p++)) << 8);
3359 return((unsigned short) (value & 0xffff));
3360}
3361
3362/*
3363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3364% %
3365% %
3366% %
3367+ R e a d B l o b M S B L o n g %
3368% %
3369% %
3370% %
3371%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3372%
cristybb503372010-05-27 20:51:26 +00003373% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003374% most-significant byte first order.
3375%
3376% The format of the ReadBlobMSBLong method is:
3377%
3378% unsigned int ReadBlobMSBLong(Image *image)
3379%
3380% A description of each parameter follows.
3381%
3382% o image: the image.
3383%
3384*/
3385MagickExport unsigned int ReadBlobMSBLong(Image *image)
3386{
3387 register const unsigned char
3388 *p;
3389
3390 register unsigned int
3391 value;
3392
3393 ssize_t
3394 count;
3395
3396 unsigned char
3397 buffer[4];
3398
3399 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003400 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00003401 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003402 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003403 if (count != 4)
3404 return(0UL);
3405 value=((unsigned int) (*p++) << 24);
3406 value|=((unsigned int) (*p++) << 16);
3407 value|=((unsigned int) (*p++) << 8);
3408 value|=(unsigned int) (*p++);
3409 return(value);
3410}
3411
3412/*
3413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3414% %
3415% %
3416% %
cristy2d3d87f2010-03-01 00:23:08 +00003417+ R e a d B l o b M S B L o n g L o n g %
3418% %
3419% %
3420% %
3421%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3422%
cristybb503372010-05-27 20:51:26 +00003423% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003424% most-significant byte first order.
3425%
3426% The format of the ReadBlobMSBLongLong method is:
3427%
3428% unsigned int ReadBlobMSBLongLong(Image *image)
3429%
3430% A description of each parameter follows.
3431%
3432% o image: the image.
3433%
3434*/
3435MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3436{
3437 register const unsigned char
3438 *p;
3439
3440 register MagickSizeType
3441 value;
3442
3443 ssize_t
3444 count;
3445
3446 unsigned char
cristy0286d852010-10-12 18:38:07 +00003447 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003448
3449 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003450 assert(image->signature == MagickCoreSignature);
cristy2d3d87f2010-03-01 00:23:08 +00003451 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003452 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
cristy2d3d87f2010-03-01 00:23:08 +00003453 if (count != 8)
3454 return(MagickULLConstant(0));
3455 value=((MagickSizeType) (*p++)) << 56;
3456 value|=((MagickSizeType) (*p++)) << 48;
3457 value|=((MagickSizeType) (*p++)) << 40;
3458 value|=((MagickSizeType) (*p++)) << 32;
3459 value|=((MagickSizeType) (*p++)) << 24;
3460 value|=((MagickSizeType) (*p++)) << 16;
3461 value|=((MagickSizeType) (*p++)) << 8;
3462 value|=((MagickSizeType) (*p++));
3463 return(value & MagickULLConstant(0xffffffffffffffff));
3464}
3465
3466/*
3467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3468% %
3469% %
3470% %
cristy3ed852e2009-09-05 21:47:34 +00003471+ R e a d B l o b M S B S h o r t %
3472% %
3473% %
3474% %
3475%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3476%
3477% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3478% most-significant byte first order.
3479%
3480% The format of the ReadBlobMSBShort method is:
3481%
3482% unsigned short ReadBlobMSBShort(Image *image)
3483%
3484% A description of each parameter follows.
3485%
3486% o image: the image.
3487%
3488*/
3489MagickExport unsigned short ReadBlobMSBShort(Image *image)
3490{
3491 register const unsigned char
3492 *p;
3493
3494 register unsigned int
3495 value;
3496
3497 ssize_t
3498 count;
3499
3500 unsigned char
3501 buffer[2];
3502
3503 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003504 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00003505 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003506 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003507 if (count != 2)
3508 return((unsigned short) 0U);
3509 value=(unsigned int) ((*p++) << 8);
3510 value|=(unsigned int) (*p++);
3511 return((unsigned short) (value & 0xffff));
3512}
3513
3514/*
3515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3516% %
3517% %
3518% %
cristybd797f12015-01-24 20:42:32 +00003519+ R e a d B l o b S t r e a m %
3520% %
3521% %
3522% %
3523%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3524%
3525% ReadBlobStream() reads data from the blob or image file and returns it. It
3526% returns a pointer to the data buffer you supply or to the image memory
3527% buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
3528% returns a count of zero and has no other results. If length is greater than
3529% SSIZE_MAX, the result is unspecified.
3530%
3531% The format of the ReadBlobStream method is:
3532%
3533% const void *ReadBlobStream(Image *image,const size_t length,void *data,
3534% ssize_t *count)
3535%
3536% A description of each parameter follows:
3537%
3538% o image: the image.
3539%
3540% o length: Specifies an integer representing the number of bytes to read
3541% from the file.
3542%
3543% o count: returns the number of bytes read.
3544%
3545% o data: Specifies an area to place the information requested from the
3546% file.
3547%
3548*/
3549MagickExport const void *ReadBlobStream(Image *image,const size_t length,
3550 void *data,ssize_t *count)
3551{
3552 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003553 assert(image->signature == MagickCoreSignature);
cristybd797f12015-01-24 20:42:32 +00003554 assert(image->blob != (BlobInfo *) NULL);
3555 assert(image->blob->type != UndefinedStream);
3556 assert(count != (ssize_t *) NULL);
3557 if (image->blob->type != BlobStream)
3558 {
3559 assert(data != NULL);
cristyce0e7b22015-05-18 00:12:46 +00003560 *count=ReadBlob(image,length,(unsigned char *) data);
cristybd797f12015-01-24 20:42:32 +00003561 return(data);
3562 }
3563 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
3564 {
3565 *count=0;
3566 image->blob->eof=MagickTrue;
3567 return(data);
3568 }
3569 data=image->blob->data+image->blob->offset;
cristyf201ba62015-07-05 13:54:28 +00003570 *count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
cristybd797f12015-01-24 20:42:32 +00003571 image->blob->offset+=(*count);
3572 if (*count != (ssize_t) length)
3573 image->blob->eof=MagickTrue;
3574 return(data);
3575}
3576
3577/*
3578%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3579% %
3580% %
3581% %
cristy3ed852e2009-09-05 21:47:34 +00003582+ R e a d B l o b S t r i n g %
3583% %
3584% %
3585% %
3586%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3587%
3588% ReadBlobString() reads characters from a blob or file until a newline
3589% character is read or an end-of-file condition is encountered.
3590%
3591% The format of the ReadBlobString method is:
3592%
3593% char *ReadBlobString(Image *image,char *string)
3594%
3595% A description of each parameter follows:
3596%
3597% o image: the image.
3598%
3599% o string: the address of a character buffer.
3600%
3601*/
3602MagickExport char *ReadBlobString(Image *image,char *string)
3603{
3604 register const unsigned char
3605 *p;
3606
cristybb503372010-05-27 20:51:26 +00003607 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003608 i;
3609
3610 ssize_t
3611 count;
3612
3613 unsigned char
3614 buffer[1];
3615
3616 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003617 assert(image->signature == MagickCoreSignature);
cristy151b66d2015-04-15 10:50:31 +00003618 for (i=0; i < (MagickPathExtent-1L); i++)
cristy3ed852e2009-09-05 21:47:34 +00003619 {
cristyce0e7b22015-05-18 00:12:46 +00003620 p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003621 if (count != 1)
3622 {
3623 if (i == 0)
3624 return((char *) NULL);
3625 break;
3626 }
3627 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003628 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003629 break;
3630 }
cristy2b5db102010-06-09 01:07:28 +00003631 if (string[i] == '\r')
3632 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003633 string[i]='\0';
3634 return(string);
3635}
3636
3637/*
3638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3639% %
3640% %
3641% %
3642+ R e f e r e n c e B l o b %
3643% %
3644% %
3645% %
3646%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3647%
3648% ReferenceBlob() increments the reference count associated with the pixel
3649% blob returning a pointer to the blob.
3650%
3651% The format of the ReferenceBlob method is:
3652%
3653% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3654%
3655% A description of each parameter follows:
3656%
3657% o blob_info: the blob_info.
3658%
3659*/
3660MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3661{
3662 assert(blob != (BlobInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003663 assert(blob->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00003664 if (blob->debug != MagickFalse)
3665 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003666 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003667 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003668 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003669 return(blob);
3670}
3671
3672/*
3673%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3674% %
3675% %
3676% %
3677+ S e e k B l o b %
3678% %
3679% %
3680% %
3681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3682%
3683% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3684% and returns the resulting offset.
3685%
3686% The format of the SeekBlob method is:
3687%
3688% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3689% const int whence)
3690%
3691% A description of each parameter follows:
3692%
3693% o image: the image.
3694%
3695% o offset: Specifies an integer representing the offset in bytes.
3696%
3697% o whence: Specifies an integer representing how the offset is
3698% treated relative to the beginning of the blob as follows:
3699%
3700% SEEK_SET Set position equal to offset bytes.
3701% SEEK_CUR Set position to current location plus offset.
3702% SEEK_END Set position to EOF plus offset.
3703%
3704*/
3705MagickExport MagickOffsetType SeekBlob(Image *image,
3706 const MagickOffsetType offset,const int whence)
3707{
3708 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003709 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00003710 if (image->debug != MagickFalse)
3711 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3712 assert(image->blob != (BlobInfo *) NULL);
3713 assert(image->blob->type != UndefinedStream);
3714 switch (image->blob->type)
3715 {
3716 case UndefinedStream:
3717 break;
cristybc20d112012-07-29 20:27:00 +00003718 case StandardStream:
3719 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003720 case FileStream:
3721 {
cristy3bb57962015-06-20 15:31:17 +00003722 if ((offset < 0) && (whence == SEEK_SET))
3723 return(-1);
cristye7b28372012-06-17 13:59:06 +00003724 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003725 return(-1);
3726 image->blob->offset=TellBlob(image);
3727 break;
3728 }
cristy3ed852e2009-09-05 21:47:34 +00003729 case PipeStream:
3730 case ZipStream:
3731 {
3732#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003733 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003734 return(-1);
3735#endif
3736 image->blob->offset=TellBlob(image);
3737 break;
3738 }
3739 case BZipStream:
3740 return(-1);
3741 case FifoStream:
3742 return(-1);
3743 case BlobStream:
3744 {
3745 switch (whence)
3746 {
3747 case SEEK_SET:
3748 default:
3749 {
3750 if (offset < 0)
3751 return(-1);
3752 image->blob->offset=offset;
3753 break;
3754 }
3755 case SEEK_CUR:
3756 {
3757 if ((image->blob->offset+offset) < 0)
3758 return(-1);
3759 image->blob->offset+=offset;
3760 break;
3761 }
3762 case SEEK_END:
3763 {
3764 if (((MagickOffsetType) image->blob->length+offset) < 0)
3765 return(-1);
3766 image->blob->offset=image->blob->length+offset;
3767 break;
3768 }
3769 }
cristy01409b62014-12-24 20:54:20 +00003770 if (image->blob->offset < (MagickOffsetType)
cristy3ed852e2009-09-05 21:47:34 +00003771 ((off_t) image->blob->length))
cristy01409b62014-12-24 20:54:20 +00003772 {
3773 image->blob->eof=MagickFalse;
3774 break;
3775 }
3776 if (image->blob->offset < (MagickOffsetType)
3777 ((off_t) image->blob->extent))
3778 break;
cristy0779de22015-05-03 12:45:49 +00003779 if (image->blob->immutable != MagickFalse)
3780 {
3781 image->blob->eof=MagickTrue;
3782 return(-1);
3783 }
cristy01409b62014-12-24 20:54:20 +00003784 image->blob->extent=(size_t) (image->blob->offset+image->blob->quantum);
3785 image->blob->quantum<<=1;
cristyf3fe18d2015-01-26 19:57:08 +00003786 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
cristy01409b62014-12-24 20:54:20 +00003787 image->blob->extent+1,sizeof(*image->blob->data));
3788 (void) SyncBlob(image);
cristy6586a802015-01-24 15:48:55 +00003789 if (image->blob->data == NULL)
cristy01409b62014-12-24 20:54:20 +00003790 {
3791 (void) DetachBlob(image->blob);
cristy3ed852e2009-09-05 21:47:34 +00003792 return(-1);
cristy01409b62014-12-24 20:54:20 +00003793 }
cristy3ed852e2009-09-05 21:47:34 +00003794 break;
3795 }
3796 }
3797 return(image->blob->offset);
3798}
3799
3800/*
3801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3802% %
3803% %
3804% %
3805+ S e t B l o b E x e m p t %
3806% %
3807% %
3808% %
3809%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3810%
3811% SetBlobExempt() sets the blob exempt status.
3812%
3813% The format of the SetBlobExempt method is:
3814%
3815% MagickBooleanType SetBlobExempt(const Image *image,
3816% const MagickBooleanType exempt)
3817%
3818% A description of each parameter follows:
3819%
3820% o image: the image.
3821%
3822% o exempt: Set to true if this blob is exempt from being closed.
3823%
3824*/
cristy7832dc22011-09-05 01:21:53 +00003825MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003826{
3827 assert(image != (const Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003828 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00003829 if (image->debug != MagickFalse)
3830 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3831 image->blob->exempt=exempt;
3832}
3833
3834/*
3835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3836% %
3837% %
3838% %
3839+ S e t B l o b E x t e n t %
3840% %
3841% %
3842% %
3843%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3844%
3845% SetBlobExtent() ensures enough space is allocated for the blob. If the
3846% method is successful, subsequent writes to bytes in the specified range are
3847% guaranteed not to fail.
3848%
3849% The format of the SetBlobExtent method is:
3850%
3851% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3852%
3853% A description of each parameter follows:
3854%
3855% o image: the image.
3856%
3857% o extent: the blob maximum extent.
3858%
3859*/
cristy7832dc22011-09-05 01:21:53 +00003860MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003861 const MagickSizeType extent)
3862{
3863 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003864 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00003865 if (image->debug != MagickFalse)
3866 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3867 assert(image->blob != (BlobInfo *) NULL);
3868 assert(image->blob->type != UndefinedStream);
3869 switch (image->blob->type)
3870 {
3871 case UndefinedStream:
3872 break;
cristybc20d112012-07-29 20:27:00 +00003873 case StandardStream:
3874 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003875 case FileStream:
3876 {
cristy38e35f42012-12-18 21:12:17 +00003877 MagickOffsetType
3878 offset;
3879
3880 ssize_t
3881 count;
3882
cristy3ed852e2009-09-05 21:47:34 +00003883 if (extent != (MagickSizeType) ((off_t) extent))
3884 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003885 offset=SeekBlob(image,0,SEEK_END);
3886 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003887 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003888 if ((MagickSizeType) offset >= extent)
3889 break;
3890 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristy0ded5cf2015-03-22 14:05:05 +00003891 if (offset < 0)
3892 break;
cristyc7591272013-01-05 16:02:28 +00003893 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3894 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003895#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3896 if (image->blob->synchronize != MagickFalse)
3897 {
3898 int
cristybb380e72014-10-31 12:56:36 +00003899 file;
cristyfa0ea942012-12-21 02:42:29 +00003900
cristy2797f472014-05-26 01:25:55 +00003901 file=fileno(image->blob->file_info.file);
3902 if ((file == -1) || (offset < 0))
3903 return(MagickFalse);
cristybb380e72014-10-31 12:56:36 +00003904 (void) posix_fallocate(file,offset,extent-offset);
cristyfa0ea942012-12-21 02:42:29 +00003905 }
3906#endif
cristy38e35f42012-12-18 21:12:17 +00003907 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003908 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003909 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003910 break;
3911 }
cristy3ed852e2009-09-05 21:47:34 +00003912 case PipeStream:
3913 case ZipStream:
3914 return(MagickFalse);
3915 case BZipStream:
3916 return(MagickFalse);
3917 case FifoStream:
3918 return(MagickFalse);
3919 case BlobStream:
3920 {
cristy38e35f42012-12-18 21:12:17 +00003921 if (extent != (MagickSizeType) ((size_t) extent))
3922 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003923 if (image->blob->mapped != MagickFalse)
3924 {
cristy38e35f42012-12-18 21:12:17 +00003925 MagickOffsetType
3926 offset;
3927
3928 ssize_t
3929 count;
3930
cristy3ed852e2009-09-05 21:47:34 +00003931 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy18aba912013-06-14 19:48:08 +00003932 RelinquishMagickResource(MapResource,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003933 if (extent != (MagickSizeType) ((off_t) extent))
3934 return(MagickFalse);
3935 offset=SeekBlob(image,0,SEEK_END);
3936 if (offset < 0)
3937 return(MagickFalse);
3938 if ((MagickSizeType) offset >= extent)
3939 break;
3940 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003941 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003942 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003943#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3944 if (image->blob->synchronize != MagickFalse)
3945 {
3946 int
cristybb380e72014-10-31 12:56:36 +00003947 file;
cristyfa0ea942012-12-21 02:42:29 +00003948
cristy6f008fd2014-05-25 23:27:26 +00003949 file=fileno(image->blob->file_info.file);
cristyf2a82ee2014-05-26 17:49:54 +00003950 if ((file == -1) || (offset < 0))
cristy6f008fd2014-05-25 23:27:26 +00003951 return(MagickFalse);
cristybb380e72014-10-31 12:56:36 +00003952 (void) posix_fallocate(file,offset,extent-offset);
cristyfa0ea942012-12-21 02:42:29 +00003953 }
3954#endif
cristy38e35f42012-12-18 21:12:17 +00003955 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003956 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003957 return(MagickFalse);
cristyac1caa22013-06-15 00:41:21 +00003958 (void) AcquireMagickResource(MapResource,extent);
cristy95888612012-04-04 21:56:52 +00003959 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003960 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003961 image->blob->extent=(size_t) extent;
3962 image->blob->length=(size_t) extent;
3963 (void) SyncBlob(image);
3964 break;
cristy3ed852e2009-09-05 21:47:34 +00003965 }
cristy3ed852e2009-09-05 21:47:34 +00003966 image->blob->extent=(size_t) extent;
3967 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3968 image->blob->extent+1,sizeof(*image->blob->data));
3969 (void) SyncBlob(image);
3970 if (image->blob->data == (unsigned char *) NULL)
3971 {
3972 (void) DetachBlob(image->blob);
3973 return(MagickFalse);
3974 }
3975 break;
3976 }
3977 }
3978 return(MagickTrue);
3979}
3980
3981/*
3982%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3983% %
3984% %
3985% %
3986+ S y n c B l o b %
3987% %
3988% %
3989% %
3990%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3991%
3992% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3993% attributes if it is an blob.
3994%
3995% The format of the SyncBlob method is:
3996%
3997% int SyncBlob(Image *image)
3998%
3999% A description of each parameter follows:
4000%
4001% o image: the image.
4002%
4003*/
4004static int SyncBlob(Image *image)
4005{
4006 int
4007 status;
4008
4009 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004010 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00004011 if (image->debug != MagickFalse)
4012 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4013 assert(image->blob != (BlobInfo *) NULL);
4014 assert(image->blob->type != UndefinedStream);
4015 status=0;
4016 switch (image->blob->type)
4017 {
4018 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00004019 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00004020 break;
4021 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004022 case PipeStream:
4023 {
cristye7b28372012-06-17 13:59:06 +00004024 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004025 break;
4026 }
4027 case ZipStream:
4028 {
4029#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004030 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00004031#endif
4032 break;
4033 }
4034 case BZipStream:
4035 {
4036#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004037 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00004038#endif
4039 break;
4040 }
4041 case FifoStream:
4042 break;
4043 case BlobStream:
cristy3ed852e2009-09-05 21:47:34 +00004044 break;
cristy3ed852e2009-09-05 21:47:34 +00004045 }
4046 return(status);
4047}
4048
4049/*
4050%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4051% %
4052% %
4053% %
4054+ T e l l B l o b %
4055% %
4056% %
4057% %
4058%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4059%
4060% TellBlob() obtains the current value of the blob or file position.
4061%
4062% The format of the TellBlob method is:
4063%
4064% MagickOffsetType TellBlob(const Image *image)
4065%
4066% A description of each parameter follows:
4067%
4068% o image: the image.
4069%
4070*/
4071MagickExport MagickOffsetType TellBlob(const Image *image)
4072{
4073 MagickOffsetType
4074 offset;
4075
4076 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004077 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00004078 if (image->debug != MagickFalse)
4079 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4080 assert(image->blob != (BlobInfo *) NULL);
4081 assert(image->blob->type != UndefinedStream);
4082 offset=(-1);
4083 switch (image->blob->type)
4084 {
4085 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00004086 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00004087 break;
4088 case FileStream:
4089 {
cristye7b28372012-06-17 13:59:06 +00004090 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004091 break;
4092 }
cristy3ed852e2009-09-05 21:47:34 +00004093 case PipeStream:
4094 break;
4095 case ZipStream:
4096 {
4097#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004098 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00004099#endif
4100 break;
4101 }
4102 case BZipStream:
4103 break;
4104 case FifoStream:
4105 break;
4106 case BlobStream:
4107 {
4108 offset=image->blob->offset;
4109 break;
4110 }
4111 }
4112 return(offset);
4113}
4114
4115/*
4116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4117% %
4118% %
4119% %
4120+ U n m a p B l o b %
4121% %
4122% %
4123% %
4124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4125%
4126% UnmapBlob() deallocates the binary large object previously allocated with
4127% the MapBlob method.
4128%
4129% The format of the UnmapBlob method is:
4130%
4131% MagickBooleanType UnmapBlob(void *map,const size_t length)
4132%
4133% A description of each parameter follows:
4134%
4135% o map: the address of the binary large object.
4136%
4137% o length: the length of the binary large object.
4138%
4139*/
4140MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4141{
cristydc8ea8e2013-07-28 20:10:44 +00004142#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00004143 int
4144 status;
4145
4146 status=munmap(map,length);
4147 return(status == -1 ? MagickFalse : MagickTrue);
4148#else
4149 (void) map;
4150 (void) length;
4151 return(MagickFalse);
4152#endif
4153}
4154
4155/*
4156%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4157% %
4158% %
4159% %
4160+ W r i t e B l o b %
4161% %
4162% %
4163% %
4164%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4165%
4166% WriteBlob() writes data to a blob or image file. It returns the number of
4167% bytes written.
4168%
4169% The format of the WriteBlob method is:
4170%
cristyac965582015-05-18 12:35:47 +00004171% ssize_t WriteBlob(Image *image,const size_t length,const void *data)
cristy3ed852e2009-09-05 21:47:34 +00004172%
4173% A description of each parameter follows:
4174%
4175% o image: the image.
4176%
4177% o length: Specifies an integer representing the number of bytes to
4178% write to the file.
4179%
4180% o data: The address of the data to write to the blob or file.
4181%
4182*/
4183MagickExport ssize_t WriteBlob(Image *image,const size_t length,
cristyac965582015-05-18 12:35:47 +00004184 const void *data)
cristy3ed852e2009-09-05 21:47:34 +00004185{
4186 int
4187 c;
4188
4189 register const unsigned char
4190 *p;
4191
4192 ssize_t
4193 count;
4194
4195 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004196 assert(image->signature == MagickCoreSignature);
cristyac965582015-05-18 12:35:47 +00004197 assert(data != (const void *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00004198 assert(image->blob != (BlobInfo *) NULL);
4199 assert(image->blob->type != UndefinedStream);
4200 if (length == 0)
4201 return(0);
4202 count=0;
cristyac965582015-05-18 12:35:47 +00004203 p=(const unsigned char *) data;
cristy3ed852e2009-09-05 21:47:34 +00004204 switch (image->blob->type)
4205 {
4206 case UndefinedStream:
4207 break;
cristyffb0ccd2015-04-11 12:45:11 +00004208 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004209 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004210 case PipeStream:
4211 {
4212 switch (length)
4213 {
4214 default:
4215 {
4216 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004217 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004218 break;
4219 }
cristydfc3f852015-04-11 12:37:16 +00004220 case 4:
4221 {
4222 c=putc((int) *p++,image->blob->file_info.file);
4223 if (c == EOF)
4224 break;
4225 count++;
4226 }
4227 case 3:
4228 {
4229 c=putc((int) *p++,image->blob->file_info.file);
4230 if (c == EOF)
4231 break;
4232 count++;
4233 }
cristy3ed852e2009-09-05 21:47:34 +00004234 case 2:
4235 {
cristye7b28372012-06-17 13:59:06 +00004236 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004237 if (c == EOF)
4238 break;
4239 count++;
4240 }
4241 case 1:
4242 {
cristye7b28372012-06-17 13:59:06 +00004243 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004244 if (c == EOF)
4245 break;
4246 count++;
4247 }
4248 case 0:
4249 break;
4250 }
4251 break;
4252 }
4253 case ZipStream:
4254 {
4255#if defined(MAGICKCORE_ZLIB_DELEGATE)
4256 switch (length)
4257 {
4258 default:
4259 {
cristye7b28372012-06-17 13:59:06 +00004260 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004261 (unsigned int) length);
4262 break;
4263 }
cristydfc3f852015-04-11 12:37:16 +00004264 case 4:
4265 {
4266 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4267 if (c == EOF)
4268 break;
4269 count++;
4270 }
4271 case 3:
4272 {
4273 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4274 if (c == EOF)
4275 break;
4276 count++;
4277 }
cristy3ed852e2009-09-05 21:47:34 +00004278 case 2:
4279 {
cristye7b28372012-06-17 13:59:06 +00004280 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004281 if (c == EOF)
4282 break;
4283 count++;
4284 }
4285 case 1:
4286 {
cristye7b28372012-06-17 13:59:06 +00004287 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004288 if (c == EOF)
4289 break;
4290 count++;
4291 }
4292 case 0:
4293 break;
4294 }
4295#endif
4296 break;
4297 }
4298 case BZipStream:
4299 {
4300#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004301 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004302 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004303#endif
4304 break;
4305 }
4306 case FifoStream:
4307 {
4308 count=(ssize_t) image->blob->stream(image,data,length);
4309 break;
4310 }
4311 case BlobStream:
4312 {
4313 register unsigned char
4314 *q;
4315
4316 if ((image->blob->offset+(MagickOffsetType) length) >=
4317 (MagickOffsetType) image->blob->extent)
4318 {
4319 if (image->blob->mapped != MagickFalse)
4320 return(0);
cristy3ed852e2009-09-05 21:47:34 +00004321 image->blob->extent+=length+image->blob->quantum;
cristyff368632014-01-27 13:01:38 +00004322 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00004323 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4324 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4325 (void) SyncBlob(image);
4326 if (image->blob->data == (unsigned char *) NULL)
4327 {
4328 (void) DetachBlob(image->blob);
4329 return(0);
4330 }
4331 }
4332 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004333 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004334 image->blob->offset+=length;
4335 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4336 image->blob->length=(size_t) image->blob->offset;
4337 count=(ssize_t) length;
4338 }
4339 }
4340 return(count);
4341}
4342
4343/*
4344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4345% %
4346% %
4347% %
4348+ W r i t e B l o b B y t e %
4349% %
4350% %
4351% %
4352%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4353%
4354% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4355% written (either 0 or 1);
4356%
4357% The format of the WriteBlobByte method is:
4358%
4359% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4360%
4361% A description of each parameter follows.
4362%
4363% o image: the image.
4364%
4365% o value: Specifies the value to write.
4366%
4367*/
4368MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4369{
4370 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004371 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00004372 return(WriteBlobStream(image,1,&value));
4373}
4374
4375/*
4376%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4377% %
4378% %
4379% %
4380+ W r i t e B l o b F l o a t %
4381% %
4382% %
4383% %
4384%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4385%
4386% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4387% specified by the endian member of the image structure.
4388%
4389% The format of the WriteBlobFloat method is:
4390%
4391% ssize_t WriteBlobFloat(Image *image,const float value)
4392%
4393% A description of each parameter follows.
4394%
4395% o image: the image.
4396%
4397% o value: Specifies the value to write.
4398%
4399*/
4400MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4401{
4402 union
4403 {
4404 unsigned int
4405 unsigned_value;
4406
4407 float
4408 float_value;
4409 } quantum;
4410
4411 quantum.unsigned_value=0U;
4412 quantum.float_value=value;
4413 return(WriteBlobLong(image,quantum.unsigned_value));
4414}
4415
4416/*
4417%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4418% %
4419% %
4420% %
4421+ W r i t e B l o b L o n g %
4422% %
4423% %
4424% %
4425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4426%
cristybb503372010-05-27 20:51:26 +00004427% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004428% specified by the endian member of the image structure.
4429%
4430% The format of the WriteBlobLong method is:
4431%
4432% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4433%
4434% A description of each parameter follows.
4435%
4436% o image: the image.
4437%
4438% o value: Specifies the value to write.
4439%
4440*/
4441MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4442{
4443 unsigned char
4444 buffer[4];
4445
4446 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004447 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00004448 if (image->endian == LSBEndian)
4449 {
4450 buffer[0]=(unsigned char) value;
4451 buffer[1]=(unsigned char) (value >> 8);
4452 buffer[2]=(unsigned char) (value >> 16);
4453 buffer[3]=(unsigned char) (value >> 24);
4454 return(WriteBlobStream(image,4,buffer));
4455 }
4456 buffer[0]=(unsigned char) (value >> 24);
4457 buffer[1]=(unsigned char) (value >> 16);
4458 buffer[2]=(unsigned char) (value >> 8);
4459 buffer[3]=(unsigned char) value;
4460 return(WriteBlobStream(image,4,buffer));
4461}
4462
4463/*
4464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4465% %
4466% %
4467% %
4468+ W r i t e B l o b S h o r t %
4469% %
4470% %
4471% %
4472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4473%
4474% WriteBlobShort() writes a short value as a 16-bit quantity in the
4475% byte-order specified by the endian member of the image structure.
4476%
4477% The format of the WriteBlobShort method is:
4478%
4479% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4480%
4481% A description of each parameter follows.
4482%
4483% o image: the image.
4484%
4485% o value: Specifies the value to write.
4486%
4487*/
4488MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4489{
4490 unsigned char
4491 buffer[2];
4492
4493 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004494 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00004495 if (image->endian == LSBEndian)
4496 {
4497 buffer[0]=(unsigned char) value;
4498 buffer[1]=(unsigned char) (value >> 8);
4499 return(WriteBlobStream(image,2,buffer));
4500 }
4501 buffer[0]=(unsigned char) (value >> 8);
4502 buffer[1]=(unsigned char) value;
4503 return(WriteBlobStream(image,2,buffer));
4504}
4505
4506/*
4507%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4508% %
4509% %
4510% %
4511+ W r i t e B l o b L S B L o n g %
4512% %
4513% %
4514% %
4515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4516%
cristybb503372010-05-27 20:51:26 +00004517% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004518% least-significant byte first order.
4519%
4520% The format of the WriteBlobLSBLong method is:
4521%
4522% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4523%
4524% A description of each parameter follows.
4525%
4526% o image: the image.
4527%
4528% o value: Specifies the value to write.
4529%
4530*/
4531MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4532{
4533 unsigned char
4534 buffer[4];
4535
4536 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004537 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00004538 buffer[0]=(unsigned char) value;
4539 buffer[1]=(unsigned char) (value >> 8);
4540 buffer[2]=(unsigned char) (value >> 16);
4541 buffer[3]=(unsigned char) (value >> 24);
4542 return(WriteBlobStream(image,4,buffer));
4543}
4544
4545/*
4546%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4547% %
4548% %
4549% %
4550+ W r i t e B l o b L S B S h o r t %
4551% %
4552% %
4553% %
4554%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4555%
cristybb503372010-05-27 20:51:26 +00004556% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004557% least-significant byte first order.
4558%
4559% The format of the WriteBlobLSBShort method is:
4560%
4561% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4562%
4563% A description of each parameter follows.
4564%
4565% o image: the image.
4566%
4567% o value: Specifies the value to write.
4568%
4569*/
4570MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4571{
4572 unsigned char
4573 buffer[2];
4574
4575 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004576 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00004577 buffer[0]=(unsigned char) value;
4578 buffer[1]=(unsigned char) (value >> 8);
4579 return(WriteBlobStream(image,2,buffer));
4580}
4581
4582/*
4583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4584% %
4585% %
4586% %
4587+ W r i t e B l o b M S B L o n g %
4588% %
4589% %
4590% %
4591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4592%
cristybb503372010-05-27 20:51:26 +00004593% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004594% most-significant byte first order.
4595%
4596% The format of the WriteBlobMSBLong method is:
4597%
4598% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4599%
4600% A description of each parameter follows.
4601%
4602% o value: Specifies the value to write.
4603%
4604% o image: the image.
4605%
4606*/
4607MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4608{
4609 unsigned char
4610 buffer[4];
4611
4612 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004613 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00004614 buffer[0]=(unsigned char) (value >> 24);
4615 buffer[1]=(unsigned char) (value >> 16);
4616 buffer[2]=(unsigned char) (value >> 8);
4617 buffer[3]=(unsigned char) value;
4618 return(WriteBlobStream(image,4,buffer));
4619}
4620
4621/*
4622%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4623% %
4624% %
4625% %
cristy2ca49922010-03-06 02:54:01 +00004626+ W r i t e B l o b M S B L o n g L o n g %
4627% %
4628% %
4629% %
4630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4631%
4632% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4633% most-significant byte first order.
4634%
4635% The format of the WriteBlobMSBLongLong method is:
4636%
4637% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4638%
4639% A description of each parameter follows.
4640%
4641% o value: Specifies the value to write.
4642%
4643% o image: the image.
4644%
4645*/
4646MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4647 const MagickSizeType value)
4648{
4649 unsigned char
4650 buffer[8];
4651
4652 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004653 assert(image->signature == MagickCoreSignature);
cristy2ca49922010-03-06 02:54:01 +00004654 buffer[0]=(unsigned char) (value >> 56);
4655 buffer[1]=(unsigned char) (value >> 48);
4656 buffer[2]=(unsigned char) (value >> 40);
4657 buffer[3]=(unsigned char) (value >> 32);
4658 buffer[4]=(unsigned char) (value >> 24);
4659 buffer[5]=(unsigned char) (value >> 16);
4660 buffer[6]=(unsigned char) (value >> 8);
4661 buffer[7]=(unsigned char) value;
4662 return(WriteBlobStream(image,8,buffer));
4663}
4664
4665/*
4666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4667% %
4668% %
4669% %
cristy3ed852e2009-09-05 21:47:34 +00004670+ W r i t e B l o b M S B S h o r t %
4671% %
4672% %
4673% %
4674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4675%
cristybb503372010-05-27 20:51:26 +00004676% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004677% most-significant byte first order.
4678%
4679% The format of the WriteBlobMSBShort method is:
4680%
4681% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4682%
4683% A description of each parameter follows.
4684%
4685% o value: Specifies the value to write.
4686%
4687% o file: Specifies the file to write the data to.
4688%
4689*/
4690MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4691{
4692 unsigned char
4693 buffer[2];
4694
4695 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004696 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00004697 buffer[0]=(unsigned char) (value >> 8);
4698 buffer[1]=(unsigned char) value;
4699 return(WriteBlobStream(image,2,buffer));
4700}
4701
4702/*
4703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4704% %
4705% %
4706% %
4707+ W r i t e B l o b S t r i n g %
4708% %
4709% %
4710% %
4711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4712%
4713% WriteBlobString() write a string to a blob. It returns the number of
4714% characters written.
4715%
4716% The format of the WriteBlobString method is:
4717%
4718% ssize_t WriteBlobString(Image *image,const char *string)
4719%
4720% A description of each parameter follows.
4721%
4722% o image: the image.
4723%
4724% o string: Specifies the string to write.
4725%
4726*/
4727MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4728{
4729 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004730 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00004731 assert(string != (const char *) NULL);
4732 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4733}