blob: e8e40e08a7c64f183f7eb211eb1abeb2eb2a6f6f [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% %
cristyb56bb242014-11-25 17:12:48 +000020% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
cristy4c08aed2011-07-01 19:47:50 +000043#include "MagickCore/studio.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/client.h"
48#include "MagickCore/constitute.h"
49#include "MagickCore/delegate.h"
50#include "MagickCore/exception.h"
51#include "MagickCore/exception-private.h"
52#include "MagickCore/image-private.h"
53#include "MagickCore/list.h"
54#include "MagickCore/locale_.h"
55#include "MagickCore/log.h"
56#include "MagickCore/magick.h"
57#include "MagickCore/memory_.h"
cristy9f3b4fc2014-02-08 14:56:20 +000058#include "MagickCore/nt-base-private.h"
cristyfb348292015-04-12 00:28:54 +000059#include "MagickCore/option.h"
cristy4c08aed2011-07-01 19:47:50 +000060#include "MagickCore/policy.h"
61#include "MagickCore/resource_.h"
62#include "MagickCore/semaphore.h"
63#include "MagickCore/string_.h"
64#include "MagickCore/string-private.h"
65#include "MagickCore/token.h"
66#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000067#include "MagickCore/utility-private.h"
cristy3ed852e2009-09-05 21:47:34 +000068#if defined(MAGICKCORE_ZLIB_DELEGATE)
69#include "zlib.h"
70#endif
71#if defined(MAGICKCORE_BZLIB_DELEGATE)
72#include "bzlib.h"
73#endif
74
75/*
76 Define declarations.
77*/
cristy38c8f5c2015-03-04 14:51:57 +000078#define MagickMaxBlobExtent (8*8192)
cristy3ed852e2009-09-05 21:47:34 +000079#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
80# define MAP_ANONYMOUS MAP_ANON
81#endif
82#if !defined(MAP_FAILED)
83#define MAP_FAILED ((void *) -1)
84#endif
cristy3ed852e2009-09-05 21:47:34 +000085#if defined(__OS2__)
86#include <io.h>
87#define _O_BINARY O_BINARY
88#endif
89
90/*
91 Typedef declarations.
92*/
cristye7b28372012-06-17 13:59:06 +000093typedef union FileInfo
94{
95 FILE
96 *file;
97
98#if defined(MAGICKCORE_ZLIB_DELEGATE)
99 gzFile
100 gzfile;
101#endif
102
103#if defined(MAGICKCORE_BZLIB_DELEGATE)
104 BZFILE
105 *bzfile;
106#endif
107} FileInfo;
108
cristy3ed852e2009-09-05 21:47:34 +0000109struct _BlobInfo
110{
111 size_t
112 length,
113 extent,
114 quantum;
115
116 MagickBooleanType
117 mapped,
118 eof;
119
120 MagickOffsetType
121 offset;
122
123 MagickSizeType
124 size;
125
126 MagickBooleanType
127 exempt,
cristy0779de22015-05-03 12:45:49 +0000128 immutable,
cristy3ed852e2009-09-05 21:47:34 +0000129 synchronize,
130 status,
131 temporary;
132
133 StreamType
134 type;
135
cristye7b28372012-06-17 13:59:06 +0000136 FileInfo
137 file_info;
cristy3ed852e2009-09-05 21:47:34 +0000138
139 struct stat
140 properties;
141
142 StreamHandler
143 stream;
144
cristyf3fe18d2015-01-26 19:57:08 +0000145 unsigned char
cristy3ed852e2009-09-05 21:47:34 +0000146 *data;
147
148 MagickBooleanType
149 debug;
150
151 SemaphoreInfo
152 *semaphore;
153
cristybb503372010-05-27 20:51:26 +0000154 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000155 reference_count;
156
cristybb503372010-05-27 20:51:26 +0000157 size_t
cristy3ed852e2009-09-05 21:47:34 +0000158 signature;
159};
160
161/*
162 Forward declarations.
163*/
164static int
165 SyncBlob(Image *);
166
167/*
168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169% %
170% %
171% %
172+ A t t a c h B l o b %
173% %
174% %
175% %
176%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177%
178% AttachBlob() attaches a blob to the BlobInfo structure.
179%
180% The format of the AttachBlob method is:
181%
182% void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
183%
184% A description of each parameter follows:
185%
186% o blob_info: Specifies a pointer to a BlobInfo structure.
187%
188% o blob: the address of a character stream in one of the image formats
189% understood by ImageMagick.
190%
191% o length: This size_t integer reflects the length in bytes of the blob.
192%
193*/
194MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
195 const size_t length)
196{
197 assert(blob_info != (BlobInfo *) NULL);
198 if (blob_info->debug != MagickFalse)
199 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
200 blob_info->length=length;
201 blob_info->extent=length;
202 blob_info->quantum=(size_t) MagickMaxBlobExtent;
203 blob_info->offset=0;
204 blob_info->type=BlobStream;
cristye7b28372012-06-17 13:59:06 +0000205 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000206 blob_info->data=(unsigned char *) blob;
207 blob_info->mapped=MagickFalse;
cristy0779de22015-05-03 12:45:49 +0000208 blob_info->immutable=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +0000209}
210
211/*
212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213% %
214% %
215% %
216+ B l o b T o F i l e %
217% %
218% %
219% %
220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221%
222% BlobToFile() writes a blob to a file. It returns MagickFalse if an error
223% occurs otherwise MagickTrue.
224%
225% The format of the BlobToFile method is:
226%
227% MagickBooleanType BlobToFile(char *filename,const void *blob,
228% const size_t length,ExceptionInfo *exception)
229%
230% A description of each parameter follows:
231%
232% o filename: Write the blob to this file.
233%
234% o blob: the address of a blob.
235%
236% o length: This length in bytes of the blob.
237%
238% o exception: return any errors or warnings in this structure.
239%
240*/
cristy3ed852e2009-09-05 21:47:34 +0000241MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
242 const size_t length,ExceptionInfo *exception)
243{
244 int
245 file;
246
247 register size_t
248 i;
249
250 ssize_t
251 count;
252
253 assert(filename != (const char *) NULL);
254 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
255 assert(blob != (const void *) NULL);
256 if (*filename == '\0')
257 file=AcquireUniqueFileResource(filename);
258 else
cristy18c6c272011-09-23 14:40:37 +0000259 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +0000260 if (file == -1)
261 {
262 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
263 return(MagickFalse);
264 }
265 for (i=0; i < length; i+=count)
266 {
cristy6586a802015-01-24 15:48:55 +0000267 count=write(file,(const char *) blob+i,MagickMin(length-i,(size_t)
268 SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +0000269 if (count <= 0)
270 {
271 count=0;
272 if (errno != EINTR)
273 break;
274 }
275 }
cristya7cb4312010-06-26 00:47:03 +0000276 file=close(file);
277 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +0000278 {
279 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
280 return(MagickFalse);
281 }
282 return(MagickTrue);
283}
284
285/*
286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
287% %
288% %
289% %
290% B l o b T o I m a g e %
291% %
292% %
293% %
294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
295%
296% BlobToImage() implements direct to memory image formats. It returns the
297% blob as an image.
298%
299% The format of the BlobToImage method is:
300%
301% Image *BlobToImage(const ImageInfo *image_info,const void *blob,
302% const size_t length,ExceptionInfo *exception)
303%
304% A description of each parameter follows:
305%
306% o image_info: the image info.
307%
308% o blob: the address of a character stream in one of the image formats
309% understood by ImageMagick.
310%
311% o length: This size_t integer reflects the length in bytes of the blob.
312%
313% o exception: return any errors or warnings in this structure.
314%
315*/
316MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
317 const size_t length,ExceptionInfo *exception)
318{
319 const MagickInfo
320 *magick_info;
321
322 Image
323 *image;
324
325 ImageInfo
326 *blob_info,
327 *clone_info;
328
329 MagickBooleanType
330 status;
331
332 assert(image_info != (ImageInfo *) NULL);
333 assert(image_info->signature == MagickSignature);
334 if (image_info->debug != MagickFalse)
335 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
336 image_info->filename);
337 assert(exception != (ExceptionInfo *) NULL);
338 if ((blob == (const void *) NULL) || (length == 0))
339 {
340 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +0000341 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +0000342 return((Image *) NULL);
343 }
344 blob_info=CloneImageInfo(image_info);
345 blob_info->blob=(void *) blob;
346 blob_info->length=length;
347 if (*blob_info->magick == '\0')
cristyd965a422010-03-03 17:47:35 +0000348 (void) SetImageInfo(blob_info,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000349 magick_info=GetMagickInfo(blob_info->magick,exception);
350 if (magick_info == (const MagickInfo *) NULL)
351 {
cristy3ed852e2009-09-05 21:47:34 +0000352 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +0000353 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +0000354 blob_info->magick);
355 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +0000356 return((Image *) NULL);
357 }
358 if (GetMagickBlobSupport(magick_info) != MagickFalse)
359 {
360 /*
361 Native blob support for this image format.
362 */
363 (void) CopyMagickString(blob_info->filename,image_info->filename,
cristy151b66d2015-04-15 10:50:31 +0000364 MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000365 (void) CopyMagickString(blob_info->magick,image_info->magick,
cristy151b66d2015-04-15 10:50:31 +0000366 MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000367 image=ReadImage(blob_info,exception);
368 if (image != (Image *) NULL)
369 (void) DetachBlob(image->blob);
370 blob_info=DestroyImageInfo(blob_info);
371 return(image);
372 }
373 /*
374 Write blob to a temporary file on disk.
375 */
376 blob_info->blob=(void *) NULL;
377 blob_info->length=0;
378 *blob_info->filename='\0';
379 status=BlobToFile(blob_info->filename,blob,length,exception);
380 if (status == MagickFalse)
381 {
382 (void) RelinquishUniqueFileResource(blob_info->filename);
383 blob_info=DestroyImageInfo(blob_info);
384 return((Image *) NULL);
385 }
386 clone_info=CloneImageInfo(blob_info);
cristy151b66d2015-04-15 10:50:31 +0000387 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +0000388 blob_info->magick,blob_info->filename);
389 image=ReadImage(clone_info,exception);
cristy540a22c2012-06-10 15:22:16 +0000390 if (image != (Image *) NULL)
391 {
392 Image
393 *images;
394
395 /*
dirk7fcec532014-04-24 18:52:40 +0000396 Restore original filenames and image format.
cristy540a22c2012-06-10 15:22:16 +0000397 */
398 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
399 {
dirk7fcec532014-04-24 18:52:40 +0000400 (void) CopyMagickString(images->filename,image_info->filename,
cristy151b66d2015-04-15 10:50:31 +0000401 MagickPathExtent);
dirk7fcec532014-04-24 18:52:40 +0000402 (void) CopyMagickString(images->magick_filename,image_info->filename,
cristy151b66d2015-04-15 10:50:31 +0000403 MagickPathExtent);
dirk7fcec532014-04-24 18:52:40 +0000404 (void) CopyMagickString(images->magick,magick_info->name,
cristy151b66d2015-04-15 10:50:31 +0000405 MagickPathExtent);
cristy540a22c2012-06-10 15:22:16 +0000406 images=GetNextImageInList(images);
407 }
408 }
cristy3ed852e2009-09-05 21:47:34 +0000409 clone_info=DestroyImageInfo(clone_info);
410 (void) RelinquishUniqueFileResource(blob_info->filename);
411 blob_info=DestroyImageInfo(blob_info);
412 return(image);
413}
414
415/*
416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
417% %
418% %
419% %
420+ C l o n e B l o b I n f o %
421% %
422% %
423% %
424%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
425%
426% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
427% blob info is NULL, a new one.
428%
429% The format of the CloneBlobInfo method is:
430%
431% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
432%
433% A description of each parameter follows:
434%
435% o blob_info: the blob info.
436%
437*/
438MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
439{
440 BlobInfo
441 *clone_info;
442
cristy73bd4a52010-10-05 11:24:23 +0000443 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
cristy3ed852e2009-09-05 21:47:34 +0000444 if (clone_info == (BlobInfo *) NULL)
445 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
446 GetBlobInfo(clone_info);
447 if (blob_info == (BlobInfo *) NULL)
448 return(clone_info);
449 clone_info->length=blob_info->length;
450 clone_info->extent=blob_info->extent;
451 clone_info->synchronize=blob_info->synchronize;
452 clone_info->quantum=blob_info->quantum;
453 clone_info->mapped=blob_info->mapped;
454 clone_info->eof=blob_info->eof;
455 clone_info->offset=blob_info->offset;
456 clone_info->size=blob_info->size;
457 clone_info->exempt=blob_info->exempt;
cristy0779de22015-05-03 12:45:49 +0000458 clone_info->immutable=blob_info->immutable;
cristy3ed852e2009-09-05 21:47:34 +0000459 clone_info->status=blob_info->status;
460 clone_info->temporary=blob_info->temporary;
461 clone_info->type=blob_info->type;
cristye7b28372012-06-17 13:59:06 +0000462 clone_info->file_info.file=blob_info->file_info.file;
cristy3ed852e2009-09-05 21:47:34 +0000463 clone_info->properties=blob_info->properties;
464 clone_info->stream=blob_info->stream;
465 clone_info->data=blob_info->data;
466 clone_info->debug=IsEventLogging();
467 clone_info->reference_count=1;
468 return(clone_info);
469}
470
471/*
472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
473% %
474% %
475% %
476+ C l o s e B l o b %
477% %
478% %
479% %
480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481%
482% CloseBlob() closes a stream associated with the image.
483%
484% The format of the CloseBlob method is:
485%
486% MagickBooleanType CloseBlob(Image *image)
487%
488% A description of each parameter follows:
489%
490% o image: the image.
491%
492*/
493MagickExport MagickBooleanType CloseBlob(Image *image)
494{
495 int
496 status;
497
498 /*
499 Close image file.
500 */
501 assert(image != (Image *) NULL);
502 assert(image->signature == MagickSignature);
503 if (image->debug != MagickFalse)
504 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
505 assert(image->blob != (BlobInfo *) NULL);
506 if (image->blob->type == UndefinedStream)
507 return(MagickTrue);
cristy7e2a7c72012-12-27 00:56:47 +0000508 status=SyncBlob(image);
cristy3ed852e2009-09-05 21:47:34 +0000509 switch (image->blob->type)
510 {
511 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000512 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000513 break;
514 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000515 case PipeStream:
516 {
cristy02ce8cc2012-12-27 00:35:49 +0000517 if (image->blob->synchronize != MagickFalse)
518 status=fsync(fileno(image->blob->file_info.file));
cristye7b28372012-06-17 13:59:06 +0000519 status=ferror(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000520 break;
521 }
522 case ZipStream:
523 {
524#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000525 (void) gzerror(image->blob->file_info.gzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000526#endif
527 break;
528 }
529 case BZipStream:
530 {
531#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000532 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000533#endif
534 break;
535 }
536 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000537 break;
cristy02ce8cc2012-12-27 00:35:49 +0000538 case BlobStream:
539 {
540 if ((image->blob->file_info.file != (FILE *) NULL) &&
541 (image->blob->synchronize != MagickFalse))
cristy5678acd2012-12-27 00:41:55 +0000542 {
543 (void) fsync(fileno(image->blob->file_info.file));
544 status=ferror(image->blob->file_info.file);
545 }
cristy02ce8cc2012-12-27 00:35:49 +0000546 break;
547 }
cristy3ed852e2009-09-05 21:47:34 +0000548 }
549 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
cristycd9e6322012-12-27 00:29:00 +0000550 image->blob->size=GetBlobSize(image);
551 image->extent=image->blob->size;
552 image->blob->eof=MagickFalse;
cristybae22e42012-12-27 00:25:59 +0000553 if (image->blob->exempt != MagickFalse)
554 {
555 image->blob->type=UndefinedStream;
556 return(image->blob->status);
557 }
cristy3ed852e2009-09-05 21:47:34 +0000558 switch (image->blob->type)
559 {
560 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000561 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000562 break;
563 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000564 {
cristye7b28372012-06-17 13:59:06 +0000565 status=fclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000566 break;
567 }
568 case PipeStream:
569 {
570#if defined(MAGICKCORE_HAVE_PCLOSE)
cristye7b28372012-06-17 13:59:06 +0000571 status=pclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000572#endif
573 break;
574 }
575 case ZipStream:
576 {
577#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000578 status=gzclose(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +0000579#endif
580 break;
581 }
582 case BZipStream:
583 {
584#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000585 BZ2_bzclose(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +0000586#endif
587 break;
588 }
589 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000590 break;
cristyff483372010-10-16 17:00:58 +0000591 case BlobStream:
592 {
cristye7b28372012-06-17 13:59:06 +0000593 if (image->blob->file_info.file != (FILE *) NULL)
cristy02ce8cc2012-12-27 00:35:49 +0000594 status=fclose(image->blob->file_info.file);
cristyff483372010-10-16 17:00:58 +0000595 break;
596 }
cristy3ed852e2009-09-05 21:47:34 +0000597 }
598 (void) DetachBlob(image->blob);
599 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
600 return(image->blob->status);
601}
602
603/*
604%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
605% %
606% %
607% %
608+ D e s t r o y B l o b %
609% %
610% %
611% %
612%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
613%
614% DestroyBlob() deallocates memory associated with a blob.
615%
616% The format of the DestroyBlob method is:
617%
618% void DestroyBlob(Image *image)
619%
620% A description of each parameter follows:
621%
622% o image: the image.
623%
624*/
625MagickExport void DestroyBlob(Image *image)
626{
627 MagickBooleanType
628 destroy;
629
630 assert(image != (Image *) NULL);
631 assert(image->signature == MagickSignature);
632 if (image->debug != MagickFalse)
633 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
634 assert(image->blob != (BlobInfo *) NULL);
635 assert(image->blob->signature == MagickSignature);
636 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000637 LockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000638 image->blob->reference_count--;
639 assert(image->blob->reference_count >= 0);
640 if (image->blob->reference_count == 0)
641 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000642 UnlockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000643 if (destroy == MagickFalse)
644 return;
645 (void) CloseBlob(image);
646 if (image->blob->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000647 {
648 (void) UnmapBlob(image->blob->data,image->blob->length);
649 RelinquishMagickResource(MapResource,image->blob->length);
650 }
cristy3ed852e2009-09-05 21:47:34 +0000651 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
cristy3d162a92014-02-16 14:05:06 +0000652 RelinquishSemaphoreInfo(&image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000653 image->blob->signature=(~MagickSignature);
654 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
655}
656
657/*
658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659% %
660% %
661% %
662+ D e t a c h B l o b %
663% %
664% %
665% %
666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667%
668% DetachBlob() detaches a blob from the BlobInfo structure.
669%
670% The format of the DetachBlob method is:
671%
cristy6586a802015-01-24 15:48:55 +0000672% void *DetachBlob(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +0000673%
674% A description of each parameter follows:
675%
676% o blob_info: Specifies a pointer to a BlobInfo structure.
677%
678*/
cristy6586a802015-01-24 15:48:55 +0000679MagickExport void *DetachBlob(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +0000680{
cristy6586a802015-01-24 15:48:55 +0000681 void
cristy3ed852e2009-09-05 21:47:34 +0000682 *data;
683
684 assert(blob_info != (BlobInfo *) NULL);
685 if (blob_info->debug != MagickFalse)
686 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
687 if (blob_info->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000688 {
689 (void) UnmapBlob(blob_info->data,blob_info->length);
cristyf3fe18d2015-01-26 19:57:08 +0000690 blob_info->data=(unsigned char *) NULL;
cristy18aba912013-06-14 19:48:08 +0000691 RelinquishMagickResource(MapResource,blob_info->length);
692 }
cristy3ed852e2009-09-05 21:47:34 +0000693 blob_info->mapped=MagickFalse;
694 blob_info->length=0;
695 blob_info->offset=0;
696 blob_info->eof=MagickFalse;
697 blob_info->exempt=MagickFalse;
cristy0779de22015-05-03 12:45:49 +0000698 blob_info->immutable=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000699 blob_info->type=UndefinedStream;
cristye7b28372012-06-17 13:59:06 +0000700 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000701 data=blob_info->data;
702 blob_info->data=(unsigned char *) NULL;
703 blob_info->stream=(StreamHandler) NULL;
704 return(data);
705}
706
707/*
708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
709% %
710% %
711% %
cristy10f10ec2014-09-20 01:00:50 +0000712+ D i s a s s o c i a t e B l o b %
713% %
714% %
715% %
716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
717%
718% DisassociateBlob() disassociates the image stream. It checks if the
719% blob of the specified image is referenced by other images. If the reference
720% count is higher then 1 a new blob is assigned to the specified image.
721%
722% The format of the DisassociateBlob method is:
723%
dirkcfe4c1c2014-09-20 07:38:59 +0000724% void DisassociateBlob(const Image *image)
cristy10f10ec2014-09-20 01:00:50 +0000725%
726% A description of each parameter follows:
727%
728% o image: the image.
729%
730*/
731MagickPrivate void DisassociateBlob(Image *image)
732{
733 BlobInfo
734 *blob;
735
736 MagickBooleanType
737 clone;
738
739 assert(image != (Image *) NULL);
740 assert(image->signature == MagickSignature);
741 if (image->debug != MagickFalse)
742 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
743 assert(image->blob != (BlobInfo *) NULL);
744 assert(image->blob->signature == MagickSignature);
745 clone=MagickFalse;
746 LockSemaphoreInfo(image->blob->semaphore);
747 assert(image->blob->reference_count >= 0);
748 if (image->blob->reference_count > 1)
749 clone=MagickTrue;
750 UnlockSemaphoreInfo(image->blob->semaphore);
751 if (clone == MagickFalse)
cristy345d8722014-09-24 16:49:02 +0000752 return;
cristy10f10ec2014-09-20 01:00:50 +0000753 blob=CloneBlobInfo(image->blob);
754 DestroyBlob(image);
755 image->blob=blob;
756}
757
758/*
759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760% %
761% %
762% %
cristyc1af14f2010-09-16 20:01:21 +0000763+ D i s c a r d B l o b B y t e s %
764% %
765% %
766% %
767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768%
769% DiscardBlobBytes() discards bytes in a blob.
770%
771% The format of the DiscardBlobBytes method is:
772%
cristy6f008fd2014-05-25 23:27:26 +0000773% MagickBooleanType DiscardBlobBytes(Image *image,
774% const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000775%
776% A description of each parameter follows.
777%
778% o image: the image.
779%
780% o length: the number of bytes to skip.
781%
782*/
cristyc1af14f2010-09-16 20:01:21 +0000783MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
cristy7753b2a2011-02-19 18:36:52 +0000784 const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000785{
cristy7753b2a2011-02-19 18:36:52 +0000786 register MagickOffsetType
cristyc1af14f2010-09-16 20:01:21 +0000787 i;
788
789 size_t
790 quantum;
791
792 ssize_t
793 count;
794
795 unsigned char
cristyf55846d2010-09-17 19:01:10 +0000796 buffer[16384];
cristyc1af14f2010-09-16 20:01:21 +0000797
798 assert(image != (Image *) NULL);
799 assert(image->signature == MagickSignature);
800 count=0;
cristy7753b2a2011-02-19 18:36:52 +0000801 for (i=0; i < (MagickOffsetType) length; i+=count)
cristyc1af14f2010-09-16 20:01:21 +0000802 {
cristy7753b2a2011-02-19 18:36:52 +0000803 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
cristyc1af14f2010-09-16 20:01:21 +0000804 (void) ReadBlobStream(image,quantum,buffer,&count);
805 if (count <= 0)
806 {
807 count=0;
808 if (errno != EINTR)
809 break;
810 }
811 }
cristy7753b2a2011-02-19 18:36:52 +0000812 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
cristyc1af14f2010-09-16 20:01:21 +0000813}
814
815/*
816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
817% %
818% %
819% %
cristy3ed852e2009-09-05 21:47:34 +0000820+ D u p l i c a t e s B l o b %
821% %
822% %
823% %
824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825%
826% DuplicateBlob() duplicates a blob descriptor.
827%
828% The format of the DuplicateBlob method is:
829%
830% void DuplicateBlob(Image *image,const Image *duplicate)
831%
832% A description of each parameter follows:
833%
834% o image: the image.
835%
836% o duplicate: the duplicate image.
837%
838*/
839MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
840{
841 assert(image != (Image *) NULL);
842 assert(image->signature == MagickSignature);
843 if (image->debug != MagickFalse)
844 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
845 assert(duplicate != (Image *) NULL);
846 assert(duplicate->signature == MagickSignature);
847 DestroyBlob(image);
848 image->blob=ReferenceBlob(duplicate->blob);
849}
850
851/*
852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853% %
854% %
855% %
856+ E O F B l o b %
857% %
858% %
859% %
860%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861%
862% EOFBlob() returns a non-zero value when EOF has been detected reading from
863% a blob or file.
864%
865% The format of the EOFBlob method is:
866%
867% int EOFBlob(const Image *image)
868%
869% A description of each parameter follows:
870%
871% o image: the image.
872%
873*/
874MagickExport int EOFBlob(const Image *image)
875{
876 assert(image != (Image *) NULL);
877 assert(image->signature == MagickSignature);
878 if (image->debug != MagickFalse)
879 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
880 assert(image->blob != (BlobInfo *) NULL);
881 assert(image->blob->type != UndefinedStream);
882 switch (image->blob->type)
883 {
884 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000885 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000886 break;
887 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000888 case PipeStream:
889 {
cristye7b28372012-06-17 13:59:06 +0000890 image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
cristy95888612012-04-04 21:56:52 +0000891 MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000892 break;
893 }
894 case ZipStream:
895 {
896 image->blob->eof=MagickFalse;
897 break;
898 }
899 case BZipStream:
900 {
901#if defined(MAGICKCORE_BZLIB_DELEGATE)
902 int
903 status;
904
905 status=0;
cristye7b28372012-06-17 13:59:06 +0000906 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000907 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
908#endif
909 break;
910 }
911 case FifoStream:
912 {
913 image->blob->eof=MagickFalse;
914 break;
915 }
916 case BlobStream:
917 break;
918 }
919 return((int) image->blob->eof);
920}
921
922/*
923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
924% %
925% %
926% %
927+ F i l e T o B l o b %
928% %
929% %
930% %
931%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
932%
cristy178edaf2011-01-23 03:42:39 +0000933% FileToBlob() returns the contents of a file as a buffer terminated with
934% the '\0' character. The length of the buffer (not including the extra
935% terminating '\0' character) is returned via the 'length' parameter. Free
936% the buffer with RelinquishMagickMemory().
cristy3ed852e2009-09-05 21:47:34 +0000937%
938% The format of the FileToBlob method is:
939%
cristy6586a802015-01-24 15:48:55 +0000940% void *FileToBlob(const char *filename,const size_t extent,
cristy3ed852e2009-09-05 21:47:34 +0000941% size_t *length,ExceptionInfo *exception)
942%
943% A description of each parameter follows:
944%
945% o blob: FileToBlob() returns the contents of a file as a blob. If
946% an error occurs NULL is returned.
947%
948% o filename: the filename.
949%
950% o extent: The maximum length of the blob.
951%
952% o length: On return, this reflects the actual length of the blob.
953%
954% o exception: return any errors or warnings in this structure.
955%
956*/
cristy6586a802015-01-24 15:48:55 +0000957MagickExport void *FileToBlob(const char *filename,const size_t extent,
cristy3ed852e2009-09-05 21:47:34 +0000958 size_t *length,ExceptionInfo *exception)
959{
960 int
961 file;
962
963 MagickOffsetType
964 offset;
965
966 register size_t
967 i;
968
969 ssize_t
970 count;
971
972 unsigned char
973 *blob;
974
975 void
976 *map;
977
978 assert(filename != (const char *) NULL);
979 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
980 assert(exception != (ExceptionInfo *) NULL);
981 *length=0;
982 file=fileno(stdin);
983 if (LocaleCompare(filename,"-") != 0)
cristy18c6c272011-09-23 14:40:37 +0000984 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +0000985 if (file == -1)
986 {
987 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
cristy6586a802015-01-24 15:48:55 +0000988 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +0000989 }
cristy7f317702011-02-18 20:40:28 +0000990 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
cristy3ed852e2009-09-05 21:47:34 +0000991 count=0;
cristyd1f55c12014-01-24 00:40:57 +0000992 if ((file == fileno(stdin)) || (offset < 0) ||
993 (offset != (MagickOffsetType) ((ssize_t) offset)))
cristy3ed852e2009-09-05 21:47:34 +0000994 {
995 size_t
996 quantum;
997
998 struct stat
cristye7b28372012-06-17 13:59:06 +0000999 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001000
1001 /*
1002 Stream is not seekable.
1003 */
cristyd1561652014-01-24 11:13:48 +00001004 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001005 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001006 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1007 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001008 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001009 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1010 for (i=0; blob != (unsigned char *) NULL; i+=count)
1011 {
cristy65d11e42013-06-14 20:06:25 +00001012 count=read(file,blob+i,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001013 if (count <= 0)
1014 {
1015 count=0;
1016 if (errno != EINTR)
1017 break;
1018 }
cristy9c66d8c2012-08-10 11:05:36 +00001019 if (~((size_t) i) < (quantum+1))
cristy3ed852e2009-09-05 21:47:34 +00001020 {
1021 blob=(unsigned char *) RelinquishMagickMemory(blob);
1022 break;
1023 }
1024 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1025 sizeof(*blob));
1026 if ((size_t) (i+count) >= extent)
1027 break;
1028 }
cristy54439632010-07-15 00:43:34 +00001029 if (LocaleCompare(filename,"-") != 0)
1030 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001031 if (blob == (unsigned char *) NULL)
1032 {
1033 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001034 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy6586a802015-01-24 15:48:55 +00001035 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00001036 }
cristya7cb4312010-06-26 00:47:03 +00001037 if (file == -1)
1038 {
1039 blob=(unsigned char *) RelinquishMagickMemory(blob);
1040 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
cristy6586a802015-01-24 15:48:55 +00001041 return(NULL);
cristya7cb4312010-06-26 00:47:03 +00001042 }
cristy7753b2a2011-02-19 18:36:52 +00001043 *length=(size_t) MagickMin(i+count,extent);
cristy3ed852e2009-09-05 21:47:34 +00001044 blob[*length]='\0';
1045 return(blob);
1046 }
cristy7753b2a2011-02-19 18:36:52 +00001047 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
cristy3ed852e2009-09-05 21:47:34 +00001048 blob=(unsigned char *) NULL;
cristy151b66d2015-04-15 10:50:31 +00001049 if (~(*length) >= (MagickPathExtent-1))
1050 blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
cristy3ed852e2009-09-05 21:47:34 +00001051 sizeof(*blob));
1052 if (blob == (unsigned char *) NULL)
1053 {
cristy54439632010-07-15 00:43:34 +00001054 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001055 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001056 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy6586a802015-01-24 15:48:55 +00001057 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00001058 }
1059 map=MapBlob(file,ReadMode,0,*length);
1060 if (map != (unsigned char *) NULL)
1061 {
cristy54aad5e2010-09-03 16:02:04 +00001062 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +00001063 (void) UnmapBlob(map,*length);
1064 }
1065 else
1066 {
cristy7f317702011-02-18 20:40:28 +00001067 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001068 for (i=0; i < *length; i+=count)
1069 {
cristy6586a802015-01-24 15:48:55 +00001070 count=read(file,blob+i,(size_t) MagickMin(*length-i,(size_t)
cristy65d11e42013-06-14 20:06:25 +00001071 SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001072 if (count <= 0)
1073 {
1074 count=0;
1075 if (errno != EINTR)
1076 break;
1077 }
1078 }
1079 if (i < *length)
1080 {
1081 file=close(file)-1;
1082 blob=(unsigned char *) RelinquishMagickMemory(blob);
1083 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
cristy6586a802015-01-24 15:48:55 +00001084 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00001085 }
1086 }
cristy3ed852e2009-09-05 21:47:34 +00001087 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001088 if (LocaleCompare(filename,"-") != 0)
1089 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001090 if (file == -1)
1091 {
1092 blob=(unsigned char *) RelinquishMagickMemory(blob);
1093 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1094 }
cristy3ed852e2009-09-05 21:47:34 +00001095 return(blob);
1096}
1097
1098/*
1099%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1100% %
1101% %
1102% %
1103% F i l e T o I m a g e %
1104% %
1105% %
1106% %
1107%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1108%
1109% FileToImage() write the contents of a file to an image.
1110%
1111% The format of the FileToImage method is:
1112%
1113% MagickBooleanType FileToImage(Image *,const char *filename)
1114%
1115% A description of each parameter follows:
1116%
1117% o image: the image.
1118%
1119% o filename: the filename.
1120%
1121*/
1122
1123static inline ssize_t WriteBlobStream(Image *image,const size_t length,
cristye2222cc2015-01-26 20:01:34 +00001124 const void *data)
cristy3ed852e2009-09-05 21:47:34 +00001125{
1126 MagickSizeType
1127 extent;
1128
1129 register unsigned char
1130 *q;
1131
1132 assert(image->blob != (BlobInfo *) NULL);
cristye2222cc2015-01-26 20:01:34 +00001133 assert(image->blob->type != UndefinedStream);
1134 assert(data != NULL);
cristy3ed852e2009-09-05 21:47:34 +00001135 if (image->blob->type != BlobStream)
cristyce0e7b22015-05-18 00:12:46 +00001136 return(WriteBlob(image,length,(const unsigned char *) data));
cristy3ed852e2009-09-05 21:47:34 +00001137 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1138 if (extent >= image->blob->extent)
1139 {
cristy3ed852e2009-09-05 21:47:34 +00001140 extent=image->blob->extent+image->blob->quantum+length;
cristyff368632014-01-27 13:01:38 +00001141 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00001142 if (SetBlobExtent(image,extent) == MagickFalse)
1143 return(0);
1144 }
1145 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001146 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001147 image->blob->offset+=length;
1148 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1149 image->blob->length=(size_t) image->blob->offset;
1150 return((ssize_t) length);
1151}
1152
cristyc82a27b2011-10-21 01:07:16 +00001153MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1154 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001155{
1156 int
1157 file;
1158
1159 size_t
1160 length,
1161 quantum;
1162
1163 ssize_t
1164 count;
1165
1166 struct stat
cristye7b28372012-06-17 13:59:06 +00001167 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001168
1169 unsigned char
1170 *blob;
1171
1172 assert(image != (const Image *) NULL);
1173 assert(image->signature == MagickSignature);
1174 assert(filename != (const char *) NULL);
1175 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
cristyd45808f2012-12-14 21:30:35 +00001176 file=fileno(stdin);
1177 if (LocaleCompare(filename,"-") != 0)
1178 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001179 if (file == -1)
1180 {
cristyc82a27b2011-10-21 01:07:16 +00001181 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001182 return(MagickFalse);
1183 }
1184 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001185 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1186 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001187 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1188 if (blob == (unsigned char *) NULL)
1189 {
cristy100a0562014-04-18 01:27:37 +00001190 file=close(file);
cristyc82a27b2011-10-21 01:07:16 +00001191 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1192 filename);
cristy3ed852e2009-09-05 21:47:34 +00001193 return(MagickFalse);
1194 }
1195 for ( ; ; )
1196 {
cristy65d11e42013-06-14 20:06:25 +00001197 count=read(file,blob,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001198 if (count <= 0)
1199 {
1200 count=0;
1201 if (errno != EINTR)
1202 break;
1203 }
1204 length=(size_t) count;
1205 count=WriteBlobStream(image,length,blob);
1206 if (count != (ssize_t) length)
1207 {
cristyc82a27b2011-10-21 01:07:16 +00001208 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001209 break;
1210 }
1211 }
cristya7cb4312010-06-26 00:47:03 +00001212 file=close(file);
1213 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001214 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001215 blob=(unsigned char *) RelinquishMagickMemory(blob);
1216 return(MagickTrue);
1217}
dirk54fae512014-09-19 20:58:22 +00001218
1219
cristy3ed852e2009-09-05 21:47:34 +00001220/*
1221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1222% %
1223% %
1224% %
1225+ G e t B l o b E r r o r %
1226% %
1227% %
1228% %
1229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1230%
1231% GetBlobError() returns MagickTrue if the blob associated with the specified
1232% image encountered an error.
1233%
1234% The format of the GetBlobError method is:
1235%
1236% MagickBooleanType GetBlobError(const Image *image)
1237%
1238% A description of each parameter follows:
1239%
1240% o image: the image.
1241%
1242*/
cristy7832dc22011-09-05 01:21:53 +00001243MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001244{
1245 assert(image != (const Image *) NULL);
1246 assert(image->signature == MagickSignature);
1247 if (image->debug != MagickFalse)
1248 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1249 return(image->blob->status);
1250}
1251
1252/*
1253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1254% %
1255% %
1256% %
1257+ G e t B l o b F i l e H a n d l e %
1258% %
1259% %
1260% %
1261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1262%
1263% GetBlobFileHandle() returns the file handle associated with the image blob.
1264%
1265% The format of the GetBlobFile method is:
1266%
1267% FILE *GetBlobFileHandle(const Image *image)
1268%
1269% A description of each parameter follows:
1270%
1271% o image: the image.
1272%
1273*/
1274MagickExport FILE *GetBlobFileHandle(const Image *image)
1275{
1276 assert(image != (const Image *) NULL);
1277 assert(image->signature == MagickSignature);
cristye7b28372012-06-17 13:59:06 +00001278 return(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001279}
1280
1281/*
1282%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1283% %
1284% %
1285% %
1286+ G e t B l o b I n f o %
1287% %
1288% %
1289% %
1290%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1291%
1292% GetBlobInfo() initializes the BlobInfo structure.
1293%
1294% The format of the GetBlobInfo method is:
1295%
1296% void GetBlobInfo(BlobInfo *blob_info)
1297%
1298% A description of each parameter follows:
1299%
1300% o blob_info: Specifies a pointer to a BlobInfo structure.
1301%
1302*/
cristy7832dc22011-09-05 01:21:53 +00001303MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001304{
1305 assert(blob_info != (BlobInfo *) NULL);
1306 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1307 blob_info->type=UndefinedStream;
1308 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1309 blob_info->properties.st_mtime=time((time_t *) NULL);
1310 blob_info->properties.st_ctime=time((time_t *) NULL);
1311 blob_info->debug=IsEventLogging();
1312 blob_info->reference_count=1;
cristy3d162a92014-02-16 14:05:06 +00001313 blob_info->semaphore=AcquireSemaphoreInfo();
cristy3ed852e2009-09-05 21:47:34 +00001314 blob_info->signature=MagickSignature;
1315}
1316
1317/*
1318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1319% %
1320% %
1321% %
1322% G e t B l o b P r o p e r t i e s %
1323% %
1324% %
1325% %
1326%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1327%
1328% GetBlobProperties() returns information about an image blob.
1329%
1330% The format of the GetBlobProperties method is:
1331%
1332% const struct stat *GetBlobProperties(const Image *image)
1333%
1334% A description of each parameter follows:
1335%
1336% o image: the image.
1337%
1338*/
cristy7832dc22011-09-05 01:21:53 +00001339MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001340{
1341 assert(image != (Image *) NULL);
1342 assert(image->signature == MagickSignature);
1343 if (image->debug != MagickFalse)
1344 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1345 return(&image->blob->properties);
1346}
1347
1348/*
1349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1350% %
1351% %
1352% %
1353+ G e t B l o b S i z e %
1354% %
1355% %
1356% %
1357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1358%
1359% GetBlobSize() returns the current length of the image file or blob; zero is
1360% returned if the size cannot be determined.
1361%
1362% The format of the GetBlobSize method is:
1363%
1364% MagickSizeType GetBlobSize(const Image *image)
1365%
1366% A description of each parameter follows:
1367%
1368% o image: the image.
1369%
1370*/
1371MagickExport MagickSizeType GetBlobSize(const Image *image)
1372{
1373 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001374 extent;
cristy3ed852e2009-09-05 21:47:34 +00001375
1376 assert(image != (Image *) NULL);
1377 assert(image->signature == MagickSignature);
1378 if (image->debug != MagickFalse)
1379 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1380 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001381 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001382 switch (image->blob->type)
1383 {
1384 case UndefinedStream:
1385 {
cristy81b8ce52010-02-05 01:53:17 +00001386 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001387 break;
1388 }
cristybc20d112012-07-29 20:27:00 +00001389 case StandardStream:
1390 {
1391 extent=image->blob->size;
1392 break;
1393 }
cristy3ed852e2009-09-05 21:47:34 +00001394 case FileStream:
1395 {
cristye7b28372012-06-17 13:59:06 +00001396 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001397 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001398 break;
1399 }
cristy3ed852e2009-09-05 21:47:34 +00001400 case PipeStream:
1401 {
cristy81b8ce52010-02-05 01:53:17 +00001402 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001403 break;
1404 }
1405 case ZipStream:
1406 case BZipStream:
1407 {
1408 MagickBooleanType
1409 status;
1410
1411 status=GetPathAttributes(image->filename,&image->blob->properties);
1412 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001413 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001414 break;
1415 }
1416 case FifoStream:
1417 break;
1418 case BlobStream:
1419 {
cristy891dc792010-03-04 01:47:16 +00001420 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001421 break;
1422 }
1423 }
cristy81b8ce52010-02-05 01:53:17 +00001424 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001425}
1426
1427/*
1428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1429% %
1430% %
1431% %
1432+ G e t B l o b S t r e a m D a t a %
1433% %
1434% %
1435% %
1436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1437%
1438% GetBlobStreamData() returns the stream data for the image.
1439%
1440% The format of the GetBlobStreamData method is:
1441%
cristy6586a802015-01-24 15:48:55 +00001442% void *GetBlobStreamData(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001443%
1444% A description of each parameter follows:
1445%
1446% o image: the image.
1447%
1448*/
cristy6586a802015-01-24 15:48:55 +00001449MagickExport void *GetBlobStreamData(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001450{
1451 assert(image != (const Image *) NULL);
1452 assert(image->signature == MagickSignature);
1453 return(image->blob->data);
1454}
1455
1456/*
1457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1458% %
1459% %
1460% %
1461+ G e t B l o b S t r e a m H a n d l e r %
1462% %
1463% %
1464% %
1465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1466%
1467% GetBlobStreamHandler() returns the stream handler for the image.
1468%
1469% The format of the GetBlobStreamHandler method is:
1470%
1471% StreamHandler GetBlobStreamHandler(const Image *image)
1472%
1473% A description of each parameter follows:
1474%
1475% o image: the image.
1476%
1477*/
cristy7832dc22011-09-05 01:21:53 +00001478MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001479{
1480 assert(image != (const Image *) NULL);
1481 assert(image->signature == MagickSignature);
1482 if (image->debug != MagickFalse)
1483 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1484 return(image->blob->stream);
1485}
1486
1487/*
1488%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1489% %
1490% %
1491% %
1492% I m a g e T o B l o b %
1493% %
1494% %
1495% %
1496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1497%
1498% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001499% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001500% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001501% etc.). This method is the equivalent of WriteImage(), but writes the
1502% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001503%
1504% The format of the ImageToBlob method is:
1505%
cristy6586a802015-01-24 15:48:55 +00001506% void *ImageToBlob(const ImageInfo *image_info,Image *image,
cristy3ed852e2009-09-05 21:47:34 +00001507% size_t *length,ExceptionInfo *exception)
1508%
1509% A description of each parameter follows:
1510%
1511% o image_info: the image info.
1512%
1513% o image: the image.
1514%
cristyd7dc7df2014-01-26 13:52:14 +00001515% o length: return the actual length of the blob.
cristy3ed852e2009-09-05 21:47:34 +00001516%
1517% o exception: return any errors or warnings in this structure.
1518%
1519*/
cristy6586a802015-01-24 15:48:55 +00001520MagickExport void *ImageToBlob(const ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001521 Image *image,size_t *length,ExceptionInfo *exception)
1522{
1523 const MagickInfo
1524 *magick_info;
1525
1526 ImageInfo
1527 *blob_info;
1528
1529 MagickBooleanType
1530 status;
1531
cristyce0e7b22015-05-18 00:12:46 +00001532 void
cristy3ed852e2009-09-05 21:47:34 +00001533 *blob;
1534
1535 assert(image_info != (const ImageInfo *) NULL);
1536 assert(image_info->signature == MagickSignature);
1537 if (image_info->debug != MagickFalse)
1538 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1539 image_info->filename);
1540 assert(image != (Image *) NULL);
1541 assert(image->signature == MagickSignature);
1542 assert(exception != (ExceptionInfo *) NULL);
1543 *length=0;
1544 blob=(unsigned char *) NULL;
1545 blob_info=CloneImageInfo(image_info);
1546 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001547 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001548 if (*blob_info->magick != '\0')
cristy151b66d2015-04-15 10:50:31 +00001549 (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001550 magick_info=GetMagickInfo(image->magick,exception);
1551 if (magick_info == (const MagickInfo *) NULL)
1552 {
1553 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001554 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +00001555 image->magick);
1556 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +00001557 return(blob);
1558 }
cristy151b66d2015-04-15 10:50:31 +00001559 (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001560 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1561 {
1562 /*
1563 Native blob support for this image format.
1564 */
cristy5facf772014-01-26 14:42:57 +00001565 blob_info->length=0;
cristy6586a802015-01-24 15:48:55 +00001566 blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
cristy5facf772014-01-26 14:42:57 +00001567 sizeof(unsigned char));
cristy6586a802015-01-24 15:48:55 +00001568 if (blob_info->blob == NULL)
cristy3ed852e2009-09-05 21:47:34 +00001569 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001570 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001571 else
1572 {
1573 (void) CloseBlob(image);
1574 image->blob->exempt=MagickTrue;
1575 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001576 status=WriteImage(blob_info,image,exception);
cristy5facf772014-01-26 14:42:57 +00001577 *length=image->blob->length;
cristyc42554f2012-08-22 12:00:43 +00001578 blob=DetachBlob(image->blob);
cristy6e50f9e2012-08-22 16:30:29 +00001579 if (status == MagickFalse)
cristyce0e7b22015-05-18 00:12:46 +00001580 blob=RelinquishMagickMemory(blob);
cristy6e50f9e2012-08-22 16:30:29 +00001581 else
cristyce0e7b22015-05-18 00:12:46 +00001582 blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001583 }
1584 }
1585 else
1586 {
1587 char
cristy151b66d2015-04-15 10:50:31 +00001588 unique[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00001589
1590 int
1591 file;
1592
1593 /*
1594 Write file to disk in blob image format.
1595 */
1596 file=AcquireUniqueFileResource(unique);
1597 if (file == -1)
1598 {
1599 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1600 image_info->filename);
1601 }
1602 else
1603 {
1604 blob_info->file=fdopen(file,"wb");
1605 if (blob_info->file != (FILE *) NULL)
1606 {
cristyce0e7b22015-05-18 00:12:46 +00001607 (void) FormatLocaleString(image->filename,MagickPathExtent,
1608 "%s:%s",image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001609 status=WriteImage(blob_info,image,exception);
dirk607010e2014-03-01 19:08:11 +00001610 (void) CloseBlob(image);
1611 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001612 if (status != MagickFalse)
cristy2c1b6e02014-01-26 15:03:02 +00001613 blob=FileToBlob(unique,~0UL,length,exception);
cristy3ed852e2009-09-05 21:47:34 +00001614 }
1615 (void) RelinquishUniqueFileResource(unique);
1616 }
1617 }
1618 blob_info=DestroyImageInfo(blob_info);
1619 return(blob);
1620}
1621
1622/*
1623%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1624% %
1625% %
1626% %
1627% I m a g e T o F i l e %
1628% %
1629% %
1630% %
1631%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1632%
1633% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1634% occurs otherwise MagickTrue.
1635%
1636% The format of the ImageToFile method is:
1637%
1638% MagickBooleanType ImageToFile(Image *image,char *filename,
1639% ExceptionInfo *exception)
1640%
1641% A description of each parameter follows:
1642%
1643% o image: the image.
1644%
1645% o filename: Write the image to this file.
1646%
1647% o exception: return any errors or warnings in this structure.
1648%
1649*/
cristy3ed852e2009-09-05 21:47:34 +00001650MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1651 ExceptionInfo *exception)
1652{
1653 int
1654 file;
1655
1656 register const unsigned char
1657 *p;
1658
1659 register size_t
1660 i;
1661
1662 size_t
1663 length,
1664 quantum;
1665
1666 ssize_t
1667 count;
1668
1669 struct stat
cristye7b28372012-06-17 13:59:06 +00001670 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001671
1672 unsigned char
1673 *buffer;
1674
1675 assert(image != (Image *) NULL);
1676 assert(image->signature == MagickSignature);
1677 assert(image->blob != (BlobInfo *) NULL);
1678 assert(image->blob->type != UndefinedStream);
1679 if (image->debug != MagickFalse)
1680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1681 assert(filename != (const char *) NULL);
1682 if (*filename == '\0')
1683 file=AcquireUniqueFileResource(filename);
1684 else
1685 if (LocaleCompare(filename,"-") == 0)
1686 file=fileno(stdout);
1687 else
cristyb70aab92012-01-31 15:04:04 +00001688 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001689 if (file == -1)
1690 {
1691 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1692 return(MagickFalse);
1693 }
1694 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001695 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1696 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001697 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001698 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1699 if (buffer == (unsigned char *) NULL)
1700 {
1701 file=close(file)-1;
1702 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001703 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001704 return(MagickFalse);
1705 }
1706 length=0;
cristyce0e7b22015-05-18 00:12:46 +00001707 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1708 for (i=0; count > 0; p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count))
cristy3ed852e2009-09-05 21:47:34 +00001709 {
1710 length=(size_t) count;
1711 for (i=0; i < length; i+=count)
1712 {
1713 count=write(file,p+i,(size_t) (length-i));
1714 if (count <= 0)
1715 {
1716 count=0;
1717 if (errno != EINTR)
1718 break;
1719 }
1720 }
1721 if (i < length)
1722 break;
1723 }
cristy54439632010-07-15 00:43:34 +00001724 if (LocaleCompare(filename,"-") != 0)
1725 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001726 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001727 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001728 {
cristye3216eb2014-04-18 17:10:21 +00001729 if (file != -1)
cristy100a0562014-04-18 01:27:37 +00001730 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001731 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1732 return(MagickFalse);
1733 }
1734 return(MagickTrue);
1735}
1736
1737/*
1738%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1739% %
1740% %
1741% %
1742% I m a g e s T o B l o b %
1743% %
1744% %
1745% %
1746%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1747%
1748% ImagesToBlob() implements direct to memory image formats. It returns the
1749% image sequence as a blob and its length. The magick member of the ImageInfo
1750% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1751%
1752% Note, some image formats do not permit multiple images to the same image
1753% stream (e.g. JPEG). in this instance, just the first image of the
1754% sequence is returned as a blob.
1755%
1756% The format of the ImagesToBlob method is:
1757%
cristy6586a802015-01-24 15:48:55 +00001758% void *ImagesToBlob(const ImageInfo *image_info,Image *images,
cristy3ed852e2009-09-05 21:47:34 +00001759% size_t *length,ExceptionInfo *exception)
1760%
1761% A description of each parameter follows:
1762%
1763% o image_info: the image info.
1764%
1765% o images: the image list.
1766%
cristybb85d6a2014-01-26 13:51:09 +00001767% o length: return the actual length of the blob.
cristy3ed852e2009-09-05 21:47:34 +00001768%
1769% o exception: return any errors or warnings in this structure.
1770%
1771*/
cristy6586a802015-01-24 15:48:55 +00001772MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
1773 size_t *length,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001774{
1775 const MagickInfo
1776 *magick_info;
1777
1778 ImageInfo
1779 *blob_info;
1780
1781 MagickBooleanType
1782 status;
1783
cristyce0e7b22015-05-18 00:12:46 +00001784 void
cristy3ed852e2009-09-05 21:47:34 +00001785 *blob;
1786
1787 assert(image_info != (const ImageInfo *) NULL);
1788 assert(image_info->signature == MagickSignature);
1789 if (image_info->debug != MagickFalse)
1790 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1791 image_info->filename);
1792 assert(images != (Image *) NULL);
1793 assert(images->signature == MagickSignature);
1794 assert(exception != (ExceptionInfo *) NULL);
1795 *length=0;
1796 blob=(unsigned char *) NULL;
1797 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001798 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1799 exception);
cristy3ed852e2009-09-05 21:47:34 +00001800 if (*blob_info->magick != '\0')
cristy151b66d2015-04-15 10:50:31 +00001801 (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001802 magick_info=GetMagickInfo(images->magick,exception);
1803 if (magick_info == (const MagickInfo *) NULL)
1804 {
1805 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001806 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +00001807 images->magick);
1808 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +00001809 return(blob);
1810 }
cristy4f1f3e82014-01-26 15:25:52 +00001811 if (GetMagickAdjoin(magick_info) == MagickFalse)
1812 {
1813 blob_info=DestroyImageInfo(blob_info);
1814 return(ImageToBlob(image_info,images,length,exception));
1815 }
cristy151b66d2015-04-15 10:50:31 +00001816 (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001817 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1818 {
1819 /*
1820 Native blob support for this images format.
1821 */
cristy5facf772014-01-26 14:42:57 +00001822 blob_info->length=0;
1823 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1824 sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001825 if (blob_info->blob == (void *) NULL)
1826 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001827 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
cristy3ed852e2009-09-05 21:47:34 +00001828 else
1829 {
cristy7a4b8c52014-01-25 22:48:06 +00001830 (void) CloseBlob(images);
cristy3ed852e2009-09-05 21:47:34 +00001831 images->blob->exempt=MagickTrue;
1832 *images->filename='\0';
1833 status=WriteImages(blob_info,images,images->filename,exception);
cristy5facf772014-01-26 14:42:57 +00001834 *length=images->blob->length;
cristy7a4b8c52014-01-25 22:48:06 +00001835 blob=DetachBlob(images->blob);
1836 if (status == MagickFalse)
cristyce0e7b22015-05-18 00:12:46 +00001837 blob=RelinquishMagickMemory(blob);
cristy7a4b8c52014-01-25 22:48:06 +00001838 else
cristyce0e7b22015-05-18 00:12:46 +00001839 blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001840 }
1841 }
1842 else
1843 {
1844 char
cristy151b66d2015-04-15 10:50:31 +00001845 filename[MagickPathExtent],
1846 unique[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00001847
1848 int
1849 file;
1850
1851 /*
1852 Write file to disk in blob images format.
1853 */
1854 file=AcquireUniqueFileResource(unique);
1855 if (file == -1)
1856 {
1857 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1858 image_info->filename);
1859 }
1860 else
1861 {
1862 blob_info->file=fdopen(file,"wb");
1863 if (blob_info->file != (FILE *) NULL)
1864 {
cristy151b66d2015-04-15 10:50:31 +00001865 (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001866 images->magick,unique);
1867 status=WriteImages(blob_info,images,filename,exception);
dirk607010e2014-03-01 19:08:11 +00001868 (void) CloseBlob(images);
cristya94f31b2014-03-01 13:25:42 +00001869 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001870 if (status != MagickFalse)
cristy2c1b6e02014-01-26 15:03:02 +00001871 blob=FileToBlob(unique,~0UL,length,exception);
cristy3ed852e2009-09-05 21:47:34 +00001872 }
1873 (void) RelinquishUniqueFileResource(unique);
1874 }
1875 }
1876 blob_info=DestroyImageInfo(blob_info);
1877 return(blob);
1878}
1879/*
1880%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1881% %
1882% %
1883% %
1884% I n j e c t I m a g e B l o b %
1885% %
1886% %
1887% %
1888%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1889%
1890% InjectImageBlob() injects the image with a copy of itself in the specified
1891% format (e.g. inject JPEG into a PDF image).
1892%
1893% The format of the InjectImageBlob method is:
1894%
1895% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1896% Image *image,Image *inject_image,const char *format,
1897% ExceptionInfo *exception)
1898%
1899% A description of each parameter follows:
1900%
1901% o image_info: the image info..
1902%
1903% o image: the image.
1904%
1905% o inject_image: inject into the image stream.
1906%
1907% o format: the image format.
1908%
1909% o exception: return any errors or warnings in this structure.
1910%
1911*/
1912MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1913 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1914{
1915 char
cristy151b66d2015-04-15 10:50:31 +00001916 filename[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00001917
1918 FILE
1919 *unique_file;
1920
1921 Image
1922 *byte_image;
1923
1924 ImageInfo
1925 *write_info;
1926
1927 int
1928 file;
1929
1930 MagickBooleanType
1931 status;
1932
cristybb503372010-05-27 20:51:26 +00001933 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001934 i;
1935
1936 size_t
1937 quantum;
1938
1939 ssize_t
1940 count;
1941
1942 struct stat
cristye7b28372012-06-17 13:59:06 +00001943 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001944
1945 unsigned char
1946 *buffer;
1947
1948 /*
1949 Write inject image to a temporary file.
1950 */
1951 assert(image_info != (ImageInfo *) NULL);
1952 assert(image_info->signature == MagickSignature);
1953 assert(image != (Image *) NULL);
1954 assert(image->signature == MagickSignature);
1955 if (image->debug != MagickFalse)
1956 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1957 assert(inject_image != (Image *) NULL);
1958 assert(inject_image->signature == MagickSignature);
1959 assert(exception != (ExceptionInfo *) NULL);
1960 unique_file=(FILE *) NULL;
1961 file=AcquireUniqueFileResource(filename);
1962 if (file != -1)
1963 unique_file=fdopen(file,"wb");
1964 if ((file == -1) || (unique_file == (FILE *) NULL))
1965 {
cristy151b66d2015-04-15 10:50:31 +00001966 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001967 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1968 image->filename);
1969 return(MagickFalse);
1970 }
1971 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1972 if (byte_image == (Image *) NULL)
1973 {
1974 (void) fclose(unique_file);
1975 (void) RelinquishUniqueFileResource(filename);
1976 return(MagickFalse);
1977 }
cristy151b66d2015-04-15 10:50:31 +00001978 (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001979 filename);
1980 DestroyBlob(byte_image);
1981 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1982 write_info=CloneImageInfo(image_info);
1983 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001984 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001985 write_info=DestroyImageInfo(write_info);
1986 byte_image=DestroyImage(byte_image);
1987 (void) fclose(unique_file);
1988 if (status == MagickFalse)
1989 {
1990 (void) RelinquishUniqueFileResource(filename);
1991 return(MagickFalse);
1992 }
1993 /*
1994 Inject into image stream.
1995 */
cristy18c6c272011-09-23 14:40:37 +00001996 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001997 if (file == -1)
1998 {
1999 (void) RelinquishUniqueFileResource(filename);
2000 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2001 image_info->filename);
2002 return(MagickFalse);
2003 }
2004 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00002005 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
2006 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00002007 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2008 if (buffer == (unsigned char *) NULL)
2009 {
2010 (void) RelinquishUniqueFileResource(filename);
cristyc658afb2015-01-21 21:45:09 +00002011 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00002012 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2013 image->filename);
2014 }
2015 for (i=0; ; i+=count)
2016 {
cristy65d11e42013-06-14 20:06:25 +00002017 count=read(file,buffer,quantum);
cristy3ed852e2009-09-05 21:47:34 +00002018 if (count <= 0)
2019 {
2020 count=0;
2021 if (errno != EINTR)
2022 break;
2023 }
2024 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2025 MagickFalse;
2026 }
cristya7cb4312010-06-26 00:47:03 +00002027 file=close(file);
2028 if (file == -1)
2029 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00002030 (void) RelinquishUniqueFileResource(filename);
2031 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2032 return(status);
2033}
2034
2035/*
2036%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2037% %
2038% %
2039% %
2040+ I s B l o b E x e m p t %
2041% %
2042% %
2043% %
2044%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2045%
2046% IsBlobExempt() returns true if the blob is exempt.
2047%
2048% The format of the IsBlobExempt method is:
2049%
2050% MagickBooleanType IsBlobExempt(const Image *image)
2051%
2052% A description of each parameter follows:
2053%
2054% o image: the image.
2055%
2056*/
cristy7832dc22011-09-05 01:21:53 +00002057MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002058{
2059 assert(image != (const Image *) NULL);
2060 assert(image->signature == MagickSignature);
2061 if (image->debug != MagickFalse)
2062 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2063 return(image->blob->exempt);
2064}
2065
2066/*
2067%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2068% %
2069% %
2070% %
2071+ I s B l o b S e e k a b l e %
2072% %
2073% %
2074% %
2075%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2076%
2077% IsBlobSeekable() returns true if the blob is seekable.
2078%
2079% The format of the IsBlobSeekable method is:
2080%
2081% MagickBooleanType IsBlobSeekable(const Image *image)
2082%
2083% A description of each parameter follows:
2084%
2085% o image: the image.
2086%
2087*/
cristy7832dc22011-09-05 01:21:53 +00002088MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002089{
2090 MagickBooleanType
2091 seekable;
2092
2093 assert(image != (const Image *) NULL);
2094 assert(image->signature == MagickSignature);
2095 if (image->debug != MagickFalse)
2096 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002097 switch (image->blob->type)
2098 {
2099 case FileStream:
2100 case BlobStream:
2101 case ZipStream:
2102 {
2103 seekable=MagickTrue;
2104 break;
2105 }
2106 default:
2107 {
2108 seekable=MagickFalse;
2109 break;
2110 }
2111 }
cristy3ed852e2009-09-05 21:47:34 +00002112 return(seekable);
2113}
2114
2115/*
2116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2117% %
2118% %
2119% %
2120+ I s B l o b T e m p o r a r y %
2121% %
2122% %
2123% %
2124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2125%
2126% IsBlobTemporary() returns true if the blob is temporary.
2127%
2128% The format of the IsBlobTemporary method is:
2129%
2130% MagickBooleanType IsBlobTemporary(const Image *image)
2131%
2132% A description of each parameter follows:
2133%
2134% o image: the image.
2135%
2136*/
cristy7832dc22011-09-05 01:21:53 +00002137MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002138{
2139 assert(image != (const Image *) NULL);
2140 assert(image->signature == MagickSignature);
2141 if (image->debug != MagickFalse)
2142 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2143 return(image->blob->temporary);
2144}
2145
2146/*
2147%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2148% %
2149% %
2150% %
2151+ M a p B l o b %
2152% %
2153% %
2154% %
2155%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2156%
2157% MapBlob() creates a mapping from a file to a binary large object.
2158%
2159% The format of the MapBlob method is:
2160%
cristy6586a802015-01-24 15:48:55 +00002161% void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
2162% const size_t length)
cristy3ed852e2009-09-05 21:47:34 +00002163%
2164% A description of each parameter follows:
2165%
2166% o file: map this file descriptor.
2167%
2168% o mode: ReadMode, WriteMode, or IOMode.
2169%
2170% o offset: starting at this offset within the file.
2171%
2172% o length: the length of the mapping is returned in this pointer.
2173%
2174*/
cristy6586a802015-01-24 15:48:55 +00002175MagickExport void *MapBlob(int file,const MapMode mode,
cristy3ed852e2009-09-05 21:47:34 +00002176 const MagickOffsetType offset,const size_t length)
2177{
cristydc8ea8e2013-07-28 20:10:44 +00002178#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00002179 int
2180 flags,
2181 protection;
2182
cristy6586a802015-01-24 15:48:55 +00002183 void
cristy3ed852e2009-09-05 21:47:34 +00002184 *map;
2185
2186 /*
2187 Map file.
2188 */
2189 flags=0;
2190 if (file == -1)
2191#if defined(MAP_ANONYMOUS)
2192 flags|=MAP_ANONYMOUS;
2193#else
cristy6586a802015-01-24 15:48:55 +00002194 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00002195#endif
2196 switch (mode)
2197 {
2198 case ReadMode:
2199 default:
2200 {
2201 protection=PROT_READ;
2202 flags|=MAP_PRIVATE;
cristy3ed852e2009-09-05 21:47:34 +00002203 break;
2204 }
2205 case WriteMode:
2206 {
2207 protection=PROT_WRITE;
2208 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002209 break;
2210 }
2211 case IOMode:
2212 {
2213 protection=PROT_READ | PROT_WRITE;
2214 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002215 break;
2216 }
2217 }
cristy56a0dbe2013-07-09 15:27:09 +00002218#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
cristy6586a802015-01-24 15:48:55 +00002219 map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
cristy56a0dbe2013-07-09 15:27:09 +00002220#else
cristy6586a802015-01-24 15:48:55 +00002221 map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,(off_t)
2222 offset);
2223 if (map == MAP_FAILED)
2224 map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
cristy56a0dbe2013-07-09 15:27:09 +00002225#endif
cristy6586a802015-01-24 15:48:55 +00002226 if (map == MAP_FAILED)
2227 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00002228 return(map);
2229#else
2230 (void) file;
2231 (void) mode;
2232 (void) offset;
2233 (void) length;
cristy6586a802015-01-24 15:48:55 +00002234 return(NULL);
cristy3ed852e2009-09-05 21:47:34 +00002235#endif
2236}
2237
2238/*
2239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2240% %
2241% %
2242% %
2243+ M S B O r d e r L o n g %
2244% %
2245% %
2246% %
2247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2248%
2249% MSBOrderLong() converts a least-significant byte first buffer of integers to
2250% most-significant byte first.
2251%
2252% The format of the MSBOrderLong method is:
2253%
2254% void MSBOrderLong(unsigned char *buffer,const size_t length)
2255%
2256% A description of each parameter follows.
2257%
2258% o buffer: Specifies a pointer to a buffer of integers.
2259%
2260% o length: Specifies the length of the buffer.
2261%
2262*/
2263MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2264{
2265 int
2266 c;
2267
2268 register unsigned char
2269 *p,
2270 *q;
2271
2272 assert(buffer != (unsigned char *) NULL);
2273 q=buffer+length;
2274 while (buffer < q)
2275 {
2276 p=buffer+3;
2277 c=(int) (*p);
2278 *p=(*buffer);
2279 *buffer++=(unsigned char) c;
2280 p=buffer+1;
2281 c=(int) (*p);
2282 *p=(*buffer);
2283 *buffer++=(unsigned char) c;
2284 buffer+=2;
2285 }
2286}
2287
2288/*
2289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2290% %
2291% %
2292% %
2293+ M S B O r d e r S h o r t %
2294% %
2295% %
2296% %
2297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2298%
2299% MSBOrderShort() converts a least-significant byte first buffer of integers
2300% to most-significant byte first.
2301%
2302% The format of the MSBOrderShort method is:
2303%
2304% void MSBOrderShort(unsigned char *p,const size_t length)
2305%
2306% A description of each parameter follows.
2307%
2308% o p: Specifies a pointer to a buffer of integers.
2309%
2310% o length: Specifies the length of the buffer.
2311%
2312*/
2313MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2314{
2315 int
2316 c;
2317
2318 register unsigned char
2319 *q;
2320
2321 assert(p != (unsigned char *) NULL);
2322 q=p+length;
2323 while (p < q)
2324 {
2325 c=(int) (*p);
2326 *p=(*(p+1));
2327 p++;
2328 *p++=(unsigned char) c;
2329 }
2330}
2331
2332/*
2333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2334% %
2335% %
2336% %
2337+ O p e n B l o b %
2338% %
2339% %
2340% %
2341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2342%
2343% OpenBlob() opens a file associated with the image. A file name of '-' sets
2344% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2345% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2346% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2347% from a system command.
2348%
2349% The format of the OpenBlob method is:
2350%
2351% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2352% const BlobMode mode,ExceptionInfo *exception)
2353%
2354% A description of each parameter follows:
2355%
2356% o image_info: the image info.
2357%
2358% o image: the image.
2359%
2360% o mode: the mode for opening the file.
2361%
2362*/
cristyfb348292015-04-12 00:28:54 +00002363
2364static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
2365 Image *image)
2366{
2367 const char
2368 *option;
2369
2370 int
2371 status;
2372
2373 size_t
2374 size;
2375
2376 size=16384;
2377 option=GetImageOption(image_info,"stream:buffer-size");
2378 if (option != (const char *) NULL)
2379 size=StringToUnsignedLong(option);
2380 status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
2381 _IONBF : _IOFBF,size);
2382 return(status == 0 ? MagickTrue : MagickFalse);
2383}
2384
cristy3ed852e2009-09-05 21:47:34 +00002385MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2386 Image *image,const BlobMode mode,ExceptionInfo *exception)
2387{
2388 char
cristy151b66d2015-04-15 10:50:31 +00002389 extension[MagickPathExtent],
2390 filename[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00002391
2392 const char
2393 *type;
2394
2395 MagickBooleanType
2396 status;
2397
2398 PolicyRights
2399 rights;
2400
2401 assert(image_info != (ImageInfo *) NULL);
2402 assert(image_info->signature == MagickSignature);
2403 if (image_info->debug != MagickFalse)
2404 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2405 image_info->filename);
2406 assert(image != (Image *) NULL);
2407 assert(image->signature == MagickSignature);
2408 if (image_info->blob != (void *) NULL)
2409 {
2410 if (image_info->stream != (StreamHandler) NULL)
2411 image->blob->stream=(StreamHandler) image_info->stream;
2412 AttachBlob(image->blob,image_info->blob,image_info->length);
2413 return(MagickTrue);
2414 }
2415 (void) DetachBlob(image->blob);
2416 switch (mode)
2417 {
2418 default: type="r"; break;
2419 case ReadBlobMode: type="r"; break;
2420 case ReadBinaryBlobMode: type="rb"; break;
2421 case WriteBlobMode: type="w"; break;
2422 case WriteBinaryBlobMode: type="w+b"; break;
2423 case AppendBlobMode: type="a"; break;
2424 case AppendBinaryBlobMode: type="a+b"; break;
2425 }
2426 if (*type != 'r')
2427 image->blob->synchronize=image_info->synchronize;
2428 if (image_info->stream != (StreamHandler) NULL)
2429 {
2430 image->blob->stream=(StreamHandler) image_info->stream;
2431 if (*type == 'w')
2432 {
2433 image->blob->type=FifoStream;
2434 return(MagickTrue);
2435 }
2436 }
2437 /*
2438 Open image file.
2439 */
2440 *filename='\0';
cristy151b66d2015-04-15 10:50:31 +00002441 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00002442 rights=ReadPolicyRights;
2443 if (*type == 'w')
2444 rights=WritePolicyRights;
2445 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2446 {
cristya9197f62010-01-12 02:23:34 +00002447 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002448 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
cristyefe601c2013-01-05 17:51:12 +00002449 "NotAuthorized","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00002450 return(MagickFalse);
2451 }
2452 if ((LocaleCompare(filename,"-") == 0) ||
2453 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2454 {
cristye7b28372012-06-17 13:59:06 +00002455 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002456#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002457 if (strchr(type,'b') != (char *) NULL)
cristye7b28372012-06-17 13:59:06 +00002458 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002459#endif
2460 image->blob->type=StandardStream;
2461 image->blob->exempt=MagickTrue;
cristyfb348292015-04-12 00:28:54 +00002462 return(SetStreamBuffering(image_info,image));
cristy3ed852e2009-09-05 21:47:34 +00002463 }
cristybc20d112012-07-29 20:27:00 +00002464 if (LocaleNCompare(filename,"fd:",3) == 0)
2465 {
2466 char
cristy151b66d2015-04-15 10:50:31 +00002467 mode[MagickPathExtent];
cristybc20d112012-07-29 20:27:00 +00002468
2469 *mode=(*type);
2470 mode[1]='\0';
2471 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2472#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2473 if (strchr(type,'b') != (char *) NULL)
2474 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2475#endif
2476 image->blob->type=StandardStream;
2477 image->blob->exempt=MagickTrue;
cristyfb348292015-04-12 00:28:54 +00002478 return(SetStreamBuffering(image_info,image));
cristybc20d112012-07-29 20:27:00 +00002479 }
cristy3ed852e2009-09-05 21:47:34 +00002480#if defined(MAGICKCORE_HAVE_POPEN)
2481 if (*filename == '|')
2482 {
2483 char
cristy151b66d2015-04-15 10:50:31 +00002484 mode[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00002485
2486 /*
2487 Pipe image to or from a system command.
2488 */
2489#if defined(SIGPIPE)
2490 if (*type == 'w')
2491 (void) signal(SIGPIPE,SIG_IGN);
2492#endif
2493 *mode=(*type);
2494 mode[1]='\0';
cristye7b28372012-06-17 13:59:06 +00002495 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2496 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002497 {
2498 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2499 return(MagickFalse);
2500 }
2501 image->blob->type=PipeStream;
2502 image->blob->exempt=MagickTrue;
cristyfb348292015-04-12 00:28:54 +00002503 return(SetStreamBuffering(image_info,image));
cristy3ed852e2009-09-05 21:47:34 +00002504 }
2505#endif
2506 status=GetPathAttributes(filename,&image->blob->properties);
2507#if defined(S_ISFIFO)
cristycd8b3312013-12-22 01:51:11 +00002508 if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
cristy3ed852e2009-09-05 21:47:34 +00002509 {
cristye7b28372012-06-17 13:59:06 +00002510 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2511 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002512 {
2513 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2514 return(MagickFalse);
2515 }
2516 image->blob->type=FileStream;
2517 image->blob->exempt=MagickTrue;
cristyfb348292015-04-12 00:28:54 +00002518 return(SetStreamBuffering(image_info,image));
cristy3ed852e2009-09-05 21:47:34 +00002519 }
2520#endif
cristybf6a7092010-06-11 02:12:15 +00002521 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002522 if (*type == 'w')
2523 {
cristy151b66d2015-04-15 10:50:31 +00002524 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
cristyb9e31362010-04-22 16:38:17 +00002525 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002526 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002527 {
2528 /*
2529 Form filename for multi-part images.
2530 */
2531 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002532 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002533 if ((LocaleCompare(filename,image->filename) == 0) &&
2534 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2535 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002536 {
cristybf7fa0d2010-02-04 00:51:10 +00002537 char
cristy151b66d2015-04-15 10:50:31 +00002538 path[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00002539
cristybf7fa0d2010-02-04 00:51:10 +00002540 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002541 if (*extension == '\0')
cristy151b66d2015-04-15 10:50:31 +00002542 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002543 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002544 else
cristy151b66d2015-04-15 10:50:31 +00002545 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002546 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002547 }
cristy151b66d2015-04-15 10:50:31 +00002548 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00002549#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002550 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002551#endif
cristye8939e72010-02-03 17:05:25 +00002552 }
cristy3ed852e2009-09-05 21:47:34 +00002553 }
cristybf6a7092010-06-11 02:12:15 +00002554 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002555 {
cristye7b28372012-06-17 13:59:06 +00002556 image->blob->file_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002557 image->blob->type=FileStream;
2558 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002559 }
2560 else
cristybf6a7092010-06-11 02:12:15 +00002561 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002562 {
cristye7b28372012-06-17 13:59:06 +00002563 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2564 if (image->blob->file_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002565 {
2566 size_t
cristybf6a7092010-06-11 02:12:15 +00002567 count;
cristy3ed852e2009-09-05 21:47:34 +00002568
cristybf6a7092010-06-11 02:12:15 +00002569 unsigned char
2570 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002571
cristybf6a7092010-06-11 02:12:15 +00002572 image->blob->type=FileStream;
cristyfb348292015-04-12 00:28:54 +00002573 (void) SetStreamBuffering(image_info,image);
cristybf6a7092010-06-11 02:12:15 +00002574 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristye7b28372012-06-17 13:59:06 +00002575 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
cristyae958042013-01-05 15:48:19 +00002576 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
cristy79fe6932012-12-25 00:31:30 +00002577 (void) fflush(image->blob->file_info.file);
cristybf6a7092010-06-11 02:12:15 +00002578 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2579 " read %.20g magic header bytes",(double) count);
2580#if defined(MAGICKCORE_ZLIB_DELEGATE)
2581 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2582 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002583 {
cristy98677002014-04-27 19:33:02 +00002584 if (image->blob->file_info.file != (FILE *) NULL)
2585 (void) fclose(image->blob->file_info.file);
2586 image->blob->file_info.file=(FILE *) NULL;
cristye7b28372012-06-17 13:59:06 +00002587 image->blob->file_info.gzfile=gzopen(filename,type);
2588 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002589 image->blob->type=ZipStream;
2590 }
2591#endif
2592#if defined(MAGICKCORE_BZLIB_DELEGATE)
2593 if (strncmp((char *) magick,"BZh",3) == 0)
2594 {
cristy98677002014-04-27 19:33:02 +00002595 if (image->blob->file_info.file != (FILE *) NULL)
2596 (void) fclose(image->blob->file_info.file);
2597 image->blob->file_info.file=(FILE *) NULL;
cristye7b28372012-06-17 13:59:06 +00002598 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2599 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002600 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002601 }
cristybf6a7092010-06-11 02:12:15 +00002602#endif
cristyc6c589d2010-07-06 01:34:57 +00002603 if (image->blob->type == FileStream)
2604 {
2605 const MagickInfo
2606 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002607
cristyc6c589d2010-07-06 01:34:57 +00002608 ExceptionInfo
2609 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002610
cristy18aba912013-06-14 19:48:08 +00002611 size_t
2612 length;
2613
cristyc6c589d2010-07-06 01:34:57 +00002614 sans_exception=AcquireExceptionInfo();
2615 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2616 sans_exception=DestroyExceptionInfo(sans_exception);
cristy2eddb3d2013-06-16 14:10:08 +00002617 length=(size_t) image->blob->properties.st_size;
cristyc6c589d2010-07-06 01:34:57 +00002618 if ((magick_info != (const MagickInfo *) NULL) &&
2619 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
cristybfdec892015-01-24 23:56:26 +00002620 (length > MagickMaxBufferExtent) &&
cristy18aba912013-06-14 19:48:08 +00002621 (AcquireMagickResource(MapResource,length) != MagickFalse))
cristyc6c589d2010-07-06 01:34:57 +00002622 {
cristyc6c589d2010-07-06 01:34:57 +00002623 void
2624 *blob;
cristybf6a7092010-06-11 02:12:15 +00002625
cristyfe00ebf2013-06-16 14:17:53 +00002626 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2627 length);
cristy18aba912013-06-14 19:48:08 +00002628 if (blob == (void *) NULL)
2629 RelinquishMagickResource(MapResource,length);
2630 else
cristyc6c589d2010-07-06 01:34:57 +00002631 {
2632 /*
2633 Format supports blobs-- use memory-mapped I/O.
2634 */
2635 if (image_info->file != (FILE *) NULL)
2636 image->blob->exempt=MagickFalse;
2637 else
2638 {
cristye7b28372012-06-17 13:59:06 +00002639 (void) fclose(image->blob->file_info.file);
2640 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002641 }
2642 AttachBlob(image->blob,blob,length);
2643 image->blob->mapped=MagickTrue;
2644 }
2645 }
2646 }
cristy3ed852e2009-09-05 21:47:34 +00002647 }
cristybf6a7092010-06-11 02:12:15 +00002648 }
2649 else
2650#if defined(MAGICKCORE_ZLIB_DELEGATE)
2651 if ((LocaleCompare(extension,"Z") == 0) ||
2652 (LocaleCompare(extension,"gz") == 0) ||
2653 (LocaleCompare(extension,"wmz") == 0) ||
2654 (LocaleCompare(extension,"svgz") == 0))
2655 {
2656 if (mode == WriteBinaryBlobMode)
2657 type="wb";
cristye7b28372012-06-17 13:59:06 +00002658 image->blob->file_info.gzfile=gzopen(filename,type);
2659 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002660 image->blob->type=ZipStream;
2661 }
2662 else
2663#endif
2664#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002665 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002666 {
cristye7b28372012-06-17 13:59:06 +00002667 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2668 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002669 image->blob->type=BZipStream;
2670 }
2671 else
2672#endif
2673 {
cristye7b28372012-06-17 13:59:06 +00002674 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2675 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002676 {
2677 image->blob->type=FileStream;
cristyfb348292015-04-12 00:28:54 +00002678 (void) SetStreamBuffering(image_info,image);
cristybf6a7092010-06-11 02:12:15 +00002679 }
2680 }
cristy3ed852e2009-09-05 21:47:34 +00002681 image->blob->status=MagickFalse;
2682 if (image->blob->type != UndefinedStream)
2683 image->blob->size=GetBlobSize(image);
2684 else
2685 {
2686 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2687 return(MagickFalse);
2688 }
2689 return(MagickTrue);
2690}
2691
2692/*
2693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2694% %
2695% %
2696% %
2697+ P i n g B l o b %
2698% %
2699% %
2700% %
2701%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2702%
2703% PingBlob() returns all the attributes of an image or image sequence except
2704% for the pixels. It is much faster and consumes far less memory than
2705% BlobToImage(). On failure, a NULL image is returned and exception
2706% describes the reason for the failure.
2707%
2708% The format of the PingBlob method is:
2709%
2710% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2711% const size_t length,ExceptionInfo *exception)
2712%
2713% A description of each parameter follows:
2714%
2715% o image_info: the image info.
2716%
2717% o blob: the address of a character stream in one of the image formats
2718% understood by ImageMagick.
2719%
2720% o length: This size_t integer reflects the length in bytes of the blob.
2721%
2722% o exception: return any errors or warnings in this structure.
2723%
2724*/
2725
2726#if defined(__cplusplus) || defined(c_plusplus)
2727extern "C" {
2728#endif
2729
2730static size_t PingStream(const Image *magick_unused(image),
2731 const void *magick_unused(pixels),const size_t columns)
2732{
2733 return(columns);
2734}
2735
2736#if defined(__cplusplus) || defined(c_plusplus)
2737}
2738#endif
2739
2740MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2741 const size_t length,ExceptionInfo *exception)
2742{
2743 Image
2744 *image;
2745
2746 ImageInfo
2747 *ping_info;
2748
2749 assert(image_info != (ImageInfo *) NULL);
2750 assert(image_info->signature == MagickSignature);
2751 if (image_info->debug != MagickFalse)
2752 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2753 image_info->filename);
2754 assert(exception != (ExceptionInfo *) NULL);
2755 if ((blob == (const void *) NULL) || (length == 0))
2756 {
2757 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +00002758 "UnrecognizedImageFormat","`%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002759 return((Image *) NULL);
2760 }
2761 ping_info=CloneImageInfo(image_info);
2762 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2763 if (ping_info->blob == (const void *) NULL)
2764 {
2765 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00002766 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002767 return((Image *) NULL);
2768 }
cristy54aad5e2010-09-03 16:02:04 +00002769 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002770 ping_info->length=length;
2771 ping_info->ping=MagickTrue;
2772 image=ReadStream(ping_info,&PingStream,exception);
2773 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2774 ping_info=DestroyImageInfo(ping_info);
2775 return(image);
2776}
2777
2778/*
2779%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2780% %
2781% %
2782% %
2783+ R e a d B l o b %
2784% %
2785% %
2786% %
2787%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2788%
2789% ReadBlob() reads data from the blob or image file and returns it. It
cristy5f3d2752013-01-05 18:53:38 +00002790% returns the number of bytes read. If length is zero, ReadBlob() returns
2791% zero and has no other results. If length is greater than SSIZE_MAX, the
2792% result is unspecified.
cristy3ed852e2009-09-05 21:47:34 +00002793%
2794% The format of the ReadBlob method is:
2795%
cristy6586a802015-01-24 15:48:55 +00002796% ssize_t ReadBlob(Image *image,const size_t length,void *data)
cristy3ed852e2009-09-05 21:47:34 +00002797%
2798% A description of each parameter follows:
2799%
2800% o image: the image.
2801%
2802% o length: Specifies an integer representing the number of bytes to read
2803% from the file.
2804%
2805% o data: Specifies an area to place the information requested from the
2806% file.
2807%
2808*/
cristy6586a802015-01-24 15:48:55 +00002809MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
cristy3ed852e2009-09-05 21:47:34 +00002810{
2811 int
2812 c;
2813
2814 register unsigned char
2815 *q;
2816
2817 ssize_t
2818 count;
2819
2820 assert(image != (Image *) NULL);
2821 assert(image->signature == MagickSignature);
2822 assert(image->blob != (BlobInfo *) NULL);
2823 assert(image->blob->type != UndefinedStream);
2824 if (length == 0)
2825 return(0);
2826 assert(data != (void *) NULL);
2827 count=0;
cristyce0e7b22015-05-18 00:12:46 +00002828 q=(unsigned char *) data;
cristy3ed852e2009-09-05 21:47:34 +00002829 switch (image->blob->type)
2830 {
2831 case UndefinedStream:
2832 break;
cristy3ed852e2009-09-05 21:47:34 +00002833 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002834 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002835 case PipeStream:
2836 {
2837 switch (length)
2838 {
2839 default:
2840 {
cristye7b28372012-06-17 13:59:06 +00002841 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002842 break;
2843 }
cristy28389292015-04-11 12:43:09 +00002844 case 4:
2845 {
2846 c=getc(image->blob->file_info.file);
2847 if (c == EOF)
2848 break;
2849 *q++=(unsigned char) c;
2850 count++;
2851 }
2852 case 3:
2853 {
2854 c=getc(image->blob->file_info.file);
2855 if (c == EOF)
2856 break;
2857 *q++=(unsigned char) c;
2858 count++;
2859 }
cristy3ed852e2009-09-05 21:47:34 +00002860 case 2:
2861 {
cristye7b28372012-06-17 13:59:06 +00002862 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002863 if (c == EOF)
2864 break;
2865 *q++=(unsigned char) c;
2866 count++;
2867 }
2868 case 1:
2869 {
cristye7b28372012-06-17 13:59:06 +00002870 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002871 if (c == EOF)
2872 break;
2873 *q++=(unsigned char) c;
2874 count++;
2875 }
2876 case 0:
2877 break;
2878 }
2879 break;
2880 }
2881 case ZipStream:
2882 {
2883#if defined(MAGICKCORE_ZLIB_DELEGATE)
2884 switch (length)
2885 {
2886 default:
2887 {
cristye7b28372012-06-17 13:59:06 +00002888 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002889 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002890 break;
2891 }
cristy28389292015-04-11 12:43:09 +00002892 case 4:
2893 {
2894 c=gzgetc(image->blob->file_info.gzfile);
2895 if (c == EOF)
2896 break;
2897 *q++=(unsigned char) c;
2898 count++;
2899 }
2900 case 3:
2901 {
2902 c=gzgetc(image->blob->file_info.gzfile);
2903 if (c == EOF)
2904 break;
2905 *q++=(unsigned char) c;
2906 count++;
2907 }
cristy3ed852e2009-09-05 21:47:34 +00002908 case 2:
2909 {
cristye7b28372012-06-17 13:59:06 +00002910 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002911 if (c == EOF)
2912 break;
2913 *q++=(unsigned char) c;
2914 count++;
2915 }
2916 case 1:
2917 {
cristye7b28372012-06-17 13:59:06 +00002918 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002919 if (c == EOF)
2920 break;
2921 *q++=(unsigned char) c;
2922 count++;
2923 }
2924 case 0:
2925 break;
2926 }
2927#endif
2928 break;
2929 }
2930 case BZipStream:
2931 {
2932#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy5f3d2752013-01-05 18:53:38 +00002933 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
cristy3ed852e2009-09-05 21:47:34 +00002934#endif
2935 break;
2936 }
2937 case FifoStream:
2938 break;
2939 case BlobStream:
2940 {
2941 register const unsigned char
2942 *p;
2943
2944 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2945 {
2946 image->blob->eof=MagickTrue;
2947 break;
2948 }
2949 p=image->blob->data+image->blob->offset;
cristyce0e7b22015-05-18 00:12:46 +00002950 count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
2951 image->blob->length-image->blob->offset);
cristy3ed852e2009-09-05 21:47:34 +00002952 image->blob->offset+=count;
2953 if (count != (ssize_t) length)
2954 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002955 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002956 break;
2957 }
2958 }
2959 return(count);
2960}
2961
2962/*
2963%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2964% %
2965% %
2966% %
2967+ R e a d B l o b B y t e %
2968% %
2969% %
2970% %
2971%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2972%
2973% ReadBlobByte() reads a single byte from the image file and returns it.
2974%
2975% The format of the ReadBlobByte method is:
2976%
2977% int ReadBlobByte(Image *image)
2978%
2979% A description of each parameter follows.
2980%
2981% o image: the image.
2982%
2983*/
2984MagickExport int ReadBlobByte(Image *image)
2985{
2986 register const unsigned char
2987 *p;
2988
2989 ssize_t
2990 count;
2991
2992 unsigned char
2993 buffer[1];
2994
2995 assert(image != (Image *) NULL);
2996 assert(image->signature == MagickSignature);
cristyce0e7b22015-05-18 00:12:46 +00002997 p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00002998 if (count != 1)
2999 return(EOF);
3000 return((int) (*p));
3001}
3002
3003/*
3004%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3005% %
3006% %
3007% %
3008+ R e a d B l o b D o u b l e %
3009% %
3010% %
3011% %
3012%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3013%
3014% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3015% specified by the endian member of the image structure.
3016%
3017% The format of the ReadBlobDouble method is:
3018%
3019% double ReadBlobDouble(Image *image)
3020%
3021% A description of each parameter follows.
3022%
3023% o image: the image.
3024%
3025*/
3026MagickExport double ReadBlobDouble(Image *image)
3027{
3028 union
3029 {
3030 MagickSizeType
3031 unsigned_value;
3032
3033 double
3034 double_value;
3035 } quantum;
3036
3037 quantum.double_value=0.0;
3038 quantum.unsigned_value=ReadBlobLongLong(image);
3039 return(quantum.double_value);
3040}
3041
3042/*
3043%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3044% %
3045% %
3046% %
3047+ R e a d B l o b F l o a t %
3048% %
3049% %
3050% %
3051%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3052%
3053% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3054% specified by the endian member of the image structure.
3055%
3056% The format of the ReadBlobFloat method is:
3057%
3058% float ReadBlobFloat(Image *image)
3059%
3060% A description of each parameter follows.
3061%
3062% o image: the image.
3063%
3064*/
3065MagickExport float ReadBlobFloat(Image *image)
3066{
3067 union
3068 {
3069 unsigned int
3070 unsigned_value;
3071
3072 float
3073 float_value;
3074 } quantum;
3075
3076 quantum.float_value=0.0;
3077 quantum.unsigned_value=ReadBlobLong(image);
3078 return(quantum.float_value);
3079}
3080
3081/*
3082%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3083% %
3084% %
3085% %
3086+ R e a d B l o b L o n g %
3087% %
3088% %
3089% %
3090%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3091%
cristybb503372010-05-27 20:51:26 +00003092% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003093% specified by the endian member of the image structure.
3094%
3095% The format of the ReadBlobLong method is:
3096%
3097% unsigned int ReadBlobLong(Image *image)
3098%
3099% A description of each parameter follows.
3100%
3101% o image: the image.
3102%
3103*/
3104MagickExport unsigned int ReadBlobLong(Image *image)
3105{
3106 register const unsigned char
3107 *p;
3108
3109 ssize_t
3110 count;
3111
3112 unsigned char
3113 buffer[4];
3114
3115 unsigned int
3116 value;
3117
3118 assert(image != (Image *) NULL);
3119 assert(image->signature == MagickSignature);
3120 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003121 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003122 if (count != 4)
3123 return(0UL);
3124 if (image->endian == LSBEndian)
3125 {
3126 value=(unsigned int) (*p++);
3127 value|=((unsigned int) (*p++)) << 8;
3128 value|=((unsigned int) (*p++)) << 16;
3129 value|=((unsigned int) (*p++)) << 24;
3130 return(value);
3131 }
3132 value=((unsigned int) (*p++)) << 24;
3133 value|=((unsigned int) (*p++)) << 16;
3134 value|=((unsigned int) (*p++)) << 8;
3135 value|=((unsigned int) (*p++));
3136 return(value);
3137}
3138
3139/*
3140%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3141% %
3142% %
3143% %
3144+ R e a d B l o b L o n g L o n g %
3145% %
3146% %
3147% %
3148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3149%
cristy4cb162a2010-05-30 03:04:47 +00003150% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3151% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003152%
cristy4cb162a2010-05-30 03:04:47 +00003153% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003154%
cristy4cb162a2010-05-30 03:04:47 +00003155% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003156%
3157% A description of each parameter follows.
3158%
3159% o image: the image.
3160%
3161*/
3162MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3163{
cristy0286d852010-10-12 18:38:07 +00003164 MagickSizeType
3165 value;
3166
cristy3ed852e2009-09-05 21:47:34 +00003167 register const unsigned char
3168 *p;
3169
3170 ssize_t
3171 count;
3172
3173 unsigned char
3174 buffer[8];
3175
cristy3ed852e2009-09-05 21:47:34 +00003176 assert(image != (Image *) NULL);
3177 assert(image->signature == MagickSignature);
3178 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003179 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003180 if (count != 8)
3181 return(MagickULLConstant(0));
3182 if (image->endian == LSBEndian)
3183 {
3184 value=(MagickSizeType) (*p++);
3185 value|=((MagickSizeType) (*p++)) << 8;
3186 value|=((MagickSizeType) (*p++)) << 16;
3187 value|=((MagickSizeType) (*p++)) << 24;
3188 value|=((MagickSizeType) (*p++)) << 32;
3189 value|=((MagickSizeType) (*p++)) << 40;
3190 value|=((MagickSizeType) (*p++)) << 48;
3191 value|=((MagickSizeType) (*p++)) << 56;
3192 return(value & MagickULLConstant(0xffffffffffffffff));
3193 }
3194 value=((MagickSizeType) (*p++)) << 56;
3195 value|=((MagickSizeType) (*p++)) << 48;
3196 value|=((MagickSizeType) (*p++)) << 40;
3197 value|=((MagickSizeType) (*p++)) << 32;
3198 value|=((MagickSizeType) (*p++)) << 24;
3199 value|=((MagickSizeType) (*p++)) << 16;
3200 value|=((MagickSizeType) (*p++)) << 8;
3201 value|=((MagickSizeType) (*p++));
3202 return(value & MagickULLConstant(0xffffffffffffffff));
3203}
3204
3205/*
3206%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3207% %
3208% %
3209% %
3210+ R e a d B l o b S h o r t %
3211% %
3212% %
3213% %
3214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3215%
3216% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3217% specified by the endian member of the image structure.
3218%
3219% The format of the ReadBlobShort method is:
3220%
3221% unsigned short ReadBlobShort(Image *image)
3222%
3223% A description of each parameter follows.
3224%
3225% o image: the image.
3226%
3227*/
3228MagickExport unsigned short ReadBlobShort(Image *image)
3229{
3230 register const unsigned char
3231 *p;
3232
3233 register unsigned int
3234 value;
3235
3236 ssize_t
3237 count;
3238
3239 unsigned char
3240 buffer[2];
3241
3242 assert(image != (Image *) NULL);
3243 assert(image->signature == MagickSignature);
3244 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003245 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003246 if (count != 2)
3247 return((unsigned short) 0U);
3248 if (image->endian == LSBEndian)
3249 {
3250 value=(unsigned int) (*p++);
3251 value|=((unsigned int) (*p++)) << 8;
3252 return((unsigned short) (value & 0xffff));
3253 }
3254 value=(unsigned int) ((*p++) << 8);
3255 value|=(unsigned int) (*p++);
3256 return((unsigned short) (value & 0xffff));
3257}
3258
3259/*
3260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3261% %
3262% %
3263% %
3264+ R e a d B l o b L S B L o n g %
3265% %
3266% %
3267% %
3268%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3269%
cristybb503372010-05-27 20:51:26 +00003270% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003271% least-significant byte first order.
3272%
3273% The format of the ReadBlobLSBLong method is:
3274%
3275% unsigned int ReadBlobLSBLong(Image *image)
3276%
3277% A description of each parameter follows.
3278%
3279% o image: the image.
3280%
3281*/
3282MagickExport unsigned int ReadBlobLSBLong(Image *image)
3283{
3284 register const unsigned char
3285 *p;
3286
3287 register unsigned int
3288 value;
3289
3290 ssize_t
3291 count;
3292
3293 unsigned char
3294 buffer[4];
3295
3296 assert(image != (Image *) NULL);
3297 assert(image->signature == MagickSignature);
3298 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003299 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003300 if (count != 4)
3301 return(0U);
3302 value=(unsigned int) (*p++);
3303 value|=((unsigned int) (*p++)) << 8;
3304 value|=((unsigned int) (*p++)) << 16;
3305 value|=((unsigned int) (*p++)) << 24;
3306 return(value);
3307}
3308
3309/*
3310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3311% %
3312% %
3313% %
3314+ R e a d B l o b L S B S h o r t %
3315% %
3316% %
3317% %
3318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3319%
3320% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3321% least-significant byte first order.
3322%
3323% The format of the ReadBlobLSBShort method is:
3324%
3325% unsigned short ReadBlobLSBShort(Image *image)
3326%
3327% A description of each parameter follows.
3328%
3329% o image: the image.
3330%
3331*/
3332MagickExport unsigned short ReadBlobLSBShort(Image *image)
3333{
3334 register const unsigned char
3335 *p;
3336
3337 register unsigned int
3338 value;
3339
3340 ssize_t
3341 count;
3342
3343 unsigned char
3344 buffer[2];
3345
3346 assert(image != (Image *) NULL);
3347 assert(image->signature == MagickSignature);
3348 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003349 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003350 if (count != 2)
3351 return((unsigned short) 0U);
3352 value=(unsigned int) (*p++);
3353 value|=((unsigned int) ((*p++)) << 8);
3354 return((unsigned short) (value & 0xffff));
3355}
3356
3357/*
3358%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3359% %
3360% %
3361% %
3362+ R e a d B l o b M S B L o n g %
3363% %
3364% %
3365% %
3366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3367%
cristybb503372010-05-27 20:51:26 +00003368% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003369% most-significant byte first order.
3370%
3371% The format of the ReadBlobMSBLong method is:
3372%
3373% unsigned int ReadBlobMSBLong(Image *image)
3374%
3375% A description of each parameter follows.
3376%
3377% o image: the image.
3378%
3379*/
3380MagickExport unsigned int ReadBlobMSBLong(Image *image)
3381{
3382 register const unsigned char
3383 *p;
3384
3385 register unsigned int
3386 value;
3387
3388 ssize_t
3389 count;
3390
3391 unsigned char
3392 buffer[4];
3393
3394 assert(image != (Image *) NULL);
3395 assert(image->signature == MagickSignature);
3396 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003397 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003398 if (count != 4)
3399 return(0UL);
3400 value=((unsigned int) (*p++) << 24);
3401 value|=((unsigned int) (*p++) << 16);
3402 value|=((unsigned int) (*p++) << 8);
3403 value|=(unsigned int) (*p++);
3404 return(value);
3405}
3406
3407/*
3408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3409% %
3410% %
3411% %
cristy2d3d87f2010-03-01 00:23:08 +00003412+ R e a d B l o b M S B L o n g L o n g %
3413% %
3414% %
3415% %
3416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3417%
cristybb503372010-05-27 20:51:26 +00003418% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003419% most-significant byte first order.
3420%
3421% The format of the ReadBlobMSBLongLong method is:
3422%
3423% unsigned int ReadBlobMSBLongLong(Image *image)
3424%
3425% A description of each parameter follows.
3426%
3427% o image: the image.
3428%
3429*/
3430MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3431{
3432 register const unsigned char
3433 *p;
3434
3435 register MagickSizeType
3436 value;
3437
3438 ssize_t
3439 count;
3440
3441 unsigned char
cristy0286d852010-10-12 18:38:07 +00003442 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003443
3444 assert(image != (Image *) NULL);
3445 assert(image->signature == MagickSignature);
3446 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003447 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
cristy2d3d87f2010-03-01 00:23:08 +00003448 if (count != 8)
3449 return(MagickULLConstant(0));
3450 value=((MagickSizeType) (*p++)) << 56;
3451 value|=((MagickSizeType) (*p++)) << 48;
3452 value|=((MagickSizeType) (*p++)) << 40;
3453 value|=((MagickSizeType) (*p++)) << 32;
3454 value|=((MagickSizeType) (*p++)) << 24;
3455 value|=((MagickSizeType) (*p++)) << 16;
3456 value|=((MagickSizeType) (*p++)) << 8;
3457 value|=((MagickSizeType) (*p++));
3458 return(value & MagickULLConstant(0xffffffffffffffff));
3459}
3460
3461/*
3462%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3463% %
3464% %
3465% %
cristy3ed852e2009-09-05 21:47:34 +00003466+ R e a d B l o b M S B S h o r t %
3467% %
3468% %
3469% %
3470%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3471%
3472% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3473% most-significant byte first order.
3474%
3475% The format of the ReadBlobMSBShort method is:
3476%
3477% unsigned short ReadBlobMSBShort(Image *image)
3478%
3479% A description of each parameter follows.
3480%
3481% o image: the image.
3482%
3483*/
3484MagickExport unsigned short ReadBlobMSBShort(Image *image)
3485{
3486 register const unsigned char
3487 *p;
3488
3489 register unsigned int
3490 value;
3491
3492 ssize_t
3493 count;
3494
3495 unsigned char
3496 buffer[2];
3497
3498 assert(image != (Image *) NULL);
3499 assert(image->signature == MagickSignature);
3500 *buffer='\0';
cristyce0e7b22015-05-18 00:12:46 +00003501 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003502 if (count != 2)
3503 return((unsigned short) 0U);
3504 value=(unsigned int) ((*p++) << 8);
3505 value|=(unsigned int) (*p++);
3506 return((unsigned short) (value & 0xffff));
3507}
3508
3509/*
3510%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3511% %
3512% %
3513% %
cristybd797f12015-01-24 20:42:32 +00003514+ R e a d B l o b S t r e a m %
3515% %
3516% %
3517% %
3518%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3519%
3520% ReadBlobStream() reads data from the blob or image file and returns it. It
3521% returns a pointer to the data buffer you supply or to the image memory
3522% buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
3523% returns a count of zero and has no other results. If length is greater than
3524% SSIZE_MAX, the result is unspecified.
3525%
3526% The format of the ReadBlobStream method is:
3527%
3528% const void *ReadBlobStream(Image *image,const size_t length,void *data,
3529% ssize_t *count)
3530%
3531% A description of each parameter follows:
3532%
3533% o image: the image.
3534%
3535% o length: Specifies an integer representing the number of bytes to read
3536% from the file.
3537%
3538% o count: returns the number of bytes read.
3539%
3540% o data: Specifies an area to place the information requested from the
3541% file.
3542%
3543*/
3544MagickExport const void *ReadBlobStream(Image *image,const size_t length,
3545 void *data,ssize_t *count)
3546{
3547 assert(image != (Image *) NULL);
3548 assert(image->signature == MagickSignature);
3549 assert(image->blob != (BlobInfo *) NULL);
3550 assert(image->blob->type != UndefinedStream);
3551 assert(count != (ssize_t *) NULL);
3552 if (image->blob->type != BlobStream)
3553 {
3554 assert(data != NULL);
cristyce0e7b22015-05-18 00:12:46 +00003555 *count=ReadBlob(image,length,(unsigned char *) data);
cristybd797f12015-01-24 20:42:32 +00003556 return(data);
3557 }
3558 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
3559 {
3560 *count=0;
3561 image->blob->eof=MagickTrue;
3562 return(data);
3563 }
3564 data=image->blob->data+image->blob->offset;
cristyce0e7b22015-05-18 00:12:46 +00003565 *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
3566 image->blob->length-image->blob->offset);
cristybd797f12015-01-24 20:42:32 +00003567 image->blob->offset+=(*count);
3568 if (*count != (ssize_t) length)
3569 image->blob->eof=MagickTrue;
3570 return(data);
3571}
3572
3573/*
3574%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3575% %
3576% %
3577% %
cristy3ed852e2009-09-05 21:47:34 +00003578+ R e a d B l o b S t r i n g %
3579% %
3580% %
3581% %
3582%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3583%
3584% ReadBlobString() reads characters from a blob or file until a newline
3585% character is read or an end-of-file condition is encountered.
3586%
3587% The format of the ReadBlobString method is:
3588%
3589% char *ReadBlobString(Image *image,char *string)
3590%
3591% A description of each parameter follows:
3592%
3593% o image: the image.
3594%
3595% o string: the address of a character buffer.
3596%
3597*/
3598MagickExport char *ReadBlobString(Image *image,char *string)
3599{
3600 register const unsigned char
3601 *p;
3602
cristybb503372010-05-27 20:51:26 +00003603 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003604 i;
3605
3606 ssize_t
3607 count;
3608
3609 unsigned char
3610 buffer[1];
3611
3612 assert(image != (Image *) NULL);
3613 assert(image->signature == MagickSignature);
cristy151b66d2015-04-15 10:50:31 +00003614 for (i=0; i < (MagickPathExtent-1L); i++)
cristy3ed852e2009-09-05 21:47:34 +00003615 {
cristyce0e7b22015-05-18 00:12:46 +00003616 p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003617 if (count != 1)
3618 {
3619 if (i == 0)
3620 return((char *) NULL);
3621 break;
3622 }
3623 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003624 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003625 break;
3626 }
cristy2b5db102010-06-09 01:07:28 +00003627 if (string[i] == '\r')
3628 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003629 string[i]='\0';
3630 return(string);
3631}
3632
3633/*
3634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3635% %
3636% %
3637% %
3638+ R e f e r e n c e B l o b %
3639% %
3640% %
3641% %
3642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3643%
3644% ReferenceBlob() increments the reference count associated with the pixel
3645% blob returning a pointer to the blob.
3646%
3647% The format of the ReferenceBlob method is:
3648%
3649% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3650%
3651% A description of each parameter follows:
3652%
3653% o blob_info: the blob_info.
3654%
3655*/
3656MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3657{
3658 assert(blob != (BlobInfo *) NULL);
3659 assert(blob->signature == MagickSignature);
3660 if (blob->debug != MagickFalse)
3661 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003662 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003663 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003664 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003665 return(blob);
3666}
3667
3668/*
3669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3670% %
3671% %
3672% %
3673+ S e e k B l o b %
3674% %
3675% %
3676% %
3677%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3678%
3679% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3680% and returns the resulting offset.
3681%
3682% The format of the SeekBlob method is:
3683%
3684% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3685% const int whence)
3686%
3687% A description of each parameter follows:
3688%
3689% o image: the image.
3690%
3691% o offset: Specifies an integer representing the offset in bytes.
3692%
3693% o whence: Specifies an integer representing how the offset is
3694% treated relative to the beginning of the blob as follows:
3695%
3696% SEEK_SET Set position equal to offset bytes.
3697% SEEK_CUR Set position to current location plus offset.
3698% SEEK_END Set position to EOF plus offset.
3699%
3700*/
3701MagickExport MagickOffsetType SeekBlob(Image *image,
3702 const MagickOffsetType offset,const int whence)
3703{
3704 assert(image != (Image *) NULL);
3705 assert(image->signature == MagickSignature);
3706 if (image->debug != MagickFalse)
3707 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3708 assert(image->blob != (BlobInfo *) NULL);
3709 assert(image->blob->type != UndefinedStream);
3710 switch (image->blob->type)
3711 {
3712 case UndefinedStream:
3713 break;
cristybc20d112012-07-29 20:27:00 +00003714 case StandardStream:
3715 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003716 case FileStream:
3717 {
cristye7b28372012-06-17 13:59:06 +00003718 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003719 return(-1);
3720 image->blob->offset=TellBlob(image);
3721 break;
3722 }
cristy3ed852e2009-09-05 21:47:34 +00003723 case PipeStream:
3724 case ZipStream:
3725 {
3726#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003727 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003728 return(-1);
3729#endif
3730 image->blob->offset=TellBlob(image);
3731 break;
3732 }
3733 case BZipStream:
3734 return(-1);
3735 case FifoStream:
3736 return(-1);
3737 case BlobStream:
3738 {
3739 switch (whence)
3740 {
3741 case SEEK_SET:
3742 default:
3743 {
3744 if (offset < 0)
3745 return(-1);
3746 image->blob->offset=offset;
3747 break;
3748 }
3749 case SEEK_CUR:
3750 {
3751 if ((image->blob->offset+offset) < 0)
3752 return(-1);
3753 image->blob->offset+=offset;
3754 break;
3755 }
3756 case SEEK_END:
3757 {
3758 if (((MagickOffsetType) image->blob->length+offset) < 0)
3759 return(-1);
3760 image->blob->offset=image->blob->length+offset;
3761 break;
3762 }
3763 }
cristy01409b62014-12-24 20:54:20 +00003764 if (image->blob->offset < (MagickOffsetType)
cristy3ed852e2009-09-05 21:47:34 +00003765 ((off_t) image->blob->length))
cristy01409b62014-12-24 20:54:20 +00003766 {
3767 image->blob->eof=MagickFalse;
3768 break;
3769 }
3770 if (image->blob->offset < (MagickOffsetType)
3771 ((off_t) image->blob->extent))
3772 break;
cristy0779de22015-05-03 12:45:49 +00003773 if (image->blob->immutable != MagickFalse)
3774 {
3775 image->blob->eof=MagickTrue;
3776 return(-1);
3777 }
cristy01409b62014-12-24 20:54:20 +00003778 image->blob->extent=(size_t) (image->blob->offset+image->blob->quantum);
3779 image->blob->quantum<<=1;
cristyf3fe18d2015-01-26 19:57:08 +00003780 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
cristy01409b62014-12-24 20:54:20 +00003781 image->blob->extent+1,sizeof(*image->blob->data));
3782 (void) SyncBlob(image);
cristy6586a802015-01-24 15:48:55 +00003783 if (image->blob->data == NULL)
cristy01409b62014-12-24 20:54:20 +00003784 {
3785 (void) DetachBlob(image->blob);
cristy3ed852e2009-09-05 21:47:34 +00003786 return(-1);
cristy01409b62014-12-24 20:54:20 +00003787 }
cristy3ed852e2009-09-05 21:47:34 +00003788 break;
3789 }
3790 }
3791 return(image->blob->offset);
3792}
3793
3794/*
3795%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3796% %
3797% %
3798% %
3799+ S e t B l o b E x e m p t %
3800% %
3801% %
3802% %
3803%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3804%
3805% SetBlobExempt() sets the blob exempt status.
3806%
3807% The format of the SetBlobExempt method is:
3808%
3809% MagickBooleanType SetBlobExempt(const Image *image,
3810% const MagickBooleanType exempt)
3811%
3812% A description of each parameter follows:
3813%
3814% o image: the image.
3815%
3816% o exempt: Set to true if this blob is exempt from being closed.
3817%
3818*/
cristy7832dc22011-09-05 01:21:53 +00003819MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003820{
3821 assert(image != (const Image *) NULL);
3822 assert(image->signature == MagickSignature);
3823 if (image->debug != MagickFalse)
3824 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3825 image->blob->exempt=exempt;
3826}
3827
3828/*
3829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3830% %
3831% %
3832% %
3833+ S e t B l o b E x t e n t %
3834% %
3835% %
3836% %
3837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3838%
3839% SetBlobExtent() ensures enough space is allocated for the blob. If the
3840% method is successful, subsequent writes to bytes in the specified range are
3841% guaranteed not to fail.
3842%
3843% The format of the SetBlobExtent method is:
3844%
3845% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3846%
3847% A description of each parameter follows:
3848%
3849% o image: the image.
3850%
3851% o extent: the blob maximum extent.
3852%
3853*/
cristy7832dc22011-09-05 01:21:53 +00003854MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003855 const MagickSizeType extent)
3856{
3857 assert(image != (Image *) NULL);
3858 assert(image->signature == MagickSignature);
3859 if (image->debug != MagickFalse)
3860 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3861 assert(image->blob != (BlobInfo *) NULL);
3862 assert(image->blob->type != UndefinedStream);
3863 switch (image->blob->type)
3864 {
3865 case UndefinedStream:
3866 break;
cristybc20d112012-07-29 20:27:00 +00003867 case StandardStream:
3868 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003869 case FileStream:
3870 {
cristy38e35f42012-12-18 21:12:17 +00003871 MagickOffsetType
3872 offset;
3873
3874 ssize_t
3875 count;
3876
cristy3ed852e2009-09-05 21:47:34 +00003877 if (extent != (MagickSizeType) ((off_t) extent))
3878 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003879 offset=SeekBlob(image,0,SEEK_END);
3880 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003881 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003882 if ((MagickSizeType) offset >= extent)
3883 break;
3884 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristy0ded5cf2015-03-22 14:05:05 +00003885 if (offset < 0)
3886 break;
cristyc7591272013-01-05 16:02:28 +00003887 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3888 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003889#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3890 if (image->blob->synchronize != MagickFalse)
3891 {
3892 int
cristybb380e72014-10-31 12:56:36 +00003893 file;
cristyfa0ea942012-12-21 02:42:29 +00003894
cristy2797f472014-05-26 01:25:55 +00003895 file=fileno(image->blob->file_info.file);
3896 if ((file == -1) || (offset < 0))
3897 return(MagickFalse);
cristybb380e72014-10-31 12:56:36 +00003898 (void) posix_fallocate(file,offset,extent-offset);
cristyfa0ea942012-12-21 02:42:29 +00003899 }
3900#endif
cristy38e35f42012-12-18 21:12:17 +00003901 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003902 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003903 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003904 break;
3905 }
cristy3ed852e2009-09-05 21:47:34 +00003906 case PipeStream:
3907 case ZipStream:
3908 return(MagickFalse);
3909 case BZipStream:
3910 return(MagickFalse);
3911 case FifoStream:
3912 return(MagickFalse);
3913 case BlobStream:
3914 {
cristy38e35f42012-12-18 21:12:17 +00003915 if (extent != (MagickSizeType) ((size_t) extent))
3916 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003917 if (image->blob->mapped != MagickFalse)
3918 {
cristy38e35f42012-12-18 21:12:17 +00003919 MagickOffsetType
3920 offset;
3921
3922 ssize_t
3923 count;
3924
cristy3ed852e2009-09-05 21:47:34 +00003925 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy18aba912013-06-14 19:48:08 +00003926 RelinquishMagickResource(MapResource,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003927 if (extent != (MagickSizeType) ((off_t) extent))
3928 return(MagickFalse);
3929 offset=SeekBlob(image,0,SEEK_END);
3930 if (offset < 0)
3931 return(MagickFalse);
3932 if ((MagickSizeType) offset >= extent)
3933 break;
3934 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003935 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003936 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003937#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3938 if (image->blob->synchronize != MagickFalse)
3939 {
3940 int
cristybb380e72014-10-31 12:56:36 +00003941 file;
cristyfa0ea942012-12-21 02:42:29 +00003942
cristy6f008fd2014-05-25 23:27:26 +00003943 file=fileno(image->blob->file_info.file);
cristyf2a82ee2014-05-26 17:49:54 +00003944 if ((file == -1) || (offset < 0))
cristy6f008fd2014-05-25 23:27:26 +00003945 return(MagickFalse);
cristybb380e72014-10-31 12:56:36 +00003946 (void) posix_fallocate(file,offset,extent-offset);
cristyfa0ea942012-12-21 02:42:29 +00003947 }
3948#endif
cristy38e35f42012-12-18 21:12:17 +00003949 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003950 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003951 return(MagickFalse);
cristyac1caa22013-06-15 00:41:21 +00003952 (void) AcquireMagickResource(MapResource,extent);
cristy95888612012-04-04 21:56:52 +00003953 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003954 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003955 image->blob->extent=(size_t) extent;
3956 image->blob->length=(size_t) extent;
3957 (void) SyncBlob(image);
3958 break;
cristy3ed852e2009-09-05 21:47:34 +00003959 }
cristy3ed852e2009-09-05 21:47:34 +00003960 image->blob->extent=(size_t) extent;
3961 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3962 image->blob->extent+1,sizeof(*image->blob->data));
3963 (void) SyncBlob(image);
3964 if (image->blob->data == (unsigned char *) NULL)
3965 {
3966 (void) DetachBlob(image->blob);
3967 return(MagickFalse);
3968 }
3969 break;
3970 }
3971 }
3972 return(MagickTrue);
3973}
3974
3975/*
3976%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3977% %
3978% %
3979% %
3980+ S y n c B l o b %
3981% %
3982% %
3983% %
3984%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3985%
3986% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3987% attributes if it is an blob.
3988%
3989% The format of the SyncBlob method is:
3990%
3991% int SyncBlob(Image *image)
3992%
3993% A description of each parameter follows:
3994%
3995% o image: the image.
3996%
3997*/
3998static int SyncBlob(Image *image)
3999{
4000 int
4001 status;
4002
4003 assert(image != (Image *) NULL);
4004 assert(image->signature == MagickSignature);
4005 if (image->debug != MagickFalse)
4006 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4007 assert(image->blob != (BlobInfo *) NULL);
4008 assert(image->blob->type != UndefinedStream);
4009 status=0;
4010 switch (image->blob->type)
4011 {
4012 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00004013 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00004014 break;
4015 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004016 case PipeStream:
4017 {
cristye7b28372012-06-17 13:59:06 +00004018 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004019 break;
4020 }
4021 case ZipStream:
4022 {
4023#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004024 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00004025#endif
4026 break;
4027 }
4028 case BZipStream:
4029 {
4030#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004031 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00004032#endif
4033 break;
4034 }
4035 case FifoStream:
4036 break;
4037 case BlobStream:
cristy3ed852e2009-09-05 21:47:34 +00004038 break;
cristy3ed852e2009-09-05 21:47:34 +00004039 }
4040 return(status);
4041}
4042
4043/*
4044%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4045% %
4046% %
4047% %
4048+ T e l l B l o b %
4049% %
4050% %
4051% %
4052%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4053%
4054% TellBlob() obtains the current value of the blob or file position.
4055%
4056% The format of the TellBlob method is:
4057%
4058% MagickOffsetType TellBlob(const Image *image)
4059%
4060% A description of each parameter follows:
4061%
4062% o image: the image.
4063%
4064*/
4065MagickExport MagickOffsetType TellBlob(const Image *image)
4066{
4067 MagickOffsetType
4068 offset;
4069
4070 assert(image != (Image *) NULL);
4071 assert(image->signature == MagickSignature);
4072 if (image->debug != MagickFalse)
4073 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4074 assert(image->blob != (BlobInfo *) NULL);
4075 assert(image->blob->type != UndefinedStream);
4076 offset=(-1);
4077 switch (image->blob->type)
4078 {
4079 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00004080 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00004081 break;
4082 case FileStream:
4083 {
cristye7b28372012-06-17 13:59:06 +00004084 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004085 break;
4086 }
cristy3ed852e2009-09-05 21:47:34 +00004087 case PipeStream:
4088 break;
4089 case ZipStream:
4090 {
4091#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004092 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00004093#endif
4094 break;
4095 }
4096 case BZipStream:
4097 break;
4098 case FifoStream:
4099 break;
4100 case BlobStream:
4101 {
4102 offset=image->blob->offset;
4103 break;
4104 }
4105 }
4106 return(offset);
4107}
4108
4109/*
4110%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4111% %
4112% %
4113% %
4114+ U n m a p B l o b %
4115% %
4116% %
4117% %
4118%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4119%
4120% UnmapBlob() deallocates the binary large object previously allocated with
4121% the MapBlob method.
4122%
4123% The format of the UnmapBlob method is:
4124%
4125% MagickBooleanType UnmapBlob(void *map,const size_t length)
4126%
4127% A description of each parameter follows:
4128%
4129% o map: the address of the binary large object.
4130%
4131% o length: the length of the binary large object.
4132%
4133*/
4134MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4135{
cristydc8ea8e2013-07-28 20:10:44 +00004136#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00004137 int
4138 status;
4139
4140 status=munmap(map,length);
4141 return(status == -1 ? MagickFalse : MagickTrue);
4142#else
4143 (void) map;
4144 (void) length;
4145 return(MagickFalse);
4146#endif
4147}
4148
4149/*
4150%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4151% %
4152% %
4153% %
4154+ W r i t e B l o b %
4155% %
4156% %
4157% %
4158%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4159%
4160% WriteBlob() writes data to a blob or image file. It returns the number of
4161% bytes written.
4162%
4163% The format of the WriteBlob method is:
4164%
cristyac965582015-05-18 12:35:47 +00004165% ssize_t WriteBlob(Image *image,const size_t length,const void *data)
cristy3ed852e2009-09-05 21:47:34 +00004166%
4167% A description of each parameter follows:
4168%
4169% o image: the image.
4170%
4171% o length: Specifies an integer representing the number of bytes to
4172% write to the file.
4173%
4174% o data: The address of the data to write to the blob or file.
4175%
4176*/
4177MagickExport ssize_t WriteBlob(Image *image,const size_t length,
cristyac965582015-05-18 12:35:47 +00004178 const void *data)
cristy3ed852e2009-09-05 21:47:34 +00004179{
4180 int
4181 c;
4182
4183 register const unsigned char
4184 *p;
4185
4186 ssize_t
4187 count;
4188
4189 assert(image != (Image *) NULL);
4190 assert(image->signature == MagickSignature);
cristyac965582015-05-18 12:35:47 +00004191 assert(data != (const void *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00004192 assert(image->blob != (BlobInfo *) NULL);
4193 assert(image->blob->type != UndefinedStream);
4194 if (length == 0)
4195 return(0);
4196 count=0;
cristyac965582015-05-18 12:35:47 +00004197 p=(const unsigned char *) data;
cristy3ed852e2009-09-05 21:47:34 +00004198 switch (image->blob->type)
4199 {
4200 case UndefinedStream:
4201 break;
cristyffb0ccd2015-04-11 12:45:11 +00004202 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004203 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004204 case PipeStream:
4205 {
4206 switch (length)
4207 {
4208 default:
4209 {
4210 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004211 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004212 break;
4213 }
cristydfc3f852015-04-11 12:37:16 +00004214 case 4:
4215 {
4216 c=putc((int) *p++,image->blob->file_info.file);
4217 if (c == EOF)
4218 break;
4219 count++;
4220 }
4221 case 3:
4222 {
4223 c=putc((int) *p++,image->blob->file_info.file);
4224 if (c == EOF)
4225 break;
4226 count++;
4227 }
cristy3ed852e2009-09-05 21:47:34 +00004228 case 2:
4229 {
cristye7b28372012-06-17 13:59:06 +00004230 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004231 if (c == EOF)
4232 break;
4233 count++;
4234 }
4235 case 1:
4236 {
cristye7b28372012-06-17 13:59:06 +00004237 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004238 if (c == EOF)
4239 break;
4240 count++;
4241 }
4242 case 0:
4243 break;
4244 }
4245 break;
4246 }
4247 case ZipStream:
4248 {
4249#if defined(MAGICKCORE_ZLIB_DELEGATE)
4250 switch (length)
4251 {
4252 default:
4253 {
cristye7b28372012-06-17 13:59:06 +00004254 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004255 (unsigned int) length);
4256 break;
4257 }
cristydfc3f852015-04-11 12:37:16 +00004258 case 4:
4259 {
4260 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4261 if (c == EOF)
4262 break;
4263 count++;
4264 }
4265 case 3:
4266 {
4267 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4268 if (c == EOF)
4269 break;
4270 count++;
4271 }
cristy3ed852e2009-09-05 21:47:34 +00004272 case 2:
4273 {
cristye7b28372012-06-17 13:59:06 +00004274 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004275 if (c == EOF)
4276 break;
4277 count++;
4278 }
4279 case 1:
4280 {
cristye7b28372012-06-17 13:59:06 +00004281 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004282 if (c == EOF)
4283 break;
4284 count++;
4285 }
4286 case 0:
4287 break;
4288 }
4289#endif
4290 break;
4291 }
4292 case BZipStream:
4293 {
4294#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004295 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004296 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004297#endif
4298 break;
4299 }
4300 case FifoStream:
4301 {
4302 count=(ssize_t) image->blob->stream(image,data,length);
4303 break;
4304 }
4305 case BlobStream:
4306 {
4307 register unsigned char
4308 *q;
4309
4310 if ((image->blob->offset+(MagickOffsetType) length) >=
4311 (MagickOffsetType) image->blob->extent)
4312 {
4313 if (image->blob->mapped != MagickFalse)
4314 return(0);
cristy3ed852e2009-09-05 21:47:34 +00004315 image->blob->extent+=length+image->blob->quantum;
cristyff368632014-01-27 13:01:38 +00004316 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00004317 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4318 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4319 (void) SyncBlob(image);
4320 if (image->blob->data == (unsigned char *) NULL)
4321 {
4322 (void) DetachBlob(image->blob);
4323 return(0);
4324 }
4325 }
4326 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004327 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004328 image->blob->offset+=length;
4329 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4330 image->blob->length=(size_t) image->blob->offset;
4331 count=(ssize_t) length;
4332 }
4333 }
4334 return(count);
4335}
4336
4337/*
4338%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4339% %
4340% %
4341% %
4342+ W r i t e B l o b B y t e %
4343% %
4344% %
4345% %
4346%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4347%
4348% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4349% written (either 0 or 1);
4350%
4351% The format of the WriteBlobByte method is:
4352%
4353% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4354%
4355% A description of each parameter follows.
4356%
4357% o image: the image.
4358%
4359% o value: Specifies the value to write.
4360%
4361*/
4362MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4363{
4364 assert(image != (Image *) NULL);
4365 assert(image->signature == MagickSignature);
4366 return(WriteBlobStream(image,1,&value));
4367}
4368
4369/*
4370%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4371% %
4372% %
4373% %
4374+ W r i t e B l o b F l o a t %
4375% %
4376% %
4377% %
4378%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4379%
4380% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4381% specified by the endian member of the image structure.
4382%
4383% The format of the WriteBlobFloat method is:
4384%
4385% ssize_t WriteBlobFloat(Image *image,const float value)
4386%
4387% A description of each parameter follows.
4388%
4389% o image: the image.
4390%
4391% o value: Specifies the value to write.
4392%
4393*/
4394MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4395{
4396 union
4397 {
4398 unsigned int
4399 unsigned_value;
4400
4401 float
4402 float_value;
4403 } quantum;
4404
4405 quantum.unsigned_value=0U;
4406 quantum.float_value=value;
4407 return(WriteBlobLong(image,quantum.unsigned_value));
4408}
4409
4410/*
4411%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4412% %
4413% %
4414% %
4415+ W r i t e B l o b L o n g %
4416% %
4417% %
4418% %
4419%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4420%
cristybb503372010-05-27 20:51:26 +00004421% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004422% specified by the endian member of the image structure.
4423%
4424% The format of the WriteBlobLong method is:
4425%
4426% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4427%
4428% A description of each parameter follows.
4429%
4430% o image: the image.
4431%
4432% o value: Specifies the value to write.
4433%
4434*/
4435MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4436{
4437 unsigned char
4438 buffer[4];
4439
4440 assert(image != (Image *) NULL);
4441 assert(image->signature == MagickSignature);
4442 if (image->endian == LSBEndian)
4443 {
4444 buffer[0]=(unsigned char) value;
4445 buffer[1]=(unsigned char) (value >> 8);
4446 buffer[2]=(unsigned char) (value >> 16);
4447 buffer[3]=(unsigned char) (value >> 24);
4448 return(WriteBlobStream(image,4,buffer));
4449 }
4450 buffer[0]=(unsigned char) (value >> 24);
4451 buffer[1]=(unsigned char) (value >> 16);
4452 buffer[2]=(unsigned char) (value >> 8);
4453 buffer[3]=(unsigned char) value;
4454 return(WriteBlobStream(image,4,buffer));
4455}
4456
4457/*
4458%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4459% %
4460% %
4461% %
4462+ W r i t e B l o b S h o r t %
4463% %
4464% %
4465% %
4466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4467%
4468% WriteBlobShort() writes a short value as a 16-bit quantity in the
4469% byte-order specified by the endian member of the image structure.
4470%
4471% The format of the WriteBlobShort method is:
4472%
4473% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4474%
4475% A description of each parameter follows.
4476%
4477% o image: the image.
4478%
4479% o value: Specifies the value to write.
4480%
4481*/
4482MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4483{
4484 unsigned char
4485 buffer[2];
4486
4487 assert(image != (Image *) NULL);
4488 assert(image->signature == MagickSignature);
4489 if (image->endian == LSBEndian)
4490 {
4491 buffer[0]=(unsigned char) value;
4492 buffer[1]=(unsigned char) (value >> 8);
4493 return(WriteBlobStream(image,2,buffer));
4494 }
4495 buffer[0]=(unsigned char) (value >> 8);
4496 buffer[1]=(unsigned char) value;
4497 return(WriteBlobStream(image,2,buffer));
4498}
4499
4500/*
4501%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4502% %
4503% %
4504% %
4505+ W r i t e B l o b L S B L o n g %
4506% %
4507% %
4508% %
4509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4510%
cristybb503372010-05-27 20:51:26 +00004511% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004512% least-significant byte first order.
4513%
4514% The format of the WriteBlobLSBLong method is:
4515%
4516% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4517%
4518% A description of each parameter follows.
4519%
4520% o image: the image.
4521%
4522% o value: Specifies the value to write.
4523%
4524*/
4525MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4526{
4527 unsigned char
4528 buffer[4];
4529
4530 assert(image != (Image *) NULL);
4531 assert(image->signature == MagickSignature);
4532 buffer[0]=(unsigned char) value;
4533 buffer[1]=(unsigned char) (value >> 8);
4534 buffer[2]=(unsigned char) (value >> 16);
4535 buffer[3]=(unsigned char) (value >> 24);
4536 return(WriteBlobStream(image,4,buffer));
4537}
4538
4539/*
4540%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4541% %
4542% %
4543% %
4544+ W r i t e B l o b L S B S h o r t %
4545% %
4546% %
4547% %
4548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4549%
cristybb503372010-05-27 20:51:26 +00004550% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004551% least-significant byte first order.
4552%
4553% The format of the WriteBlobLSBShort method is:
4554%
4555% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4556%
4557% A description of each parameter follows.
4558%
4559% o image: the image.
4560%
4561% o value: Specifies the value to write.
4562%
4563*/
4564MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4565{
4566 unsigned char
4567 buffer[2];
4568
4569 assert(image != (Image *) NULL);
4570 assert(image->signature == MagickSignature);
4571 buffer[0]=(unsigned char) value;
4572 buffer[1]=(unsigned char) (value >> 8);
4573 return(WriteBlobStream(image,2,buffer));
4574}
4575
4576/*
4577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4578% %
4579% %
4580% %
4581+ W r i t e B l o b M S B L o n g %
4582% %
4583% %
4584% %
4585%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4586%
cristybb503372010-05-27 20:51:26 +00004587% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004588% most-significant byte first order.
4589%
4590% The format of the WriteBlobMSBLong method is:
4591%
4592% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4593%
4594% A description of each parameter follows.
4595%
4596% o value: Specifies the value to write.
4597%
4598% o image: the image.
4599%
4600*/
4601MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4602{
4603 unsigned char
4604 buffer[4];
4605
4606 assert(image != (Image *) NULL);
4607 assert(image->signature == MagickSignature);
4608 buffer[0]=(unsigned char) (value >> 24);
4609 buffer[1]=(unsigned char) (value >> 16);
4610 buffer[2]=(unsigned char) (value >> 8);
4611 buffer[3]=(unsigned char) value;
4612 return(WriteBlobStream(image,4,buffer));
4613}
4614
4615/*
4616%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4617% %
4618% %
4619% %
cristy2ca49922010-03-06 02:54:01 +00004620+ W r i t e B l o b M S B L o n g L o n g %
4621% %
4622% %
4623% %
4624%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4625%
4626% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4627% most-significant byte first order.
4628%
4629% The format of the WriteBlobMSBLongLong method is:
4630%
4631% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4632%
4633% A description of each parameter follows.
4634%
4635% o value: Specifies the value to write.
4636%
4637% o image: the image.
4638%
4639*/
4640MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4641 const MagickSizeType value)
4642{
4643 unsigned char
4644 buffer[8];
4645
4646 assert(image != (Image *) NULL);
4647 assert(image->signature == MagickSignature);
4648 buffer[0]=(unsigned char) (value >> 56);
4649 buffer[1]=(unsigned char) (value >> 48);
4650 buffer[2]=(unsigned char) (value >> 40);
4651 buffer[3]=(unsigned char) (value >> 32);
4652 buffer[4]=(unsigned char) (value >> 24);
4653 buffer[5]=(unsigned char) (value >> 16);
4654 buffer[6]=(unsigned char) (value >> 8);
4655 buffer[7]=(unsigned char) value;
4656 return(WriteBlobStream(image,8,buffer));
4657}
4658
4659/*
4660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4661% %
4662% %
4663% %
cristy3ed852e2009-09-05 21:47:34 +00004664+ W r i t e B l o b M S B S h o r t %
4665% %
4666% %
4667% %
4668%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4669%
cristybb503372010-05-27 20:51:26 +00004670% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004671% most-significant byte first order.
4672%
4673% The format of the WriteBlobMSBShort method is:
4674%
4675% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4676%
4677% A description of each parameter follows.
4678%
4679% o value: Specifies the value to write.
4680%
4681% o file: Specifies the file to write the data to.
4682%
4683*/
4684MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4685{
4686 unsigned char
4687 buffer[2];
4688
4689 assert(image != (Image *) NULL);
4690 assert(image->signature == MagickSignature);
4691 buffer[0]=(unsigned char) (value >> 8);
4692 buffer[1]=(unsigned char) value;
4693 return(WriteBlobStream(image,2,buffer));
4694}
4695
4696/*
4697%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4698% %
4699% %
4700% %
4701+ W r i t e B l o b S t r i n g %
4702% %
4703% %
4704% %
4705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4706%
4707% WriteBlobString() write a string to a blob. It returns the number of
4708% characters written.
4709%
4710% The format of the WriteBlobString method is:
4711%
4712% ssize_t WriteBlobString(Image *image,const char *string)
4713%
4714% A description of each parameter follows.
4715%
4716% o image: the image.
4717%
4718% o string: Specifies the string to write.
4719%
4720*/
4721MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4722{
4723 assert(image != (Image *) NULL);
4724 assert(image->signature == MagickSignature);
4725 assert(string != (const char *) NULL);
4726 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4727}