blob: fb7b7ce5174c8203288f83d1616f123efa51e0d4 [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 %
16% John Cristy %
17% 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;
967 if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset)))
968 {
969 size_t
970 quantum;
971
972 struct stat
cristye7b28372012-06-17 13:59:06 +0000973 file_stats;
cristy3ed852e2009-09-05 21:47:34 +0000974
975 /*
976 Stream is not seekable.
977 */
978 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +0000979 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
980 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +0000981 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +0000982 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
983 for (i=0; blob != (unsigned char *) NULL; i+=count)
984 {
cristy65d11e42013-06-14 20:06:25 +0000985 count=read(file,blob+i,quantum);
cristy3ed852e2009-09-05 21:47:34 +0000986 if (count <= 0)
987 {
988 count=0;
989 if (errno != EINTR)
990 break;
991 }
cristy9c66d8c2012-08-10 11:05:36 +0000992 if (~((size_t) i) < (quantum+1))
cristy3ed852e2009-09-05 21:47:34 +0000993 {
994 blob=(unsigned char *) RelinquishMagickMemory(blob);
995 break;
996 }
997 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
998 sizeof(*blob));
999 if ((size_t) (i+count) >= extent)
1000 break;
1001 }
cristy54439632010-07-15 00:43:34 +00001002 if (LocaleCompare(filename,"-") != 0)
1003 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001004 if (blob == (unsigned char *) NULL)
1005 {
1006 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001007 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001008 return((unsigned char *) NULL);
1009 }
cristya7cb4312010-06-26 00:47:03 +00001010 if (file == -1)
1011 {
1012 blob=(unsigned char *) RelinquishMagickMemory(blob);
1013 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1014 return((unsigned char *) NULL);
1015 }
cristy7753b2a2011-02-19 18:36:52 +00001016 *length=(size_t) MagickMin(i+count,extent);
cristy3ed852e2009-09-05 21:47:34 +00001017 blob[*length]='\0';
1018 return(blob);
1019 }
cristy7753b2a2011-02-19 18:36:52 +00001020 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
cristy3ed852e2009-09-05 21:47:34 +00001021 blob=(unsigned char *) NULL;
cristy37e0b382011-06-07 13:31:21 +00001022 if (~(*length) >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +00001023 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1024 sizeof(*blob));
1025 if (blob == (unsigned char *) NULL)
1026 {
cristy54439632010-07-15 00:43:34 +00001027 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001028 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001029 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001030 return((unsigned char *) NULL);
1031 }
1032 map=MapBlob(file,ReadMode,0,*length);
1033 if (map != (unsigned char *) NULL)
1034 {
cristy54aad5e2010-09-03 16:02:04 +00001035 (void) memcpy(blob,map,*length);
cristy3ed852e2009-09-05 21:47:34 +00001036 (void) UnmapBlob(map,*length);
1037 }
1038 else
1039 {
cristy7f317702011-02-18 20:40:28 +00001040 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +00001041 for (i=0; i < *length; i+=count)
1042 {
cristy65d11e42013-06-14 20:06:25 +00001043 count=read(file,blob+i,(size_t) MagickMin(*length-i,(MagickSizeType)
1044 SSIZE_MAX));
cristy3ed852e2009-09-05 21:47:34 +00001045 if (count <= 0)
1046 {
1047 count=0;
1048 if (errno != EINTR)
1049 break;
1050 }
1051 }
1052 if (i < *length)
1053 {
1054 file=close(file)-1;
1055 blob=(unsigned char *) RelinquishMagickMemory(blob);
1056 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1057 return((unsigned char *) NULL);
1058 }
1059 }
cristy3ed852e2009-09-05 21:47:34 +00001060 blob[*length]='\0';
cristy54439632010-07-15 00:43:34 +00001061 if (LocaleCompare(filename,"-") != 0)
1062 file=close(file);
cristya7cb4312010-06-26 00:47:03 +00001063 if (file == -1)
1064 {
1065 blob=(unsigned char *) RelinquishMagickMemory(blob);
1066 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1067 }
cristy3ed852e2009-09-05 21:47:34 +00001068 return(blob);
1069}
1070
1071/*
1072%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1073% %
1074% %
1075% %
1076% F i l e T o I m a g e %
1077% %
1078% %
1079% %
1080%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1081%
1082% FileToImage() write the contents of a file to an image.
1083%
1084% The format of the FileToImage method is:
1085%
1086% MagickBooleanType FileToImage(Image *,const char *filename)
1087%
1088% A description of each parameter follows:
1089%
1090% o image: the image.
1091%
1092% o filename: the filename.
1093%
1094*/
1095
1096static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1097 const unsigned char *data)
1098{
1099 MagickSizeType
1100 extent;
1101
1102 register unsigned char
1103 *q;
1104
1105 assert(image->blob != (BlobInfo *) NULL);
1106 if (image->blob->type != BlobStream)
1107 return(WriteBlob(image,length,data));
1108 assert(image->blob->type != UndefinedStream);
1109 assert(data != (void *) NULL);
1110 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1111 if (extent >= image->blob->extent)
1112 {
1113 image->blob->quantum<<=1;
1114 extent=image->blob->extent+image->blob->quantum+length;
1115 if (SetBlobExtent(image,extent) == MagickFalse)
1116 return(0);
1117 }
1118 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00001119 (void) memcpy(q,data,length);
cristy3ed852e2009-09-05 21:47:34 +00001120 image->blob->offset+=length;
1121 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1122 image->blob->length=(size_t) image->blob->offset;
1123 return((ssize_t) length);
1124}
1125
cristyc82a27b2011-10-21 01:07:16 +00001126MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1127 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001128{
1129 int
1130 file;
1131
1132 size_t
1133 length,
1134 quantum;
1135
1136 ssize_t
1137 count;
1138
1139 struct stat
cristye7b28372012-06-17 13:59:06 +00001140 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001141
1142 unsigned char
1143 *blob;
1144
1145 assert(image != (const Image *) NULL);
1146 assert(image->signature == MagickSignature);
1147 assert(filename != (const char *) NULL);
1148 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
cristyd45808f2012-12-14 21:30:35 +00001149 file=fileno(stdin);
1150 if (LocaleCompare(filename,"-") != 0)
1151 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001152 if (file == -1)
1153 {
cristyc82a27b2011-10-21 01:07:16 +00001154 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001155 return(MagickFalse);
1156 }
1157 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001158 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1159 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001160 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1161 if (blob == (unsigned char *) NULL)
1162 {
cristyc82a27b2011-10-21 01:07:16 +00001163 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1164 filename);
cristy3ed852e2009-09-05 21:47:34 +00001165 return(MagickFalse);
1166 }
1167 for ( ; ; )
1168 {
cristy65d11e42013-06-14 20:06:25 +00001169 count=read(file,blob,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001170 if (count <= 0)
1171 {
1172 count=0;
1173 if (errno != EINTR)
1174 break;
1175 }
1176 length=(size_t) count;
1177 count=WriteBlobStream(image,length,blob);
1178 if (count != (ssize_t) length)
1179 {
cristyc82a27b2011-10-21 01:07:16 +00001180 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001181 break;
1182 }
1183 }
cristya7cb4312010-06-26 00:47:03 +00001184 file=close(file);
1185 if (file == -1)
cristyc82a27b2011-10-21 01:07:16 +00001186 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001187 blob=(unsigned char *) RelinquishMagickMemory(blob);
1188 return(MagickTrue);
1189}
1190
1191/*
1192%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1193% %
1194% %
1195% %
1196+ G e t B l o b E r r o r %
1197% %
1198% %
1199% %
1200%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1201%
1202% GetBlobError() returns MagickTrue if the blob associated with the specified
1203% image encountered an error.
1204%
1205% The format of the GetBlobError method is:
1206%
1207% MagickBooleanType GetBlobError(const Image *image)
1208%
1209% A description of each parameter follows:
1210%
1211% o image: the image.
1212%
1213*/
cristy7832dc22011-09-05 01:21:53 +00001214MagickPrivate MagickBooleanType GetBlobError(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001215{
1216 assert(image != (const Image *) NULL);
1217 assert(image->signature == MagickSignature);
1218 if (image->debug != MagickFalse)
1219 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1220 return(image->blob->status);
1221}
1222
1223/*
1224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1225% %
1226% %
1227% %
1228+ G e t B l o b F i l e H a n d l e %
1229% %
1230% %
1231% %
1232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1233%
1234% GetBlobFileHandle() returns the file handle associated with the image blob.
1235%
1236% The format of the GetBlobFile method is:
1237%
1238% FILE *GetBlobFileHandle(const Image *image)
1239%
1240% A description of each parameter follows:
1241%
1242% o image: the image.
1243%
1244*/
1245MagickExport FILE *GetBlobFileHandle(const Image *image)
1246{
1247 assert(image != (const Image *) NULL);
1248 assert(image->signature == MagickSignature);
cristye7b28372012-06-17 13:59:06 +00001249 return(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00001250}
1251
1252/*
1253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1254% %
1255% %
1256% %
1257+ G e t B l o b I n f o %
1258% %
1259% %
1260% %
1261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1262%
1263% GetBlobInfo() initializes the BlobInfo structure.
1264%
1265% The format of the GetBlobInfo method is:
1266%
1267% void GetBlobInfo(BlobInfo *blob_info)
1268%
1269% A description of each parameter follows:
1270%
1271% o blob_info: Specifies a pointer to a BlobInfo structure.
1272%
1273*/
cristy7832dc22011-09-05 01:21:53 +00001274MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
cristy3ed852e2009-09-05 21:47:34 +00001275{
1276 assert(blob_info != (BlobInfo *) NULL);
1277 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1278 blob_info->type=UndefinedStream;
1279 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1280 blob_info->properties.st_mtime=time((time_t *) NULL);
1281 blob_info->properties.st_ctime=time((time_t *) NULL);
1282 blob_info->debug=IsEventLogging();
1283 blob_info->reference_count=1;
1284 blob_info->semaphore=AllocateSemaphoreInfo();
1285 blob_info->signature=MagickSignature;
1286}
1287
1288/*
1289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1290% %
1291% %
1292% %
1293% G e t B l o b P r o p e r t i e s %
1294% %
1295% %
1296% %
1297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1298%
1299% GetBlobProperties() returns information about an image blob.
1300%
1301% The format of the GetBlobProperties method is:
1302%
1303% const struct stat *GetBlobProperties(const Image *image)
1304%
1305% A description of each parameter follows:
1306%
1307% o image: the image.
1308%
1309*/
cristy7832dc22011-09-05 01:21:53 +00001310MagickPrivate const struct stat *GetBlobProperties(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001311{
1312 assert(image != (Image *) NULL);
1313 assert(image->signature == MagickSignature);
1314 if (image->debug != MagickFalse)
1315 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1316 return(&image->blob->properties);
1317}
1318
1319/*
1320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1321% %
1322% %
1323% %
1324+ G e t B l o b S i z e %
1325% %
1326% %
1327% %
1328%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1329%
1330% GetBlobSize() returns the current length of the image file or blob; zero is
1331% returned if the size cannot be determined.
1332%
1333% The format of the GetBlobSize method is:
1334%
1335% MagickSizeType GetBlobSize(const Image *image)
1336%
1337% A description of each parameter follows:
1338%
1339% o image: the image.
1340%
1341*/
1342MagickExport MagickSizeType GetBlobSize(const Image *image)
1343{
1344 MagickSizeType
cristy81b8ce52010-02-05 01:53:17 +00001345 extent;
cristy3ed852e2009-09-05 21:47:34 +00001346
1347 assert(image != (Image *) NULL);
1348 assert(image->signature == MagickSignature);
1349 if (image->debug != MagickFalse)
1350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1351 assert(image->blob != (BlobInfo *) NULL);
cristy81b8ce52010-02-05 01:53:17 +00001352 extent=0;
cristy3ed852e2009-09-05 21:47:34 +00001353 switch (image->blob->type)
1354 {
1355 case UndefinedStream:
1356 {
cristy81b8ce52010-02-05 01:53:17 +00001357 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001358 break;
1359 }
cristybc20d112012-07-29 20:27:00 +00001360 case StandardStream:
1361 {
1362 extent=image->blob->size;
1363 break;
1364 }
cristy3ed852e2009-09-05 21:47:34 +00001365 case FileStream:
1366 {
cristye7b28372012-06-17 13:59:06 +00001367 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
cristy81b8ce52010-02-05 01:53:17 +00001368 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001369 break;
1370 }
cristy3ed852e2009-09-05 21:47:34 +00001371 case PipeStream:
1372 {
cristy81b8ce52010-02-05 01:53:17 +00001373 extent=image->blob->size;
cristy3ed852e2009-09-05 21:47:34 +00001374 break;
1375 }
1376 case ZipStream:
1377 case BZipStream:
1378 {
1379 MagickBooleanType
1380 status;
1381
1382 status=GetPathAttributes(image->filename,&image->blob->properties);
1383 if (status != MagickFalse)
cristy81b8ce52010-02-05 01:53:17 +00001384 extent=(MagickSizeType) image->blob->properties.st_size;
cristy3ed852e2009-09-05 21:47:34 +00001385 break;
1386 }
1387 case FifoStream:
1388 break;
1389 case BlobStream:
1390 {
cristy891dc792010-03-04 01:47:16 +00001391 extent=(MagickSizeType) image->blob->length;
cristy3ed852e2009-09-05 21:47:34 +00001392 break;
1393 }
1394 }
cristy81b8ce52010-02-05 01:53:17 +00001395 return(extent);
cristy3ed852e2009-09-05 21:47:34 +00001396}
1397
1398/*
1399%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1400% %
1401% %
1402% %
1403+ G e t B l o b S t r e a m D a t a %
1404% %
1405% %
1406% %
1407%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1408%
1409% GetBlobStreamData() returns the stream data for the image.
1410%
1411% The format of the GetBlobStreamData method is:
1412%
1413% unsigned char *GetBlobStreamData(const Image *image)
1414%
1415% A description of each parameter follows:
1416%
1417% o image: the image.
1418%
1419*/
1420MagickExport unsigned char *GetBlobStreamData(const Image *image)
1421{
1422 assert(image != (const Image *) NULL);
1423 assert(image->signature == MagickSignature);
1424 return(image->blob->data);
1425}
1426
1427/*
1428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1429% %
1430% %
1431% %
1432+ G e t B l o b S t r e a m H a n d l e r %
1433% %
1434% %
1435% %
1436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1437%
1438% GetBlobStreamHandler() returns the stream handler for the image.
1439%
1440% The format of the GetBlobStreamHandler method is:
1441%
1442% StreamHandler GetBlobStreamHandler(const Image *image)
1443%
1444% A description of each parameter follows:
1445%
1446% o image: the image.
1447%
1448*/
cristy7832dc22011-09-05 01:21:53 +00001449MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001450{
1451 assert(image != (const Image *) NULL);
1452 assert(image->signature == MagickSignature);
1453 if (image->debug != MagickFalse)
1454 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1455 return(image->blob->stream);
1456}
1457
1458/*
1459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1460% %
1461% %
1462% %
1463% I m a g e T o B l o b %
1464% %
1465% %
1466% %
1467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1468%
1469% ImageToBlob() implements direct to memory image formats. It returns the
cristy1a1b5622011-02-15 02:40:42 +00001470% image as a formatted blob and its length. The magick member of the Image
glennrpfdd9aff2011-02-15 18:50:05 +00001471% structure determines the format of the returned blob (GIF, JPEG, PNG,
cristy1a1b5622011-02-15 02:40:42 +00001472% etc.). This method is the equivalent of WriteImage(), but writes the
1473% formatted "file" to a memory buffer rather than to an actual file.
cristy3ed852e2009-09-05 21:47:34 +00001474%
1475% The format of the ImageToBlob method is:
1476%
1477% unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1478% size_t *length,ExceptionInfo *exception)
1479%
1480% A description of each parameter follows:
1481%
1482% o image_info: the image info.
1483%
1484% o image: the image.
1485%
1486% o length: This pointer to a size_t integer sets the initial length of the
1487% blob. On return, it reflects the actual length of the blob.
1488%
1489% o exception: return any errors or warnings in this structure.
1490%
1491*/
1492MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1493 Image *image,size_t *length,ExceptionInfo *exception)
1494{
1495 const MagickInfo
1496 *magick_info;
1497
1498 ImageInfo
1499 *blob_info;
1500
1501 MagickBooleanType
1502 status;
1503
1504 unsigned char
1505 *blob;
1506
1507 assert(image_info != (const ImageInfo *) NULL);
1508 assert(image_info->signature == MagickSignature);
1509 if (image_info->debug != MagickFalse)
1510 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1511 image_info->filename);
1512 assert(image != (Image *) NULL);
1513 assert(image->signature == MagickSignature);
1514 assert(exception != (ExceptionInfo *) NULL);
1515 *length=0;
1516 blob=(unsigned char *) NULL;
1517 blob_info=CloneImageInfo(image_info);
1518 blob_info->adjoin=MagickFalse;
cristyd965a422010-03-03 17:47:35 +00001519 (void) SetImageInfo(blob_info,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001520 if (*blob_info->magick != '\0')
1521 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1522 magick_info=GetMagickInfo(image->magick,exception);
1523 if (magick_info == (const MagickInfo *) NULL)
1524 {
1525 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001526 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001527 image->filename);
1528 return(blob);
1529 }
1530 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1531 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1532 {
1533 /*
1534 Native blob support for this image format.
1535 */
1536 blob_info->length=0;
1537 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1538 sizeof(unsigned char));
1539 if (blob_info->blob == (void *) NULL)
1540 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001541 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001542 else
1543 {
1544 (void) CloseBlob(image);
1545 image->blob->exempt=MagickTrue;
1546 *image->filename='\0';
cristy6f9e0d32011-08-28 16:32:09 +00001547 status=WriteImage(blob_info,image,exception);
cristyc42554f2012-08-22 12:00:43 +00001548 *length=image->blob->length;
1549 blob=DetachBlob(image->blob);
cristy6e50f9e2012-08-22 16:30:29 +00001550 if (status == MagickFalse)
1551 blob=(unsigned char *) RelinquishMagickMemory(blob);
1552 else
1553 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1554 sizeof(*blob));
cristy3ed852e2009-09-05 21:47:34 +00001555 }
1556 }
1557 else
1558 {
1559 char
1560 unique[MaxTextExtent];
1561
1562 int
1563 file;
1564
1565 /*
1566 Write file to disk in blob image format.
1567 */
1568 file=AcquireUniqueFileResource(unique);
1569 if (file == -1)
1570 {
1571 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1572 image_info->filename);
1573 }
1574 else
1575 {
1576 blob_info->file=fdopen(file,"wb");
1577 if (blob_info->file != (FILE *) NULL)
1578 {
cristyb51dff52011-05-19 16:55:47 +00001579 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001580 image->magick,unique);
cristy6f9e0d32011-08-28 16:32:09 +00001581 status=WriteImage(blob_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001582 (void) fclose(blob_info->file);
cristy6f9e0d32011-08-28 16:32:09 +00001583 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001584 blob=FileToBlob(image->filename,~0UL,length,exception);
1585 }
1586 (void) RelinquishUniqueFileResource(unique);
1587 }
1588 }
1589 blob_info=DestroyImageInfo(blob_info);
1590 return(blob);
1591}
1592
1593/*
1594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1595% %
1596% %
1597% %
1598% I m a g e T o F i l e %
1599% %
1600% %
1601% %
1602%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1603%
1604% ImageToFile() writes an image to a file. It returns MagickFalse if an error
1605% occurs otherwise MagickTrue.
1606%
1607% The format of the ImageToFile method is:
1608%
1609% MagickBooleanType ImageToFile(Image *image,char *filename,
1610% ExceptionInfo *exception)
1611%
1612% A description of each parameter follows:
1613%
1614% o image: the image.
1615%
1616% o filename: Write the image to this file.
1617%
1618% o exception: return any errors or warnings in this structure.
1619%
1620*/
cristy3ed852e2009-09-05 21:47:34 +00001621MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1622 ExceptionInfo *exception)
1623{
1624 int
1625 file;
1626
1627 register const unsigned char
1628 *p;
1629
1630 register size_t
1631 i;
1632
1633 size_t
1634 length,
1635 quantum;
1636
1637 ssize_t
1638 count;
1639
1640 struct stat
cristye7b28372012-06-17 13:59:06 +00001641 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001642
1643 unsigned char
1644 *buffer;
1645
1646 assert(image != (Image *) NULL);
1647 assert(image->signature == MagickSignature);
1648 assert(image->blob != (BlobInfo *) NULL);
1649 assert(image->blob->type != UndefinedStream);
1650 if (image->debug != MagickFalse)
1651 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1652 assert(filename != (const char *) NULL);
1653 if (*filename == '\0')
1654 file=AcquireUniqueFileResource(filename);
1655 else
1656 if (LocaleCompare(filename,"-") == 0)
1657 file=fileno(stdout);
1658 else
cristyb70aab92012-01-31 15:04:04 +00001659 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +00001660 if (file == -1)
1661 {
1662 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1663 return(MagickFalse);
1664 }
1665 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001666 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1667 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
cristy7753b2a2011-02-19 18:36:52 +00001668 MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001669 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1670 if (buffer == (unsigned char *) NULL)
1671 {
1672 file=close(file)-1;
1673 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001674 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00001675 return(MagickFalse);
1676 }
1677 length=0;
1678 p=ReadBlobStream(image,quantum,buffer,&count);
1679 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1680 {
1681 length=(size_t) count;
1682 for (i=0; i < length; i+=count)
1683 {
1684 count=write(file,p+i,(size_t) (length-i));
1685 if (count <= 0)
1686 {
1687 count=0;
1688 if (errno != EINTR)
1689 break;
1690 }
1691 }
1692 if (i < length)
1693 break;
1694 }
cristy54439632010-07-15 00:43:34 +00001695 if (LocaleCompare(filename,"-") != 0)
1696 file=close(file);
cristy3ed852e2009-09-05 21:47:34 +00001697 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
cristya7cb4312010-06-26 00:47:03 +00001698 if ((file == -1) || (i < length))
cristy3ed852e2009-09-05 21:47:34 +00001699 {
1700 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1701 return(MagickFalse);
1702 }
1703 return(MagickTrue);
1704}
1705
1706/*
1707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1708% %
1709% %
1710% %
1711% I m a g e s T o B l o b %
1712% %
1713% %
1714% %
1715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1716%
1717% ImagesToBlob() implements direct to memory image formats. It returns the
1718% image sequence as a blob and its length. The magick member of the ImageInfo
1719% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1720%
1721% Note, some image formats do not permit multiple images to the same image
1722% stream (e.g. JPEG). in this instance, just the first image of the
1723% sequence is returned as a blob.
1724%
1725% The format of the ImagesToBlob method is:
1726%
1727% unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1728% size_t *length,ExceptionInfo *exception)
1729%
1730% A description of each parameter follows:
1731%
1732% o image_info: the image info.
1733%
1734% o images: the image list.
1735%
1736% o length: This pointer to a size_t integer sets the initial length of the
1737% blob. On return, it reflects the actual length of the blob.
1738%
1739% o exception: return any errors or warnings in this structure.
1740%
1741*/
1742MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1743 Image *images,size_t *length,ExceptionInfo *exception)
1744{
1745 const MagickInfo
1746 *magick_info;
1747
1748 ImageInfo
1749 *blob_info;
1750
1751 MagickBooleanType
1752 status;
1753
1754 unsigned char
1755 *blob;
1756
1757 assert(image_info != (const ImageInfo *) NULL);
1758 assert(image_info->signature == MagickSignature);
1759 if (image_info->debug != MagickFalse)
1760 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1761 image_info->filename);
1762 assert(images != (Image *) NULL);
1763 assert(images->signature == MagickSignature);
1764 assert(exception != (ExceptionInfo *) NULL);
1765 *length=0;
1766 blob=(unsigned char *) NULL;
1767 blob_info=CloneImageInfo(image_info);
cristyd965a422010-03-03 17:47:35 +00001768 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1769 exception);
cristy3ed852e2009-09-05 21:47:34 +00001770 if (*blob_info->magick != '\0')
1771 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1772 if (blob_info->adjoin == MagickFalse)
1773 {
1774 blob_info=DestroyImageInfo(blob_info);
1775 return(ImageToBlob(image_info,images,length,exception));
1776 }
1777 magick_info=GetMagickInfo(images->magick,exception);
1778 if (magick_info == (const MagickInfo *) NULL)
1779 {
1780 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001781 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001782 images->filename);
1783 return(blob);
1784 }
1785 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1786 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1787 {
1788 /*
1789 Native blob support for this images format.
1790 */
1791 blob_info->length=0;
1792 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1793 sizeof(unsigned char));
1794 if (blob_info->blob == (void *) NULL)
1795 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001796 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
cristy3ed852e2009-09-05 21:47:34 +00001797 else
1798 {
1799 images->blob->exempt=MagickTrue;
1800 *images->filename='\0';
1801 status=WriteImages(blob_info,images,images->filename,exception);
cristyb24e2402011-10-07 00:48:39 +00001802 if ((status != MagickFalse) && (images->blob->length != 0))
cristy3ed852e2009-09-05 21:47:34 +00001803 {
1804 *length=images->blob->length;
1805 blob=DetachBlob(images->blob);
1806 blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1807 sizeof(*blob));
1808 }
1809 }
1810 }
1811 else
1812 {
1813 char
1814 filename[MaxTextExtent],
1815 unique[MaxTextExtent];
1816
1817 int
1818 file;
1819
1820 /*
1821 Write file to disk in blob images format.
1822 */
1823 file=AcquireUniqueFileResource(unique);
1824 if (file == -1)
1825 {
1826 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1827 image_info->filename);
1828 }
1829 else
1830 {
1831 blob_info->file=fdopen(file,"wb");
1832 if (blob_info->file != (FILE *) NULL)
1833 {
cristyb51dff52011-05-19 16:55:47 +00001834 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001835 images->magick,unique);
1836 status=WriteImages(blob_info,images,filename,exception);
1837 (void) fclose(blob_info->file);
cristyb24e2402011-10-07 00:48:39 +00001838 if (status != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001839 blob=FileToBlob(images->filename,~0UL,length,exception);
1840 }
1841 (void) RelinquishUniqueFileResource(unique);
1842 }
1843 }
1844 blob_info=DestroyImageInfo(blob_info);
1845 return(blob);
1846}
1847/*
1848%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1849% %
1850% %
1851% %
1852% I n j e c t I m a g e B l o b %
1853% %
1854% %
1855% %
1856%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1857%
1858% InjectImageBlob() injects the image with a copy of itself in the specified
1859% format (e.g. inject JPEG into a PDF image).
1860%
1861% The format of the InjectImageBlob method is:
1862%
1863% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1864% Image *image,Image *inject_image,const char *format,
1865% ExceptionInfo *exception)
1866%
1867% A description of each parameter follows:
1868%
1869% o image_info: the image info..
1870%
1871% o image: the image.
1872%
1873% o inject_image: inject into the image stream.
1874%
1875% o format: the image format.
1876%
1877% o exception: return any errors or warnings in this structure.
1878%
1879*/
1880MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1881 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1882{
1883 char
1884 filename[MaxTextExtent];
1885
1886 FILE
1887 *unique_file;
1888
1889 Image
1890 *byte_image;
1891
1892 ImageInfo
1893 *write_info;
1894
1895 int
1896 file;
1897
1898 MagickBooleanType
1899 status;
1900
cristybb503372010-05-27 20:51:26 +00001901 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001902 i;
1903
1904 size_t
1905 quantum;
1906
1907 ssize_t
1908 count;
1909
1910 struct stat
cristye7b28372012-06-17 13:59:06 +00001911 file_stats;
cristy3ed852e2009-09-05 21:47:34 +00001912
1913 unsigned char
1914 *buffer;
1915
1916 /*
1917 Write inject image to a temporary file.
1918 */
1919 assert(image_info != (ImageInfo *) NULL);
1920 assert(image_info->signature == MagickSignature);
1921 assert(image != (Image *) NULL);
1922 assert(image->signature == MagickSignature);
1923 if (image->debug != MagickFalse)
1924 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1925 assert(inject_image != (Image *) NULL);
1926 assert(inject_image->signature == MagickSignature);
1927 assert(exception != (ExceptionInfo *) NULL);
1928 unique_file=(FILE *) NULL;
1929 file=AcquireUniqueFileResource(filename);
1930 if (file != -1)
1931 unique_file=fdopen(file,"wb");
1932 if ((file == -1) || (unique_file == (FILE *) NULL))
1933 {
1934 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1935 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1936 image->filename);
1937 return(MagickFalse);
1938 }
1939 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1940 if (byte_image == (Image *) NULL)
1941 {
1942 (void) fclose(unique_file);
1943 (void) RelinquishUniqueFileResource(filename);
1944 return(MagickFalse);
1945 }
cristyb51dff52011-05-19 16:55:47 +00001946 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
cristy3ed852e2009-09-05 21:47:34 +00001947 filename);
1948 DestroyBlob(byte_image);
1949 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1950 write_info=CloneImageInfo(image_info);
1951 SetImageInfoFile(write_info,unique_file);
cristy6f9e0d32011-08-28 16:32:09 +00001952 status=WriteImage(write_info,byte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001953 write_info=DestroyImageInfo(write_info);
1954 byte_image=DestroyImage(byte_image);
1955 (void) fclose(unique_file);
1956 if (status == MagickFalse)
1957 {
1958 (void) RelinquishUniqueFileResource(filename);
1959 return(MagickFalse);
1960 }
1961 /*
1962 Inject into image stream.
1963 */
cristy18c6c272011-09-23 14:40:37 +00001964 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +00001965 if (file == -1)
1966 {
1967 (void) RelinquishUniqueFileResource(filename);
1968 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1969 image_info->filename);
1970 return(MagickFalse);
1971 }
1972 quantum=(size_t) MagickMaxBufferExtent;
cristye7b28372012-06-17 13:59:06 +00001973 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1974 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
cristy3ed852e2009-09-05 21:47:34 +00001975 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1976 if (buffer == (unsigned char *) NULL)
1977 {
1978 (void) RelinquishUniqueFileResource(filename);
1979 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1980 image->filename);
1981 }
1982 for (i=0; ; i+=count)
1983 {
cristy65d11e42013-06-14 20:06:25 +00001984 count=read(file,buffer,quantum);
cristy3ed852e2009-09-05 21:47:34 +00001985 if (count <= 0)
1986 {
1987 count=0;
1988 if (errno != EINTR)
1989 break;
1990 }
1991 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1992 MagickFalse;
1993 }
cristya7cb4312010-06-26 00:47:03 +00001994 file=close(file);
1995 if (file == -1)
1996 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
cristy3ed852e2009-09-05 21:47:34 +00001997 (void) RelinquishUniqueFileResource(filename);
1998 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1999 return(status);
2000}
2001
2002/*
2003%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2004% %
2005% %
2006% %
2007+ I s B l o b E x e m p t %
2008% %
2009% %
2010% %
2011%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2012%
2013% IsBlobExempt() returns true if the blob is exempt.
2014%
2015% The format of the IsBlobExempt method is:
2016%
2017% MagickBooleanType IsBlobExempt(const Image *image)
2018%
2019% A description of each parameter follows:
2020%
2021% o image: the image.
2022%
2023*/
cristy7832dc22011-09-05 01:21:53 +00002024MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002025{
2026 assert(image != (const Image *) NULL);
2027 assert(image->signature == MagickSignature);
2028 if (image->debug != MagickFalse)
2029 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2030 return(image->blob->exempt);
2031}
2032
2033/*
2034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2035% %
2036% %
2037% %
2038+ I s B l o b S e e k a b l e %
2039% %
2040% %
2041% %
2042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2043%
2044% IsBlobSeekable() returns true if the blob is seekable.
2045%
2046% The format of the IsBlobSeekable method is:
2047%
2048% MagickBooleanType IsBlobSeekable(const Image *image)
2049%
2050% A description of each parameter follows:
2051%
2052% o image: the image.
2053%
2054*/
cristy7832dc22011-09-05 01:21:53 +00002055MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002056{
2057 MagickBooleanType
2058 seekable;
2059
2060 assert(image != (const Image *) NULL);
2061 assert(image->signature == MagickSignature);
2062 if (image->debug != MagickFalse)
2063 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyb8a98812012-01-31 15:30:59 +00002064 switch (image->blob->type)
2065 {
2066 case FileStream:
2067 case BlobStream:
2068 case ZipStream:
2069 {
2070 seekable=MagickTrue;
2071 break;
2072 }
2073 default:
2074 {
2075 seekable=MagickFalse;
2076 break;
2077 }
2078 }
cristy3ed852e2009-09-05 21:47:34 +00002079 return(seekable);
2080}
2081
2082/*
2083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2084% %
2085% %
2086% %
2087+ I s B l o b T e m p o r a r y %
2088% %
2089% %
2090% %
2091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2092%
2093% IsBlobTemporary() returns true if the blob is temporary.
2094%
2095% The format of the IsBlobTemporary method is:
2096%
2097% MagickBooleanType IsBlobTemporary(const Image *image)
2098%
2099% A description of each parameter follows:
2100%
2101% o image: the image.
2102%
2103*/
cristy7832dc22011-09-05 01:21:53 +00002104MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
cristy3ed852e2009-09-05 21:47:34 +00002105{
2106 assert(image != (const Image *) NULL);
2107 assert(image->signature == MagickSignature);
2108 if (image->debug != MagickFalse)
2109 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2110 return(image->blob->temporary);
2111}
2112
2113/*
2114%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2115% %
2116% %
2117% %
2118+ M a p B l o b %
2119% %
2120% %
2121% %
2122%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2123%
2124% MapBlob() creates a mapping from a file to a binary large object.
2125%
2126% The format of the MapBlob method is:
2127%
2128% unsigned char *MapBlob(int file,const MapMode mode,
2129% const MagickOffsetType offset,const size_t length)
2130%
2131% A description of each parameter follows:
2132%
2133% o file: map this file descriptor.
2134%
2135% o mode: ReadMode, WriteMode, or IOMode.
2136%
2137% o offset: starting at this offset within the file.
2138%
2139% o length: the length of the mapping is returned in this pointer.
2140%
2141*/
2142MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2143 const MagickOffsetType offset,const size_t length)
2144{
cristydc8ea8e2013-07-28 20:10:44 +00002145#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00002146 int
2147 flags,
2148 protection;
2149
2150 unsigned char
2151 *map;
2152
2153 /*
2154 Map file.
2155 */
2156 flags=0;
2157 if (file == -1)
2158#if defined(MAP_ANONYMOUS)
2159 flags|=MAP_ANONYMOUS;
2160#else
2161 return((unsigned char *) NULL);
2162#endif
2163 switch (mode)
2164 {
2165 case ReadMode:
2166 default:
2167 {
2168 protection=PROT_READ;
2169 flags|=MAP_PRIVATE;
cristy3ed852e2009-09-05 21:47:34 +00002170 break;
2171 }
2172 case WriteMode:
2173 {
2174 protection=PROT_WRITE;
2175 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002176 break;
2177 }
2178 case IOMode:
2179 {
2180 protection=PROT_READ | PROT_WRITE;
2181 flags|=MAP_SHARED;
cristy3ed852e2009-09-05 21:47:34 +00002182 break;
2183 }
2184 }
cristy56a0dbe2013-07-09 15:27:09 +00002185#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2186 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2187 (off_t) offset);
2188#else
2189 map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
2190 MAP_HUGETLB,file,(off_t) offset);
2191 if (map == (unsigned char *) MAP_FAILED)
2192 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2193 (off_t) offset);
2194#endif
cristy3ed852e2009-09-05 21:47:34 +00002195 if (map == (unsigned char *) MAP_FAILED)
2196 return((unsigned char *) NULL);
2197 return(map);
2198#else
2199 (void) file;
2200 (void) mode;
2201 (void) offset;
2202 (void) length;
2203 return((unsigned char *) NULL);
2204#endif
2205}
2206
2207/*
2208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2209% %
2210% %
2211% %
2212+ M S B O r d e r L o n g %
2213% %
2214% %
2215% %
2216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2217%
2218% MSBOrderLong() converts a least-significant byte first buffer of integers to
2219% most-significant byte first.
2220%
2221% The format of the MSBOrderLong method is:
2222%
2223% void MSBOrderLong(unsigned char *buffer,const size_t length)
2224%
2225% A description of each parameter follows.
2226%
2227% o buffer: Specifies a pointer to a buffer of integers.
2228%
2229% o length: Specifies the length of the buffer.
2230%
2231*/
2232MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2233{
2234 int
2235 c;
2236
2237 register unsigned char
2238 *p,
2239 *q;
2240
2241 assert(buffer != (unsigned char *) NULL);
2242 q=buffer+length;
2243 while (buffer < q)
2244 {
2245 p=buffer+3;
2246 c=(int) (*p);
2247 *p=(*buffer);
2248 *buffer++=(unsigned char) c;
2249 p=buffer+1;
2250 c=(int) (*p);
2251 *p=(*buffer);
2252 *buffer++=(unsigned char) c;
2253 buffer+=2;
2254 }
2255}
2256
2257/*
2258%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2259% %
2260% %
2261% %
2262+ M S B O r d e r S h o r t %
2263% %
2264% %
2265% %
2266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2267%
2268% MSBOrderShort() converts a least-significant byte first buffer of integers
2269% to most-significant byte first.
2270%
2271% The format of the MSBOrderShort method is:
2272%
2273% void MSBOrderShort(unsigned char *p,const size_t length)
2274%
2275% A description of each parameter follows.
2276%
2277% o p: Specifies a pointer to a buffer of integers.
2278%
2279% o length: Specifies the length of the buffer.
2280%
2281*/
2282MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2283{
2284 int
2285 c;
2286
2287 register unsigned char
2288 *q;
2289
2290 assert(p != (unsigned char *) NULL);
2291 q=p+length;
2292 while (p < q)
2293 {
2294 c=(int) (*p);
2295 *p=(*(p+1));
2296 p++;
2297 *p++=(unsigned char) c;
2298 }
2299}
2300
2301/*
2302%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2303% %
2304% %
2305% %
2306+ O p e n B l o b %
2307% %
2308% %
2309% %
2310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2311%
2312% OpenBlob() opens a file associated with the image. A file name of '-' sets
2313% the file to stdin for type 'r' and stdout for type 'w'. If the filename
2314% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2315% compressed for type 'w'. If the filename prefix is '|', it is piped to or
2316% from a system command.
2317%
2318% The format of the OpenBlob method is:
2319%
2320% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2321% const BlobMode mode,ExceptionInfo *exception)
2322%
2323% A description of each parameter follows:
2324%
2325% o image_info: the image info.
2326%
2327% o image: the image.
2328%
2329% o mode: the mode for opening the file.
2330%
2331*/
2332MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2333 Image *image,const BlobMode mode,ExceptionInfo *exception)
2334{
2335 char
cristybf6a7092010-06-11 02:12:15 +00002336 extension[MaxTextExtent],
cristy3ed852e2009-09-05 21:47:34 +00002337 filename[MaxTextExtent];
2338
2339 const char
2340 *type;
2341
2342 MagickBooleanType
2343 status;
2344
2345 PolicyRights
2346 rights;
2347
2348 assert(image_info != (ImageInfo *) NULL);
2349 assert(image_info->signature == MagickSignature);
2350 if (image_info->debug != MagickFalse)
2351 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2352 image_info->filename);
2353 assert(image != (Image *) NULL);
2354 assert(image->signature == MagickSignature);
2355 if (image_info->blob != (void *) NULL)
2356 {
2357 if (image_info->stream != (StreamHandler) NULL)
2358 image->blob->stream=(StreamHandler) image_info->stream;
2359 AttachBlob(image->blob,image_info->blob,image_info->length);
2360 return(MagickTrue);
2361 }
2362 (void) DetachBlob(image->blob);
2363 switch (mode)
2364 {
2365 default: type="r"; break;
2366 case ReadBlobMode: type="r"; break;
2367 case ReadBinaryBlobMode: type="rb"; break;
2368 case WriteBlobMode: type="w"; break;
2369 case WriteBinaryBlobMode: type="w+b"; break;
2370 case AppendBlobMode: type="a"; break;
2371 case AppendBinaryBlobMode: type="a+b"; break;
2372 }
2373 if (*type != 'r')
2374 image->blob->synchronize=image_info->synchronize;
2375 if (image_info->stream != (StreamHandler) NULL)
2376 {
2377 image->blob->stream=(StreamHandler) image_info->stream;
2378 if (*type == 'w')
2379 {
2380 image->blob->type=FifoStream;
2381 return(MagickTrue);
2382 }
2383 }
2384 /*
2385 Open image file.
2386 */
2387 *filename='\0';
2388 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2389 rights=ReadPolicyRights;
2390 if (*type == 'w')
2391 rights=WritePolicyRights;
2392 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2393 {
cristya9197f62010-01-12 02:23:34 +00002394 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +00002395 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
cristyefe601c2013-01-05 17:51:12 +00002396 "NotAuthorized","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +00002397 return(MagickFalse);
2398 }
2399 if ((LocaleCompare(filename,"-") == 0) ||
2400 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2401 {
cristye7b28372012-06-17 13:59:06 +00002402 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
cristy0157aea2010-04-24 21:12:18 +00002403#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +00002404 if (strchr(type,'b') != (char *) NULL)
cristye7b28372012-06-17 13:59:06 +00002405 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
cristy3ed852e2009-09-05 21:47:34 +00002406#endif
2407 image->blob->type=StandardStream;
2408 image->blob->exempt=MagickTrue;
2409 return(MagickTrue);
2410 }
cristybc20d112012-07-29 20:27:00 +00002411 if (LocaleNCompare(filename,"fd:",3) == 0)
2412 {
2413 char
2414 mode[MaxTextExtent];
2415
2416 *mode=(*type);
2417 mode[1]='\0';
2418 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2419#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2420 if (strchr(type,'b') != (char *) NULL)
2421 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2422#endif
2423 image->blob->type=StandardStream;
2424 image->blob->exempt=MagickTrue;
2425 return(MagickTrue);
2426 }
cristy3ed852e2009-09-05 21:47:34 +00002427#if defined(MAGICKCORE_HAVE_POPEN)
2428 if (*filename == '|')
2429 {
2430 char
2431 mode[MaxTextExtent];
2432
2433 /*
2434 Pipe image to or from a system command.
2435 */
2436#if defined(SIGPIPE)
2437 if (*type == 'w')
2438 (void) signal(SIGPIPE,SIG_IGN);
2439#endif
2440 *mode=(*type);
2441 mode[1]='\0';
cristye7b28372012-06-17 13:59:06 +00002442 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2443 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002444 {
2445 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2446 return(MagickFalse);
2447 }
2448 image->blob->type=PipeStream;
2449 image->blob->exempt=MagickTrue;
2450 return(MagickTrue);
2451 }
2452#endif
2453 status=GetPathAttributes(filename,&image->blob->properties);
2454#if defined(S_ISFIFO)
2455 if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2456 {
cristye7b28372012-06-17 13:59:06 +00002457 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2458 if (image->blob->file_info.file == (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002459 {
2460 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2461 return(MagickFalse);
2462 }
2463 image->blob->type=FileStream;
2464 image->blob->exempt=MagickTrue;
2465 return(MagickTrue);
2466 }
2467#endif
cristybf6a7092010-06-11 02:12:15 +00002468 GetPathComponent(image->filename,ExtensionPath,extension);
cristy3ed852e2009-09-05 21:47:34 +00002469 if (*type == 'w')
2470 {
cristye8939e72010-02-03 17:05:25 +00002471 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
cristyb9e31362010-04-22 16:38:17 +00002472 if ((image_info->adjoin == MagickFalse) ||
cristy7f223062011-03-12 01:37:20 +00002473 (strchr(filename,'%') != (char *) NULL))
cristye8939e72010-02-03 17:05:25 +00002474 {
2475 /*
2476 Form filename for multi-part images.
2477 */
2478 (void) InterpretImageFilename(image_info,image,image->filename,(int)
cristy6fccee12011-10-20 18:43:18 +00002479 image->scene,filename,exception);
cristy498cab92010-02-09 17:08:05 +00002480 if ((LocaleCompare(filename,image->filename) == 0) &&
2481 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2482 (GetNextImageInList(image) != (Image *) NULL)))
cristye8939e72010-02-03 17:05:25 +00002483 {
cristybf7fa0d2010-02-04 00:51:10 +00002484 char
cristybf7fa0d2010-02-04 00:51:10 +00002485 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00002486
cristybf7fa0d2010-02-04 00:51:10 +00002487 GetPathComponent(image->filename,RootPath,path);
cristybf7fa0d2010-02-04 00:51:10 +00002488 if (*extension == '\0')
cristyb51dff52011-05-19 16:55:47 +00002489 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
cristye8c25f92010-06-03 00:53:06 +00002490 path,(double) image->scene);
cristybf7fa0d2010-02-04 00:51:10 +00002491 else
cristyb51dff52011-05-19 16:55:47 +00002492 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
cristy9e1d53f2010-12-16 13:44:43 +00002493 path,(double) image->scene,extension);
cristye8939e72010-02-03 17:05:25 +00002494 }
2495 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00002496#if defined(macintosh)
cristye8939e72010-02-03 17:05:25 +00002497 SetApplicationType(filename,image_info->magick,'8BIM');
cristy3ed852e2009-09-05 21:47:34 +00002498#endif
cristye8939e72010-02-03 17:05:25 +00002499 }
cristy3ed852e2009-09-05 21:47:34 +00002500 }
cristybf6a7092010-06-11 02:12:15 +00002501 if (image_info->file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002502 {
cristye7b28372012-06-17 13:59:06 +00002503 image->blob->file_info.file=image_info->file;
cristybf6a7092010-06-11 02:12:15 +00002504 image->blob->type=FileStream;
2505 image->blob->exempt=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00002506 }
2507 else
cristybf6a7092010-06-11 02:12:15 +00002508 if (*type == 'r')
cristy3ed852e2009-09-05 21:47:34 +00002509 {
cristye7b28372012-06-17 13:59:06 +00002510 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2511 if (image->blob->file_info.file != (FILE *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002512 {
2513 size_t
cristybf6a7092010-06-11 02:12:15 +00002514 count;
cristy3ed852e2009-09-05 21:47:34 +00002515
cristybf6a7092010-06-11 02:12:15 +00002516 unsigned char
2517 magick[3];
cristy3ed852e2009-09-05 21:47:34 +00002518
cristybf6a7092010-06-11 02:12:15 +00002519 image->blob->type=FileStream;
2520#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002521 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2522 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002523#endif
2524 (void) ResetMagickMemory(magick,0,sizeof(magick));
cristye7b28372012-06-17 13:59:06 +00002525 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
cristyae958042013-01-05 15:48:19 +00002526 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
cristy79fe6932012-12-25 00:31:30 +00002527 (void) fflush(image->blob->file_info.file);
cristybf6a7092010-06-11 02:12:15 +00002528 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2529 " read %.20g magic header bytes",(double) count);
2530#if defined(MAGICKCORE_ZLIB_DELEGATE)
2531 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2532 ((int) magick[2] == 0x08))
cristy3ed852e2009-09-05 21:47:34 +00002533 {
cristye7b28372012-06-17 13:59:06 +00002534 (void) fclose(image->blob->file_info.file);
2535 image->blob->file_info.gzfile=gzopen(filename,type);
2536 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002537 image->blob->type=ZipStream;
2538 }
2539#endif
2540#if defined(MAGICKCORE_BZLIB_DELEGATE)
2541 if (strncmp((char *) magick,"BZh",3) == 0)
2542 {
cristye7b28372012-06-17 13:59:06 +00002543 (void) fclose(image->blob->file_info.file);
2544 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2545 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002546 image->blob->type=BZipStream;
cristy3ed852e2009-09-05 21:47:34 +00002547 }
cristybf6a7092010-06-11 02:12:15 +00002548#endif
cristyc6c589d2010-07-06 01:34:57 +00002549 if (image->blob->type == FileStream)
2550 {
2551 const MagickInfo
2552 *magick_info;
cristybf6a7092010-06-11 02:12:15 +00002553
cristyc6c589d2010-07-06 01:34:57 +00002554 ExceptionInfo
2555 *sans_exception;
cristybf6a7092010-06-11 02:12:15 +00002556
cristy18aba912013-06-14 19:48:08 +00002557 size_t
2558 length;
2559
cristyc6c589d2010-07-06 01:34:57 +00002560 sans_exception=AcquireExceptionInfo();
2561 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2562 sans_exception=DestroyExceptionInfo(sans_exception);
cristy2eddb3d2013-06-16 14:10:08 +00002563 length=(size_t) image->blob->properties.st_size;
cristyc6c589d2010-07-06 01:34:57 +00002564 if ((magick_info != (const MagickInfo *) NULL) &&
2565 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
cristy7c242ea2013-06-21 17:19:53 +00002566 (length <= MagickMaxBufferExtent) &&
cristy18aba912013-06-14 19:48:08 +00002567 (AcquireMagickResource(MapResource,length) != MagickFalse))
cristyc6c589d2010-07-06 01:34:57 +00002568 {
cristyc6c589d2010-07-06 01:34:57 +00002569 void
2570 *blob;
cristybf6a7092010-06-11 02:12:15 +00002571
cristyfe00ebf2013-06-16 14:17:53 +00002572 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2573 length);
cristy18aba912013-06-14 19:48:08 +00002574 if (blob == (void *) NULL)
2575 RelinquishMagickResource(MapResource,length);
2576 else
cristyc6c589d2010-07-06 01:34:57 +00002577 {
2578 /*
2579 Format supports blobs-- use memory-mapped I/O.
2580 */
2581 if (image_info->file != (FILE *) NULL)
2582 image->blob->exempt=MagickFalse;
2583 else
2584 {
cristye7b28372012-06-17 13:59:06 +00002585 (void) fclose(image->blob->file_info.file);
2586 image->blob->file_info.file=(FILE *) NULL;
cristyc6c589d2010-07-06 01:34:57 +00002587 }
2588 AttachBlob(image->blob,blob,length);
2589 image->blob->mapped=MagickTrue;
2590 }
2591 }
2592 }
cristy3ed852e2009-09-05 21:47:34 +00002593 }
cristybf6a7092010-06-11 02:12:15 +00002594 }
2595 else
2596#if defined(MAGICKCORE_ZLIB_DELEGATE)
2597 if ((LocaleCompare(extension,"Z") == 0) ||
2598 (LocaleCompare(extension,"gz") == 0) ||
2599 (LocaleCompare(extension,"wmz") == 0) ||
2600 (LocaleCompare(extension,"svgz") == 0))
2601 {
2602 if (mode == WriteBinaryBlobMode)
2603 type="wb";
cristye7b28372012-06-17 13:59:06 +00002604 image->blob->file_info.gzfile=gzopen(filename,type);
2605 if (image->blob->file_info.gzfile != (gzFile) NULL)
cristybf6a7092010-06-11 02:12:15 +00002606 image->blob->type=ZipStream;
2607 }
2608 else
2609#endif
2610#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy4b3e27d2012-01-31 15:34:52 +00002611 if (LocaleCompare(extension,"bz2") == 0)
cristybf6a7092010-06-11 02:12:15 +00002612 {
cristye7b28372012-06-17 13:59:06 +00002613 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2614 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002615 image->blob->type=BZipStream;
2616 }
2617 else
2618#endif
2619 {
cristye7b28372012-06-17 13:59:06 +00002620 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2621 if (image->blob->file_info.file != (FILE *) NULL)
cristybf6a7092010-06-11 02:12:15 +00002622 {
2623 image->blob->type=FileStream;
2624#if defined(MAGICKCORE_HAVE_SETVBUF)
cristyefe601c2013-01-05 17:51:12 +00002625 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2626 _IOFBF,16384);
cristybf6a7092010-06-11 02:12:15 +00002627#endif
2628 }
2629 }
cristy3ed852e2009-09-05 21:47:34 +00002630 image->blob->status=MagickFalse;
2631 if (image->blob->type != UndefinedStream)
2632 image->blob->size=GetBlobSize(image);
2633 else
2634 {
2635 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2636 return(MagickFalse);
2637 }
2638 return(MagickTrue);
2639}
2640
2641/*
2642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2643% %
2644% %
2645% %
2646+ P i n g B l o b %
2647% %
2648% %
2649% %
2650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2651%
2652% PingBlob() returns all the attributes of an image or image sequence except
2653% for the pixels. It is much faster and consumes far less memory than
2654% BlobToImage(). On failure, a NULL image is returned and exception
2655% describes the reason for the failure.
2656%
2657% The format of the PingBlob method is:
2658%
2659% Image *PingBlob(const ImageInfo *image_info,const void *blob,
2660% const size_t length,ExceptionInfo *exception)
2661%
2662% A description of each parameter follows:
2663%
2664% o image_info: the image info.
2665%
2666% o blob: the address of a character stream in one of the image formats
2667% understood by ImageMagick.
2668%
2669% o length: This size_t integer reflects the length in bytes of the blob.
2670%
2671% o exception: return any errors or warnings in this structure.
2672%
2673*/
2674
2675#if defined(__cplusplus) || defined(c_plusplus)
2676extern "C" {
2677#endif
2678
2679static size_t PingStream(const Image *magick_unused(image),
2680 const void *magick_unused(pixels),const size_t columns)
2681{
2682 return(columns);
2683}
2684
2685#if defined(__cplusplus) || defined(c_plusplus)
2686}
2687#endif
2688
2689MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2690 const size_t length,ExceptionInfo *exception)
2691{
2692 Image
2693 *image;
2694
2695 ImageInfo
2696 *ping_info;
2697
2698 assert(image_info != (ImageInfo *) NULL);
2699 assert(image_info->signature == MagickSignature);
2700 if (image_info->debug != MagickFalse)
2701 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2702 image_info->filename);
2703 assert(exception != (ExceptionInfo *) NULL);
2704 if ((blob == (const void *) NULL) || (length == 0))
2705 {
2706 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
cristyefe601c2013-01-05 17:51:12 +00002707 "UnrecognizedImageFormat","`%s'",image_info->magick);
cristy3ed852e2009-09-05 21:47:34 +00002708 return((Image *) NULL);
2709 }
2710 ping_info=CloneImageInfo(image_info);
2711 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2712 if (ping_info->blob == (const void *) NULL)
2713 {
2714 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00002715 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
cristy3ed852e2009-09-05 21:47:34 +00002716 return((Image *) NULL);
2717 }
cristy54aad5e2010-09-03 16:02:04 +00002718 (void) memcpy(ping_info->blob,blob,length);
cristy3ed852e2009-09-05 21:47:34 +00002719 ping_info->length=length;
2720 ping_info->ping=MagickTrue;
2721 image=ReadStream(ping_info,&PingStream,exception);
2722 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2723 ping_info=DestroyImageInfo(ping_info);
2724 return(image);
2725}
2726
2727/*
2728%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2729% %
2730% %
2731% %
2732+ R e a d B l o b %
2733% %
2734% %
2735% %
2736%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2737%
2738% ReadBlob() reads data from the blob or image file and returns it. It
cristy5f3d2752013-01-05 18:53:38 +00002739% returns the number of bytes read. If length is zero, ReadBlob() returns
2740% zero and has no other results. If length is greater than SSIZE_MAX, the
2741% result is unspecified.
cristy3ed852e2009-09-05 21:47:34 +00002742%
2743% The format of the ReadBlob method is:
2744%
2745% ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2746%
2747% A description of each parameter follows:
2748%
2749% o image: the image.
2750%
2751% o length: Specifies an integer representing the number of bytes to read
2752% from the file.
2753%
2754% o data: Specifies an area to place the information requested from the
2755% file.
2756%
2757*/
2758MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2759 unsigned char *data)
2760{
2761 int
2762 c;
2763
2764 register unsigned char
2765 *q;
2766
2767 ssize_t
2768 count;
2769
2770 assert(image != (Image *) NULL);
2771 assert(image->signature == MagickSignature);
2772 assert(image->blob != (BlobInfo *) NULL);
2773 assert(image->blob->type != UndefinedStream);
2774 if (length == 0)
2775 return(0);
2776 assert(data != (void *) NULL);
2777 count=0;
2778 q=data;
2779 switch (image->blob->type)
2780 {
2781 case UndefinedStream:
2782 break;
cristy3ed852e2009-09-05 21:47:34 +00002783 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00002784 {
cristy8faec1e2013-04-25 19:41:22 +00002785 register ssize_t
2786 i;
2787
2788 for (i=0; i < (ssize_t) length; i+=count)
2789 {
cristy7c242ea2013-06-21 17:19:53 +00002790 count=read(fileno(image->blob->file_info.file),q+i,(size_t)
cristy8faec1e2013-04-25 19:41:22 +00002791 MagickMin(length-i,(MagickSizeType) SSIZE_MAX));
2792 if (count <= 0)
2793 {
2794 count=0;
2795 if (errno != EINTR)
2796 break;
2797 }
2798 }
2799 count=i;
cristybc20d112012-07-29 20:27:00 +00002800 break;
2801 }
2802 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00002803 case PipeStream:
2804 {
2805 switch (length)
2806 {
2807 default:
2808 {
cristye7b28372012-06-17 13:59:06 +00002809 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002810 break;
2811 }
2812 case 2:
2813 {
cristye7b28372012-06-17 13:59:06 +00002814 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002815 if (c == EOF)
2816 break;
2817 *q++=(unsigned char) c;
2818 count++;
2819 }
2820 case 1:
2821 {
cristye7b28372012-06-17 13:59:06 +00002822 c=getc(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00002823 if (c == EOF)
2824 break;
2825 *q++=(unsigned char) c;
2826 count++;
2827 }
2828 case 0:
2829 break;
2830 }
2831 break;
2832 }
2833 case ZipStream:
2834 {
2835#if defined(MAGICKCORE_ZLIB_DELEGATE)
2836 switch (length)
2837 {
2838 default:
2839 {
cristye7b28372012-06-17 13:59:06 +00002840 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
cristy95888612012-04-04 21:56:52 +00002841 (unsigned int) length);
cristy3ed852e2009-09-05 21:47:34 +00002842 break;
2843 }
2844 case 2:
2845 {
cristye7b28372012-06-17 13:59:06 +00002846 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002847 if (c == EOF)
2848 break;
2849 *q++=(unsigned char) c;
2850 count++;
2851 }
2852 case 1:
2853 {
cristye7b28372012-06-17 13:59:06 +00002854 c=gzgetc(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00002855 if (c == EOF)
2856 break;
2857 *q++=(unsigned char) c;
2858 count++;
2859 }
2860 case 0:
2861 break;
2862 }
2863#endif
2864 break;
2865 }
2866 case BZipStream:
2867 {
2868#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristy5f3d2752013-01-05 18:53:38 +00002869 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
cristy3ed852e2009-09-05 21:47:34 +00002870#endif
2871 break;
2872 }
2873 case FifoStream:
2874 break;
2875 case BlobStream:
2876 {
2877 register const unsigned char
2878 *p;
2879
2880 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2881 {
2882 image->blob->eof=MagickTrue;
2883 break;
2884 }
2885 p=image->blob->data+image->blob->offset;
cristye7b28372012-06-17 13:59:06 +00002886 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2887 image->blob->offset));
cristy3ed852e2009-09-05 21:47:34 +00002888 image->blob->offset+=count;
2889 if (count != (ssize_t) length)
2890 image->blob->eof=MagickTrue;
cristy54aad5e2010-09-03 16:02:04 +00002891 (void) memcpy(q,p,(size_t) count);
cristy3ed852e2009-09-05 21:47:34 +00002892 break;
2893 }
2894 }
2895 return(count);
2896}
2897
2898/*
2899%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2900% %
2901% %
2902% %
2903+ R e a d B l o b B y t e %
2904% %
2905% %
2906% %
2907%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2908%
2909% ReadBlobByte() reads a single byte from the image file and returns it.
2910%
2911% The format of the ReadBlobByte method is:
2912%
2913% int ReadBlobByte(Image *image)
2914%
2915% A description of each parameter follows.
2916%
2917% o image: the image.
2918%
2919*/
2920MagickExport int ReadBlobByte(Image *image)
2921{
2922 register const unsigned char
2923 *p;
2924
2925 ssize_t
2926 count;
2927
2928 unsigned char
2929 buffer[1];
2930
2931 assert(image != (Image *) NULL);
2932 assert(image->signature == MagickSignature);
2933 p=ReadBlobStream(image,1,buffer,&count);
2934 if (count != 1)
2935 return(EOF);
2936 return((int) (*p));
2937}
2938
2939/*
2940%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2941% %
2942% %
2943% %
2944+ R e a d B l o b D o u b l e %
2945% %
2946% %
2947% %
2948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2949%
2950% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2951% specified by the endian member of the image structure.
2952%
2953% The format of the ReadBlobDouble method is:
2954%
2955% double ReadBlobDouble(Image *image)
2956%
2957% A description of each parameter follows.
2958%
2959% o image: the image.
2960%
2961*/
2962MagickExport double ReadBlobDouble(Image *image)
2963{
2964 union
2965 {
2966 MagickSizeType
2967 unsigned_value;
2968
2969 double
2970 double_value;
2971 } quantum;
2972
2973 quantum.double_value=0.0;
2974 quantum.unsigned_value=ReadBlobLongLong(image);
2975 return(quantum.double_value);
2976}
2977
2978/*
2979%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2980% %
2981% %
2982% %
2983+ R e a d B l o b F l o a t %
2984% %
2985% %
2986% %
2987%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2988%
2989% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2990% specified by the endian member of the image structure.
2991%
2992% The format of the ReadBlobFloat method is:
2993%
2994% float ReadBlobFloat(Image *image)
2995%
2996% A description of each parameter follows.
2997%
2998% o image: the image.
2999%
3000*/
3001MagickExport float ReadBlobFloat(Image *image)
3002{
3003 union
3004 {
3005 unsigned int
3006 unsigned_value;
3007
3008 float
3009 float_value;
3010 } quantum;
3011
3012 quantum.float_value=0.0;
3013 quantum.unsigned_value=ReadBlobLong(image);
3014 return(quantum.float_value);
3015}
3016
3017/*
3018%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3019% %
3020% %
3021% %
3022+ R e a d B l o b L o n g %
3023% %
3024% %
3025% %
3026%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3027%
cristybb503372010-05-27 20:51:26 +00003028% ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00003029% specified by the endian member of the image structure.
3030%
3031% The format of the ReadBlobLong method is:
3032%
3033% unsigned int ReadBlobLong(Image *image)
3034%
3035% A description of each parameter follows.
3036%
3037% o image: the image.
3038%
3039*/
3040MagickExport unsigned int ReadBlobLong(Image *image)
3041{
3042 register const unsigned char
3043 *p;
3044
3045 ssize_t
3046 count;
3047
3048 unsigned char
3049 buffer[4];
3050
3051 unsigned int
3052 value;
3053
3054 assert(image != (Image *) NULL);
3055 assert(image->signature == MagickSignature);
3056 *buffer='\0';
3057 p=ReadBlobStream(image,4,buffer,&count);
3058 if (count != 4)
3059 return(0UL);
3060 if (image->endian == LSBEndian)
3061 {
3062 value=(unsigned int) (*p++);
3063 value|=((unsigned int) (*p++)) << 8;
3064 value|=((unsigned int) (*p++)) << 16;
3065 value|=((unsigned int) (*p++)) << 24;
3066 return(value);
3067 }
3068 value=((unsigned int) (*p++)) << 24;
3069 value|=((unsigned int) (*p++)) << 16;
3070 value|=((unsigned int) (*p++)) << 8;
3071 value|=((unsigned int) (*p++));
3072 return(value);
3073}
3074
3075/*
3076%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3077% %
3078% %
3079% %
3080+ R e a d B l o b L o n g L o n g %
3081% %
3082% %
3083% %
3084%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3085%
cristy4cb162a2010-05-30 03:04:47 +00003086% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3087% byte-order specified by the endian member of the image structure.
cristy3ed852e2009-09-05 21:47:34 +00003088%
cristy4cb162a2010-05-30 03:04:47 +00003089% The format of the ReadBlobLongLong method is:
cristy3ed852e2009-09-05 21:47:34 +00003090%
cristy4cb162a2010-05-30 03:04:47 +00003091% MagickSizeType ReadBlobLongLong(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00003092%
3093% A description of each parameter follows.
3094%
3095% o image: the image.
3096%
3097*/
3098MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3099{
cristy0286d852010-10-12 18:38:07 +00003100 MagickSizeType
3101 value;
3102
cristy3ed852e2009-09-05 21:47:34 +00003103 register const unsigned char
3104 *p;
3105
3106 ssize_t
3107 count;
3108
3109 unsigned char
3110 buffer[8];
3111
cristy3ed852e2009-09-05 21:47:34 +00003112 assert(image != (Image *) NULL);
3113 assert(image->signature == MagickSignature);
3114 *buffer='\0';
3115 p=ReadBlobStream(image,8,buffer,&count);
3116 if (count != 8)
3117 return(MagickULLConstant(0));
3118 if (image->endian == LSBEndian)
3119 {
3120 value=(MagickSizeType) (*p++);
3121 value|=((MagickSizeType) (*p++)) << 8;
3122 value|=((MagickSizeType) (*p++)) << 16;
3123 value|=((MagickSizeType) (*p++)) << 24;
3124 value|=((MagickSizeType) (*p++)) << 32;
3125 value|=((MagickSizeType) (*p++)) << 40;
3126 value|=((MagickSizeType) (*p++)) << 48;
3127 value|=((MagickSizeType) (*p++)) << 56;
3128 return(value & MagickULLConstant(0xffffffffffffffff));
3129 }
3130 value=((MagickSizeType) (*p++)) << 56;
3131 value|=((MagickSizeType) (*p++)) << 48;
3132 value|=((MagickSizeType) (*p++)) << 40;
3133 value|=((MagickSizeType) (*p++)) << 32;
3134 value|=((MagickSizeType) (*p++)) << 24;
3135 value|=((MagickSizeType) (*p++)) << 16;
3136 value|=((MagickSizeType) (*p++)) << 8;
3137 value|=((MagickSizeType) (*p++));
3138 return(value & MagickULLConstant(0xffffffffffffffff));
3139}
3140
3141/*
3142%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3143% %
3144% %
3145% %
3146+ R e a d B l o b S h o r t %
3147% %
3148% %
3149% %
3150%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3151%
3152% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3153% specified by the endian member of the image structure.
3154%
3155% The format of the ReadBlobShort method is:
3156%
3157% unsigned short ReadBlobShort(Image *image)
3158%
3159% A description of each parameter follows.
3160%
3161% o image: the image.
3162%
3163*/
3164MagickExport unsigned short ReadBlobShort(Image *image)
3165{
3166 register const unsigned char
3167 *p;
3168
3169 register unsigned int
3170 value;
3171
3172 ssize_t
3173 count;
3174
3175 unsigned char
3176 buffer[2];
3177
3178 assert(image != (Image *) NULL);
3179 assert(image->signature == MagickSignature);
3180 *buffer='\0';
3181 p=ReadBlobStream(image,2,buffer,&count);
3182 if (count != 2)
3183 return((unsigned short) 0U);
3184 if (image->endian == LSBEndian)
3185 {
3186 value=(unsigned int) (*p++);
3187 value|=((unsigned int) (*p++)) << 8;
3188 return((unsigned short) (value & 0xffff));
3189 }
3190 value=(unsigned int) ((*p++) << 8);
3191 value|=(unsigned int) (*p++);
3192 return((unsigned short) (value & 0xffff));
3193}
3194
3195/*
3196%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3197% %
3198% %
3199% %
3200+ R e a d B l o b L S B L o n g %
3201% %
3202% %
3203% %
3204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3205%
cristybb503372010-05-27 20:51:26 +00003206% ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003207% least-significant byte first order.
3208%
3209% The format of the ReadBlobLSBLong method is:
3210%
3211% unsigned int ReadBlobLSBLong(Image *image)
3212%
3213% A description of each parameter follows.
3214%
3215% o image: the image.
3216%
3217*/
3218MagickExport unsigned int ReadBlobLSBLong(Image *image)
3219{
3220 register const unsigned char
3221 *p;
3222
3223 register unsigned int
3224 value;
3225
3226 ssize_t
3227 count;
3228
3229 unsigned char
3230 buffer[4];
3231
3232 assert(image != (Image *) NULL);
3233 assert(image->signature == MagickSignature);
3234 *buffer='\0';
3235 p=ReadBlobStream(image,4,buffer,&count);
3236 if (count != 4)
3237 return(0U);
3238 value=(unsigned int) (*p++);
3239 value|=((unsigned int) (*p++)) << 8;
3240 value|=((unsigned int) (*p++)) << 16;
3241 value|=((unsigned int) (*p++)) << 24;
3242 return(value);
3243}
3244
3245/*
3246%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3247% %
3248% %
3249% %
3250+ R e a d B l o b L S B S h o r t %
3251% %
3252% %
3253% %
3254%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3255%
3256% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3257% least-significant byte first order.
3258%
3259% The format of the ReadBlobLSBShort method is:
3260%
3261% unsigned short ReadBlobLSBShort(Image *image)
3262%
3263% A description of each parameter follows.
3264%
3265% o image: the image.
3266%
3267*/
3268MagickExport unsigned short ReadBlobLSBShort(Image *image)
3269{
3270 register const unsigned char
3271 *p;
3272
3273 register unsigned int
3274 value;
3275
3276 ssize_t
3277 count;
3278
3279 unsigned char
3280 buffer[2];
3281
3282 assert(image != (Image *) NULL);
3283 assert(image->signature == MagickSignature);
3284 *buffer='\0';
3285 p=ReadBlobStream(image,2,buffer,&count);
3286 if (count != 2)
3287 return((unsigned short) 0U);
3288 value=(unsigned int) (*p++);
3289 value|=((unsigned int) ((*p++)) << 8);
3290 return((unsigned short) (value & 0xffff));
3291}
3292
3293/*
3294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3295% %
3296% %
3297% %
3298+ R e a d B l o b M S B L o n g %
3299% %
3300% %
3301% %
3302%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3303%
cristybb503372010-05-27 20:51:26 +00003304% ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00003305% most-significant byte first order.
3306%
3307% The format of the ReadBlobMSBLong method is:
3308%
3309% unsigned int ReadBlobMSBLong(Image *image)
3310%
3311% A description of each parameter follows.
3312%
3313% o image: the image.
3314%
3315*/
3316MagickExport unsigned int ReadBlobMSBLong(Image *image)
3317{
3318 register const unsigned char
3319 *p;
3320
3321 register unsigned int
3322 value;
3323
3324 ssize_t
3325 count;
3326
3327 unsigned char
3328 buffer[4];
3329
3330 assert(image != (Image *) NULL);
3331 assert(image->signature == MagickSignature);
3332 *buffer='\0';
3333 p=ReadBlobStream(image,4,buffer,&count);
3334 if (count != 4)
3335 return(0UL);
3336 value=((unsigned int) (*p++) << 24);
3337 value|=((unsigned int) (*p++) << 16);
3338 value|=((unsigned int) (*p++) << 8);
3339 value|=(unsigned int) (*p++);
3340 return(value);
3341}
3342
3343/*
3344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3345% %
3346% %
3347% %
cristy2d3d87f2010-03-01 00:23:08 +00003348+ R e a d B l o b M S B L o n g L o n g %
3349% %
3350% %
3351% %
3352%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3353%
cristybb503372010-05-27 20:51:26 +00003354% ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
cristy2d3d87f2010-03-01 00:23:08 +00003355% most-significant byte first order.
3356%
3357% The format of the ReadBlobMSBLongLong method is:
3358%
3359% unsigned int ReadBlobMSBLongLong(Image *image)
3360%
3361% A description of each parameter follows.
3362%
3363% o image: the image.
3364%
3365*/
3366MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3367{
3368 register const unsigned char
3369 *p;
3370
3371 register MagickSizeType
3372 value;
3373
3374 ssize_t
3375 count;
3376
3377 unsigned char
cristy0286d852010-10-12 18:38:07 +00003378 buffer[8];
cristy2d3d87f2010-03-01 00:23:08 +00003379
3380 assert(image != (Image *) NULL);
3381 assert(image->signature == MagickSignature);
3382 *buffer='\0';
3383 p=ReadBlobStream(image,8,buffer,&count);
3384 if (count != 8)
3385 return(MagickULLConstant(0));
3386 value=((MagickSizeType) (*p++)) << 56;
3387 value|=((MagickSizeType) (*p++)) << 48;
3388 value|=((MagickSizeType) (*p++)) << 40;
3389 value|=((MagickSizeType) (*p++)) << 32;
3390 value|=((MagickSizeType) (*p++)) << 24;
3391 value|=((MagickSizeType) (*p++)) << 16;
3392 value|=((MagickSizeType) (*p++)) << 8;
3393 value|=((MagickSizeType) (*p++));
3394 return(value & MagickULLConstant(0xffffffffffffffff));
3395}
3396
3397/*
3398%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3399% %
3400% %
3401% %
cristy3ed852e2009-09-05 21:47:34 +00003402+ R e a d B l o b M S B S h o r t %
3403% %
3404% %
3405% %
3406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3407%
3408% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3409% most-significant byte first order.
3410%
3411% The format of the ReadBlobMSBShort method is:
3412%
3413% unsigned short ReadBlobMSBShort(Image *image)
3414%
3415% A description of each parameter follows.
3416%
3417% o image: the image.
3418%
3419*/
3420MagickExport unsigned short ReadBlobMSBShort(Image *image)
3421{
3422 register const unsigned char
3423 *p;
3424
3425 register unsigned int
3426 value;
3427
3428 ssize_t
3429 count;
3430
3431 unsigned char
3432 buffer[2];
3433
3434 assert(image != (Image *) NULL);
3435 assert(image->signature == MagickSignature);
3436 *buffer='\0';
3437 p=ReadBlobStream(image,2,buffer,&count);
3438 if (count != 2)
3439 return((unsigned short) 0U);
3440 value=(unsigned int) ((*p++) << 8);
3441 value|=(unsigned int) (*p++);
3442 return((unsigned short) (value & 0xffff));
3443}
3444
3445/*
3446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3447% %
3448% %
3449% %
3450+ R e a d B l o b S t r i n g %
3451% %
3452% %
3453% %
3454%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3455%
3456% ReadBlobString() reads characters from a blob or file until a newline
3457% character is read or an end-of-file condition is encountered.
3458%
3459% The format of the ReadBlobString method is:
3460%
3461% char *ReadBlobString(Image *image,char *string)
3462%
3463% A description of each parameter follows:
3464%
3465% o image: the image.
3466%
3467% o string: the address of a character buffer.
3468%
3469*/
3470MagickExport char *ReadBlobString(Image *image,char *string)
3471{
3472 register const unsigned char
3473 *p;
3474
cristybb503372010-05-27 20:51:26 +00003475 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003476 i;
3477
3478 ssize_t
3479 count;
3480
3481 unsigned char
3482 buffer[1];
3483
3484 assert(image != (Image *) NULL);
3485 assert(image->signature == MagickSignature);
3486 for (i=0; i < (MaxTextExtent-1L); i++)
3487 {
3488 p=ReadBlobStream(image,1,buffer,&count);
3489 if (count != 1)
3490 {
3491 if (i == 0)
3492 return((char *) NULL);
3493 break;
3494 }
3495 string[i]=(char) (*p);
cristy2b5db102010-06-09 01:07:28 +00003496 if ((string[i] == '\r') || (string[i] == '\n'))
cristy3ed852e2009-09-05 21:47:34 +00003497 break;
3498 }
cristy2b5db102010-06-09 01:07:28 +00003499 if (string[i] == '\r')
3500 (void) ReadBlobStream(image,1,buffer,&count);
cristy3ed852e2009-09-05 21:47:34 +00003501 string[i]='\0';
3502 return(string);
3503}
3504
3505/*
3506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3507% %
3508% %
3509% %
3510+ R e f e r e n c e B l o b %
3511% %
3512% %
3513% %
3514%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3515%
3516% ReferenceBlob() increments the reference count associated with the pixel
3517% blob returning a pointer to the blob.
3518%
3519% The format of the ReferenceBlob method is:
3520%
3521% BlobInfo ReferenceBlob(BlobInfo *blob_info)
3522%
3523% A description of each parameter follows:
3524%
3525% o blob_info: the blob_info.
3526%
3527*/
3528MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3529{
3530 assert(blob != (BlobInfo *) NULL);
3531 assert(blob->signature == MagickSignature);
3532 if (blob->debug != MagickFalse)
3533 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00003534 LockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003535 blob->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00003536 UnlockSemaphoreInfo(blob->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00003537 return(blob);
3538}
3539
3540/*
3541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3542% %
3543% %
3544% %
3545+ S e e k B l o b %
3546% %
3547% %
3548% %
3549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3550%
3551% SeekBlob() sets the offset in bytes from the beginning of a blob or file
3552% and returns the resulting offset.
3553%
3554% The format of the SeekBlob method is:
3555%
3556% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3557% const int whence)
3558%
3559% A description of each parameter follows:
3560%
3561% o image: the image.
3562%
3563% o offset: Specifies an integer representing the offset in bytes.
3564%
3565% o whence: Specifies an integer representing how the offset is
3566% treated relative to the beginning of the blob as follows:
3567%
3568% SEEK_SET Set position equal to offset bytes.
3569% SEEK_CUR Set position to current location plus offset.
3570% SEEK_END Set position to EOF plus offset.
3571%
3572*/
3573MagickExport MagickOffsetType SeekBlob(Image *image,
3574 const MagickOffsetType offset,const int whence)
3575{
3576 assert(image != (Image *) NULL);
3577 assert(image->signature == MagickSignature);
3578 if (image->debug != MagickFalse)
3579 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3580 assert(image->blob != (BlobInfo *) NULL);
3581 assert(image->blob->type != UndefinedStream);
3582 switch (image->blob->type)
3583 {
3584 case UndefinedStream:
3585 break;
cristybc20d112012-07-29 20:27:00 +00003586 case StandardStream:
3587 return(-1);
cristy3ed852e2009-09-05 21:47:34 +00003588 case FileStream:
3589 {
cristye7b28372012-06-17 13:59:06 +00003590 if (fseek(image->blob->file_info.file,offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003591 return(-1);
3592 image->blob->offset=TellBlob(image);
3593 break;
3594 }
cristy3ed852e2009-09-05 21:47:34 +00003595 case PipeStream:
3596 case ZipStream:
3597 {
3598#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003599 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
cristy3ed852e2009-09-05 21:47:34 +00003600 return(-1);
3601#endif
3602 image->blob->offset=TellBlob(image);
3603 break;
3604 }
3605 case BZipStream:
3606 return(-1);
3607 case FifoStream:
3608 return(-1);
3609 case BlobStream:
3610 {
3611 switch (whence)
3612 {
3613 case SEEK_SET:
3614 default:
3615 {
3616 if (offset < 0)
3617 return(-1);
3618 image->blob->offset=offset;
3619 break;
3620 }
3621 case SEEK_CUR:
3622 {
3623 if ((image->blob->offset+offset) < 0)
3624 return(-1);
3625 image->blob->offset+=offset;
3626 break;
3627 }
3628 case SEEK_END:
3629 {
3630 if (((MagickOffsetType) image->blob->length+offset) < 0)
3631 return(-1);
3632 image->blob->offset=image->blob->length+offset;
3633 break;
3634 }
3635 }
3636 if (image->blob->offset <= (MagickOffsetType)
3637 ((off_t) image->blob->length))
3638 image->blob->eof=MagickFalse;
3639 else
3640 if (image->blob->mapped != MagickFalse)
3641 return(-1);
3642 else
3643 {
3644 image->blob->extent=(size_t) (image->blob->offset+
3645 image->blob->quantum);
3646 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3647 image->blob->data,image->blob->extent+1,
3648 sizeof(*image->blob->data));
3649 (void) SyncBlob(image);
3650 if (image->blob->data == (unsigned char *) NULL)
3651 {
3652 (void) DetachBlob(image->blob);
3653 return(-1);
3654 }
3655 }
3656 break;
3657 }
3658 }
3659 return(image->blob->offset);
3660}
3661
3662/*
3663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3664% %
3665% %
3666% %
3667+ S e t B l o b E x e m p t %
3668% %
3669% %
3670% %
3671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3672%
3673% SetBlobExempt() sets the blob exempt status.
3674%
3675% The format of the SetBlobExempt method is:
3676%
3677% MagickBooleanType SetBlobExempt(const Image *image,
3678% const MagickBooleanType exempt)
3679%
3680% A description of each parameter follows:
3681%
3682% o image: the image.
3683%
3684% o exempt: Set to true if this blob is exempt from being closed.
3685%
3686*/
cristy7832dc22011-09-05 01:21:53 +00003687MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
cristy3ed852e2009-09-05 21:47:34 +00003688{
3689 assert(image != (const Image *) NULL);
3690 assert(image->signature == MagickSignature);
3691 if (image->debug != MagickFalse)
3692 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3693 image->blob->exempt=exempt;
3694}
3695
3696/*
3697%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3698% %
3699% %
3700% %
3701+ S e t B l o b E x t e n t %
3702% %
3703% %
3704% %
3705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3706%
3707% SetBlobExtent() ensures enough space is allocated for the blob. If the
3708% method is successful, subsequent writes to bytes in the specified range are
3709% guaranteed not to fail.
3710%
3711% The format of the SetBlobExtent method is:
3712%
3713% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3714%
3715% A description of each parameter follows:
3716%
3717% o image: the image.
3718%
3719% o extent: the blob maximum extent.
3720%
3721*/
cristy7832dc22011-09-05 01:21:53 +00003722MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
cristy3ed852e2009-09-05 21:47:34 +00003723 const MagickSizeType extent)
3724{
3725 assert(image != (Image *) NULL);
3726 assert(image->signature == MagickSignature);
3727 if (image->debug != MagickFalse)
3728 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3729 assert(image->blob != (BlobInfo *) NULL);
3730 assert(image->blob->type != UndefinedStream);
3731 switch (image->blob->type)
3732 {
3733 case UndefinedStream:
3734 break;
cristybc20d112012-07-29 20:27:00 +00003735 case StandardStream:
3736 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003737 case FileStream:
3738 {
cristy38e35f42012-12-18 21:12:17 +00003739 MagickOffsetType
3740 offset;
3741
3742 ssize_t
3743 count;
3744
cristy3ed852e2009-09-05 21:47:34 +00003745 if (extent != (MagickSizeType) ((off_t) extent))
3746 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003747 offset=SeekBlob(image,0,SEEK_END);
3748 if (offset < 0)
cristy3ed852e2009-09-05 21:47:34 +00003749 return(MagickFalse);
cristy38e35f42012-12-18 21:12:17 +00003750 if ((MagickSizeType) offset >= extent)
3751 break;
3752 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003753 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3754 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003755#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3756 if (image->blob->synchronize != MagickFalse)
3757 {
3758 int
3759 status;
3760
3761 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3762 extent-offset);
3763 if (status != 0)
3764 return(MagickFalse);
3765 }
3766#endif
cristy38e35f42012-12-18 21:12:17 +00003767 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003768 if (count != 1)
cristy38e35f42012-12-18 21:12:17 +00003769 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003770 break;
3771 }
cristy3ed852e2009-09-05 21:47:34 +00003772 case PipeStream:
3773 case ZipStream:
3774 return(MagickFalse);
3775 case BZipStream:
3776 return(MagickFalse);
3777 case FifoStream:
3778 return(MagickFalse);
3779 case BlobStream:
3780 {
cristy38e35f42012-12-18 21:12:17 +00003781 if (extent != (MagickSizeType) ((size_t) extent))
3782 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00003783 if (image->blob->mapped != MagickFalse)
3784 {
cristy38e35f42012-12-18 21:12:17 +00003785 MagickOffsetType
3786 offset;
3787
3788 ssize_t
3789 count;
3790
cristy3ed852e2009-09-05 21:47:34 +00003791 (void) UnmapBlob(image->blob->data,image->blob->length);
cristy18aba912013-06-14 19:48:08 +00003792 RelinquishMagickResource(MapResource,image->blob->length);
cristy38e35f42012-12-18 21:12:17 +00003793 if (extent != (MagickSizeType) ((off_t) extent))
3794 return(MagickFalse);
3795 offset=SeekBlob(image,0,SEEK_END);
3796 if (offset < 0)
3797 return(MagickFalse);
3798 if ((MagickSizeType) offset >= extent)
3799 break;
3800 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003801 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
cristy38e35f42012-12-18 21:12:17 +00003802 image->blob->file_info.file);
cristyfa0ea942012-12-21 02:42:29 +00003803#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3804 if (image->blob->synchronize != MagickFalse)
3805 {
3806 int
3807 status;
3808
3809 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3810 extent-offset);
3811 if (status != 0)
3812 return(MagickFalse);
3813 }
3814#endif
cristy38e35f42012-12-18 21:12:17 +00003815 offset=SeekBlob(image,offset,SEEK_SET);
cristyc7591272013-01-05 16:02:28 +00003816 if (count != 1)
cristyefe601c2013-01-05 17:51:12 +00003817 return(MagickFalse);
cristyac1caa22013-06-15 00:41:21 +00003818 (void) AcquireMagickResource(MapResource,extent);
cristy95888612012-04-04 21:56:52 +00003819 image->blob->data=(unsigned char*) MapBlob(fileno(
cristye7b28372012-06-17 13:59:06 +00003820 image->blob->file_info.file),WriteMode,0,(size_t) extent);
cristy3ed852e2009-09-05 21:47:34 +00003821 image->blob->extent=(size_t) extent;
3822 image->blob->length=(size_t) extent;
3823 (void) SyncBlob(image);
3824 break;
cristy3ed852e2009-09-05 21:47:34 +00003825 }
cristy3ed852e2009-09-05 21:47:34 +00003826 image->blob->extent=(size_t) extent;
3827 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3828 image->blob->extent+1,sizeof(*image->blob->data));
3829 (void) SyncBlob(image);
3830 if (image->blob->data == (unsigned char *) NULL)
3831 {
3832 (void) DetachBlob(image->blob);
3833 return(MagickFalse);
3834 }
3835 break;
3836 }
3837 }
3838 return(MagickTrue);
3839}
3840
3841/*
3842%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3843% %
3844% %
3845% %
3846+ S y n c B l o b %
3847% %
3848% %
3849% %
3850%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3851%
3852% SyncBlob() flushes the datastream if it is a file or synchronizes the data
3853% attributes if it is an blob.
3854%
3855% The format of the SyncBlob method is:
3856%
3857% int SyncBlob(Image *image)
3858%
3859% A description of each parameter follows:
3860%
3861% o image: the image.
3862%
3863*/
3864static int SyncBlob(Image *image)
3865{
3866 int
3867 status;
3868
3869 assert(image != (Image *) NULL);
3870 assert(image->signature == MagickSignature);
3871 if (image->debug != MagickFalse)
3872 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3873 assert(image->blob != (BlobInfo *) NULL);
3874 assert(image->blob->type != UndefinedStream);
3875 status=0;
3876 switch (image->blob->type)
3877 {
3878 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003879 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003880 break;
3881 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00003882 case PipeStream:
3883 {
cristye7b28372012-06-17 13:59:06 +00003884 status=fflush(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003885 break;
3886 }
3887 case ZipStream:
3888 {
3889#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003890 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
cristy3ed852e2009-09-05 21:47:34 +00003891#endif
3892 break;
3893 }
3894 case BZipStream:
3895 {
3896#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003897 status=BZ2_bzflush(image->blob->file_info.bzfile);
cristy3ed852e2009-09-05 21:47:34 +00003898#endif
3899 break;
3900 }
3901 case FifoStream:
3902 break;
3903 case BlobStream:
cristy3ed852e2009-09-05 21:47:34 +00003904 break;
cristy3ed852e2009-09-05 21:47:34 +00003905 }
3906 return(status);
3907}
3908
3909/*
3910%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3911% %
3912% %
3913% %
3914+ T e l l B l o b %
3915% %
3916% %
3917% %
3918%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3919%
3920% TellBlob() obtains the current value of the blob or file position.
3921%
3922% The format of the TellBlob method is:
3923%
3924% MagickOffsetType TellBlob(const Image *image)
3925%
3926% A description of each parameter follows:
3927%
3928% o image: the image.
3929%
3930*/
3931MagickExport MagickOffsetType TellBlob(const Image *image)
3932{
3933 MagickOffsetType
3934 offset;
3935
3936 assert(image != (Image *) NULL);
3937 assert(image->signature == MagickSignature);
3938 if (image->debug != MagickFalse)
3939 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3940 assert(image->blob != (BlobInfo *) NULL);
3941 assert(image->blob->type != UndefinedStream);
3942 offset=(-1);
3943 switch (image->blob->type)
3944 {
3945 case UndefinedStream:
cristybc20d112012-07-29 20:27:00 +00003946 case StandardStream:
cristy3ed852e2009-09-05 21:47:34 +00003947 break;
3948 case FileStream:
3949 {
cristye7b28372012-06-17 13:59:06 +00003950 offset=ftell(image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00003951 break;
3952 }
cristy3ed852e2009-09-05 21:47:34 +00003953 case PipeStream:
3954 break;
3955 case ZipStream:
3956 {
3957#if defined(MAGICKCORE_ZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00003958 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
cristy3ed852e2009-09-05 21:47:34 +00003959#endif
3960 break;
3961 }
3962 case BZipStream:
3963 break;
3964 case FifoStream:
3965 break;
3966 case BlobStream:
3967 {
3968 offset=image->blob->offset;
3969 break;
3970 }
3971 }
3972 return(offset);
3973}
3974
3975/*
3976%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3977% %
3978% %
3979% %
3980+ U n m a p B l o b %
3981% %
3982% %
3983% %
3984%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3985%
3986% UnmapBlob() deallocates the binary large object previously allocated with
3987% the MapBlob method.
3988%
3989% The format of the UnmapBlob method is:
3990%
3991% MagickBooleanType UnmapBlob(void *map,const size_t length)
3992%
3993% A description of each parameter follows:
3994%
3995% o map: the address of the binary large object.
3996%
3997% o length: the length of the binary large object.
3998%
3999*/
4000MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4001{
cristydc8ea8e2013-07-28 20:10:44 +00004002#if defined(MAGICKCORE_HAVE_MMAP)
cristy3ed852e2009-09-05 21:47:34 +00004003 int
4004 status;
4005
4006 status=munmap(map,length);
4007 return(status == -1 ? MagickFalse : MagickTrue);
4008#else
4009 (void) map;
4010 (void) length;
4011 return(MagickFalse);
4012#endif
4013}
4014
4015/*
4016%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4017% %
4018% %
4019% %
4020+ W r i t e B l o b %
4021% %
4022% %
4023% %
4024%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4025%
4026% WriteBlob() writes data to a blob or image file. It returns the number of
4027% bytes written.
4028%
4029% The format of the WriteBlob method is:
4030%
4031% ssize_t WriteBlob(Image *image,const size_t length,
4032% const unsigned char *data)
4033%
4034% A description of each parameter follows:
4035%
4036% o image: the image.
4037%
4038% o length: Specifies an integer representing the number of bytes to
4039% write to the file.
4040%
4041% o data: The address of the data to write to the blob or file.
4042%
4043*/
4044MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4045 const unsigned char *data)
4046{
4047 int
4048 c;
4049
4050 register const unsigned char
4051 *p;
4052
4053 ssize_t
4054 count;
4055
4056 assert(image != (Image *) NULL);
4057 assert(image->signature == MagickSignature);
4058 assert(data != (const unsigned char *) NULL);
4059 assert(image->blob != (BlobInfo *) NULL);
4060 assert(image->blob->type != UndefinedStream);
4061 if (length == 0)
4062 return(0);
4063 count=0;
4064 p=data;
4065 switch (image->blob->type)
4066 {
4067 case UndefinedStream:
4068 break;
cristy3ed852e2009-09-05 21:47:34 +00004069 case StandardStream:
cristybc20d112012-07-29 20:27:00 +00004070 {
cristy5f3d2752013-01-05 18:53:38 +00004071 count=write(fileno(image->blob->file_info.file),data,length);
cristybc20d112012-07-29 20:27:00 +00004072 break;
4073 }
4074 case FileStream:
cristy3ed852e2009-09-05 21:47:34 +00004075 case PipeStream:
4076 {
4077 switch (length)
4078 {
4079 default:
4080 {
4081 count=(ssize_t) fwrite((const char *) data,1,length,
cristye7b28372012-06-17 13:59:06 +00004082 image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004083 break;
4084 }
4085 case 2:
4086 {
cristye7b28372012-06-17 13:59:06 +00004087 c=putc((int) *p++,image->blob->file_info.file);
cristy3ed852e2009-09-05 21:47:34 +00004088 if (c == EOF)
4089 break;
4090 count++;
4091 }
4092 case 1:
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 0:
4100 break;
4101 }
4102 break;
4103 }
4104 case ZipStream:
4105 {
4106#if defined(MAGICKCORE_ZLIB_DELEGATE)
4107 switch (length)
4108 {
4109 default:
4110 {
cristye7b28372012-06-17 13:59:06 +00004111 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
cristy3ed852e2009-09-05 21:47:34 +00004112 (unsigned int) length);
4113 break;
4114 }
4115 case 2:
4116 {
cristye7b28372012-06-17 13:59:06 +00004117 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
cristy3ed852e2009-09-05 21:47:34 +00004118 if (c == EOF)
4119 break;
4120 count++;
4121 }
4122 case 1:
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 0:
4130 break;
4131 }
4132#endif
4133 break;
4134 }
4135 case BZipStream:
4136 {
4137#if defined(MAGICKCORE_BZLIB_DELEGATE)
cristye7b28372012-06-17 13:59:06 +00004138 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
cristy95888612012-04-04 21:56:52 +00004139 (int) length);
cristy3ed852e2009-09-05 21:47:34 +00004140#endif
4141 break;
4142 }
4143 case FifoStream:
4144 {
4145 count=(ssize_t) image->blob->stream(image,data,length);
4146 break;
4147 }
4148 case BlobStream:
4149 {
4150 register unsigned char
4151 *q;
4152
4153 if ((image->blob->offset+(MagickOffsetType) length) >=
4154 (MagickOffsetType) image->blob->extent)
4155 {
4156 if (image->blob->mapped != MagickFalse)
4157 return(0);
4158 image->blob->quantum<<=1;
4159 image->blob->extent+=length+image->blob->quantum;
4160 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4161 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4162 (void) SyncBlob(image);
4163 if (image->blob->data == (unsigned char *) NULL)
4164 {
4165 (void) DetachBlob(image->blob);
4166 return(0);
4167 }
4168 }
4169 q=image->blob->data+image->blob->offset;
cristy54aad5e2010-09-03 16:02:04 +00004170 (void) memcpy(q,p,length);
cristy3ed852e2009-09-05 21:47:34 +00004171 image->blob->offset+=length;
4172 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4173 image->blob->length=(size_t) image->blob->offset;
4174 count=(ssize_t) length;
4175 }
4176 }
4177 return(count);
4178}
4179
4180/*
4181%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4182% %
4183% %
4184% %
4185+ W r i t e B l o b B y t e %
4186% %
4187% %
4188% %
4189%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4190%
4191% WriteBlobByte() write an integer to a blob. It returns the number of bytes
4192% written (either 0 or 1);
4193%
4194% The format of the WriteBlobByte method is:
4195%
4196% ssize_t WriteBlobByte(Image *image,const unsigned char value)
4197%
4198% A description of each parameter follows.
4199%
4200% o image: the image.
4201%
4202% o value: Specifies the value to write.
4203%
4204*/
4205MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4206{
4207 assert(image != (Image *) NULL);
4208 assert(image->signature == MagickSignature);
4209 return(WriteBlobStream(image,1,&value));
4210}
4211
4212/*
4213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4214% %
4215% %
4216% %
4217+ W r i t e B l o b F l o a t %
4218% %
4219% %
4220% %
4221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4222%
4223% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4224% specified by the endian member of the image structure.
4225%
4226% The format of the WriteBlobFloat method is:
4227%
4228% ssize_t WriteBlobFloat(Image *image,const float value)
4229%
4230% A description of each parameter follows.
4231%
4232% o image: the image.
4233%
4234% o value: Specifies the value to write.
4235%
4236*/
4237MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4238{
4239 union
4240 {
4241 unsigned int
4242 unsigned_value;
4243
4244 float
4245 float_value;
4246 } quantum;
4247
4248 quantum.unsigned_value=0U;
4249 quantum.float_value=value;
4250 return(WriteBlobLong(image,quantum.unsigned_value));
4251}
4252
4253/*
4254%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4255% %
4256% %
4257% %
4258+ W r i t e B l o b L o n g %
4259% %
4260% %
4261% %
4262%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4263%
cristybb503372010-05-27 20:51:26 +00004264% WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
cristy3ed852e2009-09-05 21:47:34 +00004265% specified by the endian member of the image structure.
4266%
4267% The format of the WriteBlobLong method is:
4268%
4269% ssize_t WriteBlobLong(Image *image,const unsigned int value)
4270%
4271% A description of each parameter follows.
4272%
4273% o image: the image.
4274%
4275% o value: Specifies the value to write.
4276%
4277*/
4278MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4279{
4280 unsigned char
4281 buffer[4];
4282
4283 assert(image != (Image *) NULL);
4284 assert(image->signature == MagickSignature);
4285 if (image->endian == LSBEndian)
4286 {
4287 buffer[0]=(unsigned char) value;
4288 buffer[1]=(unsigned char) (value >> 8);
4289 buffer[2]=(unsigned char) (value >> 16);
4290 buffer[3]=(unsigned char) (value >> 24);
4291 return(WriteBlobStream(image,4,buffer));
4292 }
4293 buffer[0]=(unsigned char) (value >> 24);
4294 buffer[1]=(unsigned char) (value >> 16);
4295 buffer[2]=(unsigned char) (value >> 8);
4296 buffer[3]=(unsigned char) value;
4297 return(WriteBlobStream(image,4,buffer));
4298}
4299
4300/*
4301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4302% %
4303% %
4304% %
4305+ W r i t e B l o b S h o r t %
4306% %
4307% %
4308% %
4309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4310%
4311% WriteBlobShort() writes a short value as a 16-bit quantity in the
4312% byte-order specified by the endian member of the image structure.
4313%
4314% The format of the WriteBlobShort method is:
4315%
4316% ssize_t WriteBlobShort(Image *image,const unsigned short value)
4317%
4318% A description of each parameter follows.
4319%
4320% o image: the image.
4321%
4322% o value: Specifies the value to write.
4323%
4324*/
4325MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4326{
4327 unsigned char
4328 buffer[2];
4329
4330 assert(image != (Image *) NULL);
4331 assert(image->signature == MagickSignature);
4332 if (image->endian == LSBEndian)
4333 {
4334 buffer[0]=(unsigned char) value;
4335 buffer[1]=(unsigned char) (value >> 8);
4336 return(WriteBlobStream(image,2,buffer));
4337 }
4338 buffer[0]=(unsigned char) (value >> 8);
4339 buffer[1]=(unsigned char) value;
4340 return(WriteBlobStream(image,2,buffer));
4341}
4342
4343/*
4344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4345% %
4346% %
4347% %
4348+ W r i t e B l o b L S B L o n g %
4349% %
4350% %
4351% %
4352%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4353%
cristybb503372010-05-27 20:51:26 +00004354% WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004355% least-significant byte first order.
4356%
4357% The format of the WriteBlobLSBLong method is:
4358%
4359% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4360%
4361% A description of each parameter follows.
4362%
4363% o image: the image.
4364%
4365% o value: Specifies the value to write.
4366%
4367*/
4368MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4369{
4370 unsigned char
4371 buffer[4];
4372
4373 assert(image != (Image *) NULL);
4374 assert(image->signature == MagickSignature);
4375 buffer[0]=(unsigned char) value;
4376 buffer[1]=(unsigned char) (value >> 8);
4377 buffer[2]=(unsigned char) (value >> 16);
4378 buffer[3]=(unsigned char) (value >> 24);
4379 return(WriteBlobStream(image,4,buffer));
4380}
4381
4382/*
4383%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4384% %
4385% %
4386% %
4387+ W r i t e B l o b L S B S h o r t %
4388% %
4389% %
4390% %
4391%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4392%
cristybb503372010-05-27 20:51:26 +00004393% WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004394% least-significant byte first order.
4395%
4396% The format of the WriteBlobLSBShort method is:
4397%
4398% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4399%
4400% A description of each parameter follows.
4401%
4402% o image: the image.
4403%
4404% o value: Specifies the value to write.
4405%
4406*/
4407MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4408{
4409 unsigned char
4410 buffer[2];
4411
4412 assert(image != (Image *) NULL);
4413 assert(image->signature == MagickSignature);
4414 buffer[0]=(unsigned char) value;
4415 buffer[1]=(unsigned char) (value >> 8);
4416 return(WriteBlobStream(image,2,buffer));
4417}
4418
4419/*
4420%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4421% %
4422% %
4423% %
4424+ W r i t e B l o b M S B L o n g %
4425% %
4426% %
4427% %
4428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4429%
cristybb503372010-05-27 20:51:26 +00004430% WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004431% most-significant byte first order.
4432%
4433% The format of the WriteBlobMSBLong method is:
4434%
4435% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4436%
4437% A description of each parameter follows.
4438%
4439% o value: Specifies the value to write.
4440%
4441% o image: the image.
4442%
4443*/
4444MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4445{
4446 unsigned char
4447 buffer[4];
4448
4449 assert(image != (Image *) NULL);
4450 assert(image->signature == MagickSignature);
4451 buffer[0]=(unsigned char) (value >> 24);
4452 buffer[1]=(unsigned char) (value >> 16);
4453 buffer[2]=(unsigned char) (value >> 8);
4454 buffer[3]=(unsigned char) value;
4455 return(WriteBlobStream(image,4,buffer));
4456}
4457
4458/*
4459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4460% %
4461% %
4462% %
cristy2ca49922010-03-06 02:54:01 +00004463+ W r i t e B l o b M S B L o n g L o n g %
4464% %
4465% %
4466% %
4467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4468%
4469% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4470% most-significant byte first order.
4471%
4472% The format of the WriteBlobMSBLongLong method is:
4473%
4474% ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4475%
4476% A description of each parameter follows.
4477%
4478% o value: Specifies the value to write.
4479%
4480% o image: the image.
4481%
4482*/
4483MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4484 const MagickSizeType value)
4485{
4486 unsigned char
4487 buffer[8];
4488
4489 assert(image != (Image *) NULL);
4490 assert(image->signature == MagickSignature);
4491 buffer[0]=(unsigned char) (value >> 56);
4492 buffer[1]=(unsigned char) (value >> 48);
4493 buffer[2]=(unsigned char) (value >> 40);
4494 buffer[3]=(unsigned char) (value >> 32);
4495 buffer[4]=(unsigned char) (value >> 24);
4496 buffer[5]=(unsigned char) (value >> 16);
4497 buffer[6]=(unsigned char) (value >> 8);
4498 buffer[7]=(unsigned char) value;
4499 return(WriteBlobStream(image,8,buffer));
4500}
4501
4502/*
4503%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4504% %
4505% %
4506% %
cristy3ed852e2009-09-05 21:47:34 +00004507+ W r i t e B l o b M S B S h o r t %
4508% %
4509% %
4510% %
4511%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4512%
cristybb503372010-05-27 20:51:26 +00004513% WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
cristy3ed852e2009-09-05 21:47:34 +00004514% most-significant byte first order.
4515%
4516% The format of the WriteBlobMSBShort method is:
4517%
4518% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4519%
4520% A description of each parameter follows.
4521%
4522% o value: Specifies the value to write.
4523%
4524% o file: Specifies the file to write the data to.
4525%
4526*/
4527MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4528{
4529 unsigned char
4530 buffer[2];
4531
4532 assert(image != (Image *) NULL);
4533 assert(image->signature == MagickSignature);
4534 buffer[0]=(unsigned char) (value >> 8);
4535 buffer[1]=(unsigned char) value;
4536 return(WriteBlobStream(image,2,buffer));
4537}
4538
4539/*
4540%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4541% %
4542% %
4543% %
4544+ W r i t e B l o b S t r i n g %
4545% %
4546% %
4547% %
4548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4549%
4550% WriteBlobString() write a string to a blob. It returns the number of
4551% characters written.
4552%
4553% The format of the WriteBlobString method is:
4554%
4555% ssize_t WriteBlobString(Image *image,const char *string)
4556%
4557% A description of each parameter follows.
4558%
4559% o image: the image.
4560%
4561% o string: Specifies the string to write.
4562%
4563*/
4564MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4565{
4566 assert(image != (Image *) NULL);
4567 assert(image->signature == MagickSignature);
4568 assert(string != (const char *) NULL);
4569 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4570}