blob: 69195eb6586a42a52f7817ae3850d52cff821c57 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% BBBB L OOO BBBB %
7% B B L O O B B %
8% BBBB L O O BBBB %
9% B B L O O B B %
10% BBBB LLLLL OOO BBBB %
11% %
12% %
13% MagickCore Binary Large OBjectS Methods %
14% %
15% Software Design %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 1999 %
18% %
19% %
cristyfe676ee2013-11-18 13:03:38 +000020% Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
cristy4c08aed2011-07-01 19:47:50 +000043#include "MagickCore/studio.h"
cristyd2d11ec2012-03-28 13:53:49 +000044#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000045#include "MagickCore/blob.h"
46#include "MagickCore/blob-private.h"
47#include "MagickCore/cache.h"
48#include "MagickCore/client.h"
49#include "MagickCore/constitute.h"
50#include "MagickCore/delegate.h"
51#include "MagickCore/exception.h"
52#include "MagickCore/exception-private.h"
53#include "MagickCore/image-private.h"
54#include "MagickCore/list.h"
55#include "MagickCore/locale_.h"
56#include "MagickCore/log.h"
57#include "MagickCore/magick.h"
58#include "MagickCore/memory_.h"
59#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 {
358 blob_info=DestroyImageInfo(blob_info);
359 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +0000360 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +0000361 image_info->filename);
362 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 /*
402 Restore original filenames.
403 */
404 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
405 {
cristy540a22c2012-06-10 15:22:16 +0000406 (void) CopyMagickMemory(images->filename,image_info->filename,
407 sizeof(images->filename));
cristybe674a62012-08-14 12:38:33 +0000408 (void) CopyMagickMemory(images->magick_filename,image_info->filename,
409 sizeof(images->magick_filename));
cristy540a22c2012-06-10 15:22:16 +0000410 images=GetNextImageInList(images);
411 }
412 }
cristy3ed852e2009-09-05 21:47:34 +0000413 clone_info=DestroyImageInfo(clone_info);
414 (void) RelinquishUniqueFileResource(blob_info->filename);
415 blob_info=DestroyImageInfo(blob_info);
416 return(image);
417}
418
419/*
420%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
421% %
422% %
423% %
424+ C l o n e B l o b I n f o %
425% %
426% %
427% %
428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429%
430% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
431% blob info is NULL, a new one.
432%
433% The format of the CloneBlobInfo method is:
434%
435% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
436%
437% A description of each parameter follows:
438%
439% o blob_info: the blob info.
440%
441*/
442MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
443{
444 BlobInfo
445 *clone_info;
446
cristy73bd4a52010-10-05 11:24:23 +0000447 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
cristy3ed852e2009-09-05 21:47:34 +0000448 if (clone_info == (BlobInfo *) NULL)
449 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
450 GetBlobInfo(clone_info);
451 if (blob_info == (BlobInfo *) NULL)
452 return(clone_info);
453 clone_info->length=blob_info->length;
454 clone_info->extent=blob_info->extent;
455 clone_info->synchronize=blob_info->synchronize;
456 clone_info->quantum=blob_info->quantum;
457 clone_info->mapped=blob_info->mapped;
458 clone_info->eof=blob_info->eof;
459 clone_info->offset=blob_info->offset;
460 clone_info->size=blob_info->size;
461 clone_info->exempt=blob_info->exempt;
462 clone_info->status=blob_info->status;
463 clone_info->temporary=blob_info->temporary;
464 clone_info->type=blob_info->type;
cristye7b28372012-06-17 13:59:06 +0000465 clone_info->file_info.file=blob_info->file_info.file;
cristy3ed852e2009-09-05 21:47:34 +0000466 clone_info->properties=blob_info->properties;
467 clone_info->stream=blob_info->stream;
468 clone_info->data=blob_info->data;
469 clone_info->debug=IsEventLogging();
470 clone_info->reference_count=1;
471 return(clone_info);
472}
473
474/*
475%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
476% %
477% %
478% %
479+ C l o s e B l o b %
480% %
481% %
482% %
483%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484%
485% CloseBlob() closes a stream associated with the image.
486%
487% The format of the CloseBlob method is:
488%
489% MagickBooleanType CloseBlob(Image *image)
490%
491% A description of each parameter follows:
492%
493% o image: the image.
494%
495*/
496MagickExport MagickBooleanType CloseBlob(Image *image)
497{
498 int
499 status;
500
501 /*
502 Close image file.
503 */
504 assert(image != (Image *) NULL);
505 assert(image->signature == MagickSignature);
506 if (image->debug != MagickFalse)
507 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
508 assert(image->blob != (BlobInfo *) NULL);
509 if (image->blob->type == UndefinedStream)
510 return(MagickTrue);
cristy7e2a7c72012-12-27 00:56:47 +0000511 status=SyncBlob(image);
cristy3ed852e2009-09-05 21:47:34 +0000512 switch (image->blob->type)
513 {
514 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000515 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000516 break;
517 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000518 case PipeStream:
519 {
cristy02ce8cc2012-12-27 00:35:49 +0000520 if (image->blob->synchronize != MagickFalse)
521 status=fsync(fileno(image->blob->file_info.file));
cristye7b28372012-06-17 13:59:06 +0000522 status=ferror(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000523 break;
524 }
525 case ZipStream:
526 {
527#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000528 (void) gzerror(image->blob->file_info.gzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000529#endif
530 break;
531 }
532 case BZipStream:
533 {
534#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000535 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000536#endif
537 break;
538 }
539 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000540 break;
cristy02ce8cc2012-12-27 00:35:49 +0000541 case BlobStream:
542 {
543 if ((image->blob->file_info.file != (FILE *) NULL) &&
544 (image->blob->synchronize != MagickFalse))
cristy5678acd2012-12-27 00:41:55 +0000545 {
546 (void) fsync(fileno(image->blob->file_info.file));
547 status=ferror(image->blob->file_info.file);
548 }
cristy02ce8cc2012-12-27 00:35:49 +0000549 break;
550 }
cristy3ed852e2009-09-05 21:47:34 +0000551 }
552 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
cristycd9e6322012-12-27 00:29:00 +0000553 image->blob->size=GetBlobSize(image);
554 image->extent=image->blob->size;
555 image->blob->eof=MagickFalse;
cristybae22e42012-12-27 00:25:59 +0000556 if (image->blob->exempt != MagickFalse)
557 {
558 image->blob->type=UndefinedStream;
559 return(image->blob->status);
560 }
cristy3ed852e2009-09-05 21:47:34 +0000561 switch (image->blob->type)
562 {
563 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000564 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000565 break;
566 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000567 {
cristye7b28372012-06-17 13:59:06 +0000568 status=fclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000569 break;
570 }
571 case PipeStream:
572 {
573#if defined(MAGICKCORE_HAVE_PCLOSE)
cristye7b28372012-06-17 13:59:06 +0000574 status=pclose(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +0000575#endif
576 break;
577 }
578 case ZipStream:
579 {
580#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000581 status=gzclose(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +0000582#endif
583 break;
584 }
585 case BZipStream:
586 {
587#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +0000588 BZ2_bzclose(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +0000589#endif
590 break;
591 }
592 case FifoStream:
cristy3ed852e2009-09-05 21:47:34 +0000593 break;
cristyff483372010-10-16 17:00:58 +0000594 case BlobStream:
595 {
cristye7b28372012-06-17 13:59:06 +0000596 if (image->blob->file_info.file != (FILE *) NULL)
cristy02ce8cc2012-12-27 00:35:49 +0000597 status=fclose(image->blob->file_info.file);
cristyff483372010-10-16 17:00:58 +0000598 break;
599 }
cristy3ed852e2009-09-05 21:47:34 +0000600 }
601 (void) DetachBlob(image->blob);
602 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
603 return(image->blob->status);
604}
605
606/*
607%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608% %
609% %
610% %
611+ D e s t r o y B l o b %
612% %
613% %
614% %
615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616%
617% DestroyBlob() deallocates memory associated with a blob.
618%
619% The format of the DestroyBlob method is:
620%
621% void DestroyBlob(Image *image)
622%
623% A description of each parameter follows:
624%
625% o image: the image.
626%
627*/
628MagickExport void DestroyBlob(Image *image)
629{
630 MagickBooleanType
631 destroy;
632
633 assert(image != (Image *) NULL);
634 assert(image->signature == MagickSignature);
635 if (image->debug != MagickFalse)
636 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
637 assert(image->blob != (BlobInfo *) NULL);
638 assert(image->blob->signature == MagickSignature);
639 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000640 LockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000641 image->blob->reference_count--;
642 assert(image->blob->reference_count >= 0);
643 if (image->blob->reference_count == 0)
644 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000645 UnlockSemaphoreInfo(image->blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000646 if (destroy == MagickFalse)
647 return;
648 (void) CloseBlob(image);
649 if (image->blob->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000650 {
651 (void) UnmapBlob(image->blob->data,image->blob->length);
652 RelinquishMagickResource(MapResource,image->blob->length);
653 }
cristy3ed852e2009-09-05 21:47:34 +0000654 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
655 DestroySemaphoreInfo(&image->blob->semaphore);
656 image->blob->signature=(~MagickSignature);
657 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
658}
659
660/*
661%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
662% %
663% %
664% %
665+ D e t a c h B l o b %
666% %
667% %
668% %
669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670%
671% DetachBlob() detaches a blob from the BlobInfo structure.
672%
673% The format of the DetachBlob method is:
674%
675% unsigned char *DetachBlob(BlobInfo *blob_info)
676%
677% A description of each parameter follows:
678%
679% o blob_info: Specifies a pointer to a BlobInfo structure.
680%
681*/
682MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
683{
684 unsigned char
685 *data;
686
687 assert(blob_info != (BlobInfo *) NULL);
688 if (blob_info->debug != MagickFalse)
689 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
690 if (blob_info->mapped != MagickFalse)
cristy18aba912013-06-14 19:48:08 +0000691 {
692 (void) UnmapBlob(blob_info->data,blob_info->length);
693 RelinquishMagickResource(MapResource,blob_info->length);
694 }
cristy3ed852e2009-09-05 21:47:34 +0000695 blob_info->mapped=MagickFalse;
696 blob_info->length=0;
697 blob_info->offset=0;
698 blob_info->eof=MagickFalse;
699 blob_info->exempt=MagickFalse;
700 blob_info->type=UndefinedStream;
cristye7b28372012-06-17 13:59:06 +0000701 blob_info->file_info.file=(FILE *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000702 data=blob_info->data;
703 blob_info->data=(unsigned char *) NULL;
704 blob_info->stream=(StreamHandler) NULL;
705 return(data);
706}
707
708/*
709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
710% %
711% %
712% %
cristyc1af14f2010-09-16 20:01:21 +0000713+ D i s c a r d B l o b B y t e s %
714% %
715% %
716% %
717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
718%
719% DiscardBlobBytes() discards bytes in a blob.
720%
721% The format of the DiscardBlobBytes method is:
722%
723% MagickBooleanType DiscardBlobBytes(Image *image,const size_t length)
724%
725% A description of each parameter follows.
726%
727% o image: the image.
728%
729% o length: the number of bytes to skip.
730%
731*/
732
733static inline const unsigned char *ReadBlobStream(Image *image,
734 const size_t length,unsigned char *data,ssize_t *count)
735{
736 assert(count != (ssize_t *) NULL);
737 assert(image->blob != (BlobInfo *) NULL);
738 if (image->blob->type != BlobStream)
739 {
740 *count=ReadBlob(image,length,data);
741 return(data);
742 }
743 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
744 {
745 *count=0;
746 image->blob->eof=MagickTrue;
747 return(data);
748 }
749 data=image->blob->data+image->blob->offset;
cristy7753b2a2011-02-19 18:36:52 +0000750 *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
cristyc1af14f2010-09-16 20:01:21 +0000751 image->blob->offset));
752 image->blob->offset+=(*count);
753 if (*count != (ssize_t) length)
754 image->blob->eof=MagickTrue;
755 return(data);
756}
757
758MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
cristy7753b2a2011-02-19 18:36:52 +0000759 const MagickSizeType length)
cristyc1af14f2010-09-16 20:01:21 +0000760{
cristy7753b2a2011-02-19 18:36:52 +0000761 register MagickOffsetType
cristyc1af14f2010-09-16 20:01:21 +0000762 i;
763
764 size_t
765 quantum;
766
767 ssize_t
768 count;
769
770 unsigned char
cristyf55846d2010-09-17 19:01:10 +0000771 buffer[16384];
cristyc1af14f2010-09-16 20:01:21 +0000772
773 assert(image != (Image *) NULL);
774 assert(image->signature == MagickSignature);
775 count=0;
cristy7753b2a2011-02-19 18:36:52 +0000776 for (i=0; i < (MagickOffsetType) length; i+=count)
cristyc1af14f2010-09-16 20:01:21 +0000777 {
cristy7753b2a2011-02-19 18:36:52 +0000778 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
cristyc1af14f2010-09-16 20:01:21 +0000779 (void) ReadBlobStream(image,quantum,buffer,&count);
780 if (count <= 0)
781 {
782 count=0;
783 if (errno != EINTR)
784 break;
785 }
786 }
cristy7753b2a2011-02-19 18:36:52 +0000787 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
cristyc1af14f2010-09-16 20:01:21 +0000788}
789
790/*
791%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
792% %
793% %
794% %
cristy3ed852e2009-09-05 21:47:34 +0000795+ D u p l i c a t e s B l o b %
796% %
797% %
798% %
799%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
800%
801% DuplicateBlob() duplicates a blob descriptor.
802%
803% The format of the DuplicateBlob method is:
804%
805% void DuplicateBlob(Image *image,const Image *duplicate)
806%
807% A description of each parameter follows:
808%
809% o image: the image.
810%
811% o duplicate: the duplicate image.
812%
813*/
814MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
815{
816 assert(image != (Image *) NULL);
817 assert(image->signature == MagickSignature);
818 if (image->debug != MagickFalse)
819 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
820 assert(duplicate != (Image *) NULL);
821 assert(duplicate->signature == MagickSignature);
822 DestroyBlob(image);
823 image->blob=ReferenceBlob(duplicate->blob);
824}
825
826/*
827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
828% %
829% %
830% %
831+ E O F B l o b %
832% %
833% %
834% %
835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
836%
837% EOFBlob() returns a non-zero value when EOF has been detected reading from
838% a blob or file.
839%
840% The format of the EOFBlob method is:
841%
842% int EOFBlob(const Image *image)
843%
844% A description of each parameter follows:
845%
846% o image: the image.
847%
848*/
849MagickExport int EOFBlob(const Image *image)
850{
851 assert(image != (Image *) NULL);
852 assert(image->signature == MagickSignature);
853 if (image->debug != MagickFalse)
854 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
855 assert(image->blob != (BlobInfo *) NULL);
856 assert(image->blob->type != UndefinedStream);
857 switch (image->blob->type)
858 {
859 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +0000860 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +0000861 break;
862 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +0000863 case PipeStream:
864 {
cristye7b28372012-06-17 13:59:06 +0000865 image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
cristy95888612012-04-04 21:56:52 +0000866 MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000867 break;
868 }
869 case ZipStream:
870 {
871 image->blob->eof=MagickFalse;
872 break;
873 }
874 case BZipStream:
875 {
876#if defined(MAGICKCORE_BZLIB_DELEGATE)
877 int
878 status;
879
880 status=0;
cristye7b28372012-06-17 13:59:06 +0000881 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
cristy3ed852e2009-09-05 21:47:34 +0000882 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
883#endif
884 break;
885 }
886 case FifoStream:
887 {
888 image->blob->eof=MagickFalse;
889 break;
890 }
891 case BlobStream:
892 break;
893 }
894 return((int) image->blob->eof);
895}
896
897/*
898%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
899% %
900% %
901% %
902+ F i l e T o B l o b %
903% %
904% %
905% %
906%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
907%
cristy178edaf2011-01-23 03:42:39 +0000908% FileToBlob() returns the contents of a file as a buffer terminated with
909% the '\0' character. The length of the buffer (not including the extra
910% terminating '\0' character) is returned via the 'length' parameter. Free
911% the buffer with RelinquishMagickMemory().
cristy3ed852e2009-09-05 21:47:34 +0000912%
913% The format of the FileToBlob method is:
914%
915% unsigned char *FileToBlob(const char *filename,const size_t extent,
916% size_t *length,ExceptionInfo *exception)
917%
918% A description of each parameter follows:
919%
920% o blob: FileToBlob() returns the contents of a file as a blob. If
921% an error occurs NULL is returned.
922%
923% o filename: the filename.
924%
925% o extent: The maximum length of the blob.
926%
927% o length: On return, this reflects the actual length of the blob.
928%
929% o exception: return any errors or warnings in this structure.
930%
931*/
932MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
933 size_t *length,ExceptionInfo *exception)
934{
935 int
936 file;
937
938 MagickOffsetType
939 offset;
940
941 register size_t
942 i;
943
944 ssize_t
945 count;
946
947 unsigned char
948 *blob;
949
950 void
951 *map;
952
953 assert(filename != (const char *) NULL);
954 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
955 assert(exception != (ExceptionInfo *) NULL);
956 *length=0;
957 file=fileno(stdin);
958 if (LocaleCompare(filename,"-") != 0)
cristy18c6c272011-09-23 14:40:37 +0000959 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +0000960 if (file == -1)
961 {
962 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
963 return((unsigned char *) NULL);
964 }
cristy7f317702011-02-18 20:40:28 +0000965 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
cristy3ed852e2009-09-05 21:47:34 +0000966 count=0;
cristyd1f55c12014-01-24 00:40:57 +0000967 if ((file == fileno(stdin)) || (offset < 0) ||
968 (offset != (MagickOffsetType) ((ssize_t) offset)))
cristy3ed852e2009-09-05 21:47:34 +0000969 {
970 size_t
971 quantum;
972
973 struct stat
cristye7b28372012-06-17 13:59:06 +0000974 file_stats;
cristy3ed852e2009-09-05 21:47:34 +0000975
976 /*
977 Stream is not seekable.
978 */
cristyd1561652014-01-24 11:13:48 +0000979 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +0000980 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +0000981 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
982 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +0000983 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +0000984 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
985 for (i=0; blob != (unsigned char *) NULL; i+=count)
986 {
cristy65d11e42013-06-14 20:06:25 +0000987 count=read(file,blob+i,quantum);
cristy3ed852e2009-09-05 21:47:34 +0000988 if (count <= 0)
989 {
990 count=0;
991 if (errno != EINTR)
992 break;
993 }
cristy9c66d8c2012-08-10 11:05:36 +0000994 if (~((size_t) i) < (quantum+1))
cristy3ed852e2009-09-05 21:47:34 +0000995 {
996 blob=(unsigned char *) RelinquishMagickMemory(blob);
997 break;
998 }
999 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1000 sizeof(*blob));
1001 if ((size_t) (i+count) >= extent)
1002 break;
1003 }
cristy54439632010-07-15 00:43:34 +00001004 if (LocaleCompare(filename,"-") != 0)
1005 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001006 if (blob == (unsigned char *) NULL)
1007 {
1008 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001009 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001010 return((unsigned char *) NULL);
1011 }
cristya7cb4312010-06-26 00:47:03 +00001012 if (file == -1)
1013 {
1014 blob=(unsigned char *) RelinquishMagickMemory(blob);
1015 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1016 return((unsigned char *) NULL);
1017 }
cristy7753b2a2011-02-19 18:36:52 +00001018 *length=(size_t) MagickMin(i+count,extent);
cristy3ed852e2009-09-05 21:47:34 +00001019 blob[*length]='\0';
1020 return(blob);
1021 }
cristy7753b2a2011-02-19 18:36:52 +00001022 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
cristy3ed852e2009-09-05 21:47:34 +00001023 blob=(unsigned char *) NULL;
cristy37e0b382011-06-07 13:31:21 +00001024 if (~(*length) >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +00001025 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1026 sizeof(*blob));
1027 if (blob == (unsigned char *) NULL)
1028 {
cristy54439632010-07-15 00:43:34 +00001029 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001030 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001031 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001032 return((unsigned char *) NULL);
1033 }
1034 map=MapBlob(file,ReadMode,0,*length);
1035 if (map != (unsigned char *) NULL)
1036 {
cristy54aad5e2010-09-03 16:02:04 +00001037 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +00001038 (void) UnmapBlob(map,*length);
1039 }
1040 else
1041 {
cristy7f317702011-02-18 20:40:28 +00001042 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001043 for (i=0; i < *length; i+=count)
1044 {
cristy65d11e42013-06-14 20:06:25 +00001045 count=read(file,blob+i,(size_t) MagickMin(*length-i,(MagickSizeType)
1046 SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001047 if (count <= 0)
1048 {
1049 count=0;
1050 if (errno != EINTR)
1051 break;
1052 }
1053 }
1054 if (i < *length)
1055 {
1056 file=close(file)-1;
1057 blob=(unsigned char *) RelinquishMagickMemory(blob);
1058 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1059 return((unsigned char *) NULL);
1060 }
1061 }
cristy3ed852e2009-09-05 21:47:34 +00001062 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001063 if (LocaleCompare(filename,"-") != 0)
1064 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001065 if (file == -1)
1066 {
1067 blob=(unsigned char *) RelinquishMagickMemory(blob);
1068 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1069 }
cristy3ed852e2009-09-05 21:47:34 +00001070 return(blob);
1071}
1072
1073/*
1074%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1075% %
1076% %
1077% %
1078% F i l e T o I m a g e %
1079% %
1080% %
1081% %
1082%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1083%
1084% FileToImage() write the contents of a file to an image.
1085%
1086% The format of the FileToImage method is:
1087%
1088% MagickBooleanType FileToImage(Image *,const char *filename)
1089%
1090% A description of each parameter follows:
1091%
1092% o image: the image.
1093%
1094% o filename: the filename.
1095%
1096*/
1097
1098static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1099 const unsigned char *data)
1100{
1101 MagickSizeType
1102 extent;
1103
1104 register unsigned char
1105 *q;
1106
1107 assert(image->blob != (BlobInfo *) NULL);
1108 if (image->blob->type != BlobStream)
1109 return(WriteBlob(image,length,data));
1110 assert(image->blob->type != UndefinedStream);
1111 assert(data != (void *) NULL);
1112 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1113 if (extent >= image->blob->extent)
1114 {
1115 image->blob->quantum<<=1;
1116 extent=image->blob->extent+image->blob->quantum+length;
1117 if (SetBlobExtent(image,extent) == MagickFalse)
1118 return(0);
1119 }
1120 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001121 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001122 image->blob->offset+=length;
1123 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1124 image->blob->length=(size_t) image->blob->offset;
1125 return((ssize_t) length);
1126}
1127
cristyc82a27b2011-10-21 01:07:16 +00001128MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1129 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001130{
1131 int
1132 file;
1133
1134 size_t
1135 length,
1136 quantum;
1137
1138 ssize_t
1139 count;
1140
1141 struct stat
cristye7b28372012-06-17 13:59:06 +00001142 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001143
1144 unsigned char
1145 *blob;
1146
1147 assert(image != (const Image *) NULL);
1148 assert(image->signature == MagickSignature);
1149 assert(filename != (const char *) NULL);
1150 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
cristyd45808f2012-12-14 21:30:35 +00001151 file=fileno(stdin);
1152 if (LocaleCompare(filename,"-") != 0)
1153 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001154 if (file == -1)
1155 {
cristyc82a27b2011-10-21 01:07:16 +00001156 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001157 return(MagickFalse);
1158 }
1159 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001160 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1161 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001162 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1163 if (blob == (unsigned char *) NULL)
1164 {
cristyc82a27b2011-10-21 01:07:16 +00001165 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1166 filename);
cristy3ed852e2009-09-05 21:47:34 +00001167 return(MagickFalse);
1168 }
1169 for ( ; ; )
1170 {
cristy65d11e42013-06-14 20:06:25 +00001171 count=read(file,blob,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001172 if (count <= 0)
1173 {
1174 count=0;
1175 if (errno != EINTR)
1176 break;
1177 }
1178 length=(size_t) count;
1179 count=WriteBlobStream(image,length,blob);
1180 if (count != (ssize_t) length)
1181 {
cristyc82a27b2011-10-21 01:07:16 +00001182 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001183 break;
1184 }
1185 }
cristya7cb4312010-06-26 00:47:03 +00001186 file=close(file);
1187 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001188 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001189 blob=(unsigned char *) RelinquishMagickMemory(blob);
1190 return(MagickTrue);
1191}
1192
1193/*
1194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1195% %
1196% %
1197% %
1198+ G e t B l o b E r r o r %
1199% %
1200% %
1201% %
1202%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1203%
1204% GetBlobError() returns MagickTrue if the blob associated with the specified
1205% image encountered an error.
1206%
1207% The format of the GetBlobError method is:
1208%
1209% MagickBooleanType GetBlobError(const Image *image)
1210%
1211% A description of each parameter follows:
1212%
1213% o image: the image.
1214%
1215*/
cristy7832dc22011-09-05 01:21:53 +00001216MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001217{
1218 assert(image != (const Image *) NULL);
1219 assert(image->signature == MagickSignature);
1220 if (image->debug != MagickFalse)
1221 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1222 return(image->blob->status);
1223}
1224
1225/*
1226%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1227% %
1228% %
1229% %
1230+ G e t B l o b F i l e H a n d l e %
1231% %
1232% %
1233% %
1234%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1235%
1236% GetBlobFileHandle() returns the file handle associated with the image blob.
1237%
1238% The format of the GetBlobFile method is:
1239%
1240% FILE *GetBlobFileHandle(const Image *image)
1241%
1242% A description of each parameter follows:
1243%
1244% o image: the image.
1245%
1246*/
1247MagickExport FILE *GetBlobFileHandle(const Image *image)
1248{
1249 assert(image != (const Image *) NULL);
1250 assert(image->signature == MagickSignature);
cristye7b28372012-06-17 13:59:06 +00001251 return(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001252}
1253
1254/*
1255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1256% %
1257% %
1258% %
1259+ G e t B l o b I n f o %
1260% %
1261% %
1262% %
1263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1264%
1265% GetBlobInfo() initializes the BlobInfo structure.
1266%
1267% The format of the GetBlobInfo method is:
1268%
1269% void GetBlobInfo(BlobInfo *blob_info)
1270%
1271% A description of each parameter follows:
1272%
1273% o blob_info: Specifies a pointer to a BlobInfo structure.
1274%
1275*/
cristy7832dc22011-09-05 01:21:53 +00001276MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001277{
1278 assert(blob_info != (BlobInfo *) NULL);
1279 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1280 blob_info->type=UndefinedStream;
1281 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1282 blob_info->properties.st_mtime=time((time_t *) NULL);
1283 blob_info->properties.st_ctime=time((time_t *) NULL);
1284 blob_info->debug=IsEventLogging();
1285 blob_info->reference_count=1;
1286 blob_info->semaphore=AllocateSemaphoreInfo();
1287 blob_info->signature=MagickSignature;
1288}
1289
1290/*
1291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1292% %
1293% %
1294% %
1295% G e t B l o b P r o p e r t i e s %
1296% %
1297% %
1298% %
1299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1300%
1301% GetBlobProperties() returns information about an image blob.
1302%
1303% The format of the GetBlobProperties method is:
1304%
1305% const struct stat *GetBlobProperties(const Image *image)
1306%
1307% A description of each parameter follows:
1308%
1309% o image: the image.
1310%
1311*/
cristy7832dc22011-09-05 01:21:53 +00001312MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001313{
1314 assert(image != (Image *) NULL);
1315 assert(image->signature == MagickSignature);
1316 if (image->debug != MagickFalse)
1317 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1318 return(&image->blob->properties);
1319}
1320
1321/*
1322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1323% %
1324% %
1325% %
1326+ G e t B l o b S i z e %
1327% %
1328% %
1329% %
1330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1331%
1332% GetBlobSize() returns the current length of the image file or blob; zero is
1333% returned if the size cannot be determined.
1334%
1335% The format of the GetBlobSize method is:
1336%
1337% MagickSizeType GetBlobSize(const Image *image)
1338%
1339% A description of each parameter follows:
1340%
1341% o image: the image.
1342%
1343*/
1344MagickExport MagickSizeType GetBlobSize(const Image *image)
1345{
1346 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001347 extent;
cristy3ed852e2009-09-05 21:47:34 +00001348
1349 assert(image != (Image *) NULL);
1350 assert(image->signature == MagickSignature);
1351 if (image->debug != MagickFalse)
1352 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1353 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001354 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001355 switch (image->blob->type)
1356 {
1357 case UndefinedStream:
1358 {
cristy81b8ce52010-02-05 01:53:17 +00001359 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001360 break;
1361 }
cristybc20d112012-07-29 20:27:00 +00001362 case StandardStream:
1363 {
1364 extent=image->blob->size;
1365 break;
1366 }
cristy3ed852e2009-09-05 21:47:34 +00001367 case FileStream:
1368 {
cristye7b28372012-06-17 13:59:06 +00001369 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001370 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001371 break;
1372 }
cristy3ed852e2009-09-05 21:47:34 +00001373 case PipeStream:
1374 {
cristy81b8ce52010-02-05 01:53:17 +00001375 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001376 break;
1377 }
1378 case ZipStream:
1379 case BZipStream:
1380 {
1381 MagickBooleanType
1382 status;
1383
1384 status=GetPathAttributes(image->filename,&image->blob->properties);
1385 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001386 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001387 break;
1388 }
1389 case FifoStream:
1390 break;
1391 case BlobStream:
1392 {
cristy891dc792010-03-04 01:47:16 +00001393 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001394 break;
1395 }
1396 }
cristy81b8ce52010-02-05 01:53:17 +00001397 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001398}
1399
1400/*
1401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1402% %
1403% %
1404% %
1405+ G e t B l o b S t r e a m D a t a %
1406% %
1407% %
1408% %
1409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1410%
1411% GetBlobStreamData() returns the stream data for the image.
1412%
1413% The format of the GetBlobStreamData method is:
1414%
1415% unsigned char *GetBlobStreamData(const Image *image)
1416%
1417% A description of each parameter follows:
1418%
1419% o image: the image.
1420%
1421*/
1422MagickExport unsigned char *GetBlobStreamData(const Image *image)
1423{
1424 assert(image != (const Image *) NULL);
1425 assert(image->signature == MagickSignature);
1426 return(image->blob->data);
1427}
1428
1429/*
1430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1431% %
1432% %
1433% %
1434+ G e t B l o b S t r e a m H a n d l e r %
1435% %
1436% %
1437% %
1438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1439%
1440% GetBlobStreamHandler() returns the stream handler for the image.
1441%
1442% The format of the GetBlobStreamHandler method is:
1443%
1444% StreamHandler GetBlobStreamHandler(const Image *image)
1445%
1446% A description of each parameter follows:
1447%
1448% o image: the image.
1449%
1450*/
cristy7832dc22011-09-05 01:21:53 +00001451MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001452{
1453 assert(image != (const Image *) NULL);
1454 assert(image->signature == MagickSignature);
1455 if (image->debug != MagickFalse)
1456 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1457 return(image->blob->stream);
1458}
1459
1460/*
1461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1462% %
1463% %
1464% %
1465% I m a g e T o B l o b %
1466% %
1467% %
1468% %
1469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1470%
1471% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001472% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001473% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001474% etc.). This method is the equivalent of WriteImage(), but writes the
1475% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001476%
1477% The format of the ImageToBlob method is:
1478%
1479% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1480% size_t *length,ExceptionInfo *exception)
1481%
1482% A description of each parameter follows:
1483%
1484% o image_info: the image info.
1485%
1486% o image: the image.
1487%
1488% o length: This pointer to a size_t integer sets the initial length of the
1489% blob. On return, it reflects the actual length of the blob.
1490%
1491% o exception: return any errors or warnings in this structure.
1492%
1493*/
1494MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1495 Image *image,size_t *length,ExceptionInfo *exception)
1496{
1497 const MagickInfo
1498 *magick_info;
1499
1500 ImageInfo
1501 *blob_info;
1502
1503 MagickBooleanType
1504 status;
1505
1506 unsigned char
1507 *blob;
1508
1509 assert(image_info != (const ImageInfo *) NULL);
1510 assert(image_info->signature == MagickSignature);
1511 if (image_info->debug != MagickFalse)
1512 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1513 image_info->filename);
1514 assert(image != (Image *) NULL);
1515 assert(image->signature == MagickSignature);
1516 assert(exception != (ExceptionInfo *) NULL);
1517 *length=0;
1518 blob=(unsigned char *) NULL;
1519 blob_info=CloneImageInfo(image_info);
1520 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001521 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001522 if (*blob_info->magick != '\0')
1523 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1524 magick_info=GetMagickInfo(image->magick,exception);
1525 if (magick_info == (const MagickInfo *) NULL)
1526 {
1527 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001528 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001529 image->filename);
1530 return(blob);
1531 }
1532 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1533 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1534 {
1535 /*
1536 Native blob support for this image format.
1537 */
1538 blob_info->length=0;
1539 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1540 sizeof(unsigned char));
1541 if (blob_info->blob == (void *) NULL)
1542 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001543 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001544 else
1545 {
1546 (void) CloseBlob(image);
1547 image->blob->exempt=MagickTrue;
1548 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001549 status=WriteImage(blob_info,image,exception);
cristyc42554f2012-08-22 12:00:43 +00001550 blob=DetachBlob(image->blob);
cristy6e50f9e2012-08-22 16:30:29 +00001551 if (status == MagickFalse)
1552 blob=(unsigned char *) RelinquishMagickMemory(blob);
1553 else
cristy7a4b8c52014-01-25 22:48:06 +00001554 {
1555 *length=image->blob->length;
1556 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1557 sizeof(*blob));
1558 }
cristy3ed852e2009-09-05 21:47:34 +00001559 }
1560 }
1561 else
1562 {
1563 char
1564 unique[MaxTextExtent];
1565
1566 int
1567 file;
1568
1569 /*
1570 Write file to disk in blob image format.
1571 */
1572 file=AcquireUniqueFileResource(unique);
1573 if (file == -1)
1574 {
1575 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1576 image_info->filename);
1577 }
1578 else
1579 {
1580 blob_info->file=fdopen(file,"wb");
1581 if (blob_info->file != (FILE *) NULL)
1582 {
cristyb51dff52011-05-19 16:55:47 +00001583 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001584 image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001585 status=WriteImage(blob_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001586 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001587 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001588 blob=FileToBlob(image->filename,~0UL,length,exception);
1589 }
1590 (void) RelinquishUniqueFileResource(unique);
1591 }
1592 }
1593 blob_info=DestroyImageInfo(blob_info);
1594 return(blob);
1595}
1596
1597/*
1598%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1599% %
1600% %
1601% %
1602% I m a g e T o F i l e %
1603% %
1604% %
1605% %
1606%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1607%
1608% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1609% occurs otherwise MagickTrue.
1610%
1611% The format of the ImageToFile method is:
1612%
1613% MagickBooleanType ImageToFile(Image *image,char *filename,
1614% ExceptionInfo *exception)
1615%
1616% A description of each parameter follows:
1617%
1618% o image: the image.
1619%
1620% o filename: Write the image to this file.
1621%
1622% o exception: return any errors or warnings in this structure.
1623%
1624*/
cristy3ed852e2009-09-05 21:47:34 +00001625MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1626 ExceptionInfo *exception)
1627{
1628 int
1629 file;
1630
1631 register const unsigned char
1632 *p;
1633
1634 register size_t
1635 i;
1636
1637 size_t
1638 length,
1639 quantum;
1640
1641 ssize_t
1642 count;
1643
1644 struct stat
cristye7b28372012-06-17 13:59:06 +00001645 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001646
1647 unsigned char
1648 *buffer;
1649
1650 assert(image != (Image *) NULL);
1651 assert(image->signature == MagickSignature);
1652 assert(image->blob != (BlobInfo *) NULL);
1653 assert(image->blob->type != UndefinedStream);
1654 if (image->debug != MagickFalse)
1655 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1656 assert(filename != (const char *) NULL);
1657 if (*filename == '\0')
1658 file=AcquireUniqueFileResource(filename);
1659 else
1660 if (LocaleCompare(filename,"-") == 0)
1661 file=fileno(stdout);
1662 else
cristyb70aab92012-01-31 15:04:04 +00001663 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001664 if (file == -1)
1665 {
1666 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1667 return(MagickFalse);
1668 }
1669 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001670 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1671 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001672 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001673 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1674 if (buffer == (unsigned char *) NULL)
1675 {
1676 file=close(file)-1;
1677 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001678 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001679 return(MagickFalse);
1680 }
1681 length=0;
1682 p=ReadBlobStream(image,quantum,buffer,&count);
1683 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1684 {
1685 length=(size_t) count;
1686 for (i=0; i < length; i+=count)
1687 {
1688 count=write(file,p+i,(size_t) (length-i));
1689 if (count <= 0)
1690 {
1691 count=0;
1692 if (errno != EINTR)
1693 break;
1694 }
1695 }
1696 if (i < length)
1697 break;
1698 }
cristy54439632010-07-15 00:43:34 +00001699 if (LocaleCompare(filename,"-") != 0)
1700 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001701 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001702 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001703 {
1704 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1705 return(MagickFalse);
1706 }
1707 return(MagickTrue);
1708}
1709
1710/*
1711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1712% %
1713% %
1714% %
1715% I m a g e s T o B l o b %
1716% %
1717% %
1718% %
1719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1720%
1721% ImagesToBlob() implements direct to memory image formats. It returns the
1722% image sequence as a blob and its length. The magick member of the ImageInfo
1723% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1724%
1725% Note, some image formats do not permit multiple images to the same image
1726% stream (e.g. JPEG). in this instance, just the first image of the
1727% sequence is returned as a blob.
1728%
1729% The format of the ImagesToBlob method is:
1730%
1731% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1732% size_t *length,ExceptionInfo *exception)
1733%
1734% A description of each parameter follows:
1735%
1736% o image_info: the image info.
1737%
1738% o images: the image list.
1739%
1740% o length: This pointer to a size_t integer sets the initial length of the
1741% blob. On return, it reflects the actual length of the blob.
1742%
1743% o exception: return any errors or warnings in this structure.
1744%
1745*/
1746MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1747 Image *images,size_t *length,ExceptionInfo *exception)
1748{
1749 const MagickInfo
1750 *magick_info;
1751
1752 ImageInfo
1753 *blob_info;
1754
1755 MagickBooleanType
1756 status;
1757
1758 unsigned char
1759 *blob;
1760
1761 assert(image_info != (const ImageInfo *) NULL);
1762 assert(image_info->signature == MagickSignature);
1763 if (image_info->debug != MagickFalse)
1764 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1765 image_info->filename);
1766 assert(images != (Image *) NULL);
1767 assert(images->signature == MagickSignature);
1768 assert(exception != (ExceptionInfo *) NULL);
1769 *length=0;
1770 blob=(unsigned char *) NULL;
1771 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001772 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1773 exception);
cristy3ed852e2009-09-05 21:47:34 +00001774 if (*blob_info->magick != '\0')
1775 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1776 if (blob_info->adjoin == MagickFalse)
1777 {
1778 blob_info=DestroyImageInfo(blob_info);
1779 return(ImageToBlob(image_info,images,length,exception));
1780 }
1781 magick_info=GetMagickInfo(images->magick,exception);
1782 if (magick_info == (const MagickInfo *) NULL)
1783 {
1784 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001785 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001786 images->filename);
1787 return(blob);
1788 }
1789 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1790 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1791 {
1792 /*
1793 Native blob support for this images format.
1794 */
1795 blob_info->length=0;
1796 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1797 sizeof(unsigned char));
1798 if (blob_info->blob == (void *) NULL)
1799 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001800 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
cristy3ed852e2009-09-05 21:47:34 +00001801 else
1802 {
cristy7a4b8c52014-01-25 22:48:06 +00001803 (void) CloseBlob(images);
cristy3ed852e2009-09-05 21:47:34 +00001804 images->blob->exempt=MagickTrue;
1805 *images->filename='\0';
1806 status=WriteImages(blob_info,images,images->filename,exception);
cristy7a4b8c52014-01-25 22:48:06 +00001807 blob=DetachBlob(images->blob);
1808 if (status == MagickFalse)
1809 blob=(unsigned char *) RelinquishMagickMemory(blob);
1810 else
cristy3ed852e2009-09-05 21:47:34 +00001811 {
1812 *length=images->blob->length;
cristy7a4b8c52014-01-25 22:48:06 +00001813 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
cristy3ed852e2009-09-05 21:47:34 +00001814 sizeof(*blob));
1815 }
1816 }
1817 }
1818 else
1819 {
1820 char
1821 filename[MaxTextExtent],
1822 unique[MaxTextExtent];
1823
1824 int
1825 file;
1826
1827 /*
1828 Write file to disk in blob images format.
1829 */
1830 file=AcquireUniqueFileResource(unique);
1831 if (file == -1)
1832 {
1833 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1834 image_info->filename);
1835 }
1836 else
1837 {
1838 blob_info->file=fdopen(file,"wb");
1839 if (blob_info->file != (FILE *) NULL)
1840 {
cristyb51dff52011-05-19 16:55:47 +00001841 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001842 images->magick,unique);
1843 status=WriteImages(blob_info,images,filename,exception);
1844 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001845 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001846 blob=FileToBlob(images->filename,~0UL,length,exception);
1847 }
1848 (void) RelinquishUniqueFileResource(unique);
1849 }
1850 }
1851 blob_info=DestroyImageInfo(blob_info);
1852 return(blob);
1853}
1854/*
1855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1856% %
1857% %
1858% %
1859% I n j e c t I m a g e B l o b %
1860% %
1861% %
1862% %
1863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1864%
1865% InjectImageBlob() injects the image with a copy of itself in the specified
1866% format (e.g. inject JPEG into a PDF image).
1867%
1868% The format of the InjectImageBlob method is:
1869%
1870% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1871% Image *image,Image *inject_image,const char *format,
1872% ExceptionInfo *exception)
1873%
1874% A description of each parameter follows:
1875%
1876% o image_info: the image info..
1877%
1878% o image: the image.
1879%
1880% o inject_image: inject into the image stream.
1881%
1882% o format: the image format.
1883%
1884% o exception: return any errors or warnings in this structure.
1885%
1886*/
1887MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1888 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1889{
1890 char
1891 filename[MaxTextExtent];
1892
1893 FILE
1894 *unique_file;
1895
1896 Image
1897 *byte_image;
1898
1899 ImageInfo
1900 *write_info;
1901
1902 int
1903 file;
1904
1905 MagickBooleanType
1906 status;
1907
cristybb503372010-05-27 20:51:26 +00001908 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001909 i;
1910
1911 size_t
1912 quantum;
1913
1914 ssize_t
1915 count;
1916
1917 struct stat
cristye7b28372012-06-17 13:59:06 +00001918 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001919
1920 unsigned char
1921 *buffer;
1922
1923 /*
1924 Write inject image to a temporary file.
1925 */
1926 assert(image_info != (ImageInfo *) NULL);
1927 assert(image_info->signature == MagickSignature);
1928 assert(image != (Image *) NULL);
1929 assert(image->signature == MagickSignature);
1930 if (image->debug != MagickFalse)
1931 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1932 assert(inject_image != (Image *) NULL);
1933 assert(inject_image->signature == MagickSignature);
1934 assert(exception != (ExceptionInfo *) NULL);
1935 unique_file=(FILE *) NULL;
1936 file=AcquireUniqueFileResource(filename);
1937 if (file != -1)
1938 unique_file=fdopen(file,"wb");
1939 if ((file == -1) || (unique_file == (FILE *) NULL))
1940 {
1941 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1942 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1943 image->filename);
1944 return(MagickFalse);
1945 }
1946 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1947 if (byte_image == (Image *) NULL)
1948 {
1949 (void) fclose(unique_file);
1950 (void) RelinquishUniqueFileResource(filename);
1951 return(MagickFalse);
1952 }
cristyb51dff52011-05-19 16:55:47 +00001953 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001954 filename);
1955 DestroyBlob(byte_image);
1956 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1957 write_info=CloneImageInfo(image_info);
1958 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001959 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001960 write_info=DestroyImageInfo(write_info);
1961 byte_image=DestroyImage(byte_image);
1962 (void) fclose(unique_file);
1963 if (status == MagickFalse)
1964 {
1965 (void) RelinquishUniqueFileResource(filename);
1966 return(MagickFalse);
1967 }
1968 /*
1969 Inject into image stream.
1970 */
cristy18c6c272011-09-23 14:40:37 +00001971 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001972 if (file == -1)
1973 {
1974 (void) RelinquishUniqueFileResource(filename);
1975 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1976 image_info->filename);
1977 return(MagickFalse);
1978 }
1979 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001980 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1981 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001982 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1983 if (buffer == (unsigned char *) NULL)
1984 {
1985 (void) RelinquishUniqueFileResource(filename);
1986 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1987 image->filename);
1988 }
1989 for (i=0; ; i+=count)
1990 {
cristy65d11e42013-06-14 20:06:25 +00001991 count=read(file,buffer,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001992 if (count <= 0)
1993 {
1994 count=0;
1995 if (errno != EINTR)
1996 break;
1997 }
1998 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1999 MagickFalse;
2000 }
cristya7cb4312010-06-26 00:47:03 +00002001 file=close(file);
2002 if (file == -1)
2003 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00002004 (void) RelinquishUniqueFileResource(filename);
2005 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2006 return(status);
2007}
2008
2009/*
2010%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2011% %
2012% %
2013% %
2014+ I s B l o b E x e m p t %
2015% %
2016% %
2017% %
2018%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2019%
2020% IsBlobExempt() returns true if the blob is exempt.
2021%
2022% The format of the IsBlobExempt method is:
2023%
2024% MagickBooleanType IsBlobExempt(const Image *image)
2025%
2026% A description of each parameter follows:
2027%
2028% o image: the image.
2029%
2030*/
cristy7832dc22011-09-05 01:21:53 +00002031MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002032{
2033 assert(image != (const Image *) NULL);
2034 assert(image->signature == MagickSignature);
2035 if (image->debug != MagickFalse)
2036 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2037 return(image->blob->exempt);
2038}
2039
2040/*
2041%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2042% %
2043% %
2044% %
2045+ I s B l o b S e e k a b l e %
2046% %
2047% %
2048% %
2049%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2050%
2051% IsBlobSeekable() returns true if the blob is seekable.
2052%
2053% The format of the IsBlobSeekable method is:
2054%
2055% MagickBooleanType IsBlobSeekable(const Image *image)
2056%
2057% A description of each parameter follows:
2058%
2059% o image: the image.
2060%
2061*/
cristy7832dc22011-09-05 01:21:53 +00002062MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002063{
2064 MagickBooleanType
2065 seekable;
2066
2067 assert(image != (const Image *) NULL);
2068 assert(image->signature == MagickSignature);
2069 if (image->debug != MagickFalse)
2070 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002071 switch (image->blob->type)
2072 {
2073 case FileStream:
2074 case BlobStream:
2075 case ZipStream:
2076 {
2077 seekable=MagickTrue;
2078 break;
2079 }
2080 default:
2081 {
2082 seekable=MagickFalse;
2083 break;
2084 }
2085 }
cristy3ed852e2009-09-05 21:47:34 +00002086 return(seekable);
2087}
2088
2089/*
2090%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2091% %
2092% %
2093% %
2094+ I s B l o b T e m p o r a r y %
2095% %
2096% %
2097% %
2098%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2099%
2100% IsBlobTemporary() returns true if the blob is temporary.
2101%
2102% The format of the IsBlobTemporary method is:
2103%
2104% MagickBooleanType IsBlobTemporary(const Image *image)
2105%
2106% A description of each parameter follows:
2107%
2108% o image: the image.
2109%
2110*/
cristy7832dc22011-09-05 01:21:53 +00002111MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002112{
2113 assert(image != (const Image *) NULL);
2114 assert(image->signature == MagickSignature);
2115 if (image->debug != MagickFalse)
2116 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2117 return(image->blob->temporary);
2118}
2119
2120/*
2121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2122% %
2123% %
2124% %
2125+ M a p B l o b %
2126% %
2127% %
2128% %
2129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2130%
2131% MapBlob() creates a mapping from a file to a binary large object.
2132%
2133% The format of the MapBlob method is:
2134%
2135% unsigned char *MapBlob(int file,const MapMode mode,
2136% const MagickOffsetType offset,const size_t length)
2137%
2138% A description of each parameter follows:
2139%
2140% o file: map this file descriptor.
2141%
2142% o mode: ReadMode, WriteMode, or IOMode.
2143%
2144% o offset: starting at this offset within the file.
2145%
2146% o length: the length of the mapping is returned in this pointer.
2147%
2148*/
2149MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2150 const MagickOffsetType offset,const size_t length)
2151{
cristydc8ea8e2013-07-28 20:10:44 +00002152#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00002153 int
2154 flags,
2155 protection;
2156
2157 unsigned char
2158 *map;
2159
2160 /*
2161 Map file.
2162 */
2163 flags=0;
2164 if (file == -1)
2165#if defined(MAP_ANONYMOUS)
2166 flags|=MAP_ANONYMOUS;
2167#else
2168 return((unsigned char *) NULL);
2169#endif
2170 switch (mode)
2171 {
2172 case ReadMode:
2173 default:
2174 {
2175 protection=PROT_READ;
2176 flags|=MAP_PRIVATE;
cristy3ed852e2009-09-05 21:47:34 +00002177 break;
2178 }
2179 case WriteMode:
2180 {
2181 protection=PROT_WRITE;
2182 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002183 break;
2184 }
2185 case IOMode:
2186 {
2187 protection=PROT_READ | PROT_WRITE;
2188 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002189 break;
2190 }
2191 }
cristy56a0dbe2013-07-09 15:27:09 +00002192#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2193 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2194 (off_t) offset);
2195#else
cristy7a4b8c52014-01-25 22:48:06 +00002196 map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
cristy56a0dbe2013-07-09 15:27:09 +00002197 MAP_HUGETLB,file,(off_t) offset);
2198 if (map == (unsigned char *) MAP_FAILED)
2199 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2200 (off_t) offset);
2201#endif
cristy3ed852e2009-09-05 21:47:34 +00002202 if (map == (unsigned char *) MAP_FAILED)
2203 return((unsigned char *) NULL);
2204 return(map);
2205#else
2206 (void) file;
2207 (void) mode;
2208 (void) offset;
2209 (void) length;
2210 return((unsigned char *) NULL);
2211#endif
2212}
2213
2214/*
2215%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2216% %
2217% %
2218% %
2219+ M S B O r d e r L o n g %
2220% %
2221% %
2222% %
2223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2224%
2225% MSBOrderLong() converts a least-significant byte first buffer of integers to
2226% most-significant byte first.
2227%
2228% The format of the MSBOrderLong method is:
2229%
2230% void MSBOrderLong(unsigned char *buffer,const size_t length)
2231%
2232% A description of each parameter follows.
2233%
2234% o buffer: Specifies a pointer to a buffer of integers.
2235%
2236% o length: Specifies the length of the buffer.
2237%
2238*/
2239MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2240{
2241 int
2242 c;
2243
2244 register unsigned char
2245 *p,
2246 *q;
2247
2248 assert(buffer != (unsigned char *) NULL);
2249 q=buffer+length;
2250 while (buffer < q)
2251 {
2252 p=buffer+3;
2253 c=(int) (*p);
2254 *p=(*buffer);
2255 *buffer++=(unsigned char) c;
2256 p=buffer+1;
2257 c=(int) (*p);
2258 *p=(*buffer);
2259 *buffer++=(unsigned char) c;
2260 buffer+=2;
2261 }
2262}
2263
2264/*
2265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2266% %
2267% %
2268% %
2269+ M S B O r d e r S h o r t %
2270% %
2271% %
2272% %
2273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2274%
2275% MSBOrderShort() converts a least-significant byte first buffer of integers
2276% to most-significant byte first.
2277%
2278% The format of the MSBOrderShort method is:
2279%
2280% void MSBOrderShort(unsigned char *p,const size_t length)
2281%
2282% A description of each parameter follows.
2283%
2284% o p: Specifies a pointer to a buffer of integers.
2285%
2286% o length: Specifies the length of the buffer.
2287%
2288*/
2289MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2290{
2291 int
2292 c;
2293
2294 register unsigned char
2295 *q;
2296
2297 assert(p != (unsigned char *) NULL);
2298 q=p+length;
2299 while (p < q)
2300 {
2301 c=(int) (*p);
2302 *p=(*(p+1));
2303 p++;
2304 *p++=(unsigned char) c;
2305 }
2306}
2307
2308/*
2309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2310% %
2311% %
2312% %
2313+ O p e n B l o b %
2314% %
2315% %
2316% %
2317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2318%
2319% OpenBlob() opens a file associated with the image. A file name of '-' sets
2320% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2321% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2322% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2323% from a system command.
2324%
2325% The format of the OpenBlob method is:
2326%
2327% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2328% const BlobMode mode,ExceptionInfo *exception)
2329%
2330% A description of each parameter follows:
2331%
2332% o image_info: the image info.
2333%
2334% o image: the image.
2335%
2336% o mode: the mode for opening the file.
2337%
2338*/
2339MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2340 Image *image,const BlobMode mode,ExceptionInfo *exception)
2341{
2342 char
cristybf6a7092010-06-11 02:12:15 +00002343 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002344 filename[MaxTextExtent];
2345
2346 const char
2347 *type;
2348
2349 MagickBooleanType
2350 status;
2351
2352 PolicyRights
2353 rights;
2354
2355 assert(image_info != (ImageInfo *) NULL);
2356 assert(image_info->signature == MagickSignature);
2357 if (image_info->debug != MagickFalse)
2358 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2359 image_info->filename);
2360 assert(image != (Image *) NULL);
2361 assert(image->signature == MagickSignature);
2362 if (image_info->blob != (void *) NULL)
2363 {
2364 if (image_info->stream != (StreamHandler) NULL)
2365 image->blob->stream=(StreamHandler) image_info->stream;
2366 AttachBlob(image->blob,image_info->blob,image_info->length);
2367 return(MagickTrue);
2368 }
2369 (void) DetachBlob(image->blob);
2370 switch (mode)
2371 {
2372 default: type="r"; break;
2373 case ReadBlobMode: type="r"; break;
2374 case ReadBinaryBlobMode: type="rb"; break;
2375 case WriteBlobMode: type="w"; break;
2376 case WriteBinaryBlobMode: type="w+b"; break;
2377 case AppendBlobMode: type="a"; break;
2378 case AppendBinaryBlobMode: type="a+b"; break;
2379 }
2380 if (*type != 'r')
2381 image->blob->synchronize=image_info->synchronize;
2382 if (image_info->stream != (StreamHandler) NULL)
2383 {
2384 image->blob->stream=(StreamHandler) image_info->stream;
2385 if (*type == 'w')
2386 {
2387 image->blob->type=FifoStream;
2388 return(MagickTrue);
2389 }
2390 }
2391 /*
2392 Open image file.
2393 */
2394 *filename='\0';
2395 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2396 rights=ReadPolicyRights;
2397 if (*type == 'w')
2398 rights=WritePolicyRights;
2399 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2400 {
cristya9197f62010-01-12 02:23:34 +00002401 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002402 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
cristyefe601c2013-01-05 17:51:12 +00002403 "NotAuthorized","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00002404 return(MagickFalse);
2405 }
2406 if ((LocaleCompare(filename,"-") == 0) ||
2407 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2408 {
cristye7b28372012-06-17 13:59:06 +00002409 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002410#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002411 if (strchr(type,'b') != (char *) NULL)
cristye7b28372012-06-17 13:59:06 +00002412 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002413#endif
2414 image->blob->type=StandardStream;
2415 image->blob->exempt=MagickTrue;
2416 return(MagickTrue);
2417 }
cristybc20d112012-07-29 20:27:00 +00002418 if (LocaleNCompare(filename,"fd:",3) == 0)
2419 {
2420 char
2421 mode[MaxTextExtent];
2422
2423 *mode=(*type);
2424 mode[1]='\0';
2425 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2426#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2427 if (strchr(type,'b') != (char *) NULL)
2428 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2429#endif
2430 image->blob->type=StandardStream;
2431 image->blob->exempt=MagickTrue;
2432 return(MagickTrue);
2433 }
cristy3ed852e2009-09-05 21:47:34 +00002434#if defined(MAGICKCORE_HAVE_POPEN)
2435 if (*filename == '|')
2436 {
2437 char
2438 mode[MaxTextExtent];
2439
2440 /*
2441 Pipe image to or from a system command.
2442 */
2443#if defined(SIGPIPE)
2444 if (*type == 'w')
2445 (void) signal(SIGPIPE,SIG_IGN);
2446#endif
2447 *mode=(*type);
2448 mode[1]='\0';
cristye7b28372012-06-17 13:59:06 +00002449 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2450 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002451 {
2452 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2453 return(MagickFalse);
2454 }
2455 image->blob->type=PipeStream;
2456 image->blob->exempt=MagickTrue;
2457 return(MagickTrue);
2458 }
2459#endif
2460 status=GetPathAttributes(filename,&image->blob->properties);
2461#if defined(S_ISFIFO)
cristycd8b3312013-12-22 01:51:11 +00002462 if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
cristy3ed852e2009-09-05 21:47:34 +00002463 {
cristye7b28372012-06-17 13:59:06 +00002464 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2465 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002466 {
2467 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2468 return(MagickFalse);
2469 }
2470 image->blob->type=FileStream;
2471 image->blob->exempt=MagickTrue;
2472 return(MagickTrue);
2473 }
2474#endif
cristybf6a7092010-06-11 02:12:15 +00002475 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002476 if (*type == 'w')
2477 {
cristye8939e72010-02-03 17:05:25 +00002478 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002479 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002480 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002481 {
2482 /*
2483 Form filename for multi-part images.
2484 */
2485 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002486 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002487 if ((LocaleCompare(filename,image->filename) == 0) &&
2488 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2489 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002490 {
cristybf7fa0d2010-02-04 00:51:10 +00002491 char
cristybf7fa0d2010-02-04 00:51:10 +00002492 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002493
cristybf7fa0d2010-02-04 00:51:10 +00002494 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002495 if (*extension == '\0')
cristyb51dff52011-05-19 16:55:47 +00002496 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002497 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002498 else
cristyb51dff52011-05-19 16:55:47 +00002499 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002500 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002501 }
2502 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002503#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002504 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002505#endif
cristye8939e72010-02-03 17:05:25 +00002506 }
cristy3ed852e2009-09-05 21:47:34 +00002507 }
cristybf6a7092010-06-11 02:12:15 +00002508 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002509 {
cristye7b28372012-06-17 13:59:06 +00002510 image->blob->file_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002511 image->blob->type=FileStream;
2512 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002513 }
2514 else
cristybf6a7092010-06-11 02:12:15 +00002515 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002516 {
cristye7b28372012-06-17 13:59:06 +00002517 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2518 if (image->blob->file_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002519 {
2520 size_t
cristybf6a7092010-06-11 02:12:15 +00002521 count;
cristy3ed852e2009-09-05 21:47:34 +00002522
cristybf6a7092010-06-11 02:12:15 +00002523 unsigned char
2524 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002525
cristybf6a7092010-06-11 02:12:15 +00002526 image->blob->type=FileStream;
2527#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002528 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2529 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002530#endif
2531 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristye7b28372012-06-17 13:59:06 +00002532 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
cristyae958042013-01-05 15:48:19 +00002533 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
cristy79fe6932012-12-25 00:31:30 +00002534 (void) fflush(image->blob->file_info.file);
cristybf6a7092010-06-11 02:12:15 +00002535 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2536 " read %.20g magic header bytes",(double) count);
2537#if defined(MAGICKCORE_ZLIB_DELEGATE)
2538 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2539 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002540 {
cristye7b28372012-06-17 13:59:06 +00002541 (void) fclose(image->blob->file_info.file);
2542 image->blob->file_info.gzfile=gzopen(filename,type);
2543 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002544 image->blob->type=ZipStream;
2545 }
2546#endif
2547#if defined(MAGICKCORE_BZLIB_DELEGATE)
2548 if (strncmp((char *) magick,"BZh",3) == 0)
2549 {
cristye7b28372012-06-17 13:59:06 +00002550 (void) fclose(image->blob->file_info.file);
2551 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2552 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002553 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002554 }
cristybf6a7092010-06-11 02:12:15 +00002555#endif
cristyc6c589d2010-07-06 01:34:57 +00002556 if (image->blob->type == FileStream)
2557 {
2558 const MagickInfo
2559 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002560
cristyc6c589d2010-07-06 01:34:57 +00002561 ExceptionInfo
2562 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002563
cristy18aba912013-06-14 19:48:08 +00002564 size_t
2565 length;
2566
cristyc6c589d2010-07-06 01:34:57 +00002567 sans_exception=AcquireExceptionInfo();
2568 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2569 sans_exception=DestroyExceptionInfo(sans_exception);
cristy2eddb3d2013-06-16 14:10:08 +00002570 length=(size_t) image->blob->properties.st_size;
cristyc6c589d2010-07-06 01:34:57 +00002571 if ((magick_info != (const MagickInfo *) NULL) &&
2572 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
cristy7c242ea2013-06-21 17:19:53 +00002573 (length <= MagickMaxBufferExtent) &&
cristy18aba912013-06-14 19:48:08 +00002574 (AcquireMagickResource(MapResource,length) != MagickFalse))
cristyc6c589d2010-07-06 01:34:57 +00002575 {
cristyc6c589d2010-07-06 01:34:57 +00002576 void
2577 *blob;
cristybf6a7092010-06-11 02:12:15 +00002578
cristyfe00ebf2013-06-16 14:17:53 +00002579 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2580 length);
cristy18aba912013-06-14 19:48:08 +00002581 if (blob == (void *) NULL)
2582 RelinquishMagickResource(MapResource,length);
2583 else
cristyc6c589d2010-07-06 01:34:57 +00002584 {
2585 /*
2586 Format supports blobs-- use memory-mapped I/O.
2587 */
2588 if (image_info->file != (FILE *) NULL)
2589 image->blob->exempt=MagickFalse;
2590 else
2591 {
cristye7b28372012-06-17 13:59:06 +00002592 (void) fclose(image->blob->file_info.file);
2593 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002594 }
2595 AttachBlob(image->blob,blob,length);
2596 image->blob->mapped=MagickTrue;
2597 }
2598 }
2599 }
cristy3ed852e2009-09-05 21:47:34 +00002600 }
cristybf6a7092010-06-11 02:12:15 +00002601 }
2602 else
2603#if defined(MAGICKCORE_ZLIB_DELEGATE)
2604 if ((LocaleCompare(extension,"Z") == 0) ||
2605 (LocaleCompare(extension,"gz") == 0) ||
2606 (LocaleCompare(extension,"wmz") == 0) ||
2607 (LocaleCompare(extension,"svgz") == 0))
2608 {
2609 if (mode == WriteBinaryBlobMode)
2610 type="wb";
cristye7b28372012-06-17 13:59:06 +00002611 image->blob->file_info.gzfile=gzopen(filename,type);
2612 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002613 image->blob->type=ZipStream;
2614 }
2615 else
2616#endif
2617#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002618 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002619 {
cristye7b28372012-06-17 13:59:06 +00002620 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2621 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002622 image->blob->type=BZipStream;
2623 }
2624 else
2625#endif
2626 {
cristye7b28372012-06-17 13:59:06 +00002627 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2628 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002629 {
2630 image->blob->type=FileStream;
2631#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002632 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2633 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002634#endif
2635 }
2636 }
cristy3ed852e2009-09-05 21:47:34 +00002637 image->blob->status=MagickFalse;
2638 if (image->blob->type != UndefinedStream)
2639 image->blob->size=GetBlobSize(image);
2640 else
2641 {
2642 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2643 return(MagickFalse);
2644 }
2645 return(MagickTrue);
2646}
2647
2648/*
2649%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2650% %
2651% %
2652% %
2653+ P i n g B l o b %
2654% %
2655% %
2656% %
2657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2658%
2659% PingBlob() returns all the attributes of an image or image sequence except
2660% for the pixels. It is much faster and consumes far less memory than
2661% BlobToImage(). On failure, a NULL image is returned and exception
2662% describes the reason for the failure.
2663%
2664% The format of the PingBlob method is:
2665%
2666% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2667% const size_t length,ExceptionInfo *exception)
2668%
2669% A description of each parameter follows:
2670%
2671% o image_info: the image info.
2672%
2673% o blob: the address of a character stream in one of the image formats
2674% understood by ImageMagick.
2675%
2676% o length: This size_t integer reflects the length in bytes of the blob.
2677%
2678% o exception: return any errors or warnings in this structure.
2679%
2680*/
2681
2682#if defined(__cplusplus) || defined(c_plusplus)
2683extern "C" {
2684#endif
2685
2686static size_t PingStream(const Image *magick_unused(image),
2687 const void *magick_unused(pixels),const size_t columns)
2688{
2689 return(columns);
2690}
2691
2692#if defined(__cplusplus) || defined(c_plusplus)
2693}
2694#endif
2695
2696MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2697 const size_t length,ExceptionInfo *exception)
2698{
2699 Image
2700 *image;
2701
2702 ImageInfo
2703 *ping_info;
2704
2705 assert(image_info != (ImageInfo *) NULL);
2706 assert(image_info->signature == MagickSignature);
2707 if (image_info->debug != MagickFalse)
2708 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2709 image_info->filename);
2710 assert(exception != (ExceptionInfo *) NULL);
2711 if ((blob == (const void *) NULL) || (length == 0))
2712 {
2713 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +00002714 "UnrecognizedImageFormat","`%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002715 return((Image *) NULL);
2716 }
2717 ping_info=CloneImageInfo(image_info);
2718 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2719 if (ping_info->blob == (const void *) NULL)
2720 {
2721 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00002722 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002723 return((Image *) NULL);
2724 }
cristy54aad5e2010-09-03 16:02:04 +00002725 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002726 ping_info->length=length;
2727 ping_info->ping=MagickTrue;
2728 image=ReadStream(ping_info,&PingStream,exception);
2729 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2730 ping_info=DestroyImageInfo(ping_info);
2731 return(image);
2732}
2733
2734/*
2735%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2736% %
2737% %
2738% %
2739+ R e a d B l o b %
2740% %
2741% %
2742% %
2743%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2744%
2745% ReadBlob() reads data from the blob or image file and returns it. It
cristy5f3d2752013-01-05 18:53:38 +00002746% returns the number of bytes read. If length is zero, ReadBlob() returns
2747% zero and has no other results. If length is greater than SSIZE_MAX, the
2748% result is unspecified.
cristy3ed852e2009-09-05 21:47:34 +00002749%
2750% The format of the ReadBlob method is:
2751%
2752% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2753%
2754% A description of each parameter follows:
2755%
2756% o image: the image.
2757%
2758% o length: Specifies an integer representing the number of bytes to read
2759% from the file.
2760%
2761% o data: Specifies an area to place the information requested from the
2762% file.
2763%
2764*/
2765MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2766 unsigned char *data)
2767{
2768 int
2769 c;
2770
2771 register unsigned char
2772 *q;
2773
2774 ssize_t
2775 count;
2776
2777 assert(image != (Image *) NULL);
2778 assert(image->signature == MagickSignature);
2779 assert(image->blob != (BlobInfo *) NULL);
2780 assert(image->blob->type != UndefinedStream);
2781 if (length == 0)
2782 return(0);
2783 assert(data != (void *) NULL);
2784 count=0;
2785 q=data;
2786 switch (image->blob->type)
2787 {
2788 case UndefinedStream:
2789 break;
cristy3ed852e2009-09-05 21:47:34 +00002790 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002791 {
cristy8faec1e2013-04-25 19:41:22 +00002792 register ssize_t
2793 i;
2794
2795 for (i=0; i < (ssize_t) length; i+=count)
2796 {
cristy7c242ea2013-06-21 17:19:53 +00002797 count=read(fileno(image->blob->file_info.file),q+i,(size_t)
cristy8faec1e2013-04-25 19:41:22 +00002798 MagickMin(length-i,(MagickSizeType) SSIZE_MAX));
2799 if (count <= 0)
2800 {
2801 count=0;
2802 if (errno != EINTR)
2803 break;
2804 }
2805 }
2806 count=i;
cristybc20d112012-07-29 20:27:00 +00002807 break;
2808 }
2809 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002810 case PipeStream:
2811 {
2812 switch (length)
2813 {
2814 default:
2815 {
cristye7b28372012-06-17 13:59:06 +00002816 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002817 break;
2818 }
2819 case 2:
2820 {
cristye7b28372012-06-17 13:59:06 +00002821 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002822 if (c == EOF)
2823 break;
2824 *q++=(unsigned char) c;
2825 count++;
2826 }
2827 case 1:
2828 {
cristye7b28372012-06-17 13:59:06 +00002829 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002830 if (c == EOF)
2831 break;
2832 *q++=(unsigned char) c;
2833 count++;
2834 }
2835 case 0:
2836 break;
2837 }
2838 break;
2839 }
2840 case ZipStream:
2841 {
2842#if defined(MAGICKCORE_ZLIB_DELEGATE)
2843 switch (length)
2844 {
2845 default:
2846 {
cristye7b28372012-06-17 13:59:06 +00002847 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002848 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002849 break;
2850 }
2851 case 2:
2852 {
cristye7b28372012-06-17 13:59:06 +00002853 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002854 if (c == EOF)
2855 break;
2856 *q++=(unsigned char) c;
2857 count++;
2858 }
2859 case 1:
2860 {
cristye7b28372012-06-17 13:59:06 +00002861 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002862 if (c == EOF)
2863 break;
2864 *q++=(unsigned char) c;
2865 count++;
2866 }
2867 case 0:
2868 break;
2869 }
2870#endif
2871 break;
2872 }
2873 case BZipStream:
2874 {
2875#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy5f3d2752013-01-05 18:53:38 +00002876 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
cristy3ed852e2009-09-05 21:47:34 +00002877#endif
2878 break;
2879 }
2880 case FifoStream:
2881 break;
2882 case BlobStream:
2883 {
2884 register const unsigned char
2885 *p;
2886
2887 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2888 {
2889 image->blob->eof=MagickTrue;
2890 break;
2891 }
2892 p=image->blob->data+image->blob->offset;
cristye7b28372012-06-17 13:59:06 +00002893 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2894 image->blob->offset));
cristy3ed852e2009-09-05 21:47:34 +00002895 image->blob->offset+=count;
2896 if (count != (ssize_t) length)
2897 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002898 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002899 break;
2900 }
2901 }
2902 return(count);
2903}
2904
2905/*
2906%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2907% %
2908% %
2909% %
2910+ R e a d B l o b B y t e %
2911% %
2912% %
2913% %
2914%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2915%
2916% ReadBlobByte() reads a single byte from the image file and returns it.
2917%
2918% The format of the ReadBlobByte method is:
2919%
2920% int ReadBlobByte(Image *image)
2921%
2922% A description of each parameter follows.
2923%
2924% o image: the image.
2925%
2926*/
2927MagickExport int ReadBlobByte(Image *image)
2928{
2929 register const unsigned char
2930 *p;
2931
2932 ssize_t
2933 count;
2934
2935 unsigned char
2936 buffer[1];
2937
2938 assert(image != (Image *) NULL);
2939 assert(image->signature == MagickSignature);
2940 p=ReadBlobStream(image,1,buffer,&count);
2941 if (count != 1)
2942 return(EOF);
2943 return((int) (*p));
2944}
2945
2946/*
2947%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2948% %
2949% %
2950% %
2951+ R e a d B l o b D o u b l e %
2952% %
2953% %
2954% %
2955%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2956%
2957% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2958% specified by the endian member of the image structure.
2959%
2960% The format of the ReadBlobDouble method is:
2961%
2962% double ReadBlobDouble(Image *image)
2963%
2964% A description of each parameter follows.
2965%
2966% o image: the image.
2967%
2968*/
2969MagickExport double ReadBlobDouble(Image *image)
2970{
2971 union
2972 {
2973 MagickSizeType
2974 unsigned_value;
2975
2976 double
2977 double_value;
2978 } quantum;
2979
2980 quantum.double_value=0.0;
2981 quantum.unsigned_value=ReadBlobLongLong(image);
2982 return(quantum.double_value);
2983}
2984
2985/*
2986%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2987% %
2988% %
2989% %
2990+ R e a d B l o b F l o a t %
2991% %
2992% %
2993% %
2994%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2995%
2996% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2997% specified by the endian member of the image structure.
2998%
2999% The format of the ReadBlobFloat method is:
3000%
3001% float ReadBlobFloat(Image *image)
3002%
3003% A description of each parameter follows.
3004%
3005% o image: the image.
3006%
3007*/
3008MagickExport float ReadBlobFloat(Image *image)
3009{
3010 union
3011 {
3012 unsigned int
3013 unsigned_value;
3014
3015 float
3016 float_value;
3017 } quantum;
3018
3019 quantum.float_value=0.0;
3020 quantum.unsigned_value=ReadBlobLong(image);
3021 return(quantum.float_value);
3022}
3023
3024/*
3025%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3026% %
3027% %
3028% %
3029+ R e a d B l o b L o n g %
3030% %
3031% %
3032% %
3033%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3034%
cristybb503372010-05-27 20:51:26 +00003035% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003036% specified by the endian member of the image structure.
3037%
3038% The format of the ReadBlobLong method is:
3039%
3040% unsigned int ReadBlobLong(Image *image)
3041%
3042% A description of each parameter follows.
3043%
3044% o image: the image.
3045%
3046*/
3047MagickExport unsigned int ReadBlobLong(Image *image)
3048{
3049 register const unsigned char
3050 *p;
3051
3052 ssize_t
3053 count;
3054
3055 unsigned char
3056 buffer[4];
3057
3058 unsigned int
3059 value;
3060
3061 assert(image != (Image *) NULL);
3062 assert(image->signature == MagickSignature);
3063 *buffer='\0';
3064 p=ReadBlobStream(image,4,buffer,&count);
3065 if (count != 4)
3066 return(0UL);
3067 if (image->endian == LSBEndian)
3068 {
3069 value=(unsigned int) (*p++);
3070 value|=((unsigned int) (*p++)) << 8;
3071 value|=((unsigned int) (*p++)) << 16;
3072 value|=((unsigned int) (*p++)) << 24;
3073 return(value);
3074 }
3075 value=((unsigned int) (*p++)) << 24;
3076 value|=((unsigned int) (*p++)) << 16;
3077 value|=((unsigned int) (*p++)) << 8;
3078 value|=((unsigned int) (*p++));
3079 return(value);
3080}
3081
3082/*
3083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3084% %
3085% %
3086% %
3087+ R e a d B l o b L o n g L o n g %
3088% %
3089% %
3090% %
3091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3092%
cristy4cb162a2010-05-30 03:04:47 +00003093% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3094% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003095%
cristy4cb162a2010-05-30 03:04:47 +00003096% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003097%
cristy4cb162a2010-05-30 03:04:47 +00003098% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003099%
3100% A description of each parameter follows.
3101%
3102% o image: the image.
3103%
3104*/
3105MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3106{
cristy0286d852010-10-12 18:38:07 +00003107 MagickSizeType
3108 value;
3109
cristy3ed852e2009-09-05 21:47:34 +00003110 register const unsigned char
3111 *p;
3112
3113 ssize_t
3114 count;
3115
3116 unsigned char
3117 buffer[8];
3118
cristy3ed852e2009-09-05 21:47:34 +00003119 assert(image != (Image *) NULL);
3120 assert(image->signature == MagickSignature);
3121 *buffer='\0';
3122 p=ReadBlobStream(image,8,buffer,&count);
3123 if (count != 8)
3124 return(MagickULLConstant(0));
3125 if (image->endian == LSBEndian)
3126 {
3127 value=(MagickSizeType) (*p++);
3128 value|=((MagickSizeType) (*p++)) << 8;
3129 value|=((MagickSizeType) (*p++)) << 16;
3130 value|=((MagickSizeType) (*p++)) << 24;
3131 value|=((MagickSizeType) (*p++)) << 32;
3132 value|=((MagickSizeType) (*p++)) << 40;
3133 value|=((MagickSizeType) (*p++)) << 48;
3134 value|=((MagickSizeType) (*p++)) << 56;
3135 return(value & MagickULLConstant(0xffffffffffffffff));
3136 }
3137 value=((MagickSizeType) (*p++)) << 56;
3138 value|=((MagickSizeType) (*p++)) << 48;
3139 value|=((MagickSizeType) (*p++)) << 40;
3140 value|=((MagickSizeType) (*p++)) << 32;
3141 value|=((MagickSizeType) (*p++)) << 24;
3142 value|=((MagickSizeType) (*p++)) << 16;
3143 value|=((MagickSizeType) (*p++)) << 8;
3144 value|=((MagickSizeType) (*p++));
3145 return(value & MagickULLConstant(0xffffffffffffffff));
3146}
3147
3148/*
3149%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3150% %
3151% %
3152% %
3153+ R e a d B l o b S h o r t %
3154% %
3155% %
3156% %
3157%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3158%
3159% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3160% specified by the endian member of the image structure.
3161%
3162% The format of the ReadBlobShort method is:
3163%
3164% unsigned short ReadBlobShort(Image *image)
3165%
3166% A description of each parameter follows.
3167%
3168% o image: the image.
3169%
3170*/
3171MagickExport unsigned short ReadBlobShort(Image *image)
3172{
3173 register const unsigned char
3174 *p;
3175
3176 register unsigned int
3177 value;
3178
3179 ssize_t
3180 count;
3181
3182 unsigned char
3183 buffer[2];
3184
3185 assert(image != (Image *) NULL);
3186 assert(image->signature == MagickSignature);
3187 *buffer='\0';
3188 p=ReadBlobStream(image,2,buffer,&count);
3189 if (count != 2)
3190 return((unsigned short) 0U);
3191 if (image->endian == LSBEndian)
3192 {
3193 value=(unsigned int) (*p++);
3194 value|=((unsigned int) (*p++)) << 8;
3195 return((unsigned short) (value & 0xffff));
3196 }
3197 value=(unsigned int) ((*p++) << 8);
3198 value|=(unsigned int) (*p++);
3199 return((unsigned short) (value & 0xffff));
3200}
3201
3202/*
3203%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3204% %
3205% %
3206% %
3207+ R e a d B l o b L S B L o n g %
3208% %
3209% %
3210% %
3211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3212%
cristybb503372010-05-27 20:51:26 +00003213% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003214% least-significant byte first order.
3215%
3216% The format of the ReadBlobLSBLong method is:
3217%
3218% unsigned int ReadBlobLSBLong(Image *image)
3219%
3220% A description of each parameter follows.
3221%
3222% o image: the image.
3223%
3224*/
3225MagickExport unsigned int ReadBlobLSBLong(Image *image)
3226{
3227 register const unsigned char
3228 *p;
3229
3230 register unsigned int
3231 value;
3232
3233 ssize_t
3234 count;
3235
3236 unsigned char
3237 buffer[4];
3238
3239 assert(image != (Image *) NULL);
3240 assert(image->signature == MagickSignature);
3241 *buffer='\0';
3242 p=ReadBlobStream(image,4,buffer,&count);
3243 if (count != 4)
3244 return(0U);
3245 value=(unsigned int) (*p++);
3246 value|=((unsigned int) (*p++)) << 8;
3247 value|=((unsigned int) (*p++)) << 16;
3248 value|=((unsigned int) (*p++)) << 24;
3249 return(value);
3250}
3251
3252/*
3253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3254% %
3255% %
3256% %
3257+ R e a d B l o b L S B S h o r t %
3258% %
3259% %
3260% %
3261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3262%
3263% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3264% least-significant byte first order.
3265%
3266% The format of the ReadBlobLSBShort method is:
3267%
3268% unsigned short ReadBlobLSBShort(Image *image)
3269%
3270% A description of each parameter follows.
3271%
3272% o image: the image.
3273%
3274*/
3275MagickExport unsigned short ReadBlobLSBShort(Image *image)
3276{
3277 register const unsigned char
3278 *p;
3279
3280 register unsigned int
3281 value;
3282
3283 ssize_t
3284 count;
3285
3286 unsigned char
3287 buffer[2];
3288
3289 assert(image != (Image *) NULL);
3290 assert(image->signature == MagickSignature);
3291 *buffer='\0';
3292 p=ReadBlobStream(image,2,buffer,&count);
3293 if (count != 2)
3294 return((unsigned short) 0U);
3295 value=(unsigned int) (*p++);
3296 value|=((unsigned int) ((*p++)) << 8);
3297 return((unsigned short) (value & 0xffff));
3298}
3299
3300/*
3301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3302% %
3303% %
3304% %
3305+ R e a d B l o b M S B L o n g %
3306% %
3307% %
3308% %
3309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3310%
cristybb503372010-05-27 20:51:26 +00003311% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003312% most-significant byte first order.
3313%
3314% The format of the ReadBlobMSBLong method is:
3315%
3316% unsigned int ReadBlobMSBLong(Image *image)
3317%
3318% A description of each parameter follows.
3319%
3320% o image: the image.
3321%
3322*/
3323MagickExport unsigned int ReadBlobMSBLong(Image *image)
3324{
3325 register const unsigned char
3326 *p;
3327
3328 register unsigned int
3329 value;
3330
3331 ssize_t
3332 count;
3333
3334 unsigned char
3335 buffer[4];
3336
3337 assert(image != (Image *) NULL);
3338 assert(image->signature == MagickSignature);
3339 *buffer='\0';
3340 p=ReadBlobStream(image,4,buffer,&count);
3341 if (count != 4)
3342 return(0UL);
3343 value=((unsigned int) (*p++) << 24);
3344 value|=((unsigned int) (*p++) << 16);
3345 value|=((unsigned int) (*p++) << 8);
3346 value|=(unsigned int) (*p++);
3347 return(value);
3348}
3349
3350/*
3351%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3352% %
3353% %
3354% %
cristy2d3d87f2010-03-01 00:23:08 +00003355+ R e a d B l o b M S B L o n g L o n g %
3356% %
3357% %
3358% %
3359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3360%
cristybb503372010-05-27 20:51:26 +00003361% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003362% most-significant byte first order.
3363%
3364% The format of the ReadBlobMSBLongLong method is:
3365%
3366% unsigned int ReadBlobMSBLongLong(Image *image)
3367%
3368% A description of each parameter follows.
3369%
3370% o image: the image.
3371%
3372*/
3373MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3374{
3375 register const unsigned char
3376 *p;
3377
3378 register MagickSizeType
3379 value;
3380
3381 ssize_t
3382 count;
3383
3384 unsigned char
cristy0286d852010-10-12 18:38:07 +00003385 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003386
3387 assert(image != (Image *) NULL);
3388 assert(image->signature == MagickSignature);
3389 *buffer='\0';
3390 p=ReadBlobStream(image,8,buffer,&count);
3391 if (count != 8)
3392 return(MagickULLConstant(0));
3393 value=((MagickSizeType) (*p++)) << 56;
3394 value|=((MagickSizeType) (*p++)) << 48;
3395 value|=((MagickSizeType) (*p++)) << 40;
3396 value|=((MagickSizeType) (*p++)) << 32;
3397 value|=((MagickSizeType) (*p++)) << 24;
3398 value|=((MagickSizeType) (*p++)) << 16;
3399 value|=((MagickSizeType) (*p++)) << 8;
3400 value|=((MagickSizeType) (*p++));
3401 return(value & MagickULLConstant(0xffffffffffffffff));
3402}
3403
3404/*
3405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3406% %
3407% %
3408% %
cristy3ed852e2009-09-05 21:47:34 +00003409+ R e a d B l o b M S B S h o r t %
3410% %
3411% %
3412% %
3413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3414%
3415% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3416% most-significant byte first order.
3417%
3418% The format of the ReadBlobMSBShort method is:
3419%
3420% unsigned short ReadBlobMSBShort(Image *image)
3421%
3422% A description of each parameter follows.
3423%
3424% o image: the image.
3425%
3426*/
3427MagickExport unsigned short ReadBlobMSBShort(Image *image)
3428{
3429 register const unsigned char
3430 *p;
3431
3432 register unsigned int
3433 value;
3434
3435 ssize_t
3436 count;
3437
3438 unsigned char
3439 buffer[2];
3440
3441 assert(image != (Image *) NULL);
3442 assert(image->signature == MagickSignature);
3443 *buffer='\0';
3444 p=ReadBlobStream(image,2,buffer,&count);
3445 if (count != 2)
3446 return((unsigned short) 0U);
3447 value=(unsigned int) ((*p++) << 8);
3448 value|=(unsigned int) (*p++);
3449 return((unsigned short) (value & 0xffff));
3450}
3451
3452/*
3453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3454% %
3455% %
3456% %
3457+ R e a d B l o b S t r i n g %
3458% %
3459% %
3460% %
3461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3462%
3463% ReadBlobString() reads characters from a blob or file until a newline
3464% character is read or an end-of-file condition is encountered.
3465%
3466% The format of the ReadBlobString method is:
3467%
3468% char *ReadBlobString(Image *image,char *string)
3469%
3470% A description of each parameter follows:
3471%
3472% o image: the image.
3473%
3474% o string: the address of a character buffer.
3475%
3476*/
3477MagickExport char *ReadBlobString(Image *image,char *string)
3478{
3479 register const unsigned char
3480 *p;
3481
cristybb503372010-05-27 20:51:26 +00003482 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003483 i;
3484
3485 ssize_t
3486 count;
3487
3488 unsigned char
3489 buffer[1];
3490
3491 assert(image != (Image *) NULL);
3492 assert(image->signature == MagickSignature);
3493 for (i=0; i < (MaxTextExtent-1L); i++)
3494 {
3495 p=ReadBlobStream(image,1,buffer,&count);
3496 if (count != 1)
3497 {
3498 if (i == 0)
3499 return((char *) NULL);
3500 break;
3501 }
3502 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003503 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003504 break;
3505 }
cristy2b5db102010-06-09 01:07:28 +00003506 if (string[i] == '\r')
3507 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003508 string[i]='\0';
3509 return(string);
3510}
3511
3512/*
3513%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3514% %
3515% %
3516% %
3517+ R e f e r e n c e B l o b %
3518% %
3519% %
3520% %
3521%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3522%
3523% ReferenceBlob() increments the reference count associated with the pixel
3524% blob returning a pointer to the blob.
3525%
3526% The format of the ReferenceBlob method is:
3527%
3528% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3529%
3530% A description of each parameter follows:
3531%
3532% o blob_info: the blob_info.
3533%
3534*/
3535MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3536{
3537 assert(blob != (BlobInfo *) NULL);
3538 assert(blob->signature == MagickSignature);
3539 if (blob->debug != MagickFalse)
3540 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003541 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003542 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003543 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003544 return(blob);
3545}
3546
3547/*
3548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3549% %
3550% %
3551% %
3552+ S e e k B l o b %
3553% %
3554% %
3555% %
3556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3557%
3558% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3559% and returns the resulting offset.
3560%
3561% The format of the SeekBlob method is:
3562%
3563% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3564% const int whence)
3565%
3566% A description of each parameter follows:
3567%
3568% o image: the image.
3569%
3570% o offset: Specifies an integer representing the offset in bytes.
3571%
3572% o whence: Specifies an integer representing how the offset is
3573% treated relative to the beginning of the blob as follows:
3574%
3575% SEEK_SET Set position equal to offset bytes.
3576% SEEK_CUR Set position to current location plus offset.
3577% SEEK_END Set position to EOF plus offset.
3578%
3579*/
3580MagickExport MagickOffsetType SeekBlob(Image *image,
3581 const MagickOffsetType offset,const int whence)
3582{
3583 assert(image != (Image *) NULL);
3584 assert(image->signature == MagickSignature);
3585 if (image->debug != MagickFalse)
3586 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3587 assert(image->blob != (BlobInfo *) NULL);
3588 assert(image->blob->type != UndefinedStream);
3589 switch (image->blob->type)
3590 {
3591 case UndefinedStream:
3592 break;
cristybc20d112012-07-29 20:27:00 +00003593 case StandardStream:
3594 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003595 case FileStream:
3596 {
cristye7b28372012-06-17 13:59:06 +00003597 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003598 return(-1);
3599 image->blob->offset=TellBlob(image);
3600 break;
3601 }
cristy3ed852e2009-09-05 21:47:34 +00003602 case PipeStream:
3603 case ZipStream:
3604 {
3605#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003606 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003607 return(-1);
3608#endif
3609 image->blob->offset=TellBlob(image);
3610 break;
3611 }
3612 case BZipStream:
3613 return(-1);
3614 case FifoStream:
3615 return(-1);
3616 case BlobStream:
3617 {
3618 switch (whence)
3619 {
3620 case SEEK_SET:
3621 default:
3622 {
3623 if (offset < 0)
3624 return(-1);
3625 image->blob->offset=offset;
3626 break;
3627 }
3628 case SEEK_CUR:
3629 {
3630 if ((image->blob->offset+offset) < 0)
3631 return(-1);
3632 image->blob->offset+=offset;
3633 break;
3634 }
3635 case SEEK_END:
3636 {
3637 if (((MagickOffsetType) image->blob->length+offset) < 0)
3638 return(-1);
3639 image->blob->offset=image->blob->length+offset;
3640 break;
3641 }
3642 }
3643 if (image->blob->offset <= (MagickOffsetType)
3644 ((off_t) image->blob->length))
3645 image->blob->eof=MagickFalse;
3646 else
3647 if (image->blob->mapped != MagickFalse)
3648 return(-1);
3649 else
3650 {
3651 image->blob->extent=(size_t) (image->blob->offset+
3652 image->blob->quantum);
3653 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3654 image->blob->data,image->blob->extent+1,
3655 sizeof(*image->blob->data));
3656 (void) SyncBlob(image);
3657 if (image->blob->data == (unsigned char *) NULL)
3658 {
3659 (void) DetachBlob(image->blob);
3660 return(-1);
3661 }
3662 }
3663 break;
3664 }
3665 }
3666 return(image->blob->offset);
3667}
3668
3669/*
3670%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3671% %
3672% %
3673% %
3674+ S e t B l o b E x e m p t %
3675% %
3676% %
3677% %
3678%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3679%
3680% SetBlobExempt() sets the blob exempt status.
3681%
3682% The format of the SetBlobExempt method is:
3683%
3684% MagickBooleanType SetBlobExempt(const Image *image,
3685% const MagickBooleanType exempt)
3686%
3687% A description of each parameter follows:
3688%
3689% o image: the image.
3690%
3691% o exempt: Set to true if this blob is exempt from being closed.
3692%
3693*/
cristy7832dc22011-09-05 01:21:53 +00003694MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003695{
3696 assert(image != (const Image *) NULL);
3697 assert(image->signature == MagickSignature);
3698 if (image->debug != MagickFalse)
3699 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3700 image->blob->exempt=exempt;
3701}
3702
3703/*
3704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3705% %
3706% %
3707% %
3708+ S e t B l o b E x t e n t %
3709% %
3710% %
3711% %
3712%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3713%
3714% SetBlobExtent() ensures enough space is allocated for the blob. If the
3715% method is successful, subsequent writes to bytes in the specified range are
3716% guaranteed not to fail.
3717%
3718% The format of the SetBlobExtent method is:
3719%
3720% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3721%
3722% A description of each parameter follows:
3723%
3724% o image: the image.
3725%
3726% o extent: the blob maximum extent.
3727%
3728*/
cristy7832dc22011-09-05 01:21:53 +00003729MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003730 const MagickSizeType extent)
3731{
3732 assert(image != (Image *) NULL);
3733 assert(image->signature == MagickSignature);
3734 if (image->debug != MagickFalse)
3735 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3736 assert(image->blob != (BlobInfo *) NULL);
3737 assert(image->blob->type != UndefinedStream);
3738 switch (image->blob->type)
3739 {
3740 case UndefinedStream:
3741 break;
cristybc20d112012-07-29 20:27:00 +00003742 case StandardStream:
3743 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003744 case FileStream:
3745 {
cristy38e35f42012-12-18 21:12:17 +00003746 MagickOffsetType
3747 offset;
3748
3749 ssize_t
3750 count;
3751
cristy3ed852e2009-09-05 21:47:34 +00003752 if (extent != (MagickSizeType) ((off_t) extent))
3753 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003754 offset=SeekBlob(image,0,SEEK_END);
3755 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003756 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003757 if ((MagickSizeType) offset >= extent)
3758 break;
3759 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003760 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3761 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003762#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3763 if (image->blob->synchronize != MagickFalse)
3764 {
3765 int
3766 status;
3767
3768 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3769 extent-offset);
3770 if (status != 0)
3771 return(MagickFalse);
3772 }
3773#endif
cristy38e35f42012-12-18 21:12:17 +00003774 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003775 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003776 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003777 break;
3778 }
cristy3ed852e2009-09-05 21:47:34 +00003779 case PipeStream:
3780 case ZipStream:
3781 return(MagickFalse);
3782 case BZipStream:
3783 return(MagickFalse);
3784 case FifoStream:
3785 return(MagickFalse);
3786 case BlobStream:
3787 {
cristy38e35f42012-12-18 21:12:17 +00003788 if (extent != (MagickSizeType) ((size_t) extent))
3789 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003790 if (image->blob->mapped != MagickFalse)
3791 {
cristy38e35f42012-12-18 21:12:17 +00003792 MagickOffsetType
3793 offset;
3794
3795 ssize_t
3796 count;
3797
cristy3ed852e2009-09-05 21:47:34 +00003798 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy18aba912013-06-14 19:48:08 +00003799 RelinquishMagickResource(MapResource,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003800 if (extent != (MagickSizeType) ((off_t) extent))
3801 return(MagickFalse);
3802 offset=SeekBlob(image,0,SEEK_END);
3803 if (offset < 0)
3804 return(MagickFalse);
3805 if ((MagickSizeType) offset >= extent)
3806 break;
3807 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003808 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003809 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003810#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3811 if (image->blob->synchronize != MagickFalse)
3812 {
3813 int
3814 status;
3815
3816 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3817 extent-offset);
3818 if (status != 0)
3819 return(MagickFalse);
3820 }
3821#endif
cristy38e35f42012-12-18 21:12:17 +00003822 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003823 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003824 return(MagickFalse);
cristyac1caa22013-06-15 00:41:21 +00003825 (void) AcquireMagickResource(MapResource,extent);
cristy95888612012-04-04 21:56:52 +00003826 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003827 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003828 image->blob->extent=(size_t) extent;
3829 image->blob->length=(size_t) extent;
3830 (void) SyncBlob(image);
3831 break;
cristy3ed852e2009-09-05 21:47:34 +00003832 }
cristy3ed852e2009-09-05 21:47:34 +00003833 image->blob->extent=(size_t) extent;
3834 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3835 image->blob->extent+1,sizeof(*image->blob->data));
3836 (void) SyncBlob(image);
3837 if (image->blob->data == (unsigned char *) NULL)
3838 {
3839 (void) DetachBlob(image->blob);
3840 return(MagickFalse);
3841 }
3842 break;
3843 }
3844 }
3845 return(MagickTrue);
3846}
3847
3848/*
3849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3850% %
3851% %
3852% %
3853+ S y n c B l o b %
3854% %
3855% %
3856% %
3857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3858%
3859% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3860% attributes if it is an blob.
3861%
3862% The format of the SyncBlob method is:
3863%
3864% int SyncBlob(Image *image)
3865%
3866% A description of each parameter follows:
3867%
3868% o image: the image.
3869%
3870*/
3871static int SyncBlob(Image *image)
3872{
3873 int
3874 status;
3875
3876 assert(image != (Image *) NULL);
3877 assert(image->signature == MagickSignature);
3878 if (image->debug != MagickFalse)
3879 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3880 assert(image->blob != (BlobInfo *) NULL);
3881 assert(image->blob->type != UndefinedStream);
3882 status=0;
3883 switch (image->blob->type)
3884 {
3885 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003886 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003887 break;
3888 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003889 case PipeStream:
3890 {
cristye7b28372012-06-17 13:59:06 +00003891 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003892 break;
3893 }
3894 case ZipStream:
3895 {
3896#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003897 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003898#endif
3899 break;
3900 }
3901 case BZipStream:
3902 {
3903#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003904 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003905#endif
3906 break;
3907 }
3908 case FifoStream:
3909 break;
3910 case BlobStream:
cristy3ed852e2009-09-05 21:47:34 +00003911 break;
cristy3ed852e2009-09-05 21:47:34 +00003912 }
3913 return(status);
3914}
3915
3916/*
3917%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3918% %
3919% %
3920% %
3921+ T e l l B l o b %
3922% %
3923% %
3924% %
3925%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3926%
3927% TellBlob() obtains the current value of the blob or file position.
3928%
3929% The format of the TellBlob method is:
3930%
3931% MagickOffsetType TellBlob(const Image *image)
3932%
3933% A description of each parameter follows:
3934%
3935% o image: the image.
3936%
3937*/
3938MagickExport MagickOffsetType TellBlob(const Image *image)
3939{
3940 MagickOffsetType
3941 offset;
3942
3943 assert(image != (Image *) NULL);
3944 assert(image->signature == MagickSignature);
3945 if (image->debug != MagickFalse)
3946 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3947 assert(image->blob != (BlobInfo *) NULL);
3948 assert(image->blob->type != UndefinedStream);
3949 offset=(-1);
3950 switch (image->blob->type)
3951 {
3952 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003953 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003954 break;
3955 case FileStream:
3956 {
cristye7b28372012-06-17 13:59:06 +00003957 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003958 break;
3959 }
cristy3ed852e2009-09-05 21:47:34 +00003960 case PipeStream:
3961 break;
3962 case ZipStream:
3963 {
3964#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003965 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003966#endif
3967 break;
3968 }
3969 case BZipStream:
3970 break;
3971 case FifoStream:
3972 break;
3973 case BlobStream:
3974 {
3975 offset=image->blob->offset;
3976 break;
3977 }
3978 }
3979 return(offset);
3980}
3981
3982/*
3983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3984% %
3985% %
3986% %
3987+ U n m a p B l o b %
3988% %
3989% %
3990% %
3991%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3992%
3993% UnmapBlob() deallocates the binary large object previously allocated with
3994% the MapBlob method.
3995%
3996% The format of the UnmapBlob method is:
3997%
3998% MagickBooleanType UnmapBlob(void *map,const size_t length)
3999%
4000% A description of each parameter follows:
4001%
4002% o map: the address of the binary large object.
4003%
4004% o length: the length of the binary large object.
4005%
4006*/
4007MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4008{
cristydc8ea8e2013-07-28 20:10:44 +00004009#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00004010 int
4011 status;
4012
4013 status=munmap(map,length);
4014 return(status == -1 ? MagickFalse : MagickTrue);
4015#else
4016 (void) map;
4017 (void) length;
4018 return(MagickFalse);
4019#endif
4020}
4021
4022/*
4023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4024% %
4025% %
4026% %
4027+ W r i t e B l o b %
4028% %
4029% %
4030% %
4031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4032%
4033% WriteBlob() writes data to a blob or image file. It returns the number of
4034% bytes written.
4035%
4036% The format of the WriteBlob method is:
4037%
4038% ssize_t WriteBlob(Image *image,const size_t length,
4039% const unsigned char *data)
4040%
4041% A description of each parameter follows:
4042%
4043% o image: the image.
4044%
4045% o length: Specifies an integer representing the number of bytes to
4046% write to the file.
4047%
4048% o data: The address of the data to write to the blob or file.
4049%
4050*/
4051MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4052 const unsigned char *data)
4053{
4054 int
4055 c;
4056
4057 register const unsigned char
4058 *p;
4059
4060 ssize_t
4061 count;
4062
4063 assert(image != (Image *) NULL);
4064 assert(image->signature == MagickSignature);
4065 assert(data != (const unsigned char *) NULL);
4066 assert(image->blob != (BlobInfo *) NULL);
4067 assert(image->blob->type != UndefinedStream);
4068 if (length == 0)
4069 return(0);
4070 count=0;
4071 p=data;
4072 switch (image->blob->type)
4073 {
4074 case UndefinedStream:
4075 break;
cristy3ed852e2009-09-05 21:47:34 +00004076 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004077 {
cristy5f3d2752013-01-05 18:53:38 +00004078 count=write(fileno(image->blob->file_info.file),data,length);
cristybc20d112012-07-29 20:27:00 +00004079 break;
4080 }
4081 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004082 case PipeStream:
4083 {
4084 switch (length)
4085 {
4086 default:
4087 {
4088 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004089 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004090 break;
4091 }
4092 case 2:
4093 {
cristye7b28372012-06-17 13:59:06 +00004094 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004095 if (c == EOF)
4096 break;
4097 count++;
4098 }
4099 case 1:
4100 {
cristye7b28372012-06-17 13:59:06 +00004101 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004102 if (c == EOF)
4103 break;
4104 count++;
4105 }
4106 case 0:
4107 break;
4108 }
4109 break;
4110 }
4111 case ZipStream:
4112 {
4113#if defined(MAGICKCORE_ZLIB_DELEGATE)
4114 switch (length)
4115 {
4116 default:
4117 {
cristye7b28372012-06-17 13:59:06 +00004118 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004119 (unsigned int) length);
4120 break;
4121 }
4122 case 2:
4123 {
cristye7b28372012-06-17 13:59:06 +00004124 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004125 if (c == EOF)
4126 break;
4127 count++;
4128 }
4129 case 1:
4130 {
cristye7b28372012-06-17 13:59:06 +00004131 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004132 if (c == EOF)
4133 break;
4134 count++;
4135 }
4136 case 0:
4137 break;
4138 }
4139#endif
4140 break;
4141 }
4142 case BZipStream:
4143 {
4144#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004145 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004146 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004147#endif
4148 break;
4149 }
4150 case FifoStream:
4151 {
4152 count=(ssize_t) image->blob->stream(image,data,length);
4153 break;
4154 }
4155 case BlobStream:
4156 {
4157 register unsigned char
4158 *q;
4159
4160 if ((image->blob->offset+(MagickOffsetType) length) >=
4161 (MagickOffsetType) image->blob->extent)
4162 {
4163 if (image->blob->mapped != MagickFalse)
4164 return(0);
4165 image->blob->quantum<<=1;
4166 image->blob->extent+=length+image->blob->quantum;
4167 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4168 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4169 (void) SyncBlob(image);
4170 if (image->blob->data == (unsigned char *) NULL)
4171 {
4172 (void) DetachBlob(image->blob);
4173 return(0);
4174 }
4175 }
4176 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004177 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004178 image->blob->offset+=length;
4179 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4180 image->blob->length=(size_t) image->blob->offset;
4181 count=(ssize_t) length;
4182 }
4183 }
4184 return(count);
4185}
4186
4187/*
4188%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4189% %
4190% %
4191% %
4192+ W r i t e B l o b B y t e %
4193% %
4194% %
4195% %
4196%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4197%
4198% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4199% written (either 0 or 1);
4200%
4201% The format of the WriteBlobByte method is:
4202%
4203% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4204%
4205% A description of each parameter follows.
4206%
4207% o image: the image.
4208%
4209% o value: Specifies the value to write.
4210%
4211*/
4212MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4213{
4214 assert(image != (Image *) NULL);
4215 assert(image->signature == MagickSignature);
4216 return(WriteBlobStream(image,1,&value));
4217}
4218
4219/*
4220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4221% %
4222% %
4223% %
4224+ W r i t e B l o b F l o a t %
4225% %
4226% %
4227% %
4228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4229%
4230% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4231% specified by the endian member of the image structure.
4232%
4233% The format of the WriteBlobFloat method is:
4234%
4235% ssize_t WriteBlobFloat(Image *image,const float value)
4236%
4237% A description of each parameter follows.
4238%
4239% o image: the image.
4240%
4241% o value: Specifies the value to write.
4242%
4243*/
4244MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4245{
4246 union
4247 {
4248 unsigned int
4249 unsigned_value;
4250
4251 float
4252 float_value;
4253 } quantum;
4254
4255 quantum.unsigned_value=0U;
4256 quantum.float_value=value;
4257 return(WriteBlobLong(image,quantum.unsigned_value));
4258}
4259
4260/*
4261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4262% %
4263% %
4264% %
4265+ W r i t e B l o b L o n g %
4266% %
4267% %
4268% %
4269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4270%
cristybb503372010-05-27 20:51:26 +00004271% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004272% specified by the endian member of the image structure.
4273%
4274% The format of the WriteBlobLong method is:
4275%
4276% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4277%
4278% A description of each parameter follows.
4279%
4280% o image: the image.
4281%
4282% o value: Specifies the value to write.
4283%
4284*/
4285MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4286{
4287 unsigned char
4288 buffer[4];
4289
4290 assert(image != (Image *) NULL);
4291 assert(image->signature == MagickSignature);
4292 if (image->endian == LSBEndian)
4293 {
4294 buffer[0]=(unsigned char) value;
4295 buffer[1]=(unsigned char) (value >> 8);
4296 buffer[2]=(unsigned char) (value >> 16);
4297 buffer[3]=(unsigned char) (value >> 24);
4298 return(WriteBlobStream(image,4,buffer));
4299 }
4300 buffer[0]=(unsigned char) (value >> 24);
4301 buffer[1]=(unsigned char) (value >> 16);
4302 buffer[2]=(unsigned char) (value >> 8);
4303 buffer[3]=(unsigned char) value;
4304 return(WriteBlobStream(image,4,buffer));
4305}
4306
4307/*
4308%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4309% %
4310% %
4311% %
4312+ W r i t e B l o b S h o r t %
4313% %
4314% %
4315% %
4316%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4317%
4318% WriteBlobShort() writes a short value as a 16-bit quantity in the
4319% byte-order specified by the endian member of the image structure.
4320%
4321% The format of the WriteBlobShort method is:
4322%
4323% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4324%
4325% A description of each parameter follows.
4326%
4327% o image: the image.
4328%
4329% o value: Specifies the value to write.
4330%
4331*/
4332MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4333{
4334 unsigned char
4335 buffer[2];
4336
4337 assert(image != (Image *) NULL);
4338 assert(image->signature == MagickSignature);
4339 if (image->endian == LSBEndian)
4340 {
4341 buffer[0]=(unsigned char) value;
4342 buffer[1]=(unsigned char) (value >> 8);
4343 return(WriteBlobStream(image,2,buffer));
4344 }
4345 buffer[0]=(unsigned char) (value >> 8);
4346 buffer[1]=(unsigned char) value;
4347 return(WriteBlobStream(image,2,buffer));
4348}
4349
4350/*
4351%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4352% %
4353% %
4354% %
4355+ W r i t e B l o b L S B L o n g %
4356% %
4357% %
4358% %
4359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4360%
cristybb503372010-05-27 20:51:26 +00004361% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004362% least-significant byte first order.
4363%
4364% The format of the WriteBlobLSBLong method is:
4365%
4366% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4367%
4368% A description of each parameter follows.
4369%
4370% o image: the image.
4371%
4372% o value: Specifies the value to write.
4373%
4374*/
4375MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4376{
4377 unsigned char
4378 buffer[4];
4379
4380 assert(image != (Image *) NULL);
4381 assert(image->signature == MagickSignature);
4382 buffer[0]=(unsigned char) value;
4383 buffer[1]=(unsigned char) (value >> 8);
4384 buffer[2]=(unsigned char) (value >> 16);
4385 buffer[3]=(unsigned char) (value >> 24);
4386 return(WriteBlobStream(image,4,buffer));
4387}
4388
4389/*
4390%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4391% %
4392% %
4393% %
4394+ W r i t e B l o b L S B S h o r t %
4395% %
4396% %
4397% %
4398%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4399%
cristybb503372010-05-27 20:51:26 +00004400% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004401% least-significant byte first order.
4402%
4403% The format of the WriteBlobLSBShort method is:
4404%
4405% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4406%
4407% A description of each parameter follows.
4408%
4409% o image: the image.
4410%
4411% o value: Specifies the value to write.
4412%
4413*/
4414MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4415{
4416 unsigned char
4417 buffer[2];
4418
4419 assert(image != (Image *) NULL);
4420 assert(image->signature == MagickSignature);
4421 buffer[0]=(unsigned char) value;
4422 buffer[1]=(unsigned char) (value >> 8);
4423 return(WriteBlobStream(image,2,buffer));
4424}
4425
4426/*
4427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4428% %
4429% %
4430% %
4431+ W r i t e B l o b M S B L o n g %
4432% %
4433% %
4434% %
4435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4436%
cristybb503372010-05-27 20:51:26 +00004437% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004438% most-significant byte first order.
4439%
4440% The format of the WriteBlobMSBLong method is:
4441%
4442% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4443%
4444% A description of each parameter follows.
4445%
4446% o value: Specifies the value to write.
4447%
4448% o image: the image.
4449%
4450*/
4451MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4452{
4453 unsigned char
4454 buffer[4];
4455
4456 assert(image != (Image *) NULL);
4457 assert(image->signature == MagickSignature);
4458 buffer[0]=(unsigned char) (value >> 24);
4459 buffer[1]=(unsigned char) (value >> 16);
4460 buffer[2]=(unsigned char) (value >> 8);
4461 buffer[3]=(unsigned char) value;
4462 return(WriteBlobStream(image,4,buffer));
4463}
4464
4465/*
4466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4467% %
4468% %
4469% %
cristy2ca49922010-03-06 02:54:01 +00004470+ W r i t e B l o b M S B L o n g L o n g %
4471% %
4472% %
4473% %
4474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4475%
4476% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4477% most-significant byte first order.
4478%
4479% The format of the WriteBlobMSBLongLong method is:
4480%
4481% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4482%
4483% A description of each parameter follows.
4484%
4485% o value: Specifies the value to write.
4486%
4487% o image: the image.
4488%
4489*/
4490MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4491 const MagickSizeType value)
4492{
4493 unsigned char
4494 buffer[8];
4495
4496 assert(image != (Image *) NULL);
4497 assert(image->signature == MagickSignature);
4498 buffer[0]=(unsigned char) (value >> 56);
4499 buffer[1]=(unsigned char) (value >> 48);
4500 buffer[2]=(unsigned char) (value >> 40);
4501 buffer[3]=(unsigned char) (value >> 32);
4502 buffer[4]=(unsigned char) (value >> 24);
4503 buffer[5]=(unsigned char) (value >> 16);
4504 buffer[6]=(unsigned char) (value >> 8);
4505 buffer[7]=(unsigned char) value;
4506 return(WriteBlobStream(image,8,buffer));
4507}
4508
4509/*
4510%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4511% %
4512% %
4513% %
cristy3ed852e2009-09-05 21:47:34 +00004514+ W r i t e B l o b M S B S h o r t %
4515% %
4516% %
4517% %
4518%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4519%
cristybb503372010-05-27 20:51:26 +00004520% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004521% most-significant byte first order.
4522%
4523% The format of the WriteBlobMSBShort method is:
4524%
4525% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4526%
4527% A description of each parameter follows.
4528%
4529% o value: Specifies the value to write.
4530%
4531% o file: Specifies the file to write the data to.
4532%
4533*/
4534MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4535{
4536 unsigned char
4537 buffer[2];
4538
4539 assert(image != (Image *) NULL);
4540 assert(image->signature == MagickSignature);
4541 buffer[0]=(unsigned char) (value >> 8);
4542 buffer[1]=(unsigned char) value;
4543 return(WriteBlobStream(image,2,buffer));
4544}
4545
4546/*
4547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4548% %
4549% %
4550% %
4551+ W r i t e B l o b S t r i n g %
4552% %
4553% %
4554% %
4555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4556%
4557% WriteBlobString() write a string to a blob. It returns the number of
4558% characters written.
4559%
4560% The format of the WriteBlobString method is:
4561%
4562% ssize_t WriteBlobString(Image *image,const char *string)
4563%
4564% A description of each parameter follows.
4565%
4566% o image: the image.
4567%
4568% o string: Specifies the string to write.
4569%
4570*/
4571MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4572{
4573 assert(image != (Image *) NULL);
4574 assert(image->signature == MagickSignature);
4575 assert(string != (const char *) NULL);
4576 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4577}