blob: 4319424ed90a22b654eb451ff68f29a51208a475 [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"
cristy4c08aed2011-07-01 19:47:50 +000059#include "MagickCore/policy.h"
60#include "MagickCore/resource_.h"
61#include "MagickCore/semaphore.h"
62#include "MagickCore/string_.h"
63#include "MagickCore/string-private.h"
64#include "MagickCore/token.h"
65#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000066#include "MagickCore/utility-private.h"
cristy3ed852e2009-09-05 21:47:34 +000067#if defined(MAGICKCORE_ZLIB_DELEGATE)
68#include "zlib.h"
69#endif
70#if defined(MAGICKCORE_BZLIB_DELEGATE)
71#include "bzlib.h"
72#endif
73
74/*
75 Define declarations.
76*/
77#define MagickMaxBlobExtent 65541
cristy3ed852e2009-09-05 21:47:34 +000078#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
79# define MAP_ANONYMOUS MAP_ANON
80#endif
81#if !defined(MAP_FAILED)
82#define MAP_FAILED ((void *) -1)
83#endif
cristy3ed852e2009-09-05 21:47:34 +000084#if defined(__OS2__)
85#include <io.h>
86#define _O_BINARY O_BINARY
87#endif
88
89/*
90 Typedef declarations.
91*/
cristye7b28372012-06-17 13:59:06 +000092typedef union FileInfo
93{
94 FILE
95 *file;
96
97#if defined(MAGICKCORE_ZLIB_DELEGATE)
98 gzFile
99 gzfile;
100#endif
101
102#if defined(MAGICKCORE_BZLIB_DELEGATE)
103 BZFILE
104 *bzfile;
105#endif
106} FileInfo;
107
cristy3ed852e2009-09-05 21:47:34 +0000108struct _BlobInfo
109{
110 size_t
111 length,
112 extent,
113 quantum;
114
115 MagickBooleanType
116 mapped,
117 eof;
118
119 MagickOffsetType
120 offset;
121
122 MagickSizeType
123 size;
124
125 MagickBooleanType
126 exempt,
127 synchronize,
128 status,
129 temporary;
130
131 StreamType
132 type;
133
cristye7b28372012-06-17 13:59:06 +0000134 FileInfo
135 file_info;
cristy3ed852e2009-09-05 21:47:34 +0000136
137 struct stat
138 properties;
139
140 StreamHandler
141 stream;
142
143 unsigned char
144 *data;
145
146 MagickBooleanType
147 debug;
148
149 SemaphoreInfo
150 *semaphore;
151
cristybb503372010-05-27 20:51:26 +0000152 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000153 reference_count;
154
cristybb503372010-05-27 20:51:26 +0000155 size_t
cristy3ed852e2009-09-05 21:47:34 +0000156 signature;
157};
158
159/*
160 Forward declarations.
161*/
162static int
163 SyncBlob(Image *);
164
165/*
166%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
167% %
168% %
169% %
170+ A t t a c h B l o b %
171% %
172% %
173% %
174%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175%
176% AttachBlob() attaches a blob to the BlobInfo structure.
177%
178% The format of the AttachBlob method is:
179%
180% void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
181%
182% A description of each parameter follows:
183%
184% o blob_info: Specifies a pointer to a BlobInfo structure.
185%
186% o blob: the address of a character stream in one of the image formats
187% understood by ImageMagick.
188%
189% o length: This size_t integer reflects the length in bytes of the blob.
190%
191*/
192MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
193 const size_t length)
194{
195 assert(blob_info != (BlobInfo *) NULL);
196 if (blob_info->debug != MagickFalse)
197 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
198 blob_info->length=length;
199 blob_info->extent=length;
200 blob_info->quantum=(size_t) MagickMaxBlobExtent;
201 blob_info->offset=0;
202 blob_info->type=BlobStream;
cristye7b28372012-06-17 13:59:06 +0000203 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000204 blob_info->data=(unsigned char *) blob;
205 blob_info->mapped=MagickFalse;
206}
207
208/*
209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210% %
211% %
212% %
213+ B l o b T o F i l e %
214% %
215% %
216% %
217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218%
219% BlobToFile() writes a blob to a file. It returns MagickFalse if an error
220% occurs otherwise MagickTrue.
221%
222% The format of the BlobToFile method is:
223%
224% MagickBooleanType BlobToFile(char *filename,const void *blob,
225% const size_t length,ExceptionInfo *exception)
226%
227% A description of each parameter follows:
228%
229% o filename: Write the blob to this file.
230%
231% o blob: the address of a blob.
232%
233% o length: This length in bytes of the blob.
234%
235% o exception: return any errors or warnings in this structure.
236%
237*/
238
cristy7753b2a2011-02-19 18:36:52 +0000239static inline MagickSizeType MagickMin(const MagickSizeType x,
240 const MagickSizeType y)
cristy3ed852e2009-09-05 21:47:34 +0000241{
242 if (x < y)
243 return(x);
244 return(y);
245}
246
247MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
248 const size_t length,ExceptionInfo *exception)
249{
250 int
251 file;
252
253 register size_t
254 i;
255
256 ssize_t
257 count;
258
259 assert(filename != (const char *) NULL);
260 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
261 assert(blob != (const void *) NULL);
262 if (*filename == '\0')
263 file=AcquireUniqueFileResource(filename);
264 else
cristy18c6c272011-09-23 14:40:37 +0000265 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +0000266 if (file == -1)
267 {
268 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
269 return(MagickFalse);
270 }
271 for (i=0; i < length; i+=count)
272 {
cristy65d11e42013-06-14 20:06:25 +0000273 count=write(file,(const char *) blob+i,(size_t) MagickMin(length-i,
274 (MagickSizeType) SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +0000275 if (count <= 0)
276 {
277 count=0;
278 if (errno != EINTR)
279 break;
280 }
281 }
cristya7cb4312010-06-26 00:47:03 +0000282 file=close(file);
283 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +0000284 {
285 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
286 return(MagickFalse);
287 }
288 return(MagickTrue);
289}
290
291/*
292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293% %
294% %
295% %
296% B l o b T o I m a g e %
297% %
298% %
299% %
300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301%
302% BlobToImage() implements direct to memory image formats. It returns the
303% blob as an image.
304%
305% The format of the BlobToImage method is:
306%
307% Image *BlobToImage(const ImageInfo *image_info,const void *blob,
308% const size_t length,ExceptionInfo *exception)
309%
310% A description of each parameter follows:
311%
312% o image_info: the image info.
313%
314% o blob: the address of a character stream in one of the image formats
315% understood by ImageMagick.
316%
317% o length: This size_t integer reflects the length in bytes of the blob.
318%
319% o exception: return any errors or warnings in this structure.
320%
321*/
322MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
323 const size_t length,ExceptionInfo *exception)
324{
325 const MagickInfo
326 *magick_info;
327
328 Image
329 *image;
330
331 ImageInfo
332 *blob_info,
333 *clone_info;
334
335 MagickBooleanType
336 status;
337
338 assert(image_info != (ImageInfo *) NULL);
339 assert(image_info->signature == MagickSignature);
340 if (image_info->debug != MagickFalse)
341 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
342 image_info->filename);
343 assert(exception != (ExceptionInfo *) NULL);
344 if ((blob == (const void *) NULL) || (length == 0))
345 {
346 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +0000347 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +0000348 return((Image *) NULL);
349 }
350 blob_info=CloneImageInfo(image_info);
351 blob_info->blob=(void *) blob;
352 blob_info->length=length;
353 if (*blob_info->magick == '\0')
cristyd965a422010-03-03 17:47:35 +0000354 (void) SetImageInfo(blob_info,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000355 magick_info=GetMagickInfo(blob_info->magick,exception);
356 if (magick_info == (const MagickInfo *) NULL)
357 {
cristy3ed852e2009-09-05 21:47:34 +0000358 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +0000359 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +0000360 blob_info->magick);
361 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +0000362 return((Image *) NULL);
363 }
364 if (GetMagickBlobSupport(magick_info) != MagickFalse)
365 {
366 /*
367 Native blob support for this image format.
368 */
369 (void) CopyMagickString(blob_info->filename,image_info->filename,
370 MaxTextExtent);
371 (void) CopyMagickString(blob_info->magick,image_info->magick,
372 MaxTextExtent);
373 image=ReadImage(blob_info,exception);
374 if (image != (Image *) NULL)
375 (void) DetachBlob(image->blob);
376 blob_info=DestroyImageInfo(blob_info);
377 return(image);
378 }
379 /*
380 Write blob to a temporary file on disk.
381 */
382 blob_info->blob=(void *) NULL;
383 blob_info->length=0;
384 *blob_info->filename='\0';
385 status=BlobToFile(blob_info->filename,blob,length,exception);
386 if (status == MagickFalse)
387 {
388 (void) RelinquishUniqueFileResource(blob_info->filename);
389 blob_info=DestroyImageInfo(blob_info);
390 return((Image *) NULL);
391 }
392 clone_info=CloneImageInfo(blob_info);
cristyb51dff52011-05-19 16:55:47 +0000393 (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +0000394 blob_info->magick,blob_info->filename);
395 image=ReadImage(clone_info,exception);
cristy540a22c2012-06-10 15:22:16 +0000396 if (image != (Image *) NULL)
397 {
398 Image
399 *images;
400
401 /*
dirk7fcec532014-04-24 18:52:40 +0000402 Restore original filenames and image format.
cristy540a22c2012-06-10 15:22:16 +0000403 */
404 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
405 {
dirk7fcec532014-04-24 18:52:40 +0000406 (void) CopyMagickString(images->filename,image_info->filename,
407 MaxTextExtent);
408 (void) CopyMagickString(images->magick_filename,image_info->filename,
409 MaxTextExtent);
410 (void) CopyMagickString(images->magick,magick_info->name,
411 MaxTextExtent);
cristy540a22c2012-06-10 15:22:16 +0000412 images=GetNextImageInList(images);
413 }
414 }
cristy3ed852e2009-09-05 21:47:34 +0000415 clone_info=DestroyImageInfo(clone_info);
416 (void) RelinquishUniqueFileResource(blob_info->filename);
417 blob_info=DestroyImageInfo(blob_info);
418 return(image);
419}
420
421/*
422%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423% %
424% %
425% %
426+ C l o n e B l o b I n f o %
427% %
428% %
429% %
430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431%
432% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
433% blob info is NULL, a new one.
434%
435% The format of the CloneBlobInfo method is:
436%
437% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
438%
439% A description of each parameter follows:
440%
441% o blob_info: the blob info.
442%
443*/
444MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
445{
446 BlobInfo
447 *clone_info;
448
cristy73bd4a52010-10-05 11:24:23 +0000449 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
cristy3ed852e2009-09-05 21:47:34 +0000450 if (clone_info == (BlobInfo *) NULL)
451 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
452 GetBlobInfo(clone_info);
453 if (blob_info == (BlobInfo *) NULL)
454 return(clone_info);
455 clone_info->length=blob_info->length;
456 clone_info->extent=blob_info->extent;
457 clone_info->synchronize=blob_info->synchronize;
458 clone_info->quantum=blob_info->quantum;
459 clone_info->mapped=blob_info->mapped;
460 clone_info->eof=blob_info->eof;
461 clone_info->offset=blob_info->offset;
462 clone_info->size=blob_info->size;
463 clone_info->exempt=blob_info->exempt;
464 clone_info->status=blob_info->status;
465 clone_info->temporary=blob_info->temporary;
466 clone_info->type=blob_info->type;
cristye7b28372012-06-17 13:59:06 +0000467 clone_info->file_info.file=blob_info->file_info.file;
cristy3ed852e2009-09-05 21:47:34 +0000468 clone_info->properties=blob_info->properties;
469 clone_info->stream=blob_info->stream;
470 clone_info->data=blob_info->data;
471 clone_info->debug=IsEventLogging();
472 clone_info->reference_count=1;
473 return(clone_info);
474}
475
476/*
477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
478% %
479% %
480% %
481+ C l o s e B l o b %
482% %
483% %
484% %
485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486%
487% CloseBlob() closes a stream associated with the image.
488%
489% The format of the CloseBlob method is:
490%
491% MagickBooleanType CloseBlob(Image *image)
492%
493% A description of each parameter follows:
494%
495% o image: the image.
496%
497*/
498MagickExport MagickBooleanType CloseBlob(Image *image)
499{
500 int
501 status;
502
503 /*
504 Close image file.
505 */
506 assert(image != (Image *) NULL);
507 assert(image->signature == MagickSignature);
508 if (image->debug != MagickFalse)
509 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
510 assert(image->blob != (BlobInfo *) NULL);
511 if (image->blob->type == UndefinedStream)
512 return(MagickTrue);
cristy7e2a7c72012-12-27 00:56:47 +0000513 status=SyncBlob(image);
cristy3ed852e2009-09-05 21:47:34 +0000514 switch (image->blob->type)
515 {
516 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000517 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000518 break;
519 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000520 case PipeStream:
521 {
cristy02ce8cc2012-12-27 00:35:49 +0000522 if (image->blob->synchronize != MagickFalse)
523 status=fsync(fileno(image->blob->file_info.file));
cristye7b28372012-06-17 13:59:06 +0000524 status=ferror(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000525 break;
526 }
527 case ZipStream:
528 {
529#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000530 (void) gzerror(image->blob->file_info.gzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000531#endif
532 break;
533 }
534 case BZipStream:
535 {
536#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000537 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000538#endif
539 break;
540 }
541 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000542 break;
cristy02ce8cc2012-12-27 00:35:49 +0000543 case BlobStream:
544 {
545 if ((image->blob->file_info.file != (FILE *) NULL) &&
546 (image->blob->synchronize != MagickFalse))
cristy5678acd2012-12-27 00:41:55 +0000547 {
548 (void) fsync(fileno(image->blob->file_info.file));
549 status=ferror(image->blob->file_info.file);
550 }
cristy02ce8cc2012-12-27 00:35:49 +0000551 break;
552 }
cristy3ed852e2009-09-05 21:47:34 +0000553 }
554 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
cristycd9e6322012-12-27 00:29:00 +0000555 image->blob->size=GetBlobSize(image);
556 image->extent=image->blob->size;
557 image->blob->eof=MagickFalse;
cristybae22e42012-12-27 00:25:59 +0000558 if (image->blob->exempt != MagickFalse)
559 {
560 image->blob->type=UndefinedStream;
561 return(image->blob->status);
562 }
cristy3ed852e2009-09-05 21:47:34 +0000563 switch (image->blob->type)
564 {
565 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000566 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000567 break;
568 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000569 {
cristye7b28372012-06-17 13:59:06 +0000570 status=fclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000571 break;
572 }
573 case PipeStream:
574 {
575#if defined(MAGICKCORE_HAVE_PCLOSE)
cristye7b28372012-06-17 13:59:06 +0000576 status=pclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000577#endif
578 break;
579 }
580 case ZipStream:
581 {
582#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000583 status=gzclose(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +0000584#endif
585 break;
586 }
587 case BZipStream:
588 {
589#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000590 BZ2_bzclose(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +0000591#endif
592 break;
593 }
594 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000595 break;
cristyff483372010-10-16 17:00:58 +0000596 case BlobStream:
597 {
cristye7b28372012-06-17 13:59:06 +0000598 if (image->blob->file_info.file != (FILE *) NULL)
cristy02ce8cc2012-12-27 00:35:49 +0000599 status=fclose(image->blob->file_info.file);
cristyff483372010-10-16 17:00:58 +0000600 break;
601 }
cristy3ed852e2009-09-05 21:47:34 +0000602 }
603 (void) DetachBlob(image->blob);
604 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
605 return(image->blob->status);
606}
607
608/*
609%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610% %
611% %
612% %
613+ D e s t r o y B l o b %
614% %
615% %
616% %
617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
618%
619% DestroyBlob() deallocates memory associated with a blob.
620%
621% The format of the DestroyBlob method is:
622%
623% void DestroyBlob(Image *image)
624%
625% A description of each parameter follows:
626%
627% o image: the image.
628%
629*/
630MagickExport void DestroyBlob(Image *image)
631{
632 MagickBooleanType
633 destroy;
634
635 assert(image != (Image *) NULL);
636 assert(image->signature == MagickSignature);
637 if (image->debug != MagickFalse)
638 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
639 assert(image->blob != (BlobInfo *) NULL);
640 assert(image->blob->signature == MagickSignature);
641 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000642 LockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000643 image->blob->reference_count--;
644 assert(image->blob->reference_count >= 0);
645 if (image->blob->reference_count == 0)
646 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000647 UnlockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000648 if (destroy == MagickFalse)
649 return;
650 (void) CloseBlob(image);
651 if (image->blob->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000652 {
653 (void) UnmapBlob(image->blob->data,image->blob->length);
654 RelinquishMagickResource(MapResource,image->blob->length);
655 }
cristy3ed852e2009-09-05 21:47:34 +0000656 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
cristy3d162a92014-02-16 14:05:06 +0000657 RelinquishSemaphoreInfo(&image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000658 image->blob->signature=(~MagickSignature);
659 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
660}
661
662/*
663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
664% %
665% %
666% %
667+ D e t a c h B l o b %
668% %
669% %
670% %
671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
672%
673% DetachBlob() detaches a blob from the BlobInfo structure.
674%
675% The format of the DetachBlob method is:
676%
677% unsigned char *DetachBlob(BlobInfo *blob_info)
678%
679% A description of each parameter follows:
680%
681% o blob_info: Specifies a pointer to a BlobInfo structure.
682%
683*/
684MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
685{
686 unsigned char
687 *data;
688
689 assert(blob_info != (BlobInfo *) NULL);
690 if (blob_info->debug != MagickFalse)
691 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
692 if (blob_info->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000693 {
694 (void) UnmapBlob(blob_info->data,blob_info->length);
cristy100a0562014-04-18 01:27:37 +0000695 blob_info->data=(unsigned char *) NULL;
cristy18aba912013-06-14 19:48:08 +0000696 RelinquishMagickResource(MapResource,blob_info->length);
697 }
cristy3ed852e2009-09-05 21:47:34 +0000698 blob_info->mapped=MagickFalse;
699 blob_info->length=0;
700 blob_info->offset=0;
701 blob_info->eof=MagickFalse;
702 blob_info->exempt=MagickFalse;
703 blob_info->type=UndefinedStream;
cristye7b28372012-06-17 13:59:06 +0000704 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000705 data=blob_info->data;
706 blob_info->data=(unsigned char *) NULL;
707 blob_info->stream=(StreamHandler) NULL;
708 return(data);
709}
710
711/*
712%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
713% %
714% %
715% %
cristy10f10ec2014-09-20 01:00:50 +0000716+ D i s a s s o c i a t e B l o b %
717% %
718% %
719% %
720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721%
722% DisassociateBlob() disassociates the image stream. It checks if the
723% blob of the specified image is referenced by other images. If the reference
724% count is higher then 1 a new blob is assigned to the specified image.
725%
726% The format of the DisassociateBlob method is:
727%
dirkcfe4c1c2014-09-20 07:38:59 +0000728% void DisassociateBlob(const Image *image)
cristy10f10ec2014-09-20 01:00:50 +0000729%
730% A description of each parameter follows:
731%
732% o image: the image.
733%
734*/
735MagickPrivate void DisassociateBlob(Image *image)
736{
737 BlobInfo
738 *blob;
739
740 MagickBooleanType
741 clone;
742
743 assert(image != (Image *) NULL);
744 assert(image->signature == MagickSignature);
745 if (image->debug != MagickFalse)
746 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
747 assert(image->blob != (BlobInfo *) NULL);
748 assert(image->blob->signature == MagickSignature);
749 clone=MagickFalse;
750 LockSemaphoreInfo(image->blob->semaphore);
751 assert(image->blob->reference_count >= 0);
752 if (image->blob->reference_count > 1)
753 clone=MagickTrue;
754 UnlockSemaphoreInfo(image->blob->semaphore);
755 if (clone == MagickFalse)
cristy345d8722014-09-24 16:49:02 +0000756 return;
cristy10f10ec2014-09-20 01:00:50 +0000757 blob=CloneBlobInfo(image->blob);
758 DestroyBlob(image);
759 image->blob=blob;
760}
761
762/*
763%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
764% %
765% %
766% %
cristyc1af14f2010-09-16 20:01:21 +0000767+ D i s c a r d B l o b B y t e s %
768% %
769% %
770% %
771%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
772%
773% DiscardBlobBytes() discards bytes in a blob.
774%
775% The format of the DiscardBlobBytes method is:
776%
cristy6f008fd2014-05-25 23:27:26 +0000777% MagickBooleanType DiscardBlobBytes(Image *image,
778% const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000779%
780% A description of each parameter follows.
781%
782% o image: the image.
783%
784% o length: the number of bytes to skip.
785%
786*/
787
788static inline const unsigned char *ReadBlobStream(Image *image,
789 const size_t length,unsigned char *data,ssize_t *count)
790{
791 assert(count != (ssize_t *) NULL);
792 assert(image->blob != (BlobInfo *) NULL);
793 if (image->blob->type != BlobStream)
794 {
795 *count=ReadBlob(image,length,data);
796 return(data);
797 }
798 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
799 {
800 *count=0;
801 image->blob->eof=MagickTrue;
802 return(data);
803 }
804 data=image->blob->data+image->blob->offset;
cristy7753b2a2011-02-19 18:36:52 +0000805 *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
cristyc1af14f2010-09-16 20:01:21 +0000806 image->blob->offset));
807 image->blob->offset+=(*count);
808 if (*count != (ssize_t) length)
809 image->blob->eof=MagickTrue;
810 return(data);
811}
812
813MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
cristy7753b2a2011-02-19 18:36:52 +0000814 const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000815{
cristy7753b2a2011-02-19 18:36:52 +0000816 register MagickOffsetType
cristyc1af14f2010-09-16 20:01:21 +0000817 i;
818
819 size_t
820 quantum;
821
822 ssize_t
823 count;
824
825 unsigned char
cristyf55846d2010-09-17 19:01:10 +0000826 buffer[16384];
cristyc1af14f2010-09-16 20:01:21 +0000827
828 assert(image != (Image *) NULL);
829 assert(image->signature == MagickSignature);
830 count=0;
cristy7753b2a2011-02-19 18:36:52 +0000831 for (i=0; i < (MagickOffsetType) length; i+=count)
cristyc1af14f2010-09-16 20:01:21 +0000832 {
cristy7753b2a2011-02-19 18:36:52 +0000833 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
cristyc1af14f2010-09-16 20:01:21 +0000834 (void) ReadBlobStream(image,quantum,buffer,&count);
835 if (count <= 0)
836 {
837 count=0;
838 if (errno != EINTR)
839 break;
840 }
841 }
cristy7753b2a2011-02-19 18:36:52 +0000842 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
cristyc1af14f2010-09-16 20:01:21 +0000843}
844
845/*
846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
847% %
848% %
849% %
cristy3ed852e2009-09-05 21:47:34 +0000850+ D u p l i c a t e s B l o b %
851% %
852% %
853% %
854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
855%
856% DuplicateBlob() duplicates a blob descriptor.
857%
858% The format of the DuplicateBlob method is:
859%
860% void DuplicateBlob(Image *image,const Image *duplicate)
861%
862% A description of each parameter follows:
863%
864% o image: the image.
865%
866% o duplicate: the duplicate image.
867%
868*/
869MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
870{
871 assert(image != (Image *) NULL);
872 assert(image->signature == MagickSignature);
873 if (image->debug != MagickFalse)
874 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
875 assert(duplicate != (Image *) NULL);
876 assert(duplicate->signature == MagickSignature);
877 DestroyBlob(image);
878 image->blob=ReferenceBlob(duplicate->blob);
879}
880
881/*
882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883% %
884% %
885% %
886+ E O F B l o b %
887% %
888% %
889% %
890%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891%
892% EOFBlob() returns a non-zero value when EOF has been detected reading from
893% a blob or file.
894%
895% The format of the EOFBlob method is:
896%
897% int EOFBlob(const Image *image)
898%
899% A description of each parameter follows:
900%
901% o image: the image.
902%
903*/
904MagickExport int EOFBlob(const Image *image)
905{
906 assert(image != (Image *) NULL);
907 assert(image->signature == MagickSignature);
908 if (image->debug != MagickFalse)
909 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
910 assert(image->blob != (BlobInfo *) NULL);
911 assert(image->blob->type != UndefinedStream);
912 switch (image->blob->type)
913 {
914 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000915 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000916 break;
917 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000918 case PipeStream:
919 {
cristye7b28372012-06-17 13:59:06 +0000920 image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
cristy95888612012-04-04 21:56:52 +0000921 MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000922 break;
923 }
924 case ZipStream:
925 {
926 image->blob->eof=MagickFalse;
927 break;
928 }
929 case BZipStream:
930 {
931#if defined(MAGICKCORE_BZLIB_DELEGATE)
932 int
933 status;
934
935 status=0;
cristye7b28372012-06-17 13:59:06 +0000936 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000937 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
938#endif
939 break;
940 }
941 case FifoStream:
942 {
943 image->blob->eof=MagickFalse;
944 break;
945 }
946 case BlobStream:
947 break;
948 }
949 return((int) image->blob->eof);
950}
951
952/*
953%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
954% %
955% %
956% %
957+ F i l e T o B l o b %
958% %
959% %
960% %
961%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
962%
cristy178edaf2011-01-23 03:42:39 +0000963% FileToBlob() returns the contents of a file as a buffer terminated with
964% the '\0' character. The length of the buffer (not including the extra
965% terminating '\0' character) is returned via the 'length' parameter. Free
966% the buffer with RelinquishMagickMemory().
cristy3ed852e2009-09-05 21:47:34 +0000967%
968% The format of the FileToBlob method is:
969%
970% unsigned char *FileToBlob(const char *filename,const size_t extent,
971% size_t *length,ExceptionInfo *exception)
972%
973% A description of each parameter follows:
974%
975% o blob: FileToBlob() returns the contents of a file as a blob. If
976% an error occurs NULL is returned.
977%
978% o filename: the filename.
979%
980% o extent: The maximum length of the blob.
981%
982% o length: On return, this reflects the actual length of the blob.
983%
984% o exception: return any errors or warnings in this structure.
985%
986*/
987MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
988 size_t *length,ExceptionInfo *exception)
989{
990 int
991 file;
992
993 MagickOffsetType
994 offset;
995
996 register size_t
997 i;
998
999 ssize_t
1000 count;
1001
1002 unsigned char
1003 *blob;
1004
1005 void
1006 *map;
1007
1008 assert(filename != (const char *) NULL);
1009 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1010 assert(exception != (ExceptionInfo *) NULL);
1011 *length=0;
1012 file=fileno(stdin);
1013 if (LocaleCompare(filename,"-") != 0)
cristy18c6c272011-09-23 14:40:37 +00001014 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001015 if (file == -1)
1016 {
1017 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1018 return((unsigned char *) NULL);
1019 }
cristy7f317702011-02-18 20:40:28 +00001020 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
cristy3ed852e2009-09-05 21:47:34 +00001021 count=0;
cristyd1f55c12014-01-24 00:40:57 +00001022 if ((file == fileno(stdin)) || (offset < 0) ||
1023 (offset != (MagickOffsetType) ((ssize_t) offset)))
cristy3ed852e2009-09-05 21:47:34 +00001024 {
1025 size_t
1026 quantum;
1027
1028 struct stat
cristye7b28372012-06-17 13:59:06 +00001029 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001030
1031 /*
1032 Stream is not seekable.
1033 */
cristyd1561652014-01-24 11:13:48 +00001034 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001035 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001036 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1037 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001038 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001039 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1040 for (i=0; blob != (unsigned char *) NULL; i+=count)
1041 {
cristy65d11e42013-06-14 20:06:25 +00001042 count=read(file,blob+i,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001043 if (count <= 0)
1044 {
1045 count=0;
1046 if (errno != EINTR)
1047 break;
1048 }
cristy9c66d8c2012-08-10 11:05:36 +00001049 if (~((size_t) i) < (quantum+1))
cristy3ed852e2009-09-05 21:47:34 +00001050 {
1051 blob=(unsigned char *) RelinquishMagickMemory(blob);
1052 break;
1053 }
1054 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1055 sizeof(*blob));
1056 if ((size_t) (i+count) >= extent)
1057 break;
1058 }
cristy54439632010-07-15 00:43:34 +00001059 if (LocaleCompare(filename,"-") != 0)
1060 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001061 if (blob == (unsigned char *) NULL)
1062 {
1063 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001064 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001065 return((unsigned char *) NULL);
1066 }
cristya7cb4312010-06-26 00:47:03 +00001067 if (file == -1)
1068 {
1069 blob=(unsigned char *) RelinquishMagickMemory(blob);
1070 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1071 return((unsigned char *) NULL);
1072 }
cristy7753b2a2011-02-19 18:36:52 +00001073 *length=(size_t) MagickMin(i+count,extent);
cristy3ed852e2009-09-05 21:47:34 +00001074 blob[*length]='\0';
1075 return(blob);
1076 }
cristy7753b2a2011-02-19 18:36:52 +00001077 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
cristy3ed852e2009-09-05 21:47:34 +00001078 blob=(unsigned char *) NULL;
cristy37e0b382011-06-07 13:31:21 +00001079 if (~(*length) >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +00001080 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1081 sizeof(*blob));
1082 if (blob == (unsigned char *) NULL)
1083 {
cristy54439632010-07-15 00:43:34 +00001084 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001085 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001086 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001087 return((unsigned char *) NULL);
1088 }
1089 map=MapBlob(file,ReadMode,0,*length);
1090 if (map != (unsigned char *) NULL)
1091 {
cristy54aad5e2010-09-03 16:02:04 +00001092 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +00001093 (void) UnmapBlob(map,*length);
1094 }
1095 else
1096 {
cristy7f317702011-02-18 20:40:28 +00001097 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001098 for (i=0; i < *length; i+=count)
1099 {
cristy65d11e42013-06-14 20:06:25 +00001100 count=read(file,blob+i,(size_t) MagickMin(*length-i,(MagickSizeType)
1101 SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001102 if (count <= 0)
1103 {
1104 count=0;
1105 if (errno != EINTR)
1106 break;
1107 }
1108 }
1109 if (i < *length)
1110 {
1111 file=close(file)-1;
1112 blob=(unsigned char *) RelinquishMagickMemory(blob);
1113 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1114 return((unsigned char *) NULL);
1115 }
1116 }
cristy3ed852e2009-09-05 21:47:34 +00001117 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001118 if (LocaleCompare(filename,"-") != 0)
1119 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001120 if (file == -1)
1121 {
1122 blob=(unsigned char *) RelinquishMagickMemory(blob);
1123 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1124 }
cristy3ed852e2009-09-05 21:47:34 +00001125 return(blob);
1126}
1127
1128/*
1129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1130% %
1131% %
1132% %
1133% F i l e T o I m a g e %
1134% %
1135% %
1136% %
1137%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1138%
1139% FileToImage() write the contents of a file to an image.
1140%
1141% The format of the FileToImage method is:
1142%
1143% MagickBooleanType FileToImage(Image *,const char *filename)
1144%
1145% A description of each parameter follows:
1146%
1147% o image: the image.
1148%
1149% o filename: the filename.
1150%
1151*/
1152
1153static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1154 const unsigned char *data)
1155{
1156 MagickSizeType
1157 extent;
1158
1159 register unsigned char
1160 *q;
1161
1162 assert(image->blob != (BlobInfo *) NULL);
1163 if (image->blob->type != BlobStream)
1164 return(WriteBlob(image,length,data));
1165 assert(image->blob->type != UndefinedStream);
1166 assert(data != (void *) NULL);
1167 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1168 if (extent >= image->blob->extent)
1169 {
cristy3ed852e2009-09-05 21:47:34 +00001170 extent=image->blob->extent+image->blob->quantum+length;
cristyff368632014-01-27 13:01:38 +00001171 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00001172 if (SetBlobExtent(image,extent) == MagickFalse)
1173 return(0);
1174 }
1175 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001176 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001177 image->blob->offset+=length;
1178 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1179 image->blob->length=(size_t) image->blob->offset;
1180 return((ssize_t) length);
1181}
1182
cristyc82a27b2011-10-21 01:07:16 +00001183MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1184 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001185{
1186 int
1187 file;
1188
1189 size_t
1190 length,
1191 quantum;
1192
1193 ssize_t
1194 count;
1195
1196 struct stat
cristye7b28372012-06-17 13:59:06 +00001197 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001198
1199 unsigned char
1200 *blob;
1201
1202 assert(image != (const Image *) NULL);
1203 assert(image->signature == MagickSignature);
1204 assert(filename != (const char *) NULL);
1205 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
cristyd45808f2012-12-14 21:30:35 +00001206 file=fileno(stdin);
1207 if (LocaleCompare(filename,"-") != 0)
1208 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001209 if (file == -1)
1210 {
cristyc82a27b2011-10-21 01:07:16 +00001211 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001212 return(MagickFalse);
1213 }
1214 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001215 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1216 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001217 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1218 if (blob == (unsigned char *) NULL)
1219 {
cristy100a0562014-04-18 01:27:37 +00001220 file=close(file);
cristyc82a27b2011-10-21 01:07:16 +00001221 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1222 filename);
cristy3ed852e2009-09-05 21:47:34 +00001223 return(MagickFalse);
1224 }
1225 for ( ; ; )
1226 {
cristy65d11e42013-06-14 20:06:25 +00001227 count=read(file,blob,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001228 if (count <= 0)
1229 {
1230 count=0;
1231 if (errno != EINTR)
1232 break;
1233 }
1234 length=(size_t) count;
1235 count=WriteBlobStream(image,length,blob);
1236 if (count != (ssize_t) length)
1237 {
cristyc82a27b2011-10-21 01:07:16 +00001238 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001239 break;
1240 }
1241 }
cristya7cb4312010-06-26 00:47:03 +00001242 file=close(file);
1243 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001244 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001245 blob=(unsigned char *) RelinquishMagickMemory(blob);
1246 return(MagickTrue);
1247}
dirk54fae512014-09-19 20:58:22 +00001248
1249
cristy3ed852e2009-09-05 21:47:34 +00001250/*
1251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1252% %
1253% %
1254% %
1255+ G e t B l o b E r r o r %
1256% %
1257% %
1258% %
1259%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1260%
1261% GetBlobError() returns MagickTrue if the blob associated with the specified
1262% image encountered an error.
1263%
1264% The format of the GetBlobError method is:
1265%
1266% MagickBooleanType GetBlobError(const Image *image)
1267%
1268% A description of each parameter follows:
1269%
1270% o image: the image.
1271%
1272*/
cristy7832dc22011-09-05 01:21:53 +00001273MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001274{
1275 assert(image != (const Image *) NULL);
1276 assert(image->signature == MagickSignature);
1277 if (image->debug != MagickFalse)
1278 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1279 return(image->blob->status);
1280}
1281
1282/*
1283%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1284% %
1285% %
1286% %
1287+ G e t B l o b F i l e H a n d l e %
1288% %
1289% %
1290% %
1291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1292%
1293% GetBlobFileHandle() returns the file handle associated with the image blob.
1294%
1295% The format of the GetBlobFile method is:
1296%
1297% FILE *GetBlobFileHandle(const Image *image)
1298%
1299% A description of each parameter follows:
1300%
1301% o image: the image.
1302%
1303*/
1304MagickExport FILE *GetBlobFileHandle(const Image *image)
1305{
1306 assert(image != (const Image *) NULL);
1307 assert(image->signature == MagickSignature);
cristye7b28372012-06-17 13:59:06 +00001308 return(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001309}
1310
1311/*
1312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1313% %
1314% %
1315% %
1316+ G e t B l o b I n f o %
1317% %
1318% %
1319% %
1320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1321%
1322% GetBlobInfo() initializes the BlobInfo structure.
1323%
1324% The format of the GetBlobInfo method is:
1325%
1326% void GetBlobInfo(BlobInfo *blob_info)
1327%
1328% A description of each parameter follows:
1329%
1330% o blob_info: Specifies a pointer to a BlobInfo structure.
1331%
1332*/
cristy7832dc22011-09-05 01:21:53 +00001333MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001334{
1335 assert(blob_info != (BlobInfo *) NULL);
1336 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1337 blob_info->type=UndefinedStream;
1338 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1339 blob_info->properties.st_mtime=time((time_t *) NULL);
1340 blob_info->properties.st_ctime=time((time_t *) NULL);
1341 blob_info->debug=IsEventLogging();
1342 blob_info->reference_count=1;
cristy3d162a92014-02-16 14:05:06 +00001343 blob_info->semaphore=AcquireSemaphoreInfo();
cristy3ed852e2009-09-05 21:47:34 +00001344 blob_info->signature=MagickSignature;
1345}
1346
1347/*
1348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1349% %
1350% %
1351% %
1352% G e t B l o b P r o p e r t i e s %
1353% %
1354% %
1355% %
1356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1357%
1358% GetBlobProperties() returns information about an image blob.
1359%
1360% The format of the GetBlobProperties method is:
1361%
1362% const struct stat *GetBlobProperties(const Image *image)
1363%
1364% A description of each parameter follows:
1365%
1366% o image: the image.
1367%
1368*/
cristy7832dc22011-09-05 01:21:53 +00001369MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001370{
1371 assert(image != (Image *) NULL);
1372 assert(image->signature == MagickSignature);
1373 if (image->debug != MagickFalse)
1374 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1375 return(&image->blob->properties);
1376}
1377
1378/*
1379%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1380% %
1381% %
1382% %
1383+ G e t B l o b S i z e %
1384% %
1385% %
1386% %
1387%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1388%
1389% GetBlobSize() returns the current length of the image file or blob; zero is
1390% returned if the size cannot be determined.
1391%
1392% The format of the GetBlobSize method is:
1393%
1394% MagickSizeType GetBlobSize(const Image *image)
1395%
1396% A description of each parameter follows:
1397%
1398% o image: the image.
1399%
1400*/
1401MagickExport MagickSizeType GetBlobSize(const Image *image)
1402{
1403 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001404 extent;
cristy3ed852e2009-09-05 21:47:34 +00001405
1406 assert(image != (Image *) NULL);
1407 assert(image->signature == MagickSignature);
1408 if (image->debug != MagickFalse)
1409 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1410 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001411 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001412 switch (image->blob->type)
1413 {
1414 case UndefinedStream:
1415 {
cristy81b8ce52010-02-05 01:53:17 +00001416 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001417 break;
1418 }
cristybc20d112012-07-29 20:27:00 +00001419 case StandardStream:
1420 {
1421 extent=image->blob->size;
1422 break;
1423 }
cristy3ed852e2009-09-05 21:47:34 +00001424 case FileStream:
1425 {
cristye7b28372012-06-17 13:59:06 +00001426 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001427 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001428 break;
1429 }
cristy3ed852e2009-09-05 21:47:34 +00001430 case PipeStream:
1431 {
cristy81b8ce52010-02-05 01:53:17 +00001432 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001433 break;
1434 }
1435 case ZipStream:
1436 case BZipStream:
1437 {
1438 MagickBooleanType
1439 status;
1440
1441 status=GetPathAttributes(image->filename,&image->blob->properties);
1442 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001443 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001444 break;
1445 }
1446 case FifoStream:
1447 break;
1448 case BlobStream:
1449 {
cristy891dc792010-03-04 01:47:16 +00001450 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001451 break;
1452 }
1453 }
cristy81b8ce52010-02-05 01:53:17 +00001454 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001455}
1456
1457/*
1458%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1459% %
1460% %
1461% %
1462+ G e t B l o b S t r e a m D a t a %
1463% %
1464% %
1465% %
1466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1467%
1468% GetBlobStreamData() returns the stream data for the image.
1469%
1470% The format of the GetBlobStreamData method is:
1471%
1472% unsigned char *GetBlobStreamData(const Image *image)
1473%
1474% A description of each parameter follows:
1475%
1476% o image: the image.
1477%
1478*/
1479MagickExport unsigned char *GetBlobStreamData(const Image *image)
1480{
1481 assert(image != (const Image *) NULL);
1482 assert(image->signature == MagickSignature);
1483 return(image->blob->data);
1484}
1485
1486/*
1487%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1488% %
1489% %
1490% %
1491+ G e t B l o b S t r e a m H a n d l e r %
1492% %
1493% %
1494% %
1495%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1496%
1497% GetBlobStreamHandler() returns the stream handler for the image.
1498%
1499% The format of the GetBlobStreamHandler method is:
1500%
1501% StreamHandler GetBlobStreamHandler(const Image *image)
1502%
1503% A description of each parameter follows:
1504%
1505% o image: the image.
1506%
1507*/
cristy7832dc22011-09-05 01:21:53 +00001508MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001509{
1510 assert(image != (const Image *) NULL);
1511 assert(image->signature == MagickSignature);
1512 if (image->debug != MagickFalse)
1513 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1514 return(image->blob->stream);
1515}
1516
1517/*
1518%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1519% %
1520% %
1521% %
1522% I m a g e T o B l o b %
1523% %
1524% %
1525% %
1526%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527%
1528% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001529% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001530% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001531% etc.). This method is the equivalent of WriteImage(), but writes the
1532% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001533%
1534% The format of the ImageToBlob method is:
1535%
1536% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1537% size_t *length,ExceptionInfo *exception)
1538%
1539% A description of each parameter follows:
1540%
1541% o image_info: the image info.
1542%
1543% o image: the image.
1544%
cristyd7dc7df2014-01-26 13:52:14 +00001545% o length: return the actual length of the blob.
cristy3ed852e2009-09-05 21:47:34 +00001546%
1547% o exception: return any errors or warnings in this structure.
1548%
1549*/
1550MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1551 Image *image,size_t *length,ExceptionInfo *exception)
1552{
1553 const MagickInfo
1554 *magick_info;
1555
1556 ImageInfo
1557 *blob_info;
1558
1559 MagickBooleanType
1560 status;
1561
1562 unsigned char
1563 *blob;
1564
1565 assert(image_info != (const ImageInfo *) NULL);
1566 assert(image_info->signature == MagickSignature);
1567 if (image_info->debug != MagickFalse)
1568 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1569 image_info->filename);
1570 assert(image != (Image *) NULL);
1571 assert(image->signature == MagickSignature);
1572 assert(exception != (ExceptionInfo *) NULL);
1573 *length=0;
1574 blob=(unsigned char *) NULL;
1575 blob_info=CloneImageInfo(image_info);
1576 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001577 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001578 if (*blob_info->magick != '\0')
1579 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1580 magick_info=GetMagickInfo(image->magick,exception);
1581 if (magick_info == (const MagickInfo *) NULL)
1582 {
1583 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001584 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +00001585 image->magick);
1586 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +00001587 return(blob);
1588 }
1589 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1590 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1591 {
1592 /*
1593 Native blob support for this image format.
1594 */
cristy5facf772014-01-26 14:42:57 +00001595 blob_info->length=0;
1596 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1597 sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001598 if (blob_info->blob == (void *) NULL)
1599 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001600 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001601 else
1602 {
1603 (void) CloseBlob(image);
1604 image->blob->exempt=MagickTrue;
1605 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001606 status=WriteImage(blob_info,image,exception);
cristy5facf772014-01-26 14:42:57 +00001607 *length=image->blob->length;
cristyc42554f2012-08-22 12:00:43 +00001608 blob=DetachBlob(image->blob);
cristy6e50f9e2012-08-22 16:30:29 +00001609 if (status == MagickFalse)
1610 blob=(unsigned char *) RelinquishMagickMemory(blob);
1611 else
cristy7a7eb372014-01-25 23:09:10 +00001612 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1613 sizeof(*blob));
cristy3ed852e2009-09-05 21:47:34 +00001614 }
1615 }
1616 else
1617 {
1618 char
1619 unique[MaxTextExtent];
1620
1621 int
1622 file;
1623
1624 /*
1625 Write file to disk in blob image format.
1626 */
1627 file=AcquireUniqueFileResource(unique);
1628 if (file == -1)
1629 {
1630 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1631 image_info->filename);
1632 }
1633 else
1634 {
1635 blob_info->file=fdopen(file,"wb");
1636 if (blob_info->file != (FILE *) NULL)
1637 {
cristyb51dff52011-05-19 16:55:47 +00001638 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001639 image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001640 status=WriteImage(blob_info,image,exception);
dirk607010e2014-03-01 19:08:11 +00001641 (void) CloseBlob(image);
1642 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001643 if (status != MagickFalse)
cristy2c1b6e02014-01-26 15:03:02 +00001644 blob=FileToBlob(unique,~0UL,length,exception);
cristy3ed852e2009-09-05 21:47:34 +00001645 }
1646 (void) RelinquishUniqueFileResource(unique);
1647 }
1648 }
1649 blob_info=DestroyImageInfo(blob_info);
1650 return(blob);
1651}
1652
1653/*
1654%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1655% %
1656% %
1657% %
1658% I m a g e T o F i l e %
1659% %
1660% %
1661% %
1662%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1663%
1664% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1665% occurs otherwise MagickTrue.
1666%
1667% The format of the ImageToFile method is:
1668%
1669% MagickBooleanType ImageToFile(Image *image,char *filename,
1670% ExceptionInfo *exception)
1671%
1672% A description of each parameter follows:
1673%
1674% o image: the image.
1675%
1676% o filename: Write the image to this file.
1677%
1678% o exception: return any errors or warnings in this structure.
1679%
1680*/
cristy3ed852e2009-09-05 21:47:34 +00001681MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1682 ExceptionInfo *exception)
1683{
1684 int
1685 file;
1686
1687 register const unsigned char
1688 *p;
1689
1690 register size_t
1691 i;
1692
1693 size_t
1694 length,
1695 quantum;
1696
1697 ssize_t
1698 count;
1699
1700 struct stat
cristye7b28372012-06-17 13:59:06 +00001701 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001702
1703 unsigned char
1704 *buffer;
1705
1706 assert(image != (Image *) NULL);
1707 assert(image->signature == MagickSignature);
1708 assert(image->blob != (BlobInfo *) NULL);
1709 assert(image->blob->type != UndefinedStream);
1710 if (image->debug != MagickFalse)
1711 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1712 assert(filename != (const char *) NULL);
1713 if (*filename == '\0')
1714 file=AcquireUniqueFileResource(filename);
1715 else
1716 if (LocaleCompare(filename,"-") == 0)
1717 file=fileno(stdout);
1718 else
cristyb70aab92012-01-31 15:04:04 +00001719 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001720 if (file == -1)
1721 {
1722 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1723 return(MagickFalse);
1724 }
1725 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001726 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1727 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001728 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001729 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1730 if (buffer == (unsigned char *) NULL)
1731 {
1732 file=close(file)-1;
1733 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001734 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001735 return(MagickFalse);
1736 }
1737 length=0;
1738 p=ReadBlobStream(image,quantum,buffer,&count);
1739 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1740 {
1741 length=(size_t) count;
1742 for (i=0; i < length; i+=count)
1743 {
1744 count=write(file,p+i,(size_t) (length-i));
1745 if (count <= 0)
1746 {
1747 count=0;
1748 if (errno != EINTR)
1749 break;
1750 }
1751 }
1752 if (i < length)
1753 break;
1754 }
cristy54439632010-07-15 00:43:34 +00001755 if (LocaleCompare(filename,"-") != 0)
1756 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001757 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001758 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001759 {
cristye3216eb2014-04-18 17:10:21 +00001760 if (file != -1)
cristy100a0562014-04-18 01:27:37 +00001761 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001762 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1763 return(MagickFalse);
1764 }
1765 return(MagickTrue);
1766}
1767
1768/*
1769%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1770% %
1771% %
1772% %
1773% I m a g e s T o B l o b %
1774% %
1775% %
1776% %
1777%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1778%
1779% ImagesToBlob() implements direct to memory image formats. It returns the
1780% image sequence as a blob and its length. The magick member of the ImageInfo
1781% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1782%
1783% Note, some image formats do not permit multiple images to the same image
1784% stream (e.g. JPEG). in this instance, just the first image of the
1785% sequence is returned as a blob.
1786%
1787% The format of the ImagesToBlob method is:
1788%
1789% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1790% size_t *length,ExceptionInfo *exception)
1791%
1792% A description of each parameter follows:
1793%
1794% o image_info: the image info.
1795%
1796% o images: the image list.
1797%
cristybb85d6a2014-01-26 13:51:09 +00001798% o length: return the actual length of the blob.
cristy3ed852e2009-09-05 21:47:34 +00001799%
1800% o exception: return any errors or warnings in this structure.
1801%
1802*/
1803MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1804 Image *images,size_t *length,ExceptionInfo *exception)
1805{
1806 const MagickInfo
1807 *magick_info;
1808
1809 ImageInfo
1810 *blob_info;
1811
1812 MagickBooleanType
1813 status;
1814
1815 unsigned char
1816 *blob;
1817
1818 assert(image_info != (const ImageInfo *) NULL);
1819 assert(image_info->signature == MagickSignature);
1820 if (image_info->debug != MagickFalse)
1821 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1822 image_info->filename);
1823 assert(images != (Image *) NULL);
1824 assert(images->signature == MagickSignature);
1825 assert(exception != (ExceptionInfo *) NULL);
1826 *length=0;
1827 blob=(unsigned char *) NULL;
1828 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001829 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1830 exception);
cristy3ed852e2009-09-05 21:47:34 +00001831 if (*blob_info->magick != '\0')
1832 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00001833 magick_info=GetMagickInfo(images->magick,exception);
1834 if (magick_info == (const MagickInfo *) NULL)
1835 {
1836 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001837 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
dirkea8856e2014-04-09 16:44:40 +00001838 images->magick);
1839 blob_info=DestroyImageInfo(blob_info);
cristy3ed852e2009-09-05 21:47:34 +00001840 return(blob);
1841 }
cristy4f1f3e82014-01-26 15:25:52 +00001842 if (GetMagickAdjoin(magick_info) == MagickFalse)
1843 {
1844 blob_info=DestroyImageInfo(blob_info);
1845 return(ImageToBlob(image_info,images,length,exception));
1846 }
cristy3ed852e2009-09-05 21:47:34 +00001847 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1848 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1849 {
1850 /*
1851 Native blob support for this images format.
1852 */
cristy5facf772014-01-26 14:42:57 +00001853 blob_info->length=0;
1854 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1855 sizeof(unsigned char));
cristy3ed852e2009-09-05 21:47:34 +00001856 if (blob_info->blob == (void *) NULL)
1857 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001858 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
cristy3ed852e2009-09-05 21:47:34 +00001859 else
1860 {
cristy7a4b8c52014-01-25 22:48:06 +00001861 (void) CloseBlob(images);
cristy3ed852e2009-09-05 21:47:34 +00001862 images->blob->exempt=MagickTrue;
1863 *images->filename='\0';
1864 status=WriteImages(blob_info,images,images->filename,exception);
cristy5facf772014-01-26 14:42:57 +00001865 *length=images->blob->length;
cristy7a4b8c52014-01-25 22:48:06 +00001866 blob=DetachBlob(images->blob);
1867 if (status == MagickFalse)
1868 blob=(unsigned char *) RelinquishMagickMemory(blob);
1869 else
cristy7a7eb372014-01-25 23:09:10 +00001870 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1871 sizeof(*blob));
cristy3ed852e2009-09-05 21:47:34 +00001872 }
1873 }
1874 else
1875 {
1876 char
1877 filename[MaxTextExtent],
1878 unique[MaxTextExtent];
1879
1880 int
1881 file;
1882
1883 /*
1884 Write file to disk in blob images format.
1885 */
1886 file=AcquireUniqueFileResource(unique);
1887 if (file == -1)
1888 {
1889 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1890 image_info->filename);
1891 }
1892 else
1893 {
1894 blob_info->file=fdopen(file,"wb");
1895 if (blob_info->file != (FILE *) NULL)
1896 {
cristyb51dff52011-05-19 16:55:47 +00001897 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001898 images->magick,unique);
1899 status=WriteImages(blob_info,images,filename,exception);
dirk607010e2014-03-01 19:08:11 +00001900 (void) CloseBlob(images);
cristya94f31b2014-03-01 13:25:42 +00001901 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001902 if (status != MagickFalse)
cristy2c1b6e02014-01-26 15:03:02 +00001903 blob=FileToBlob(unique,~0UL,length,exception);
cristy3ed852e2009-09-05 21:47:34 +00001904 }
1905 (void) RelinquishUniqueFileResource(unique);
1906 }
1907 }
1908 blob_info=DestroyImageInfo(blob_info);
1909 return(blob);
1910}
1911/*
1912%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1913% %
1914% %
1915% %
1916% I n j e c t I m a g e B l o b %
1917% %
1918% %
1919% %
1920%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1921%
1922% InjectImageBlob() injects the image with a copy of itself in the specified
1923% format (e.g. inject JPEG into a PDF image).
1924%
1925% The format of the InjectImageBlob method is:
1926%
1927% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1928% Image *image,Image *inject_image,const char *format,
1929% ExceptionInfo *exception)
1930%
1931% A description of each parameter follows:
1932%
1933% o image_info: the image info..
1934%
1935% o image: the image.
1936%
1937% o inject_image: inject into the image stream.
1938%
1939% o format: the image format.
1940%
1941% o exception: return any errors or warnings in this structure.
1942%
1943*/
1944MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1945 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1946{
1947 char
1948 filename[MaxTextExtent];
1949
1950 FILE
1951 *unique_file;
1952
1953 Image
1954 *byte_image;
1955
1956 ImageInfo
1957 *write_info;
1958
1959 int
1960 file;
1961
1962 MagickBooleanType
1963 status;
1964
cristybb503372010-05-27 20:51:26 +00001965 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001966 i;
1967
1968 size_t
1969 quantum;
1970
1971 ssize_t
1972 count;
1973
1974 struct stat
cristye7b28372012-06-17 13:59:06 +00001975 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001976
1977 unsigned char
1978 *buffer;
1979
1980 /*
1981 Write inject image to a temporary file.
1982 */
1983 assert(image_info != (ImageInfo *) NULL);
1984 assert(image_info->signature == MagickSignature);
1985 assert(image != (Image *) NULL);
1986 assert(image->signature == MagickSignature);
1987 if (image->debug != MagickFalse)
1988 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1989 assert(inject_image != (Image *) NULL);
1990 assert(inject_image->signature == MagickSignature);
1991 assert(exception != (ExceptionInfo *) NULL);
1992 unique_file=(FILE *) NULL;
1993 file=AcquireUniqueFileResource(filename);
1994 if (file != -1)
1995 unique_file=fdopen(file,"wb");
1996 if ((file == -1) || (unique_file == (FILE *) NULL))
1997 {
1998 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1999 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2000 image->filename);
2001 return(MagickFalse);
2002 }
2003 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2004 if (byte_image == (Image *) NULL)
2005 {
2006 (void) fclose(unique_file);
2007 (void) RelinquishUniqueFileResource(filename);
2008 return(MagickFalse);
2009 }
cristyb51dff52011-05-19 16:55:47 +00002010 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00002011 filename);
2012 DestroyBlob(byte_image);
2013 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2014 write_info=CloneImageInfo(image_info);
2015 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00002016 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002017 write_info=DestroyImageInfo(write_info);
2018 byte_image=DestroyImage(byte_image);
2019 (void) fclose(unique_file);
2020 if (status == MagickFalse)
2021 {
2022 (void) RelinquishUniqueFileResource(filename);
2023 return(MagickFalse);
2024 }
2025 /*
2026 Inject into image stream.
2027 */
cristy18c6c272011-09-23 14:40:37 +00002028 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00002029 if (file == -1)
2030 {
2031 (void) RelinquishUniqueFileResource(filename);
2032 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2033 image_info->filename);
2034 return(MagickFalse);
2035 }
2036 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00002037 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
2038 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00002039 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2040 if (buffer == (unsigned char *) NULL)
2041 {
2042 (void) RelinquishUniqueFileResource(filename);
2043 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2044 image->filename);
2045 }
2046 for (i=0; ; i+=count)
2047 {
cristy65d11e42013-06-14 20:06:25 +00002048 count=read(file,buffer,quantum);
cristy3ed852e2009-09-05 21:47:34 +00002049 if (count <= 0)
2050 {
2051 count=0;
2052 if (errno != EINTR)
2053 break;
2054 }
2055 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2056 MagickFalse;
2057 }
cristya7cb4312010-06-26 00:47:03 +00002058 file=close(file);
2059 if (file == -1)
2060 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00002061 (void) RelinquishUniqueFileResource(filename);
2062 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2063 return(status);
2064}
2065
2066/*
2067%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2068% %
2069% %
2070% %
2071+ I s B l o b E x e m p t %
2072% %
2073% %
2074% %
2075%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2076%
2077% IsBlobExempt() returns true if the blob is exempt.
2078%
2079% The format of the IsBlobExempt method is:
2080%
2081% MagickBooleanType IsBlobExempt(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 IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002089{
2090 assert(image != (const Image *) NULL);
2091 assert(image->signature == MagickSignature);
2092 if (image->debug != MagickFalse)
2093 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2094 return(image->blob->exempt);
2095}
2096
2097/*
2098%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2099% %
2100% %
2101% %
2102+ I s B l o b S e e k a b l e %
2103% %
2104% %
2105% %
2106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2107%
2108% IsBlobSeekable() returns true if the blob is seekable.
2109%
2110% The format of the IsBlobSeekable method is:
2111%
2112% MagickBooleanType IsBlobSeekable(const Image *image)
2113%
2114% A description of each parameter follows:
2115%
2116% o image: the image.
2117%
2118*/
cristy7832dc22011-09-05 01:21:53 +00002119MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002120{
2121 MagickBooleanType
2122 seekable;
2123
2124 assert(image != (const Image *) NULL);
2125 assert(image->signature == MagickSignature);
2126 if (image->debug != MagickFalse)
2127 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002128 switch (image->blob->type)
2129 {
2130 case FileStream:
2131 case BlobStream:
2132 case ZipStream:
2133 {
2134 seekable=MagickTrue;
2135 break;
2136 }
2137 default:
2138 {
2139 seekable=MagickFalse;
2140 break;
2141 }
2142 }
cristy3ed852e2009-09-05 21:47:34 +00002143 return(seekable);
2144}
2145
2146/*
2147%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2148% %
2149% %
2150% %
2151+ I s B l o b T e m p o r a r y %
2152% %
2153% %
2154% %
2155%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2156%
2157% IsBlobTemporary() returns true if the blob is temporary.
2158%
2159% The format of the IsBlobTemporary method is:
2160%
2161% MagickBooleanType IsBlobTemporary(const Image *image)
2162%
2163% A description of each parameter follows:
2164%
2165% o image: the image.
2166%
2167*/
cristy7832dc22011-09-05 01:21:53 +00002168MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002169{
2170 assert(image != (const Image *) NULL);
2171 assert(image->signature == MagickSignature);
2172 if (image->debug != MagickFalse)
2173 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2174 return(image->blob->temporary);
2175}
2176
2177/*
2178%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2179% %
2180% %
2181% %
2182+ M a p B l o b %
2183% %
2184% %
2185% %
2186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2187%
2188% MapBlob() creates a mapping from a file to a binary large object.
2189%
2190% The format of the MapBlob method is:
2191%
2192% unsigned char *MapBlob(int file,const MapMode mode,
2193% const MagickOffsetType offset,const size_t length)
2194%
2195% A description of each parameter follows:
2196%
2197% o file: map this file descriptor.
2198%
2199% o mode: ReadMode, WriteMode, or IOMode.
2200%
2201% o offset: starting at this offset within the file.
2202%
2203% o length: the length of the mapping is returned in this pointer.
2204%
2205*/
2206MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2207 const MagickOffsetType offset,const size_t length)
2208{
cristydc8ea8e2013-07-28 20:10:44 +00002209#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00002210 int
2211 flags,
2212 protection;
2213
2214 unsigned char
2215 *map;
2216
2217 /*
2218 Map file.
2219 */
2220 flags=0;
2221 if (file == -1)
2222#if defined(MAP_ANONYMOUS)
2223 flags|=MAP_ANONYMOUS;
2224#else
2225 return((unsigned char *) NULL);
2226#endif
2227 switch (mode)
2228 {
2229 case ReadMode:
2230 default:
2231 {
2232 protection=PROT_READ;
2233 flags|=MAP_PRIVATE;
cristy3ed852e2009-09-05 21:47:34 +00002234 break;
2235 }
2236 case WriteMode:
2237 {
2238 protection=PROT_WRITE;
2239 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002240 break;
2241 }
2242 case IOMode:
2243 {
2244 protection=PROT_READ | PROT_WRITE;
2245 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002246 break;
2247 }
2248 }
cristy56a0dbe2013-07-09 15:27:09 +00002249#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2250 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2251 (off_t) offset);
2252#else
cristy7a4b8c52014-01-25 22:48:06 +00002253 map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
cristy56a0dbe2013-07-09 15:27:09 +00002254 MAP_HUGETLB,file,(off_t) offset);
2255 if (map == (unsigned char *) MAP_FAILED)
2256 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2257 (off_t) offset);
2258#endif
cristy3ed852e2009-09-05 21:47:34 +00002259 if (map == (unsigned char *) MAP_FAILED)
2260 return((unsigned char *) NULL);
2261 return(map);
2262#else
2263 (void) file;
2264 (void) mode;
2265 (void) offset;
2266 (void) length;
2267 return((unsigned char *) NULL);
2268#endif
2269}
2270
2271/*
2272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2273% %
2274% %
2275% %
2276+ M S B O r d e r L o n g %
2277% %
2278% %
2279% %
2280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2281%
2282% MSBOrderLong() converts a least-significant byte first buffer of integers to
2283% most-significant byte first.
2284%
2285% The format of the MSBOrderLong method is:
2286%
2287% void MSBOrderLong(unsigned char *buffer,const size_t length)
2288%
2289% A description of each parameter follows.
2290%
2291% o buffer: Specifies a pointer to a buffer of integers.
2292%
2293% o length: Specifies the length of the buffer.
2294%
2295*/
2296MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2297{
2298 int
2299 c;
2300
2301 register unsigned char
2302 *p,
2303 *q;
2304
2305 assert(buffer != (unsigned char *) NULL);
2306 q=buffer+length;
2307 while (buffer < q)
2308 {
2309 p=buffer+3;
2310 c=(int) (*p);
2311 *p=(*buffer);
2312 *buffer++=(unsigned char) c;
2313 p=buffer+1;
2314 c=(int) (*p);
2315 *p=(*buffer);
2316 *buffer++=(unsigned char) c;
2317 buffer+=2;
2318 }
2319}
2320
2321/*
2322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2323% %
2324% %
2325% %
2326+ M S B O r d e r S h o r t %
2327% %
2328% %
2329% %
2330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2331%
2332% MSBOrderShort() converts a least-significant byte first buffer of integers
2333% to most-significant byte first.
2334%
2335% The format of the MSBOrderShort method is:
2336%
2337% void MSBOrderShort(unsigned char *p,const size_t length)
2338%
2339% A description of each parameter follows.
2340%
2341% o p: Specifies a pointer to a buffer of integers.
2342%
2343% o length: Specifies the length of the buffer.
2344%
2345*/
2346MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2347{
2348 int
2349 c;
2350
2351 register unsigned char
2352 *q;
2353
2354 assert(p != (unsigned char *) NULL);
2355 q=p+length;
2356 while (p < q)
2357 {
2358 c=(int) (*p);
2359 *p=(*(p+1));
2360 p++;
2361 *p++=(unsigned char) c;
2362 }
2363}
2364
2365/*
2366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2367% %
2368% %
2369% %
2370+ O p e n B l o b %
2371% %
2372% %
2373% %
2374%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2375%
2376% OpenBlob() opens a file associated with the image. A file name of '-' sets
2377% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2378% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2379% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2380% from a system command.
2381%
2382% The format of the OpenBlob method is:
2383%
2384% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2385% const BlobMode mode,ExceptionInfo *exception)
2386%
2387% A description of each parameter follows:
2388%
2389% o image_info: the image info.
2390%
2391% o image: the image.
2392%
2393% o mode: the mode for opening the file.
2394%
2395*/
2396MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2397 Image *image,const BlobMode mode,ExceptionInfo *exception)
2398{
2399 char
cristybf6a7092010-06-11 02:12:15 +00002400 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002401 filename[MaxTextExtent];
2402
2403 const char
2404 *type;
2405
2406 MagickBooleanType
2407 status;
2408
2409 PolicyRights
2410 rights;
2411
2412 assert(image_info != (ImageInfo *) NULL);
2413 assert(image_info->signature == MagickSignature);
2414 if (image_info->debug != MagickFalse)
2415 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2416 image_info->filename);
2417 assert(image != (Image *) NULL);
2418 assert(image->signature == MagickSignature);
2419 if (image_info->blob != (void *) NULL)
2420 {
2421 if (image_info->stream != (StreamHandler) NULL)
2422 image->blob->stream=(StreamHandler) image_info->stream;
2423 AttachBlob(image->blob,image_info->blob,image_info->length);
2424 return(MagickTrue);
2425 }
2426 (void) DetachBlob(image->blob);
2427 switch (mode)
2428 {
2429 default: type="r"; break;
2430 case ReadBlobMode: type="r"; break;
2431 case ReadBinaryBlobMode: type="rb"; break;
2432 case WriteBlobMode: type="w"; break;
2433 case WriteBinaryBlobMode: type="w+b"; break;
2434 case AppendBlobMode: type="a"; break;
2435 case AppendBinaryBlobMode: type="a+b"; break;
2436 }
2437 if (*type != 'r')
2438 image->blob->synchronize=image_info->synchronize;
2439 if (image_info->stream != (StreamHandler) NULL)
2440 {
2441 image->blob->stream=(StreamHandler) image_info->stream;
2442 if (*type == 'w')
2443 {
2444 image->blob->type=FifoStream;
2445 return(MagickTrue);
2446 }
2447 }
2448 /*
2449 Open image file.
2450 */
2451 *filename='\0';
2452 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2453 rights=ReadPolicyRights;
2454 if (*type == 'w')
2455 rights=WritePolicyRights;
2456 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2457 {
cristya9197f62010-01-12 02:23:34 +00002458 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002459 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
cristyefe601c2013-01-05 17:51:12 +00002460 "NotAuthorized","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00002461 return(MagickFalse);
2462 }
2463 if ((LocaleCompare(filename,"-") == 0) ||
2464 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2465 {
cristye7b28372012-06-17 13:59:06 +00002466 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002467#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002468 if (strchr(type,'b') != (char *) NULL)
cristye7b28372012-06-17 13:59:06 +00002469 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002470#endif
2471 image->blob->type=StandardStream;
2472 image->blob->exempt=MagickTrue;
2473 return(MagickTrue);
2474 }
cristybc20d112012-07-29 20:27:00 +00002475 if (LocaleNCompare(filename,"fd:",3) == 0)
2476 {
2477 char
2478 mode[MaxTextExtent];
2479
2480 *mode=(*type);
2481 mode[1]='\0';
2482 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2483#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2484 if (strchr(type,'b') != (char *) NULL)
2485 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2486#endif
2487 image->blob->type=StandardStream;
2488 image->blob->exempt=MagickTrue;
2489 return(MagickTrue);
2490 }
cristy3ed852e2009-09-05 21:47:34 +00002491#if defined(MAGICKCORE_HAVE_POPEN)
2492 if (*filename == '|')
2493 {
2494 char
2495 mode[MaxTextExtent];
2496
2497 /*
2498 Pipe image to or from a system command.
2499 */
2500#if defined(SIGPIPE)
2501 if (*type == 'w')
2502 (void) signal(SIGPIPE,SIG_IGN);
2503#endif
2504 *mode=(*type);
2505 mode[1]='\0';
cristye7b28372012-06-17 13:59:06 +00002506 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2507 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002508 {
2509 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2510 return(MagickFalse);
2511 }
2512 image->blob->type=PipeStream;
2513 image->blob->exempt=MagickTrue;
2514 return(MagickTrue);
2515 }
2516#endif
2517 status=GetPathAttributes(filename,&image->blob->properties);
2518#if defined(S_ISFIFO)
cristycd8b3312013-12-22 01:51:11 +00002519 if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
cristy3ed852e2009-09-05 21:47:34 +00002520 {
cristye7b28372012-06-17 13:59:06 +00002521 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2522 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002523 {
2524 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2525 return(MagickFalse);
2526 }
2527 image->blob->type=FileStream;
2528 image->blob->exempt=MagickTrue;
2529 return(MagickTrue);
2530 }
2531#endif
cristybf6a7092010-06-11 02:12:15 +00002532 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002533 if (*type == 'w')
2534 {
cristye8939e72010-02-03 17:05:25 +00002535 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002536 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002537 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002538 {
2539 /*
2540 Form filename for multi-part images.
2541 */
2542 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002543 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002544 if ((LocaleCompare(filename,image->filename) == 0) &&
2545 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2546 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002547 {
cristybf7fa0d2010-02-04 00:51:10 +00002548 char
cristybf7fa0d2010-02-04 00:51:10 +00002549 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002550
cristybf7fa0d2010-02-04 00:51:10 +00002551 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002552 if (*extension == '\0')
cristyb51dff52011-05-19 16:55:47 +00002553 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002554 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002555 else
cristyb51dff52011-05-19 16:55:47 +00002556 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002557 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002558 }
2559 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002560#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002561 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002562#endif
cristye8939e72010-02-03 17:05:25 +00002563 }
cristy3ed852e2009-09-05 21:47:34 +00002564 }
cristybf6a7092010-06-11 02:12:15 +00002565 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002566 {
cristye7b28372012-06-17 13:59:06 +00002567 image->blob->file_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002568 image->blob->type=FileStream;
2569 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002570 }
2571 else
cristybf6a7092010-06-11 02:12:15 +00002572 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002573 {
cristye7b28372012-06-17 13:59:06 +00002574 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2575 if (image->blob->file_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002576 {
2577 size_t
cristybf6a7092010-06-11 02:12:15 +00002578 count;
cristy3ed852e2009-09-05 21:47:34 +00002579
cristybf6a7092010-06-11 02:12:15 +00002580 unsigned char
2581 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002582
cristybf6a7092010-06-11 02:12:15 +00002583 image->blob->type=FileStream;
2584#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002585 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2586 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002587#endif
2588 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristye7b28372012-06-17 13:59:06 +00002589 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
cristyae958042013-01-05 15:48:19 +00002590 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
cristy79fe6932012-12-25 00:31:30 +00002591 (void) fflush(image->blob->file_info.file);
cristybf6a7092010-06-11 02:12:15 +00002592 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2593 " read %.20g magic header bytes",(double) count);
2594#if defined(MAGICKCORE_ZLIB_DELEGATE)
2595 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2596 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002597 {
cristy98677002014-04-27 19:33:02 +00002598 if (image->blob->file_info.file != (FILE *) NULL)
2599 (void) fclose(image->blob->file_info.file);
2600 image->blob->file_info.file=(FILE *) NULL;
cristye7b28372012-06-17 13:59:06 +00002601 image->blob->file_info.gzfile=gzopen(filename,type);
2602 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002603 image->blob->type=ZipStream;
2604 }
2605#endif
2606#if defined(MAGICKCORE_BZLIB_DELEGATE)
2607 if (strncmp((char *) magick,"BZh",3) == 0)
2608 {
cristy98677002014-04-27 19:33:02 +00002609 if (image->blob->file_info.file != (FILE *) NULL)
2610 (void) fclose(image->blob->file_info.file);
2611 image->blob->file_info.file=(FILE *) NULL;
cristye7b28372012-06-17 13:59:06 +00002612 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2613 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002614 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002615 }
cristybf6a7092010-06-11 02:12:15 +00002616#endif
cristyc6c589d2010-07-06 01:34:57 +00002617 if (image->blob->type == FileStream)
2618 {
2619 const MagickInfo
2620 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002621
cristyc6c589d2010-07-06 01:34:57 +00002622 ExceptionInfo
2623 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002624
cristy18aba912013-06-14 19:48:08 +00002625 size_t
2626 length;
2627
cristyc6c589d2010-07-06 01:34:57 +00002628 sans_exception=AcquireExceptionInfo();
2629 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2630 sans_exception=DestroyExceptionInfo(sans_exception);
cristy2eddb3d2013-06-16 14:10:08 +00002631 length=(size_t) image->blob->properties.st_size;
cristyc6c589d2010-07-06 01:34:57 +00002632 if ((magick_info != (const MagickInfo *) NULL) &&
2633 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
cristy7c242ea2013-06-21 17:19:53 +00002634 (length <= MagickMaxBufferExtent) &&
cristy18aba912013-06-14 19:48:08 +00002635 (AcquireMagickResource(MapResource,length) != MagickFalse))
cristyc6c589d2010-07-06 01:34:57 +00002636 {
cristyc6c589d2010-07-06 01:34:57 +00002637 void
2638 *blob;
cristybf6a7092010-06-11 02:12:15 +00002639
cristyfe00ebf2013-06-16 14:17:53 +00002640 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2641 length);
cristy18aba912013-06-14 19:48:08 +00002642 if (blob == (void *) NULL)
2643 RelinquishMagickResource(MapResource,length);
2644 else
cristyc6c589d2010-07-06 01:34:57 +00002645 {
2646 /*
2647 Format supports blobs-- use memory-mapped I/O.
2648 */
2649 if (image_info->file != (FILE *) NULL)
2650 image->blob->exempt=MagickFalse;
2651 else
2652 {
cristye7b28372012-06-17 13:59:06 +00002653 (void) fclose(image->blob->file_info.file);
2654 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002655 }
2656 AttachBlob(image->blob,blob,length);
2657 image->blob->mapped=MagickTrue;
2658 }
2659 }
2660 }
cristy3ed852e2009-09-05 21:47:34 +00002661 }
cristybf6a7092010-06-11 02:12:15 +00002662 }
2663 else
2664#if defined(MAGICKCORE_ZLIB_DELEGATE)
2665 if ((LocaleCompare(extension,"Z") == 0) ||
2666 (LocaleCompare(extension,"gz") == 0) ||
2667 (LocaleCompare(extension,"wmz") == 0) ||
2668 (LocaleCompare(extension,"svgz") == 0))
2669 {
2670 if (mode == WriteBinaryBlobMode)
2671 type="wb";
cristye7b28372012-06-17 13:59:06 +00002672 image->blob->file_info.gzfile=gzopen(filename,type);
2673 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002674 image->blob->type=ZipStream;
2675 }
2676 else
2677#endif
2678#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002679 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002680 {
cristye7b28372012-06-17 13:59:06 +00002681 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2682 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002683 image->blob->type=BZipStream;
2684 }
2685 else
2686#endif
2687 {
cristye7b28372012-06-17 13:59:06 +00002688 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2689 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002690 {
2691 image->blob->type=FileStream;
2692#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002693 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2694 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002695#endif
2696 }
2697 }
cristy3ed852e2009-09-05 21:47:34 +00002698 image->blob->status=MagickFalse;
2699 if (image->blob->type != UndefinedStream)
2700 image->blob->size=GetBlobSize(image);
2701 else
2702 {
2703 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2704 return(MagickFalse);
2705 }
2706 return(MagickTrue);
2707}
2708
2709/*
2710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2711% %
2712% %
2713% %
2714+ P i n g B l o b %
2715% %
2716% %
2717% %
2718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2719%
2720% PingBlob() returns all the attributes of an image or image sequence except
2721% for the pixels. It is much faster and consumes far less memory than
2722% BlobToImage(). On failure, a NULL image is returned and exception
2723% describes the reason for the failure.
2724%
2725% The format of the PingBlob method is:
2726%
2727% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2728% const size_t length,ExceptionInfo *exception)
2729%
2730% A description of each parameter follows:
2731%
2732% o image_info: the image info.
2733%
2734% o blob: the address of a character stream in one of the image formats
2735% understood by ImageMagick.
2736%
2737% o length: This size_t integer reflects the length in bytes of the blob.
2738%
2739% o exception: return any errors or warnings in this structure.
2740%
2741*/
2742
2743#if defined(__cplusplus) || defined(c_plusplus)
2744extern "C" {
2745#endif
2746
2747static size_t PingStream(const Image *magick_unused(image),
2748 const void *magick_unused(pixels),const size_t columns)
2749{
2750 return(columns);
2751}
2752
2753#if defined(__cplusplus) || defined(c_plusplus)
2754}
2755#endif
2756
2757MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2758 const size_t length,ExceptionInfo *exception)
2759{
2760 Image
2761 *image;
2762
2763 ImageInfo
2764 *ping_info;
2765
2766 assert(image_info != (ImageInfo *) NULL);
2767 assert(image_info->signature == MagickSignature);
2768 if (image_info->debug != MagickFalse)
2769 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2770 image_info->filename);
2771 assert(exception != (ExceptionInfo *) NULL);
2772 if ((blob == (const void *) NULL) || (length == 0))
2773 {
2774 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +00002775 "UnrecognizedImageFormat","`%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002776 return((Image *) NULL);
2777 }
2778 ping_info=CloneImageInfo(image_info);
2779 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2780 if (ping_info->blob == (const void *) NULL)
2781 {
2782 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00002783 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002784 return((Image *) NULL);
2785 }
cristy54aad5e2010-09-03 16:02:04 +00002786 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002787 ping_info->length=length;
2788 ping_info->ping=MagickTrue;
2789 image=ReadStream(ping_info,&PingStream,exception);
2790 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2791 ping_info=DestroyImageInfo(ping_info);
2792 return(image);
2793}
2794
2795/*
2796%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2797% %
2798% %
2799% %
2800+ R e a d B l o b %
2801% %
2802% %
2803% %
2804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2805%
2806% ReadBlob() reads data from the blob or image file and returns it. It
cristy5f3d2752013-01-05 18:53:38 +00002807% returns the number of bytes read. If length is zero, ReadBlob() returns
2808% zero and has no other results. If length is greater than SSIZE_MAX, the
2809% result is unspecified.
cristy3ed852e2009-09-05 21:47:34 +00002810%
2811% The format of the ReadBlob method is:
2812%
2813% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2814%
2815% A description of each parameter follows:
2816%
2817% o image: the image.
2818%
2819% o length: Specifies an integer representing the number of bytes to read
2820% from the file.
2821%
2822% o data: Specifies an area to place the information requested from the
2823% file.
2824%
2825*/
2826MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2827 unsigned char *data)
2828{
2829 int
2830 c;
2831
2832 register unsigned char
2833 *q;
2834
2835 ssize_t
2836 count;
2837
2838 assert(image != (Image *) NULL);
2839 assert(image->signature == MagickSignature);
2840 assert(image->blob != (BlobInfo *) NULL);
2841 assert(image->blob->type != UndefinedStream);
2842 if (length == 0)
2843 return(0);
2844 assert(data != (void *) NULL);
2845 count=0;
2846 q=data;
2847 switch (image->blob->type)
2848 {
2849 case UndefinedStream:
2850 break;
cristy3ed852e2009-09-05 21:47:34 +00002851 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002852 {
cristy8faec1e2013-04-25 19:41:22 +00002853 register ssize_t
2854 i;
2855
2856 for (i=0; i < (ssize_t) length; i+=count)
2857 {
cristy7c242ea2013-06-21 17:19:53 +00002858 count=read(fileno(image->blob->file_info.file),q+i,(size_t)
cristy8faec1e2013-04-25 19:41:22 +00002859 MagickMin(length-i,(MagickSizeType) SSIZE_MAX));
2860 if (count <= 0)
2861 {
2862 count=0;
2863 if (errno != EINTR)
2864 break;
2865 }
2866 }
2867 count=i;
cristybc20d112012-07-29 20:27:00 +00002868 break;
2869 }
2870 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002871 case PipeStream:
2872 {
2873 switch (length)
2874 {
2875 default:
2876 {
cristye7b28372012-06-17 13:59:06 +00002877 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002878 break;
2879 }
2880 case 2:
2881 {
cristye7b28372012-06-17 13:59:06 +00002882 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002883 if (c == EOF)
2884 break;
2885 *q++=(unsigned char) c;
2886 count++;
2887 }
2888 case 1:
2889 {
cristye7b28372012-06-17 13:59:06 +00002890 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002891 if (c == EOF)
2892 break;
2893 *q++=(unsigned char) c;
2894 count++;
2895 }
2896 case 0:
2897 break;
2898 }
2899 break;
2900 }
2901 case ZipStream:
2902 {
2903#if defined(MAGICKCORE_ZLIB_DELEGATE)
2904 switch (length)
2905 {
2906 default:
2907 {
cristye7b28372012-06-17 13:59:06 +00002908 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002909 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002910 break;
2911 }
2912 case 2:
2913 {
cristye7b28372012-06-17 13:59:06 +00002914 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002915 if (c == EOF)
2916 break;
2917 *q++=(unsigned char) c;
2918 count++;
2919 }
2920 case 1:
2921 {
cristye7b28372012-06-17 13:59:06 +00002922 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002923 if (c == EOF)
2924 break;
2925 *q++=(unsigned char) c;
2926 count++;
2927 }
2928 case 0:
2929 break;
2930 }
2931#endif
2932 break;
2933 }
2934 case BZipStream:
2935 {
2936#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy5f3d2752013-01-05 18:53:38 +00002937 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
cristy3ed852e2009-09-05 21:47:34 +00002938#endif
2939 break;
2940 }
2941 case FifoStream:
2942 break;
2943 case BlobStream:
2944 {
2945 register const unsigned char
2946 *p;
2947
2948 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2949 {
2950 image->blob->eof=MagickTrue;
2951 break;
2952 }
2953 p=image->blob->data+image->blob->offset;
cristye7b28372012-06-17 13:59:06 +00002954 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2955 image->blob->offset));
cristy3ed852e2009-09-05 21:47:34 +00002956 image->blob->offset+=count;
2957 if (count != (ssize_t) length)
2958 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002959 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002960 break;
2961 }
2962 }
2963 return(count);
2964}
2965
2966/*
2967%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2968% %
2969% %
2970% %
2971+ R e a d B l o b B y t e %
2972% %
2973% %
2974% %
2975%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2976%
2977% ReadBlobByte() reads a single byte from the image file and returns it.
2978%
2979% The format of the ReadBlobByte method is:
2980%
2981% int ReadBlobByte(Image *image)
2982%
2983% A description of each parameter follows.
2984%
2985% o image: the image.
2986%
2987*/
2988MagickExport int ReadBlobByte(Image *image)
2989{
2990 register const unsigned char
2991 *p;
2992
2993 ssize_t
2994 count;
2995
2996 unsigned char
2997 buffer[1];
2998
2999 assert(image != (Image *) NULL);
3000 assert(image->signature == MagickSignature);
3001 p=ReadBlobStream(image,1,buffer,&count);
3002 if (count != 1)
3003 return(EOF);
3004 return((int) (*p));
3005}
3006
3007/*
3008%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3009% %
3010% %
3011% %
3012+ R e a d B l o b D o u b l e %
3013% %
3014% %
3015% %
3016%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3017%
3018% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3019% specified by the endian member of the image structure.
3020%
3021% The format of the ReadBlobDouble method is:
3022%
3023% double ReadBlobDouble(Image *image)
3024%
3025% A description of each parameter follows.
3026%
3027% o image: the image.
3028%
3029*/
3030MagickExport double ReadBlobDouble(Image *image)
3031{
3032 union
3033 {
3034 MagickSizeType
3035 unsigned_value;
3036
3037 double
3038 double_value;
3039 } quantum;
3040
3041 quantum.double_value=0.0;
3042 quantum.unsigned_value=ReadBlobLongLong(image);
3043 return(quantum.double_value);
3044}
3045
3046/*
3047%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3048% %
3049% %
3050% %
3051+ R e a d B l o b F l o a t %
3052% %
3053% %
3054% %
3055%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3056%
3057% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3058% specified by the endian member of the image structure.
3059%
3060% The format of the ReadBlobFloat method is:
3061%
3062% float ReadBlobFloat(Image *image)
3063%
3064% A description of each parameter follows.
3065%
3066% o image: the image.
3067%
3068*/
3069MagickExport float ReadBlobFloat(Image *image)
3070{
3071 union
3072 {
3073 unsigned int
3074 unsigned_value;
3075
3076 float
3077 float_value;
3078 } quantum;
3079
3080 quantum.float_value=0.0;
3081 quantum.unsigned_value=ReadBlobLong(image);
3082 return(quantum.float_value);
3083}
3084
3085/*
3086%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3087% %
3088% %
3089% %
3090+ R e a d B l o b L o n g %
3091% %
3092% %
3093% %
3094%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3095%
cristybb503372010-05-27 20:51:26 +00003096% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003097% specified by the endian member of the image structure.
3098%
3099% The format of the ReadBlobLong method is:
3100%
3101% unsigned int ReadBlobLong(Image *image)
3102%
3103% A description of each parameter follows.
3104%
3105% o image: the image.
3106%
3107*/
3108MagickExport unsigned int ReadBlobLong(Image *image)
3109{
3110 register const unsigned char
3111 *p;
3112
3113 ssize_t
3114 count;
3115
3116 unsigned char
3117 buffer[4];
3118
3119 unsigned int
3120 value;
3121
3122 assert(image != (Image *) NULL);
3123 assert(image->signature == MagickSignature);
3124 *buffer='\0';
3125 p=ReadBlobStream(image,4,buffer,&count);
3126 if (count != 4)
3127 return(0UL);
3128 if (image->endian == LSBEndian)
3129 {
3130 value=(unsigned int) (*p++);
3131 value|=((unsigned int) (*p++)) << 8;
3132 value|=((unsigned int) (*p++)) << 16;
3133 value|=((unsigned int) (*p++)) << 24;
3134 return(value);
3135 }
3136 value=((unsigned int) (*p++)) << 24;
3137 value|=((unsigned int) (*p++)) << 16;
3138 value|=((unsigned int) (*p++)) << 8;
3139 value|=((unsigned int) (*p++));
3140 return(value);
3141}
3142
3143/*
3144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3145% %
3146% %
3147% %
3148+ R e a d B l o b L o n g L o n g %
3149% %
3150% %
3151% %
3152%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3153%
cristy4cb162a2010-05-30 03:04:47 +00003154% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3155% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003156%
cristy4cb162a2010-05-30 03:04:47 +00003157% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003158%
cristy4cb162a2010-05-30 03:04:47 +00003159% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003160%
3161% A description of each parameter follows.
3162%
3163% o image: the image.
3164%
3165*/
3166MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3167{
cristy0286d852010-10-12 18:38:07 +00003168 MagickSizeType
3169 value;
3170
cristy3ed852e2009-09-05 21:47:34 +00003171 register const unsigned char
3172 *p;
3173
3174 ssize_t
3175 count;
3176
3177 unsigned char
3178 buffer[8];
3179
cristy3ed852e2009-09-05 21:47:34 +00003180 assert(image != (Image *) NULL);
3181 assert(image->signature == MagickSignature);
3182 *buffer='\0';
3183 p=ReadBlobStream(image,8,buffer,&count);
3184 if (count != 8)
3185 return(MagickULLConstant(0));
3186 if (image->endian == LSBEndian)
3187 {
3188 value=(MagickSizeType) (*p++);
3189 value|=((MagickSizeType) (*p++)) << 8;
3190 value|=((MagickSizeType) (*p++)) << 16;
3191 value|=((MagickSizeType) (*p++)) << 24;
3192 value|=((MagickSizeType) (*p++)) << 32;
3193 value|=((MagickSizeType) (*p++)) << 40;
3194 value|=((MagickSizeType) (*p++)) << 48;
3195 value|=((MagickSizeType) (*p++)) << 56;
3196 return(value & MagickULLConstant(0xffffffffffffffff));
3197 }
3198 value=((MagickSizeType) (*p++)) << 56;
3199 value|=((MagickSizeType) (*p++)) << 48;
3200 value|=((MagickSizeType) (*p++)) << 40;
3201 value|=((MagickSizeType) (*p++)) << 32;
3202 value|=((MagickSizeType) (*p++)) << 24;
3203 value|=((MagickSizeType) (*p++)) << 16;
3204 value|=((MagickSizeType) (*p++)) << 8;
3205 value|=((MagickSizeType) (*p++));
3206 return(value & MagickULLConstant(0xffffffffffffffff));
3207}
3208
3209/*
3210%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3211% %
3212% %
3213% %
3214+ R e a d B l o b S h o r t %
3215% %
3216% %
3217% %
3218%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3219%
3220% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3221% specified by the endian member of the image structure.
3222%
3223% The format of the ReadBlobShort method is:
3224%
3225% unsigned short ReadBlobShort(Image *image)
3226%
3227% A description of each parameter follows.
3228%
3229% o image: the image.
3230%
3231*/
3232MagickExport unsigned short ReadBlobShort(Image *image)
3233{
3234 register const unsigned char
3235 *p;
3236
3237 register unsigned int
3238 value;
3239
3240 ssize_t
3241 count;
3242
3243 unsigned char
3244 buffer[2];
3245
3246 assert(image != (Image *) NULL);
3247 assert(image->signature == MagickSignature);
3248 *buffer='\0';
3249 p=ReadBlobStream(image,2,buffer,&count);
3250 if (count != 2)
3251 return((unsigned short) 0U);
3252 if (image->endian == LSBEndian)
3253 {
3254 value=(unsigned int) (*p++);
3255 value|=((unsigned int) (*p++)) << 8;
3256 return((unsigned short) (value & 0xffff));
3257 }
3258 value=(unsigned int) ((*p++) << 8);
3259 value|=(unsigned int) (*p++);
3260 return((unsigned short) (value & 0xffff));
3261}
3262
3263/*
3264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3265% %
3266% %
3267% %
3268+ R e a d B l o b L S B L o n g %
3269% %
3270% %
3271% %
3272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3273%
cristybb503372010-05-27 20:51:26 +00003274% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003275% least-significant byte first order.
3276%
3277% The format of the ReadBlobLSBLong method is:
3278%
3279% unsigned int ReadBlobLSBLong(Image *image)
3280%
3281% A description of each parameter follows.
3282%
3283% o image: the image.
3284%
3285*/
3286MagickExport unsigned int ReadBlobLSBLong(Image *image)
3287{
3288 register const unsigned char
3289 *p;
3290
3291 register unsigned int
3292 value;
3293
3294 ssize_t
3295 count;
3296
3297 unsigned char
3298 buffer[4];
3299
3300 assert(image != (Image *) NULL);
3301 assert(image->signature == MagickSignature);
3302 *buffer='\0';
3303 p=ReadBlobStream(image,4,buffer,&count);
3304 if (count != 4)
3305 return(0U);
3306 value=(unsigned int) (*p++);
3307 value|=((unsigned int) (*p++)) << 8;
3308 value|=((unsigned int) (*p++)) << 16;
3309 value|=((unsigned int) (*p++)) << 24;
3310 return(value);
3311}
3312
3313/*
3314%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3315% %
3316% %
3317% %
3318+ R e a d B l o b L S B S h o r t %
3319% %
3320% %
3321% %
3322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3323%
3324% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3325% least-significant byte first order.
3326%
3327% The format of the ReadBlobLSBShort method is:
3328%
3329% unsigned short ReadBlobLSBShort(Image *image)
3330%
3331% A description of each parameter follows.
3332%
3333% o image: the image.
3334%
3335*/
3336MagickExport unsigned short ReadBlobLSBShort(Image *image)
3337{
3338 register const unsigned char
3339 *p;
3340
3341 register unsigned int
3342 value;
3343
3344 ssize_t
3345 count;
3346
3347 unsigned char
3348 buffer[2];
3349
3350 assert(image != (Image *) NULL);
3351 assert(image->signature == MagickSignature);
3352 *buffer='\0';
3353 p=ReadBlobStream(image,2,buffer,&count);
3354 if (count != 2)
3355 return((unsigned short) 0U);
3356 value=(unsigned int) (*p++);
3357 value|=((unsigned int) ((*p++)) << 8);
3358 return((unsigned short) (value & 0xffff));
3359}
3360
3361/*
3362%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3363% %
3364% %
3365% %
3366+ R e a d B l o b M S B L o n g %
3367% %
3368% %
3369% %
3370%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3371%
cristybb503372010-05-27 20:51:26 +00003372% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003373% most-significant byte first order.
3374%
3375% The format of the ReadBlobMSBLong method is:
3376%
3377% unsigned int ReadBlobMSBLong(Image *image)
3378%
3379% A description of each parameter follows.
3380%
3381% o image: the image.
3382%
3383*/
3384MagickExport unsigned int ReadBlobMSBLong(Image *image)
3385{
3386 register const unsigned char
3387 *p;
3388
3389 register unsigned int
3390 value;
3391
3392 ssize_t
3393 count;
3394
3395 unsigned char
3396 buffer[4];
3397
3398 assert(image != (Image *) NULL);
3399 assert(image->signature == MagickSignature);
3400 *buffer='\0';
3401 p=ReadBlobStream(image,4,buffer,&count);
3402 if (count != 4)
3403 return(0UL);
3404 value=((unsigned int) (*p++) << 24);
3405 value|=((unsigned int) (*p++) << 16);
3406 value|=((unsigned int) (*p++) << 8);
3407 value|=(unsigned int) (*p++);
3408 return(value);
3409}
3410
3411/*
3412%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3413% %
3414% %
3415% %
cristy2d3d87f2010-03-01 00:23:08 +00003416+ R e a d B l o b M S B L o n g L o n g %
3417% %
3418% %
3419% %
3420%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3421%
cristybb503372010-05-27 20:51:26 +00003422% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003423% most-significant byte first order.
3424%
3425% The format of the ReadBlobMSBLongLong method is:
3426%
3427% unsigned int ReadBlobMSBLongLong(Image *image)
3428%
3429% A description of each parameter follows.
3430%
3431% o image: the image.
3432%
3433*/
3434MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3435{
3436 register const unsigned char
3437 *p;
3438
3439 register MagickSizeType
3440 value;
3441
3442 ssize_t
3443 count;
3444
3445 unsigned char
cristy0286d852010-10-12 18:38:07 +00003446 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003447
3448 assert(image != (Image *) NULL);
3449 assert(image->signature == MagickSignature);
3450 *buffer='\0';
3451 p=ReadBlobStream(image,8,buffer,&count);
3452 if (count != 8)
3453 return(MagickULLConstant(0));
3454 value=((MagickSizeType) (*p++)) << 56;
3455 value|=((MagickSizeType) (*p++)) << 48;
3456 value|=((MagickSizeType) (*p++)) << 40;
3457 value|=((MagickSizeType) (*p++)) << 32;
3458 value|=((MagickSizeType) (*p++)) << 24;
3459 value|=((MagickSizeType) (*p++)) << 16;
3460 value|=((MagickSizeType) (*p++)) << 8;
3461 value|=((MagickSizeType) (*p++));
3462 return(value & MagickULLConstant(0xffffffffffffffff));
3463}
3464
3465/*
3466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3467% %
3468% %
3469% %
cristy3ed852e2009-09-05 21:47:34 +00003470+ R e a d B l o b M S B S h o r t %
3471% %
3472% %
3473% %
3474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3475%
3476% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3477% most-significant byte first order.
3478%
3479% The format of the ReadBlobMSBShort method is:
3480%
3481% unsigned short ReadBlobMSBShort(Image *image)
3482%
3483% A description of each parameter follows.
3484%
3485% o image: the image.
3486%
3487*/
3488MagickExport unsigned short ReadBlobMSBShort(Image *image)
3489{
3490 register const unsigned char
3491 *p;
3492
3493 register unsigned int
3494 value;
3495
3496 ssize_t
3497 count;
3498
3499 unsigned char
3500 buffer[2];
3501
3502 assert(image != (Image *) NULL);
3503 assert(image->signature == MagickSignature);
3504 *buffer='\0';
3505 p=ReadBlobStream(image,2,buffer,&count);
3506 if (count != 2)
3507 return((unsigned short) 0U);
3508 value=(unsigned int) ((*p++) << 8);
3509 value|=(unsigned int) (*p++);
3510 return((unsigned short) (value & 0xffff));
3511}
3512
3513/*
3514%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3515% %
3516% %
3517% %
3518+ R e a d B l o b S t r i n g %
3519% %
3520% %
3521% %
3522%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3523%
3524% ReadBlobString() reads characters from a blob or file until a newline
3525% character is read or an end-of-file condition is encountered.
3526%
3527% The format of the ReadBlobString method is:
3528%
3529% char *ReadBlobString(Image *image,char *string)
3530%
3531% A description of each parameter follows:
3532%
3533% o image: the image.
3534%
3535% o string: the address of a character buffer.
3536%
3537*/
3538MagickExport char *ReadBlobString(Image *image,char *string)
3539{
3540 register const unsigned char
3541 *p;
3542
cristybb503372010-05-27 20:51:26 +00003543 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003544 i;
3545
3546 ssize_t
3547 count;
3548
3549 unsigned char
3550 buffer[1];
3551
3552 assert(image != (Image *) NULL);
3553 assert(image->signature == MagickSignature);
3554 for (i=0; i < (MaxTextExtent-1L); i++)
3555 {
3556 p=ReadBlobStream(image,1,buffer,&count);
3557 if (count != 1)
3558 {
3559 if (i == 0)
3560 return((char *) NULL);
3561 break;
3562 }
3563 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003564 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003565 break;
3566 }
cristy2b5db102010-06-09 01:07:28 +00003567 if (string[i] == '\r')
3568 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003569 string[i]='\0';
3570 return(string);
3571}
3572
3573/*
3574%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3575% %
3576% %
3577% %
3578+ R e f e r e n c e B l o b %
3579% %
3580% %
3581% %
3582%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3583%
3584% ReferenceBlob() increments the reference count associated with the pixel
3585% blob returning a pointer to the blob.
3586%
3587% The format of the ReferenceBlob method is:
3588%
3589% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3590%
3591% A description of each parameter follows:
3592%
3593% o blob_info: the blob_info.
3594%
3595*/
3596MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3597{
3598 assert(blob != (BlobInfo *) NULL);
3599 assert(blob->signature == MagickSignature);
3600 if (blob->debug != MagickFalse)
3601 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003602 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003603 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003604 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003605 return(blob);
3606}
3607
3608/*
3609%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3610% %
3611% %
3612% %
3613+ S e e k B l o b %
3614% %
3615% %
3616% %
3617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3618%
3619% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3620% and returns the resulting offset.
3621%
3622% The format of the SeekBlob method is:
3623%
3624% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3625% const int whence)
3626%
3627% A description of each parameter follows:
3628%
3629% o image: the image.
3630%
3631% o offset: Specifies an integer representing the offset in bytes.
3632%
3633% o whence: Specifies an integer representing how the offset is
3634% treated relative to the beginning of the blob as follows:
3635%
3636% SEEK_SET Set position equal to offset bytes.
3637% SEEK_CUR Set position to current location plus offset.
3638% SEEK_END Set position to EOF plus offset.
3639%
3640*/
3641MagickExport MagickOffsetType SeekBlob(Image *image,
3642 const MagickOffsetType offset,const int whence)
3643{
3644 assert(image != (Image *) NULL);
3645 assert(image->signature == MagickSignature);
3646 if (image->debug != MagickFalse)
3647 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3648 assert(image->blob != (BlobInfo *) NULL);
3649 assert(image->blob->type != UndefinedStream);
3650 switch (image->blob->type)
3651 {
3652 case UndefinedStream:
3653 break;
cristybc20d112012-07-29 20:27:00 +00003654 case StandardStream:
3655 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003656 case FileStream:
3657 {
cristyb7144222014-05-18 21:09:22 +00003658 if ((whence == SEEK_SET) && (offset < 0))
3659 return(-1);
cristye7b28372012-06-17 13:59:06 +00003660 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003661 return(-1);
3662 image->blob->offset=TellBlob(image);
3663 break;
3664 }
cristy3ed852e2009-09-05 21:47:34 +00003665 case PipeStream:
3666 case ZipStream:
3667 {
3668#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003669 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003670 return(-1);
3671#endif
3672 image->blob->offset=TellBlob(image);
3673 break;
3674 }
3675 case BZipStream:
3676 return(-1);
3677 case FifoStream:
3678 return(-1);
3679 case BlobStream:
3680 {
3681 switch (whence)
3682 {
3683 case SEEK_SET:
3684 default:
3685 {
3686 if (offset < 0)
3687 return(-1);
3688 image->blob->offset=offset;
3689 break;
3690 }
3691 case SEEK_CUR:
3692 {
3693 if ((image->blob->offset+offset) < 0)
3694 return(-1);
3695 image->blob->offset+=offset;
3696 break;
3697 }
3698 case SEEK_END:
3699 {
3700 if (((MagickOffsetType) image->blob->length+offset) < 0)
3701 return(-1);
3702 image->blob->offset=image->blob->length+offset;
3703 break;
3704 }
3705 }
3706 if (image->blob->offset <= (MagickOffsetType)
3707 ((off_t) image->blob->length))
3708 image->blob->eof=MagickFalse;
3709 else
3710 if (image->blob->mapped != MagickFalse)
3711 return(-1);
3712 else
3713 {
3714 image->blob->extent=(size_t) (image->blob->offset+
3715 image->blob->quantum);
cristyff368632014-01-27 13:01:38 +00003716 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00003717 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3718 image->blob->data,image->blob->extent+1,
3719 sizeof(*image->blob->data));
3720 (void) SyncBlob(image);
3721 if (image->blob->data == (unsigned char *) NULL)
3722 {
3723 (void) DetachBlob(image->blob);
3724 return(-1);
3725 }
3726 }
3727 break;
3728 }
3729 }
3730 return(image->blob->offset);
3731}
3732
3733/*
3734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3735% %
3736% %
3737% %
3738+ S e t B l o b E x e m p t %
3739% %
3740% %
3741% %
3742%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3743%
3744% SetBlobExempt() sets the blob exempt status.
3745%
3746% The format of the SetBlobExempt method is:
3747%
3748% MagickBooleanType SetBlobExempt(const Image *image,
3749% const MagickBooleanType exempt)
3750%
3751% A description of each parameter follows:
3752%
3753% o image: the image.
3754%
3755% o exempt: Set to true if this blob is exempt from being closed.
3756%
3757*/
cristy7832dc22011-09-05 01:21:53 +00003758MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003759{
3760 assert(image != (const Image *) NULL);
3761 assert(image->signature == MagickSignature);
3762 if (image->debug != MagickFalse)
3763 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3764 image->blob->exempt=exempt;
3765}
3766
3767/*
3768%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3769% %
3770% %
3771% %
3772+ S e t B l o b E x t e n t %
3773% %
3774% %
3775% %
3776%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3777%
3778% SetBlobExtent() ensures enough space is allocated for the blob. If the
3779% method is successful, subsequent writes to bytes in the specified range are
3780% guaranteed not to fail.
3781%
3782% The format of the SetBlobExtent method is:
3783%
3784% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3785%
3786% A description of each parameter follows:
3787%
3788% o image: the image.
3789%
3790% o extent: the blob maximum extent.
3791%
3792*/
cristy7832dc22011-09-05 01:21:53 +00003793MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003794 const MagickSizeType extent)
3795{
3796 assert(image != (Image *) NULL);
3797 assert(image->signature == MagickSignature);
3798 if (image->debug != MagickFalse)
3799 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3800 assert(image->blob != (BlobInfo *) NULL);
3801 assert(image->blob->type != UndefinedStream);
3802 switch (image->blob->type)
3803 {
3804 case UndefinedStream:
3805 break;
cristybc20d112012-07-29 20:27:00 +00003806 case StandardStream:
3807 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003808 case FileStream:
3809 {
cristy38e35f42012-12-18 21:12:17 +00003810 MagickOffsetType
3811 offset;
3812
3813 ssize_t
3814 count;
3815
cristy3ed852e2009-09-05 21:47:34 +00003816 if (extent != (MagickSizeType) ((off_t) extent))
3817 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003818 offset=SeekBlob(image,0,SEEK_END);
3819 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003820 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003821 if ((MagickSizeType) offset >= extent)
3822 break;
3823 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003824 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3825 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003826#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3827 if (image->blob->synchronize != MagickFalse)
3828 {
3829 int
cristybb380e72014-10-31 12:56:36 +00003830 file;
cristyfa0ea942012-12-21 02:42:29 +00003831
cristy2797f472014-05-26 01:25:55 +00003832 file=fileno(image->blob->file_info.file);
3833 if ((file == -1) || (offset < 0))
3834 return(MagickFalse);
cristybb380e72014-10-31 12:56:36 +00003835 (void) posix_fallocate(file,offset,extent-offset);
cristyfa0ea942012-12-21 02:42:29 +00003836 }
3837#endif
cristy38e35f42012-12-18 21:12:17 +00003838 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003839 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003840 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003841 break;
3842 }
cristy3ed852e2009-09-05 21:47:34 +00003843 case PipeStream:
3844 case ZipStream:
3845 return(MagickFalse);
3846 case BZipStream:
3847 return(MagickFalse);
3848 case FifoStream:
3849 return(MagickFalse);
3850 case BlobStream:
3851 {
cristy38e35f42012-12-18 21:12:17 +00003852 if (extent != (MagickSizeType) ((size_t) extent))
3853 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003854 if (image->blob->mapped != MagickFalse)
3855 {
cristy38e35f42012-12-18 21:12:17 +00003856 MagickOffsetType
3857 offset;
3858
3859 ssize_t
3860 count;
3861
cristy3ed852e2009-09-05 21:47:34 +00003862 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy18aba912013-06-14 19:48:08 +00003863 RelinquishMagickResource(MapResource,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003864 if (extent != (MagickSizeType) ((off_t) extent))
3865 return(MagickFalse);
3866 offset=SeekBlob(image,0,SEEK_END);
3867 if (offset < 0)
3868 return(MagickFalse);
3869 if ((MagickSizeType) offset >= extent)
3870 break;
3871 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003872 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003873 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003874#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3875 if (image->blob->synchronize != MagickFalse)
3876 {
3877 int
cristybb380e72014-10-31 12:56:36 +00003878 file;
cristyfa0ea942012-12-21 02:42:29 +00003879
cristy6f008fd2014-05-25 23:27:26 +00003880 file=fileno(image->blob->file_info.file);
cristyf2a82ee2014-05-26 17:49:54 +00003881 if ((file == -1) || (offset < 0))
cristy6f008fd2014-05-25 23:27:26 +00003882 return(MagickFalse);
cristybb380e72014-10-31 12:56:36 +00003883 (void) posix_fallocate(file,offset,extent-offset);
cristyfa0ea942012-12-21 02:42:29 +00003884 }
3885#endif
cristy38e35f42012-12-18 21:12:17 +00003886 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003887 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003888 return(MagickFalse);
cristyac1caa22013-06-15 00:41:21 +00003889 (void) AcquireMagickResource(MapResource,extent);
cristy95888612012-04-04 21:56:52 +00003890 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003891 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003892 image->blob->extent=(size_t) extent;
3893 image->blob->length=(size_t) extent;
3894 (void) SyncBlob(image);
3895 break;
cristy3ed852e2009-09-05 21:47:34 +00003896 }
cristy3ed852e2009-09-05 21:47:34 +00003897 image->blob->extent=(size_t) extent;
3898 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3899 image->blob->extent+1,sizeof(*image->blob->data));
3900 (void) SyncBlob(image);
3901 if (image->blob->data == (unsigned char *) NULL)
3902 {
3903 (void) DetachBlob(image->blob);
3904 return(MagickFalse);
3905 }
3906 break;
3907 }
3908 }
3909 return(MagickTrue);
3910}
3911
3912/*
3913%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3914% %
3915% %
3916% %
3917+ S y n c B l o b %
3918% %
3919% %
3920% %
3921%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3922%
3923% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3924% attributes if it is an blob.
3925%
3926% The format of the SyncBlob method is:
3927%
3928% int SyncBlob(Image *image)
3929%
3930% A description of each parameter follows:
3931%
3932% o image: the image.
3933%
3934*/
3935static int SyncBlob(Image *image)
3936{
3937 int
3938 status;
3939
3940 assert(image != (Image *) NULL);
3941 assert(image->signature == MagickSignature);
3942 if (image->debug != MagickFalse)
3943 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3944 assert(image->blob != (BlobInfo *) NULL);
3945 assert(image->blob->type != UndefinedStream);
3946 status=0;
3947 switch (image->blob->type)
3948 {
3949 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003950 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003951 break;
3952 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003953 case PipeStream:
3954 {
cristye7b28372012-06-17 13:59:06 +00003955 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003956 break;
3957 }
3958 case ZipStream:
3959 {
3960#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003961 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003962#endif
3963 break;
3964 }
3965 case BZipStream:
3966 {
3967#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003968 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003969#endif
3970 break;
3971 }
3972 case FifoStream:
3973 break;
3974 case BlobStream:
cristy3ed852e2009-09-05 21:47:34 +00003975 break;
cristy3ed852e2009-09-05 21:47:34 +00003976 }
3977 return(status);
3978}
3979
3980/*
3981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3982% %
3983% %
3984% %
3985+ T e l l B l o b %
3986% %
3987% %
3988% %
3989%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3990%
3991% TellBlob() obtains the current value of the blob or file position.
3992%
3993% The format of the TellBlob method is:
3994%
3995% MagickOffsetType TellBlob(const Image *image)
3996%
3997% A description of each parameter follows:
3998%
3999% o image: the image.
4000%
4001*/
4002MagickExport MagickOffsetType TellBlob(const Image *image)
4003{
4004 MagickOffsetType
4005 offset;
4006
4007 assert(image != (Image *) NULL);
4008 assert(image->signature == MagickSignature);
4009 if (image->debug != MagickFalse)
4010 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4011 assert(image->blob != (BlobInfo *) NULL);
4012 assert(image->blob->type != UndefinedStream);
4013 offset=(-1);
4014 switch (image->blob->type)
4015 {
4016 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00004017 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00004018 break;
4019 case FileStream:
4020 {
cristye7b28372012-06-17 13:59:06 +00004021 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004022 break;
4023 }
cristy3ed852e2009-09-05 21:47:34 +00004024 case PipeStream:
4025 break;
4026 case ZipStream:
4027 {
4028#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004029 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00004030#endif
4031 break;
4032 }
4033 case BZipStream:
4034 break;
4035 case FifoStream:
4036 break;
4037 case BlobStream:
4038 {
4039 offset=image->blob->offset;
4040 break;
4041 }
4042 }
4043 return(offset);
4044}
4045
4046/*
4047%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4048% %
4049% %
4050% %
4051+ U n m a p B l o b %
4052% %
4053% %
4054% %
4055%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4056%
4057% UnmapBlob() deallocates the binary large object previously allocated with
4058% the MapBlob method.
4059%
4060% The format of the UnmapBlob method is:
4061%
4062% MagickBooleanType UnmapBlob(void *map,const size_t length)
4063%
4064% A description of each parameter follows:
4065%
4066% o map: the address of the binary large object.
4067%
4068% o length: the length of the binary large object.
4069%
4070*/
4071MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4072{
cristydc8ea8e2013-07-28 20:10:44 +00004073#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00004074 int
4075 status;
4076
4077 status=munmap(map,length);
4078 return(status == -1 ? MagickFalse : MagickTrue);
4079#else
4080 (void) map;
4081 (void) length;
4082 return(MagickFalse);
4083#endif
4084}
4085
4086/*
4087%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4088% %
4089% %
4090% %
4091+ W r i t e B l o b %
4092% %
4093% %
4094% %
4095%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4096%
4097% WriteBlob() writes data to a blob or image file. It returns the number of
4098% bytes written.
4099%
4100% The format of the WriteBlob method is:
4101%
4102% ssize_t WriteBlob(Image *image,const size_t length,
4103% const unsigned char *data)
4104%
4105% A description of each parameter follows:
4106%
4107% o image: the image.
4108%
4109% o length: Specifies an integer representing the number of bytes to
4110% write to the file.
4111%
4112% o data: The address of the data to write to the blob or file.
4113%
4114*/
4115MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4116 const unsigned char *data)
4117{
4118 int
4119 c;
4120
4121 register const unsigned char
4122 *p;
4123
4124 ssize_t
4125 count;
4126
4127 assert(image != (Image *) NULL);
4128 assert(image->signature == MagickSignature);
4129 assert(data != (const unsigned char *) NULL);
4130 assert(image->blob != (BlobInfo *) NULL);
4131 assert(image->blob->type != UndefinedStream);
4132 if (length == 0)
4133 return(0);
4134 count=0;
4135 p=data;
4136 switch (image->blob->type)
4137 {
4138 case UndefinedStream:
4139 break;
cristy3ed852e2009-09-05 21:47:34 +00004140 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004141 {
cristy5f3d2752013-01-05 18:53:38 +00004142 count=write(fileno(image->blob->file_info.file),data,length);
cristybc20d112012-07-29 20:27:00 +00004143 break;
4144 }
4145 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004146 case PipeStream:
4147 {
4148 switch (length)
4149 {
4150 default:
4151 {
4152 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004153 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004154 break;
4155 }
4156 case 2:
4157 {
cristye7b28372012-06-17 13:59:06 +00004158 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004159 if (c == EOF)
4160 break;
4161 count++;
4162 }
4163 case 1:
4164 {
cristye7b28372012-06-17 13:59:06 +00004165 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004166 if (c == EOF)
4167 break;
4168 count++;
4169 }
4170 case 0:
4171 break;
4172 }
4173 break;
4174 }
4175 case ZipStream:
4176 {
4177#if defined(MAGICKCORE_ZLIB_DELEGATE)
4178 switch (length)
4179 {
4180 default:
4181 {
cristye7b28372012-06-17 13:59:06 +00004182 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004183 (unsigned int) length);
4184 break;
4185 }
4186 case 2:
4187 {
cristye7b28372012-06-17 13:59:06 +00004188 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004189 if (c == EOF)
4190 break;
4191 count++;
4192 }
4193 case 1:
4194 {
cristye7b28372012-06-17 13:59:06 +00004195 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004196 if (c == EOF)
4197 break;
4198 count++;
4199 }
4200 case 0:
4201 break;
4202 }
4203#endif
4204 break;
4205 }
4206 case BZipStream:
4207 {
4208#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004209 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004210 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004211#endif
4212 break;
4213 }
4214 case FifoStream:
4215 {
4216 count=(ssize_t) image->blob->stream(image,data,length);
4217 break;
4218 }
4219 case BlobStream:
4220 {
4221 register unsigned char
4222 *q;
4223
4224 if ((image->blob->offset+(MagickOffsetType) length) >=
4225 (MagickOffsetType) image->blob->extent)
4226 {
4227 if (image->blob->mapped != MagickFalse)
4228 return(0);
cristy3ed852e2009-09-05 21:47:34 +00004229 image->blob->extent+=length+image->blob->quantum;
cristyff368632014-01-27 13:01:38 +00004230 image->blob->quantum<<=1;
cristy3ed852e2009-09-05 21:47:34 +00004231 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4232 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4233 (void) SyncBlob(image);
4234 if (image->blob->data == (unsigned char *) NULL)
4235 {
4236 (void) DetachBlob(image->blob);
4237 return(0);
4238 }
4239 }
4240 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004241 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004242 image->blob->offset+=length;
4243 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4244 image->blob->length=(size_t) image->blob->offset;
4245 count=(ssize_t) length;
4246 }
4247 }
4248 return(count);
4249}
4250
4251/*
4252%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4253% %
4254% %
4255% %
4256+ W r i t e B l o b B y t e %
4257% %
4258% %
4259% %
4260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4261%
4262% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4263% written (either 0 or 1);
4264%
4265% The format of the WriteBlobByte method is:
4266%
4267% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4268%
4269% A description of each parameter follows.
4270%
4271% o image: the image.
4272%
4273% o value: Specifies the value to write.
4274%
4275*/
4276MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4277{
4278 assert(image != (Image *) NULL);
4279 assert(image->signature == MagickSignature);
4280 return(WriteBlobStream(image,1,&value));
4281}
4282
4283/*
4284%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4285% %
4286% %
4287% %
4288+ W r i t e B l o b F l o a t %
4289% %
4290% %
4291% %
4292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4293%
4294% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4295% specified by the endian member of the image structure.
4296%
4297% The format of the WriteBlobFloat method is:
4298%
4299% ssize_t WriteBlobFloat(Image *image,const float value)
4300%
4301% A description of each parameter follows.
4302%
4303% o image: the image.
4304%
4305% o value: Specifies the value to write.
4306%
4307*/
4308MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4309{
4310 union
4311 {
4312 unsigned int
4313 unsigned_value;
4314
4315 float
4316 float_value;
4317 } quantum;
4318
4319 quantum.unsigned_value=0U;
4320 quantum.float_value=value;
4321 return(WriteBlobLong(image,quantum.unsigned_value));
4322}
4323
4324/*
4325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4326% %
4327% %
4328% %
4329+ W r i t e B l o b L o n g %
4330% %
4331% %
4332% %
4333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4334%
cristybb503372010-05-27 20:51:26 +00004335% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004336% specified by the endian member of the image structure.
4337%
4338% The format of the WriteBlobLong method is:
4339%
4340% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4341%
4342% A description of each parameter follows.
4343%
4344% o image: the image.
4345%
4346% o value: Specifies the value to write.
4347%
4348*/
4349MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4350{
4351 unsigned char
4352 buffer[4];
4353
4354 assert(image != (Image *) NULL);
4355 assert(image->signature == MagickSignature);
4356 if (image->endian == LSBEndian)
4357 {
4358 buffer[0]=(unsigned char) value;
4359 buffer[1]=(unsigned char) (value >> 8);
4360 buffer[2]=(unsigned char) (value >> 16);
4361 buffer[3]=(unsigned char) (value >> 24);
4362 return(WriteBlobStream(image,4,buffer));
4363 }
4364 buffer[0]=(unsigned char) (value >> 24);
4365 buffer[1]=(unsigned char) (value >> 16);
4366 buffer[2]=(unsigned char) (value >> 8);
4367 buffer[3]=(unsigned char) value;
4368 return(WriteBlobStream(image,4,buffer));
4369}
4370
4371/*
4372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4373% %
4374% %
4375% %
4376+ W r i t e B l o b S h o r t %
4377% %
4378% %
4379% %
4380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4381%
4382% WriteBlobShort() writes a short value as a 16-bit quantity in the
4383% byte-order specified by the endian member of the image structure.
4384%
4385% The format of the WriteBlobShort method is:
4386%
4387% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4388%
4389% A description of each parameter follows.
4390%
4391% o image: the image.
4392%
4393% o value: Specifies the value to write.
4394%
4395*/
4396MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4397{
4398 unsigned char
4399 buffer[2];
4400
4401 assert(image != (Image *) NULL);
4402 assert(image->signature == MagickSignature);
4403 if (image->endian == LSBEndian)
4404 {
4405 buffer[0]=(unsigned char) value;
4406 buffer[1]=(unsigned char) (value >> 8);
4407 return(WriteBlobStream(image,2,buffer));
4408 }
4409 buffer[0]=(unsigned char) (value >> 8);
4410 buffer[1]=(unsigned char) value;
4411 return(WriteBlobStream(image,2,buffer));
4412}
4413
4414/*
4415%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4416% %
4417% %
4418% %
4419+ W r i t e B l o b L S B L o n g %
4420% %
4421% %
4422% %
4423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4424%
cristybb503372010-05-27 20:51:26 +00004425% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004426% least-significant byte first order.
4427%
4428% The format of the WriteBlobLSBLong method is:
4429%
4430% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4431%
4432% A description of each parameter follows.
4433%
4434% o image: the image.
4435%
4436% o value: Specifies the value to write.
4437%
4438*/
4439MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4440{
4441 unsigned char
4442 buffer[4];
4443
4444 assert(image != (Image *) NULL);
4445 assert(image->signature == MagickSignature);
4446 buffer[0]=(unsigned char) value;
4447 buffer[1]=(unsigned char) (value >> 8);
4448 buffer[2]=(unsigned char) (value >> 16);
4449 buffer[3]=(unsigned char) (value >> 24);
4450 return(WriteBlobStream(image,4,buffer));
4451}
4452
4453/*
4454%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4455% %
4456% %
4457% %
4458+ W r i t e B l o b L S B S h o r t %
4459% %
4460% %
4461% %
4462%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4463%
cristybb503372010-05-27 20:51:26 +00004464% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004465% least-significant byte first order.
4466%
4467% The format of the WriteBlobLSBShort method is:
4468%
4469% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4470%
4471% A description of each parameter follows.
4472%
4473% o image: the image.
4474%
4475% o value: Specifies the value to write.
4476%
4477*/
4478MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4479{
4480 unsigned char
4481 buffer[2];
4482
4483 assert(image != (Image *) NULL);
4484 assert(image->signature == MagickSignature);
4485 buffer[0]=(unsigned char) value;
4486 buffer[1]=(unsigned char) (value >> 8);
4487 return(WriteBlobStream(image,2,buffer));
4488}
4489
4490/*
4491%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4492% %
4493% %
4494% %
4495+ W r i t e B l o b M S B L o n g %
4496% %
4497% %
4498% %
4499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4500%
cristybb503372010-05-27 20:51:26 +00004501% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004502% most-significant byte first order.
4503%
4504% The format of the WriteBlobMSBLong method is:
4505%
4506% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4507%
4508% A description of each parameter follows.
4509%
4510% o value: Specifies the value to write.
4511%
4512% o image: the image.
4513%
4514*/
4515MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4516{
4517 unsigned char
4518 buffer[4];
4519
4520 assert(image != (Image *) NULL);
4521 assert(image->signature == MagickSignature);
4522 buffer[0]=(unsigned char) (value >> 24);
4523 buffer[1]=(unsigned char) (value >> 16);
4524 buffer[2]=(unsigned char) (value >> 8);
4525 buffer[3]=(unsigned char) value;
4526 return(WriteBlobStream(image,4,buffer));
4527}
4528
4529/*
4530%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4531% %
4532% %
4533% %
cristy2ca49922010-03-06 02:54:01 +00004534+ W r i t e B l o b M S B L o n g L o n g %
4535% %
4536% %
4537% %
4538%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4539%
4540% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4541% most-significant byte first order.
4542%
4543% The format of the WriteBlobMSBLongLong method is:
4544%
4545% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4546%
4547% A description of each parameter follows.
4548%
4549% o value: Specifies the value to write.
4550%
4551% o image: the image.
4552%
4553*/
4554MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4555 const MagickSizeType value)
4556{
4557 unsigned char
4558 buffer[8];
4559
4560 assert(image != (Image *) NULL);
4561 assert(image->signature == MagickSignature);
4562 buffer[0]=(unsigned char) (value >> 56);
4563 buffer[1]=(unsigned char) (value >> 48);
4564 buffer[2]=(unsigned char) (value >> 40);
4565 buffer[3]=(unsigned char) (value >> 32);
4566 buffer[4]=(unsigned char) (value >> 24);
4567 buffer[5]=(unsigned char) (value >> 16);
4568 buffer[6]=(unsigned char) (value >> 8);
4569 buffer[7]=(unsigned char) value;
4570 return(WriteBlobStream(image,8,buffer));
4571}
4572
4573/*
4574%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4575% %
4576% %
4577% %
cristy3ed852e2009-09-05 21:47:34 +00004578+ W r i t e B l o b M S B S h o r t %
4579% %
4580% %
4581% %
4582%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4583%
cristybb503372010-05-27 20:51:26 +00004584% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004585% most-significant byte first order.
4586%
4587% The format of the WriteBlobMSBShort method is:
4588%
4589% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4590%
4591% A description of each parameter follows.
4592%
4593% o value: Specifies the value to write.
4594%
4595% o file: Specifies the file to write the data to.
4596%
4597*/
4598MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4599{
4600 unsigned char
4601 buffer[2];
4602
4603 assert(image != (Image *) NULL);
4604 assert(image->signature == MagickSignature);
4605 buffer[0]=(unsigned char) (value >> 8);
4606 buffer[1]=(unsigned char) value;
4607 return(WriteBlobStream(image,2,buffer));
4608}
4609
4610/*
4611%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4612% %
4613% %
4614% %
4615+ W r i t e B l o b S t r i n g %
4616% %
4617% %
4618% %
4619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4620%
4621% WriteBlobString() write a string to a blob. It returns the number of
4622% characters written.
4623%
4624% The format of the WriteBlobString method is:
4625%
4626% ssize_t WriteBlobString(Image *image,const char *string)
4627%
4628% A description of each parameter follows.
4629%
4630% o image: the image.
4631%
4632% o string: Specifies the string to write.
4633%
4634*/
4635MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4636{
4637 assert(image != (Image *) NULL);
4638 assert(image->signature == MagickSignature);
4639 assert(string != (const char *) NULL);
4640 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4641}