~ubuntu-branches/debian/jessie/imagemagick/jessie

« back to all changes in this revision

Viewing changes to .pc/0007-Fix-build-with-zlibg-1.2.6.patch/magick/blob.c

  • Committer: Package Import Robot
  • Author(s): Vincent Fourmond
  • Date: 2012-02-22 23:08:56 UTC
  • Revision ID: package-import@ubuntu.com-20120222230856-q903mimvv21ioxke
Tags: 8:6.6.9.7-6
* Security bug fix: "Invalid validation DoS
  CVE-2012-0247/CVE-2012-02478", thanks to Henri Salo (Closes: #659339).
* Bumping urgency to high to fix open security issue in testing
* Apply patch from revision r6606 to fix compilation with newer zlib.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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
%                                                                             %
 
20
%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
 
21
%  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
*/
 
43
#include "magick/studio.h"
 
44
#include "magick/blob.h"
 
45
#include "magick/blob-private.h"
 
46
#include "magick/cache.h"
 
47
#include "magick/client.h"
 
48
#include "magick/constitute.h"
 
49
#include "magick/delegate.h"
 
50
#include "magick/exception.h"
 
51
#include "magick/exception-private.h"
 
52
#include "magick/image-private.h"
 
53
#include "magick/list.h"
 
54
#include "magick/log.h"
 
55
#include "magick/magick.h"
 
56
#include "magick/memory_.h"
 
57
#include "magick/policy.h"
 
58
#include "magick/resource_.h"
 
59
#include "magick/semaphore.h"
 
60
#include "magick/string_.h"
 
61
#include "magick/string-private.h"
 
62
#include "magick/token.h"
 
63
#include "magick/utility.h"
 
64
#if defined(MAGICKCORE_HAVE_MMAP_FILEIO) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
 
65
# include <sys/mman.h>
 
66
#endif
 
67
#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
 
78
#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
 
84
#if !defined(MS_SYNC)
 
85
#define MS_SYNC  0x04
 
86
#endif
 
87
#if defined(__OS2__)
 
88
#include <io.h>
 
89
#define _O_BINARY O_BINARY
 
90
#endif
 
91
 
 
92
/*
 
93
  Typedef declarations.
 
94
*/
 
95
struct _BlobInfo
 
96
{
 
97
  size_t
 
98
    length,
 
99
    extent,
 
100
    quantum;
 
101
 
 
102
  MagickBooleanType
 
103
    mapped,
 
104
    eof;
 
105
 
 
106
  MagickOffsetType
 
107
    offset;
 
108
 
 
109
  MagickSizeType
 
110
    size;
 
111
 
 
112
  MagickBooleanType
 
113
    exempt,
 
114
    synchronize,
 
115
    status,
 
116
    temporary;
 
117
 
 
118
  StreamType
 
119
    type;
 
120
 
 
121
  FILE
 
122
    *file;
 
123
 
 
124
  struct stat
 
125
    properties;
 
126
 
 
127
  StreamHandler
 
128
    stream;
 
129
 
 
130
  unsigned char
 
131
    *data;
 
132
 
 
133
  MagickBooleanType
 
134
    debug;
 
135
 
 
136
  SemaphoreInfo
 
137
    *semaphore;
 
138
 
 
139
  ssize_t
 
140
    reference_count;
 
141
 
 
142
  size_t
 
143
    signature;
 
144
};
 
145
 
 
146
/*
 
147
  Forward declarations.
 
148
*/
 
149
static int
 
150
  SyncBlob(Image *);
 
151
 
 
152
/*
 
153
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
154
%                                                                             %
 
155
%                                                                             %
 
156
%                                                                             %
 
157
+   A t t a c h B l o b                                                       %
 
158
%                                                                             %
 
159
%                                                                             %
 
160
%                                                                             %
 
161
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
162
%
 
163
%  AttachBlob() attaches a blob to the BlobInfo structure.
 
164
%
 
165
%  The format of the AttachBlob method is:
 
166
%
 
167
%      void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
 
168
%
 
169
%  A description of each parameter follows:
 
170
%
 
171
%    o blob_info: Specifies a pointer to a BlobInfo structure.
 
172
%
 
173
%    o blob: the address of a character stream in one of the image formats
 
174
%      understood by ImageMagick.
 
175
%
 
176
%    o length: This size_t integer reflects the length in bytes of the blob.
 
177
%
 
178
*/
 
179
MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
 
180
  const size_t length)
 
181
{
 
182
  assert(blob_info != (BlobInfo *) NULL);
 
183
  if (blob_info->debug != MagickFalse)
 
184
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
 
185
  blob_info->length=length;
 
186
  blob_info->extent=length;
 
187
  blob_info->quantum=(size_t) MagickMaxBlobExtent;
 
188
  blob_info->offset=0;
 
189
  blob_info->type=BlobStream;
 
190
  blob_info->file=(FILE *) NULL;
 
191
  blob_info->data=(unsigned char *) blob;
 
192
  blob_info->mapped=MagickFalse;
 
193
}
 
194
 
 
195
/*
 
196
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
197
%                                                                             %
 
198
%                                                                             %
 
199
%                                                                             %
 
200
+   B l o b T o F i l e                                                       %
 
201
%                                                                             %
 
202
%                                                                             %
 
203
%                                                                             %
 
204
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
205
%
 
206
%  BlobToFile() writes a blob to a file.  It returns MagickFalse if an error
 
207
%  occurs otherwise MagickTrue.
 
208
%
 
209
%  The format of the BlobToFile method is:
 
210
%
 
211
%       MagickBooleanType BlobToFile(char *filename,const void *blob,
 
212
%         const size_t length,ExceptionInfo *exception)
 
213
%
 
214
%  A description of each parameter follows:
 
215
%
 
216
%    o filename: Write the blob to this file.
 
217
%
 
218
%    o blob: the address of a blob.
 
219
%
 
220
%    o length: This length in bytes of the blob.
 
221
%
 
222
%    o exception: return any errors or warnings in this structure.
 
223
%
 
224
*/
 
225
 
 
226
static inline MagickSizeType MagickMin(const MagickSizeType x,
 
227
  const MagickSizeType y)
 
228
{
 
229
  if (x < y)
 
230
    return(x);
 
231
  return(y);
 
232
}
 
233
 
 
234
MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
 
235
  const size_t length,ExceptionInfo *exception)
 
236
{
 
237
  int
 
238
    file;
 
239
 
 
240
  register size_t
 
241
    i;
 
242
 
 
243
  ssize_t
 
244
    count;
 
245
 
 
246
  assert(filename != (const char *) NULL);
 
247
  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
 
248
  assert(blob != (const void *) NULL);
 
249
  if (*filename == '\0')
 
250
    file=AcquireUniqueFileResource(filename);
 
251
  else
 
252
    file=open(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
 
253
  if (file == -1)
 
254
    {
 
255
      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
 
256
      return(MagickFalse);
 
257
    }
 
258
  for (i=0; i < length; i+=count)
 
259
  {
 
260
    count=(ssize_t) write(file,(const char *) blob+i,(size_t) MagickMin(length-
 
261
      i,(MagickSizeType) SSIZE_MAX));
 
262
    if (count <= 0)
 
263
      {
 
264
        count=0;
 
265
        if (errno != EINTR)
 
266
          break;
 
267
      }
 
268
  }
 
269
  file=close(file);
 
270
  if ((file == -1) || (i < length))
 
271
    {
 
272
      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
 
273
      return(MagickFalse);
 
274
    }
 
275
  return(MagickTrue);
 
276
}
 
277
 
 
278
/*
 
279
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
280
%                                                                             %
 
281
%                                                                             %
 
282
%                                                                             %
 
283
%   B l o b T o I m a g e                                                     %
 
284
%                                                                             %
 
285
%                                                                             %
 
286
%                                                                             %
 
287
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
288
%
 
289
%  BlobToImage() implements direct to memory image formats.  It returns the
 
290
%  blob as an image.
 
291
%
 
292
%  The format of the BlobToImage method is:
 
293
%
 
294
%      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
 
295
%        const size_t length,ExceptionInfo *exception)
 
296
%
 
297
%  A description of each parameter follows:
 
298
%
 
299
%    o image_info: the image info.
 
300
%
 
301
%    o blob: the address of a character stream in one of the image formats
 
302
%      understood by ImageMagick.
 
303
%
 
304
%    o length: This size_t integer reflects the length in bytes of the blob.
 
305
%
 
306
%    o exception: return any errors or warnings in this structure.
 
307
%
 
308
*/
 
309
MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
 
310
  const size_t length,ExceptionInfo *exception)
 
311
{
 
312
  const MagickInfo
 
313
    *magick_info;
 
314
 
 
315
  Image
 
316
    *image;
 
317
 
 
318
  ImageInfo
 
319
    *blob_info,
 
320
    *clone_info;
 
321
 
 
322
  MagickBooleanType
 
323
    status;
 
324
 
 
325
  assert(image_info != (ImageInfo *) NULL);
 
326
  assert(image_info->signature == MagickSignature);
 
327
  if (image_info->debug != MagickFalse)
 
328
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
 
329
      image_info->filename);
 
330
  assert(exception != (ExceptionInfo *) NULL);
 
331
  if ((blob == (const void *) NULL) || (length == 0))
 
332
    {
 
333
      (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
 
334
        "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
 
335
      return((Image *) NULL);
 
336
    }
 
337
  blob_info=CloneImageInfo(image_info);
 
338
  blob_info->blob=(void *) blob;
 
339
  blob_info->length=length;
 
340
  if (*blob_info->magick == '\0')
 
341
    (void) SetImageInfo(blob_info,0,exception);
 
342
  magick_info=GetMagickInfo(blob_info->magick,exception);
 
343
  if (magick_info == (const MagickInfo *) NULL)
 
344
    {
 
345
      blob_info=DestroyImageInfo(blob_info);
 
346
      (void) ThrowMagickException(exception,GetMagickModule(),
 
347
        MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
 
348
        image_info->filename);
 
349
      return((Image *) NULL);
 
350
    }
 
351
  if (GetMagickBlobSupport(magick_info) != MagickFalse)
 
352
    {
 
353
      /*
 
354
        Native blob support for this image format.
 
355
      */
 
356
      (void) CopyMagickString(blob_info->filename,image_info->filename,
 
357
        MaxTextExtent);
 
358
      (void) CopyMagickString(blob_info->magick,image_info->magick,
 
359
        MaxTextExtent);
 
360
      image=ReadImage(blob_info,exception);
 
361
      if (image != (Image *) NULL)
 
362
        (void) DetachBlob(image->blob);
 
363
      blob_info=DestroyImageInfo(blob_info);
 
364
      return(image);
 
365
    }
 
366
  /*
 
367
    Write blob to a temporary file on disk.
 
368
  */
 
369
  blob_info->blob=(void *) NULL;
 
370
  blob_info->length=0;
 
371
  *blob_info->filename='\0';
 
372
  status=BlobToFile(blob_info->filename,blob,length,exception);
 
373
  if (status == MagickFalse)
 
374
    {
 
375
      (void) RelinquishUniqueFileResource(blob_info->filename);
 
376
      blob_info=DestroyImageInfo(blob_info);
 
377
      return((Image *) NULL);
 
378
    }
 
379
  clone_info=CloneImageInfo(blob_info);
 
380
  (void) FormatMagickString(clone_info->filename,MaxTextExtent,"%s:%s",
 
381
    blob_info->magick,blob_info->filename);
 
382
  image=ReadImage(clone_info,exception);
 
383
  clone_info=DestroyImageInfo(clone_info);
 
384
  (void) RelinquishUniqueFileResource(blob_info->filename);
 
385
  blob_info=DestroyImageInfo(blob_info);
 
386
  return(image);
 
387
}
 
388
 
 
389
/*
 
390
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
391
%                                                                             %
 
392
%                                                                             %
 
393
%                                                                             %
 
394
+   C l o n e B l o b I n f o                                                 %
 
395
%                                                                             %
 
396
%                                                                             %
 
397
%                                                                             %
 
398
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
399
%
 
400
%  CloneBlobInfo() makes a duplicate of the given blob info structure, or if
 
401
%  blob info is NULL, a new one.
 
402
%
 
403
%  The format of the CloneBlobInfo method is:
 
404
%
 
405
%      BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
 
406
%
 
407
%  A description of each parameter follows:
 
408
%
 
409
%    o blob_info: the blob info.
 
410
%
 
411
*/
 
412
MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
 
413
{
 
414
  BlobInfo
 
415
    *clone_info;
 
416
 
 
417
  clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
 
418
  if (clone_info == (BlobInfo *) NULL)
 
419
    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
 
420
  GetBlobInfo(clone_info);
 
421
  if (blob_info == (BlobInfo *) NULL)
 
422
    return(clone_info);
 
423
  clone_info->length=blob_info->length;
 
424
  clone_info->extent=blob_info->extent;
 
425
  clone_info->synchronize=blob_info->synchronize;
 
426
  clone_info->quantum=blob_info->quantum;
 
427
  clone_info->mapped=blob_info->mapped;
 
428
  clone_info->eof=blob_info->eof;
 
429
  clone_info->offset=blob_info->offset;
 
430
  clone_info->size=blob_info->size;
 
431
  clone_info->exempt=blob_info->exempt;
 
432
  clone_info->status=blob_info->status;
 
433
  clone_info->temporary=blob_info->temporary;
 
434
  clone_info->type=blob_info->type;
 
435
  clone_info->file=blob_info->file;
 
436
  clone_info->properties=blob_info->properties;
 
437
  clone_info->stream=blob_info->stream;
 
438
  clone_info->data=blob_info->data;
 
439
  clone_info->debug=IsEventLogging();
 
440
  clone_info->reference_count=1;
 
441
  return(clone_info);
 
442
}
 
443
 
 
444
/*
 
445
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
446
%                                                                             %
 
447
%                                                                             %
 
448
%                                                                             %
 
449
+   C l o s e B l o b                                                         %
 
450
%                                                                             %
 
451
%                                                                             %
 
452
%                                                                             %
 
453
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
454
%
 
455
%  CloseBlob() closes a stream associated with the image.
 
456
%
 
457
%  The format of the CloseBlob method is:
 
458
%
 
459
%      MagickBooleanType CloseBlob(Image *image)
 
460
%
 
461
%  A description of each parameter follows:
 
462
%
 
463
%    o image: the image.
 
464
%
 
465
*/
 
466
MagickExport MagickBooleanType CloseBlob(Image *image)
 
467
{
 
468
  int
 
469
    status;
 
470
 
 
471
  /*
 
472
    Close image file.
 
473
  */
 
474
  assert(image != (Image *) NULL);
 
475
  assert(image->signature == MagickSignature);
 
476
  if (image->debug != MagickFalse)
 
477
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
478
  assert(image->blob != (BlobInfo *) NULL);
 
479
  if (image->blob->type == UndefinedStream)
 
480
    return(MagickTrue);
 
481
  if (image->blob->synchronize != MagickFalse)
 
482
    SyncBlob(image);
 
483
  image->blob->size=GetBlobSize(image);
 
484
  image->extent=image->blob->size;
 
485
  image->blob->eof=MagickFalse;
 
486
  if (image->blob->exempt != MagickFalse)
 
487
    {
 
488
      image->blob->type=UndefinedStream;
 
489
      return(MagickTrue);
 
490
    }
 
491
  status=0;
 
492
  switch (image->blob->type)
 
493
  {
 
494
    case UndefinedStream:
 
495
      break;
 
496
    case FileStream:
 
497
    case StandardStream:
 
498
    case PipeStream:
 
499
    {
 
500
      status=ferror(image->blob->file);
 
501
      break;
 
502
    }
 
503
    case ZipStream:
 
504
    {
 
505
#if defined(MAGICKCORE_ZLIB_DELEGATE)
 
506
      (void) gzerror(image->blob->file,&status);
 
507
#endif
 
508
      break;
 
509
    }
 
510
    case BZipStream:
 
511
    {
 
512
#if defined(MAGICKCORE_BZLIB_DELEGATE)
 
513
      (void) BZ2_bzerror((BZFILE *) image->blob->file,&status);
 
514
#endif
 
515
      break;
 
516
    }
 
517
    case FifoStream:
 
518
    case BlobStream:
 
519
      break;
 
520
  }
 
521
  image->blob->status=status < 0 ? MagickTrue : MagickFalse;
 
522
  switch (image->blob->type)
 
523
  {
 
524
    case UndefinedStream:
 
525
      break;
 
526
    case FileStream:
 
527
    case StandardStream:
 
528
    {
 
529
      if (image->blob->synchronize != MagickFalse)
 
530
        {
 
531
          status=fflush(image->blob->file);
 
532
          status=fsync(fileno(image->blob->file));
 
533
        }
 
534
      status=fclose(image->blob->file);
 
535
      break;
 
536
    }
 
537
    case PipeStream:
 
538
    {
 
539
#if defined(MAGICKCORE_HAVE_PCLOSE)
 
540
      status=pclose(image->blob->file);
 
541
#endif
 
542
      break;
 
543
    }
 
544
    case ZipStream:
 
545
    {
 
546
#if defined(MAGICKCORE_ZLIB_DELEGATE)
 
547
      status=gzclose(image->blob->file);
 
548
#endif
 
549
      break;
 
550
    }
 
551
    case BZipStream:
 
552
    {
 
553
#if defined(MAGICKCORE_BZLIB_DELEGATE)
 
554
      BZ2_bzclose((BZFILE *) image->blob->file);
 
555
#endif
 
556
      break;
 
557
    }
 
558
    case FifoStream:
 
559
      break;
 
560
    case BlobStream:
 
561
    {
 
562
      if (image->blob->file != (FILE *) NULL)
 
563
        {
 
564
          if (image->blob->synchronize != MagickFalse)
 
565
            (void) fsync(fileno(image->blob->file));
 
566
          status=fclose(image->blob->file);
 
567
        }
 
568
      break;
 
569
    }
 
570
  }
 
571
  (void) DetachBlob(image->blob);
 
572
  image->blob->status=status < 0 ? MagickTrue : MagickFalse;
 
573
  return(image->blob->status);
 
574
}
 
575
 
 
576
/*
 
577
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
578
%                                                                             %
 
579
%                                                                             %
 
580
%                                                                             %
 
581
+   D e s t r o y B l o b                                                     %
 
582
%                                                                             %
 
583
%                                                                             %
 
584
%                                                                             %
 
585
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
586
%
 
587
%  DestroyBlob() deallocates memory associated with a blob.
 
588
%
 
589
%  The format of the DestroyBlob method is:
 
590
%
 
591
%      void DestroyBlob(Image *image)
 
592
%
 
593
%  A description of each parameter follows:
 
594
%
 
595
%    o image: the image.
 
596
%
 
597
*/
 
598
MagickExport void DestroyBlob(Image *image)
 
599
{
 
600
  MagickBooleanType
 
601
    destroy;
 
602
 
 
603
  assert(image != (Image *) NULL);
 
604
  assert(image->signature == MagickSignature);
 
605
  if (image->debug != MagickFalse)
 
606
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
607
  assert(image->blob != (BlobInfo *) NULL);
 
608
  assert(image->blob->signature == MagickSignature);
 
609
  destroy=MagickFalse;
 
610
  LockSemaphoreInfo(image->blob->semaphore);
 
611
  image->blob->reference_count--;
 
612
  assert(image->blob->reference_count >= 0);
 
613
  if (image->blob->reference_count == 0)
 
614
    destroy=MagickTrue;
 
615
  UnlockSemaphoreInfo(image->blob->semaphore);
 
616
  if (destroy == MagickFalse)
 
617
    return;
 
618
  (void) CloseBlob(image);
 
619
  if (image->blob->mapped != MagickFalse)
 
620
    (void) UnmapBlob(image->blob->data,image->blob->length);
 
621
  if (image->blob->semaphore != (SemaphoreInfo *) NULL)
 
622
    DestroySemaphoreInfo(&image->blob->semaphore);
 
623
  image->blob->signature=(~MagickSignature);
 
624
  image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
 
625
}
 
626
 
 
627
/*
 
628
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
629
%                                                                             %
 
630
%                                                                             %
 
631
%                                                                             %
 
632
+   D e t a c h B l o b                                                       %
 
633
%                                                                             %
 
634
%                                                                             %
 
635
%                                                                             %
 
636
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
637
%
 
638
%  DetachBlob() detaches a blob from the BlobInfo structure.
 
639
%
 
640
%  The format of the DetachBlob method is:
 
641
%
 
642
%      unsigned char *DetachBlob(BlobInfo *blob_info)
 
643
%
 
644
%  A description of each parameter follows:
 
645
%
 
646
%    o blob_info: Specifies a pointer to a BlobInfo structure.
 
647
%
 
648
*/
 
649
MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
 
650
{
 
651
  unsigned char
 
652
    *data;
 
653
 
 
654
  assert(blob_info != (BlobInfo *) NULL);
 
655
  if (blob_info->debug != MagickFalse)
 
656
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
 
657
  if (blob_info->mapped != MagickFalse)
 
658
    (void) UnmapBlob(blob_info->data,blob_info->length);
 
659
  blob_info->mapped=MagickFalse;
 
660
  blob_info->length=0;
 
661
  blob_info->offset=0;
 
662
  blob_info->eof=MagickFalse;
 
663
  blob_info->exempt=MagickFalse;
 
664
  blob_info->type=UndefinedStream;
 
665
  blob_info->file=(FILE *) NULL;
 
666
  data=blob_info->data;
 
667
  blob_info->data=(unsigned char *) NULL;
 
668
  blob_info->stream=(StreamHandler) NULL;
 
669
  return(data);
 
670
}
 
671
 
 
672
/*
 
673
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
674
%                                                                             %
 
675
%                                                                             %
 
676
%                                                                             %
 
677
+  D i s c a r d B l o b B y t e s                                            %
 
678
%                                                                             %
 
679
%                                                                             %
 
680
%                                                                             %
 
681
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
682
%
 
683
%  DiscardBlobBytes() discards bytes in a blob.
 
684
%
 
685
%  The format of the DiscardBlobBytes method is:
 
686
%
 
687
%      MagickBooleanType DiscardBlobBytes(Image *image,const size_t length)
 
688
%
 
689
%  A description of each parameter follows.
 
690
%
 
691
%    o image: the image.
 
692
%
 
693
%    o length:  the number of bytes to skip.
 
694
%
 
695
*/
 
696
 
 
697
static inline const unsigned char *ReadBlobStream(Image *image,
 
698
  const size_t length,unsigned char *data,ssize_t *count)
 
699
{
 
700
  assert(count != (ssize_t *) NULL);
 
701
  assert(image->blob != (BlobInfo *) NULL);
 
702
  if (image->blob->type != BlobStream)
 
703
    {
 
704
      *count=ReadBlob(image,length,data);
 
705
      return(data);
 
706
    }
 
707
  if (image->blob->offset >= (MagickOffsetType) image->blob->length)
 
708
    {
 
709
      *count=0;
 
710
      image->blob->eof=MagickTrue;
 
711
      return(data);
 
712
    }
 
713
  data=image->blob->data+image->blob->offset;
 
714
  *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
 
715
    image->blob->offset));
 
716
  image->blob->offset+=(*count);
 
717
  if (*count != (ssize_t) length)
 
718
    image->blob->eof=MagickTrue;
 
719
  return(data);
 
720
}
 
721
 
 
722
MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
 
723
  const MagickSizeType length)
 
724
{
 
725
  register MagickOffsetType
 
726
    i;
 
727
 
 
728
  size_t
 
729
    quantum;
 
730
 
 
731
  ssize_t
 
732
    count;
 
733
 
 
734
  unsigned char
 
735
    buffer[16384];
 
736
 
 
737
  assert(image != (Image *) NULL);
 
738
  assert(image->signature == MagickSignature);
 
739
  count=0;
 
740
  for (i=0; i < (MagickOffsetType) length; i+=count)
 
741
  {
 
742
    quantum=(size_t) MagickMin(length-i,sizeof(buffer));
 
743
    (void) ReadBlobStream(image,quantum,buffer,&count);
 
744
    if (count <= 0)
 
745
      {
 
746
        count=0;
 
747
        if (errno != EINTR)
 
748
          break;
 
749
      }
 
750
  }
 
751
  return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
 
752
}
 
753
 
 
754
/*
 
755
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
756
%                                                                             %
 
757
%                                                                             %
 
758
%                                                                             %
 
759
+   D u p l i c a t e s B l o b                                               %
 
760
%                                                                             %
 
761
%                                                                             %
 
762
%                                                                             %
 
763
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
764
%
 
765
%  DuplicateBlob() duplicates a blob descriptor.
 
766
%
 
767
%  The format of the DuplicateBlob method is:
 
768
%
 
769
%      void DuplicateBlob(Image *image,const Image *duplicate)
 
770
%
 
771
%  A description of each parameter follows:
 
772
%
 
773
%    o image: the image.
 
774
%
 
775
%    o duplicate: the duplicate image.
 
776
%
 
777
*/
 
778
MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
 
779
{
 
780
  assert(image != (Image *) NULL);
 
781
  assert(image->signature == MagickSignature);
 
782
  if (image->debug != MagickFalse)
 
783
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
784
  assert(duplicate != (Image *) NULL);
 
785
  assert(duplicate->signature == MagickSignature);
 
786
  DestroyBlob(image);
 
787
  image->blob=ReferenceBlob(duplicate->blob);
 
788
}
 
789
 
 
790
/*
 
791
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
792
%                                                                             %
 
793
%                                                                             %
 
794
%                                                                             %
 
795
+  E O F B l o b                                                              %
 
796
%                                                                             %
 
797
%                                                                             %
 
798
%                                                                             %
 
799
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
800
%
 
801
%  EOFBlob() returns a non-zero value when EOF has been detected reading from
 
802
%  a blob or file.
 
803
%
 
804
%  The format of the EOFBlob method is:
 
805
%
 
806
%      int EOFBlob(const Image *image)
 
807
%
 
808
%  A description of each parameter follows:
 
809
%
 
810
%    o image: the image.
 
811
%
 
812
*/
 
813
MagickExport int EOFBlob(const Image *image)
 
814
{
 
815
  assert(image != (Image *) NULL);
 
816
  assert(image->signature == MagickSignature);
 
817
  if (image->debug != MagickFalse)
 
818
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
 
819
  assert(image->blob != (BlobInfo *) NULL);
 
820
  assert(image->blob->type != UndefinedStream);
 
821
  switch (image->blob->type)
 
822
  {
 
823
    case UndefinedStream:
 
824
      break;
 
825
    case FileStream:
 
826
    case StandardStream:
 
827
    case PipeStream:
 
828
    {
 
829
      image->blob->eof=feof(image->blob->file) != 0 ? MagickTrue : MagickFalse;
 
830
      break;
 
831
    }
 
832
    case ZipStream:
 
833
    {
 
834
      image->blob->eof=MagickFalse;
 
835
      break;
 
836
    }
 
837
    case BZipStream:
 
838
    {
 
839
#if defined(MAGICKCORE_BZLIB_DELEGATE)
 
840
      int
 
841
        status;
 
842
 
 
843
      status=0;
 
844
      (void) BZ2_bzerror((BZFILE *) image->blob->file,&status);
 
845
      image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
 
846
#endif
 
847
      break;
 
848
    }
 
849
    case FifoStream:
 
850
    {
 
851
      image->blob->eof=MagickFalse;
 
852
      break;
 
853
    }
 
854
    case BlobStream:
 
855
      break;
 
856
  }
 
857
  return((int) image->blob->eof);
 
858
}
 
859
 
 
860
/*
 
861
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
862
%                                                                             %
 
863
%                                                                             %
 
864
%                                                                             %
 
865
+   F i l e T o B l o b                                                       %
 
866
%                                                                             %
 
867
%                                                                             %
 
868
%                                                                             %
 
869
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
870
%
 
871
%  FileToBlob() returns the contents of a file as a buffer terminated with
 
872
%  the '\0' character.  The length of the buffer (not including the extra
 
873
%  terminating '\0' character) is returned via the 'length' parameter.  Free
 
874
%  the buffer with RelinquishMagickMemory().
 
875
%
 
876
%  The format of the FileToBlob method is:
 
877
%
 
878
%      unsigned char *FileToBlob(const char *filename,const size_t extent,
 
879
%        size_t *length,ExceptionInfo *exception)
 
880
%
 
881
%  A description of each parameter follows:
 
882
%
 
883
%    o blob:  FileToBlob() returns the contents of a file as a blob.  If
 
884
%      an error occurs NULL is returned.
 
885
%
 
886
%    o filename: the filename.
 
887
%
 
888
%    o extent:  The maximum length of the blob.
 
889
%
 
890
%    o length: On return, this reflects the actual length of the blob.
 
891
%
 
892
%    o exception: return any errors or warnings in this structure.
 
893
%
 
894
*/
 
895
MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
 
896
  size_t *length,ExceptionInfo *exception)
 
897
{
 
898
  int
 
899
    file;
 
900
 
 
901
  MagickOffsetType
 
902
    offset;
 
903
 
 
904
  register size_t
 
905
    i;
 
906
 
 
907
  ssize_t
 
908
    count;
 
909
 
 
910
  unsigned char
 
911
    *blob;
 
912
 
 
913
  void
 
914
    *map;
 
915
 
 
916
  assert(filename != (const char *) NULL);
 
917
  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
 
918
  assert(exception != (ExceptionInfo *) NULL);
 
919
  *length=0;
 
920
  file=fileno(stdin);
 
921
  if (LocaleCompare(filename,"-") != 0)
 
922
    file=open(filename,O_RDONLY | O_BINARY);
 
923
  if (file == -1)
 
924
    {
 
925
      ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
 
926
      return((unsigned char *) NULL);
 
927
    }
 
928
  offset=(MagickOffsetType) lseek(file,0,SEEK_END);
 
929
  count=0;
 
930
  if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset)))
 
931
    {
 
932
      size_t
 
933
        quantum;
 
934
 
 
935
      struct stat
 
936
        file_info;
 
937
 
 
938
      /*
 
939
        Stream is not seekable.
 
940
      */
 
941
      quantum=(size_t) MagickMaxBufferExtent;
 
942
      if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
 
943
        quantum=(size_t) MagickMin((MagickSizeType) file_info.st_size,
 
944
          MagickMaxBufferExtent);
 
945
      blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
 
946
      for (i=0; blob != (unsigned char *) NULL; i+=count)
 
947
      {
 
948
        count=(ssize_t) read(file,blob+i,quantum);
 
949
        if (count <= 0)
 
950
          {
 
951
            count=0;
 
952
            if (errno != EINTR)
 
953
              break;
 
954
          }
 
955
        if (~(1UL*i) < (quantum+1))
 
956
          {
 
957
            blob=(unsigned char *) RelinquishMagickMemory(blob);
 
958
            break;
 
959
          }
 
960
        blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
 
961
          sizeof(*blob));
 
962
        if ((size_t) (i+count) >= extent)
 
963
          break;
 
964
      }
 
965
      if (LocaleCompare(filename,"-") != 0)
 
966
        file=close(file);
 
967
      if (blob == (unsigned char *) NULL)
 
968
        {
 
969
          (void) ThrowMagickException(exception,GetMagickModule(),
 
970
            ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
 
971
          return((unsigned char *) NULL);
 
972
        }
 
973
      if (file == -1)
 
974
        {
 
975
          blob=(unsigned char *) RelinquishMagickMemory(blob);
 
976
          ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
 
977
          return((unsigned char *) NULL);
 
978
        }
 
979
      *length=(size_t) MagickMin(i+count,extent);
 
980
      blob[*length]='\0';
 
981
      return(blob);
 
982
    }
 
983
  *length=(size_t) MagickMin((MagickSizeType) offset,extent);
 
984
  blob=(unsigned char *) NULL;
 
985
  if (~(*length) >= MaxTextExtent)
 
986
    blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
 
987
      sizeof(*blob));
 
988
  if (blob == (unsigned char *) NULL)
 
989
    {
 
990
      file=close(file);
 
991
      (void) ThrowMagickException(exception,GetMagickModule(),
 
992
        ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
 
993
      return((unsigned char *) NULL);
 
994
    }
 
995
  map=MapBlob(file,ReadMode,0,*length);
 
996
  if (map != (unsigned char *) NULL)
 
997
    {
 
998
      (void) memcpy(blob,map,*length);
 
999
      (void) UnmapBlob(map,*length);
 
1000
    }
 
1001
  else
 
1002
    {
 
1003
      (void) lseek(file,0,SEEK_SET);
 
1004
      for (i=0; i < *length; i+=count)
 
1005
      {
 
1006
        count=(ssize_t) read(file,blob+i,(size_t) MagickMin(*length-i,
 
1007
          (MagickSizeType) SSIZE_MAX));
 
1008
        if (count <= 0)
 
1009
          {
 
1010
            count=0;
 
1011
            if (errno != EINTR)
 
1012
              break;
 
1013
          }
 
1014
      }
 
1015
      if (i < *length)
 
1016
        {
 
1017
          file=close(file)-1;
 
1018
          blob=(unsigned char *) RelinquishMagickMemory(blob);
 
1019
          ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
 
1020
          return((unsigned char *) NULL);
 
1021
        }
 
1022
    }
 
1023
  blob[*length]='\0';
 
1024
  if (LocaleCompare(filename,"-") != 0)
 
1025
    file=close(file);
 
1026
  if (file == -1)
 
1027
    {
 
1028
      blob=(unsigned char *) RelinquishMagickMemory(blob);
 
1029
      ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
 
1030
    }
 
1031
  return(blob);
 
1032
}
 
1033
 
 
1034
/*
 
1035
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1036
%                                                                             %
 
1037
%                                                                             %
 
1038
%                                                                             %
 
1039
%   F i l e T o I m a g e                                                     %
 
1040
%                                                                             %
 
1041
%                                                                             %
 
1042
%                                                                             %
 
1043
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1044
%
 
1045
%  FileToImage() write the contents of a file to an image.
 
1046
%
 
1047
%  The format of the FileToImage method is:
 
1048
%
 
1049
%      MagickBooleanType FileToImage(Image *,const char *filename)
 
1050
%
 
1051
%  A description of each parameter follows:
 
1052
%
 
1053
%    o image: the image.
 
1054
%
 
1055
%    o filename: the filename.
 
1056
%
 
1057
*/
 
1058
 
 
1059
static inline ssize_t WriteBlobStream(Image *image,const size_t length,
 
1060
  const unsigned char *data)
 
1061
{
 
1062
  MagickSizeType
 
1063
    extent;
 
1064
 
 
1065
  register unsigned char
 
1066
    *q;
 
1067
 
 
1068
  assert(image->blob != (BlobInfo *) NULL);
 
1069
  if (image->blob->type != BlobStream)
 
1070
    return(WriteBlob(image,length,data));
 
1071
  assert(image->blob->type != UndefinedStream);
 
1072
  assert(data != (void *) NULL);
 
1073
  extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
 
1074
  if (extent >= image->blob->extent)
 
1075
    {
 
1076
      image->blob->quantum<<=1;
 
1077
      extent=image->blob->extent+image->blob->quantum+length;
 
1078
      if (SetBlobExtent(image,extent) == MagickFalse)
 
1079
        return(0);
 
1080
    }
 
1081
  q=image->blob->data+image->blob->offset;
 
1082
  (void) memcpy(q,data,length);
 
1083
  image->blob->offset+=length;
 
1084
  if (image->blob->offset >= (MagickOffsetType) image->blob->length)
 
1085
    image->blob->length=(size_t) image->blob->offset;
 
1086
  return((ssize_t) length);
 
1087
}
 
1088
 
 
1089
MagickExport MagickBooleanType FileToImage(Image *image,const char *filename)
 
1090
{
 
1091
  int
 
1092
    file;
 
1093
 
 
1094
  size_t
 
1095
    length,
 
1096
    quantum;
 
1097
 
 
1098
  ssize_t
 
1099
    count;
 
1100
 
 
1101
  struct stat
 
1102
    file_info;
 
1103
 
 
1104
  unsigned char
 
1105
    *blob;
 
1106
 
 
1107
  assert(image != (const Image *) NULL);
 
1108
  assert(image->signature == MagickSignature);
 
1109
  assert(filename != (const char *) NULL);
 
1110
  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
 
1111
  file=open(filename,O_RDONLY | O_BINARY);
 
1112
  if (file == -1)
 
1113
    {
 
1114
      ThrowFileException(&image->exception,BlobError,"UnableToOpenBlob",
 
1115
        filename);
 
1116
      return(MagickFalse);
 
1117
    }
 
1118
  quantum=(size_t) MagickMaxBufferExtent;
 
1119
  if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
 
1120
    quantum=(size_t) MagickMin(file_info.st_size,MagickMaxBufferExtent);
 
1121
  blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
 
1122
  if (blob == (unsigned char *) NULL)
 
1123
    {
 
1124
      ThrowFileException(&image->exception,ResourceLimitError,
 
1125
        "MemoryAllocationFailed",filename);
 
1126
      return(MagickFalse);
 
1127
    }
 
1128
  for ( ; ; )
 
1129
  {
 
1130
    count=(ssize_t) read(file,blob,quantum);
 
1131
    if (count <= 0)
 
1132
      {
 
1133
        count=0;
 
1134
        if (errno != EINTR)
 
1135
          break;
 
1136
      }
 
1137
    length=(size_t) count;
 
1138
    count=WriteBlobStream(image,length,blob);
 
1139
    if (count != (ssize_t) length)
 
1140
      {
 
1141
        ThrowFileException(&image->exception,BlobError,"UnableToWriteBlob",
 
1142
          filename);
 
1143
        break;
 
1144
      }
 
1145
  }
 
1146
  file=close(file);
 
1147
  if (file == -1)
 
1148
    ThrowFileException(&image->exception,BlobError,"UnableToWriteBlob",
 
1149
      filename);
 
1150
  blob=(unsigned char *) RelinquishMagickMemory(blob);
 
1151
  return(MagickTrue);
 
1152
}
 
1153
 
 
1154
/*
 
1155
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1156
%                                                                             %
 
1157
%                                                                             %
 
1158
%                                                                             %
 
1159
+   G e t B l o b E r r o r                                                   %
 
1160
%                                                                             %
 
1161
%                                                                             %
 
1162
%                                                                             %
 
1163
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1164
%
 
1165
%  GetBlobError() returns MagickTrue if the blob associated with the specified
 
1166
%  image encountered an error.
 
1167
%
 
1168
%  The format of the GetBlobError method is:
 
1169
%
 
1170
%       MagickBooleanType GetBlobError(const Image *image)
 
1171
%
 
1172
%  A description of each parameter follows:
 
1173
%
 
1174
%    o image: the image.
 
1175
%
 
1176
*/
 
1177
MagickExport MagickBooleanType GetBlobError(const Image *image)
 
1178
{
 
1179
  assert(image != (const Image *) NULL);
 
1180
  assert(image->signature == MagickSignature);
 
1181
  if (image->debug != MagickFalse)
 
1182
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
1183
  return(image->blob->status);
 
1184
}
 
1185
 
 
1186
/*
 
1187
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1188
%                                                                             %
 
1189
%                                                                             %
 
1190
%                                                                             %
 
1191
+   G e t B l o b F i l e H a n d l e                                         %
 
1192
%                                                                             %
 
1193
%                                                                             %
 
1194
%                                                                             %
 
1195
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1196
%
 
1197
%  GetBlobFileHandle() returns the file handle associated with the image blob.
 
1198
%
 
1199
%  The format of the GetBlobFile method is:
 
1200
%
 
1201
%      FILE *GetBlobFileHandle(const Image *image)
 
1202
%
 
1203
%  A description of each parameter follows:
 
1204
%
 
1205
%    o image: the image.
 
1206
%
 
1207
*/
 
1208
MagickExport FILE *GetBlobFileHandle(const Image *image)
 
1209
{
 
1210
  assert(image != (const Image *) NULL);
 
1211
  assert(image->signature == MagickSignature);
 
1212
  return(image->blob->file);
 
1213
}
 
1214
 
 
1215
/*
 
1216
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1217
%                                                                             %
 
1218
%                                                                             %
 
1219
%                                                                             %
 
1220
+   G e t B l o b I n f o                                                     %
 
1221
%                                                                             %
 
1222
%                                                                             %
 
1223
%                                                                             %
 
1224
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1225
%
 
1226
%  GetBlobInfo() initializes the BlobInfo structure.
 
1227
%
 
1228
%  The format of the GetBlobInfo method is:
 
1229
%
 
1230
%      void GetBlobInfo(BlobInfo *blob_info)
 
1231
%
 
1232
%  A description of each parameter follows:
 
1233
%
 
1234
%    o blob_info: Specifies a pointer to a BlobInfo structure.
 
1235
%
 
1236
*/
 
1237
MagickExport void GetBlobInfo(BlobInfo *blob_info)
 
1238
{
 
1239
  assert(blob_info != (BlobInfo *) NULL);
 
1240
  (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
 
1241
  blob_info->type=UndefinedStream;
 
1242
  blob_info->quantum=(size_t) MagickMaxBlobExtent;
 
1243
  blob_info->properties.st_mtime=time((time_t *) NULL);
 
1244
  blob_info->properties.st_ctime=time((time_t *) NULL);
 
1245
  blob_info->debug=IsEventLogging();
 
1246
  blob_info->reference_count=1;
 
1247
  blob_info->semaphore=AllocateSemaphoreInfo();
 
1248
  blob_info->signature=MagickSignature;
 
1249
}
 
1250
 
 
1251
/*
 
1252
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1253
%                                                                             %
 
1254
%                                                                             %
 
1255
%                                                                             %
 
1256
%  G e t B l o b P r o p e r t i e s                                          %
 
1257
%                                                                             %
 
1258
%                                                                             %
 
1259
%                                                                             %
 
1260
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1261
%
 
1262
%  GetBlobProperties() returns information about an image blob.
 
1263
%
 
1264
%  The format of the GetBlobProperties method is:
 
1265
%
 
1266
%      const struct stat *GetBlobProperties(const Image *image)
 
1267
%
 
1268
%  A description of each parameter follows:
 
1269
%
 
1270
%    o image: the image.
 
1271
%
 
1272
*/
 
1273
MagickExport const struct stat *GetBlobProperties(const Image *image)
 
1274
{
 
1275
  assert(image != (Image *) NULL);
 
1276
  assert(image->signature == MagickSignature);
 
1277
  if (image->debug != MagickFalse)
 
1278
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
1279
  return(&image->blob->properties);
 
1280
}
 
1281
 
 
1282
/*
 
1283
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1284
%                                                                             %
 
1285
%                                                                             %
 
1286
%                                                                             %
 
1287
+  G e t B l o b S i z e                                                      %
 
1288
%                                                                             %
 
1289
%                                                                             %
 
1290
%                                                                             %
 
1291
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1292
%
 
1293
%  GetBlobSize() returns the current length of the image file or blob; zero is
 
1294
%  returned if the size cannot be determined.
 
1295
%
 
1296
%  The format of the GetBlobSize method is:
 
1297
%
 
1298
%      MagickSizeType GetBlobSize(const Image *image)
 
1299
%
 
1300
%  A description of each parameter follows:
 
1301
%
 
1302
%    o image: the image.
 
1303
%
 
1304
*/
 
1305
MagickExport MagickSizeType GetBlobSize(const Image *image)
 
1306
{
 
1307
  MagickSizeType
 
1308
    extent;
 
1309
 
 
1310
  assert(image != (Image *) NULL);
 
1311
  assert(image->signature == MagickSignature);
 
1312
  if (image->debug != MagickFalse)
 
1313
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
1314
  assert(image->blob != (BlobInfo *) NULL);
 
1315
  extent=0;
 
1316
  switch (image->blob->type)
 
1317
  {
 
1318
    case UndefinedStream:
 
1319
    {
 
1320
      extent=image->blob->size;
 
1321
      break;
 
1322
    }
 
1323
    case FileStream:
 
1324
    {
 
1325
      if (fstat(fileno(image->blob->file),&image->blob->properties) == 0)
 
1326
        extent=(MagickSizeType) image->blob->properties.st_size;
 
1327
      break;
 
1328
    }
 
1329
    case StandardStream:
 
1330
    case PipeStream:
 
1331
    {
 
1332
      extent=image->blob->size;
 
1333
      break;
 
1334
    }
 
1335
    case ZipStream:
 
1336
    case BZipStream:
 
1337
    {
 
1338
      MagickBooleanType
 
1339
        status;
 
1340
 
 
1341
      status=GetPathAttributes(image->filename,&image->blob->properties);
 
1342
      if (status != MagickFalse)
 
1343
        extent=(MagickSizeType) image->blob->properties.st_size;
 
1344
      break;
 
1345
    }
 
1346
    case FifoStream:
 
1347
      break;
 
1348
    case BlobStream:
 
1349
    {
 
1350
      extent=(MagickSizeType) image->blob->length;
 
1351
      break;
 
1352
    }
 
1353
  }
 
1354
  return(extent);
 
1355
}
 
1356
 
 
1357
/*
 
1358
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1359
%                                                                             %
 
1360
%                                                                             %
 
1361
%                                                                             %
 
1362
+   G e t B l o b S t r e a m D a t a                                         %
 
1363
%                                                                             %
 
1364
%                                                                             %
 
1365
%                                                                             %
 
1366
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1367
%
 
1368
%  GetBlobStreamData() returns the stream data for the image.
 
1369
%
 
1370
%  The format of the GetBlobStreamData method is:
 
1371
%
 
1372
%      unsigned char *GetBlobStreamData(const Image *image)
 
1373
%
 
1374
%  A description of each parameter follows:
 
1375
%
 
1376
%    o image: the image.
 
1377
%
 
1378
*/
 
1379
MagickExport unsigned char *GetBlobStreamData(const Image *image)
 
1380
{
 
1381
  assert(image != (const Image *) NULL);
 
1382
  assert(image->signature == MagickSignature);
 
1383
  return(image->blob->data);
 
1384
}
 
1385
 
 
1386
/*
 
1387
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1388
%                                                                             %
 
1389
%                                                                             %
 
1390
%                                                                             %
 
1391
+   G e t B l o b S t r e a m H a n d l e r                                   %
 
1392
%                                                                             %
 
1393
%                                                                             %
 
1394
%                                                                             %
 
1395
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1396
%
 
1397
%  GetBlobStreamHandler() returns the stream handler for the image.
 
1398
%
 
1399
%  The format of the GetBlobStreamHandler method is:
 
1400
%
 
1401
%      StreamHandler GetBlobStreamHandler(const Image *image)
 
1402
%
 
1403
%  A description of each parameter follows:
 
1404
%
 
1405
%    o image: the image.
 
1406
%
 
1407
*/
 
1408
MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
 
1409
{
 
1410
  assert(image != (const Image *) NULL);
 
1411
  assert(image->signature == MagickSignature);
 
1412
  if (image->debug != MagickFalse)
 
1413
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
1414
  return(image->blob->stream);
 
1415
}
 
1416
 
 
1417
/*
 
1418
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1419
%                                                                             %
 
1420
%                                                                             %
 
1421
%                                                                             %
 
1422
%   I m a g e T o B l o b                                                     %
 
1423
%                                                                             %
 
1424
%                                                                             %
 
1425
%                                                                             %
 
1426
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1427
%
 
1428
%  ImageToBlob() implements direct to memory image formats.  It returns the
 
1429
%  image as a formatted blob and its length.  The magick member of the Image
 
1430
%  structure determines the format of the returned blob (GIF, JPEG, PNG,
 
1431
%  etc.).  This method is the equivalent of WriteImage(), but writes the
 
1432
%  formatted "file" to a memory buffer rather than to an actual file.
 
1433
%
 
1434
%  The format of the ImageToBlob method is:
 
1435
%
 
1436
%      unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
 
1437
%        size_t *length,ExceptionInfo *exception)
 
1438
%
 
1439
%  A description of each parameter follows:
 
1440
%
 
1441
%    o image_info: the image info.
 
1442
%
 
1443
%    o image: the image.
 
1444
%
 
1445
%    o length: This pointer to a size_t integer sets the initial length of the
 
1446
%      blob.  On return, it reflects the actual length of the blob.
 
1447
%
 
1448
%    o exception: return any errors or warnings in this structure.
 
1449
%
 
1450
*/
 
1451
MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
 
1452
  Image *image,size_t *length,ExceptionInfo *exception)
 
1453
{
 
1454
  const MagickInfo
 
1455
    *magick_info;
 
1456
 
 
1457
  ImageInfo
 
1458
    *blob_info;
 
1459
 
 
1460
  MagickBooleanType
 
1461
    status;
 
1462
 
 
1463
  unsigned char
 
1464
    *blob;
 
1465
 
 
1466
  assert(image_info != (const ImageInfo *) NULL);
 
1467
  assert(image_info->signature == MagickSignature);
 
1468
  if (image_info->debug != MagickFalse)
 
1469
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
 
1470
      image_info->filename);
 
1471
  assert(image != (Image *) NULL);
 
1472
  assert(image->signature == MagickSignature);
 
1473
  assert(exception != (ExceptionInfo *) NULL);
 
1474
  *length=0;
 
1475
  blob=(unsigned char *) NULL;
 
1476
  blob_info=CloneImageInfo(image_info);
 
1477
  blob_info->adjoin=MagickFalse;
 
1478
  (void) SetImageInfo(blob_info,1,exception);
 
1479
  if (*blob_info->magick != '\0')
 
1480
    (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
 
1481
  magick_info=GetMagickInfo(image->magick,exception);
 
1482
  if (magick_info == (const MagickInfo *) NULL)
 
1483
    {
 
1484
      (void) ThrowMagickException(exception,GetMagickModule(),
 
1485
        MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
 
1486
        image->filename);
 
1487
      return(blob);
 
1488
    }
 
1489
  (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
 
1490
  if (GetMagickBlobSupport(magick_info) != MagickFalse)
 
1491
    {
 
1492
      /*
 
1493
        Native blob support for this image format.
 
1494
      */
 
1495
      blob_info->length=0;
 
1496
      blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
 
1497
        sizeof(unsigned char));
 
1498
      if (blob_info->blob == (void *) NULL)
 
1499
        (void) ThrowMagickException(exception,GetMagickModule(),
 
1500
          ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
 
1501
      else
 
1502
        {
 
1503
          (void) CloseBlob(image);
 
1504
          image->blob->exempt=MagickTrue;
 
1505
          *image->filename='\0';
 
1506
          status=WriteImage(blob_info,image);
 
1507
          if ((status == MagickFalse) || (image->blob->length == 0))
 
1508
            InheritException(exception,&image->exception);
 
1509
          else
 
1510
            {
 
1511
              *length=image->blob->length;
 
1512
              blob=DetachBlob(image->blob);
 
1513
              blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
 
1514
                sizeof(*blob));
 
1515
            }
 
1516
        }
 
1517
    }
 
1518
  else
 
1519
    {
 
1520
      char
 
1521
        unique[MaxTextExtent];
 
1522
 
 
1523
      int
 
1524
        file;
 
1525
 
 
1526
      /*
 
1527
        Write file to disk in blob image format.
 
1528
      */
 
1529
      file=AcquireUniqueFileResource(unique);
 
1530
      if (file == -1)
 
1531
        {
 
1532
          ThrowFileException(exception,BlobError,"UnableToWriteBlob",
 
1533
            image_info->filename);
 
1534
        }
 
1535
      else
 
1536
        {
 
1537
          blob_info->file=fdopen(file,"wb");
 
1538
          if (blob_info->file != (FILE *) NULL)
 
1539
            {
 
1540
              (void) FormatMagickString(image->filename,MaxTextExtent,"%s:%s",
 
1541
                image->magick,unique);
 
1542
              status=WriteImage(blob_info,image);
 
1543
              (void) fclose(blob_info->file);
 
1544
              if (status == MagickFalse)
 
1545
                InheritException(exception,&image->exception);
 
1546
              else
 
1547
                blob=FileToBlob(image->filename,~0UL,length,exception);
 
1548
            }
 
1549
          (void) RelinquishUniqueFileResource(unique);
 
1550
        }
 
1551
    }
 
1552
  blob_info=DestroyImageInfo(blob_info);
 
1553
  return(blob);
 
1554
}
 
1555
 
 
1556
/*
 
1557
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1558
%                                                                             %
 
1559
%                                                                             %
 
1560
%                                                                             %
 
1561
%   I m a g e T o F i l e                                                     %
 
1562
%                                                                             %
 
1563
%                                                                             %
 
1564
%                                                                             %
 
1565
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1566
%
 
1567
%  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
 
1568
%  occurs otherwise MagickTrue.
 
1569
%
 
1570
%  The format of the ImageToFile method is:
 
1571
%
 
1572
%       MagickBooleanType ImageToFile(Image *image,char *filename,
 
1573
%         ExceptionInfo *exception)
 
1574
%
 
1575
%  A description of each parameter follows:
 
1576
%
 
1577
%    o image: the image.
 
1578
%
 
1579
%    o filename: Write the image to this file.
 
1580
%
 
1581
%    o exception: return any errors or warnings in this structure.
 
1582
%
 
1583
*/
 
1584
MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
 
1585
  ExceptionInfo *exception)
 
1586
{
 
1587
  int
 
1588
    file;
 
1589
 
 
1590
  register const unsigned char
 
1591
    *p;
 
1592
 
 
1593
  register size_t
 
1594
    i;
 
1595
 
 
1596
  size_t
 
1597
    length,
 
1598
    quantum;
 
1599
 
 
1600
  ssize_t
 
1601
    count;
 
1602
 
 
1603
  struct stat
 
1604
    file_info;
 
1605
 
 
1606
  unsigned char
 
1607
    *buffer;
 
1608
 
 
1609
  assert(image != (Image *) NULL);
 
1610
  assert(image->signature == MagickSignature);
 
1611
  assert(image->blob != (BlobInfo *) NULL);
 
1612
  assert(image->blob->type != UndefinedStream);
 
1613
  if (image->debug != MagickFalse)
 
1614
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
 
1615
  assert(filename != (const char *) NULL);
 
1616
  if (*filename == '\0')
 
1617
    file=AcquireUniqueFileResource(filename);
 
1618
  else
 
1619
    if (LocaleCompare(filename,"-") == 0)
 
1620
      file=fileno(stdout);
 
1621
    else
 
1622
      file=open(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
 
1623
  if (file == -1)
 
1624
    {
 
1625
      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
 
1626
      return(MagickFalse);
 
1627
    }
 
1628
  quantum=(size_t) MagickMaxBufferExtent;
 
1629
  if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
 
1630
    quantum=(size_t) MagickMin((MagickSizeType) file_info.st_size,
 
1631
      MagickMaxBufferExtent);
 
1632
  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
 
1633
  if (buffer == (unsigned char *) NULL)
 
1634
    {
 
1635
      file=close(file)-1;
 
1636
      (void) ThrowMagickException(exception,GetMagickModule(),
 
1637
        ResourceLimitError,"MemoryAllocationError","`%s'",filename);
 
1638
      return(MagickFalse);
 
1639
    }
 
1640
  length=0;
 
1641
  p=ReadBlobStream(image,quantum,buffer,&count);
 
1642
  for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
 
1643
  {
 
1644
    length=(size_t) count;
 
1645
    for (i=0; i < length; i+=count)
 
1646
    {
 
1647
      count=write(file,p+i,(size_t) (length-i));
 
1648
      if (count <= 0)
 
1649
        {
 
1650
          count=0;
 
1651
          if (errno != EINTR)
 
1652
            break;
 
1653
        }
 
1654
    }
 
1655
    if (i < length)
 
1656
      break;
 
1657
  }
 
1658
  if (LocaleCompare(filename,"-") != 0)
 
1659
    file=close(file);
 
1660
  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
 
1661
  if ((file == -1) || (i < length))
 
1662
    {
 
1663
      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
 
1664
      return(MagickFalse);
 
1665
    }
 
1666
  return(MagickTrue);
 
1667
}
 
1668
 
 
1669
/*
 
1670
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1671
%                                                                             %
 
1672
%                                                                             %
 
1673
%                                                                             %
 
1674
%   I m a g e s T o B l o b                                                   %
 
1675
%                                                                             %
 
1676
%                                                                             %
 
1677
%                                                                             %
 
1678
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1679
%
 
1680
%  ImagesToBlob() implements direct to memory image formats.  It returns the
 
1681
%  image sequence as a blob and its length.  The magick member of the ImageInfo
 
1682
%  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
 
1683
%
 
1684
%  Note, some image formats do not permit multiple images to the same image
 
1685
%  stream (e.g. JPEG).  in this instance, just the first image of the
 
1686
%  sequence is returned as a blob.
 
1687
%
 
1688
%  The format of the ImagesToBlob method is:
 
1689
%
 
1690
%      unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
 
1691
%        size_t *length,ExceptionInfo *exception)
 
1692
%
 
1693
%  A description of each parameter follows:
 
1694
%
 
1695
%    o image_info: the image info.
 
1696
%
 
1697
%    o images: the image list.
 
1698
%
 
1699
%    o length: This pointer to a size_t integer sets the initial length of the
 
1700
%      blob.  On return, it reflects the actual length of the blob.
 
1701
%
 
1702
%    o exception: return any errors or warnings in this structure.
 
1703
%
 
1704
*/
 
1705
MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
 
1706
  Image *images,size_t *length,ExceptionInfo *exception)
 
1707
{
 
1708
  const MagickInfo
 
1709
    *magick_info;
 
1710
 
 
1711
  ImageInfo
 
1712
    *blob_info;
 
1713
 
 
1714
  MagickBooleanType
 
1715
    status;
 
1716
 
 
1717
  unsigned char
 
1718
    *blob;
 
1719
 
 
1720
  assert(image_info != (const ImageInfo *) NULL);
 
1721
  assert(image_info->signature == MagickSignature);
 
1722
  if (image_info->debug != MagickFalse)
 
1723
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
 
1724
      image_info->filename);
 
1725
  assert(images != (Image *) NULL);
 
1726
  assert(images->signature == MagickSignature);
 
1727
  assert(exception != (ExceptionInfo *) NULL);
 
1728
  *length=0;
 
1729
  blob=(unsigned char *) NULL;
 
1730
  blob_info=CloneImageInfo(image_info);
 
1731
  (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
 
1732
    exception);
 
1733
  if (*blob_info->magick != '\0')
 
1734
    (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
 
1735
  if (blob_info->adjoin == MagickFalse)
 
1736
    {
 
1737
      blob_info=DestroyImageInfo(blob_info);
 
1738
      return(ImageToBlob(image_info,images,length,exception));
 
1739
    }
 
1740
  magick_info=GetMagickInfo(images->magick,exception);
 
1741
  if (magick_info == (const MagickInfo *) NULL)
 
1742
    {
 
1743
      (void) ThrowMagickException(exception,GetMagickModule(),
 
1744
        MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
 
1745
        images->filename);
 
1746
      return(blob);
 
1747
    }
 
1748
  (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
 
1749
  if (GetMagickBlobSupport(magick_info) != MagickFalse)
 
1750
    {
 
1751
      /*
 
1752
        Native blob support for this images format.
 
1753
      */
 
1754
      blob_info->length=0;
 
1755
      blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
 
1756
        sizeof(unsigned char));
 
1757
      if (blob_info->blob == (void *) NULL)
 
1758
        (void) ThrowMagickException(exception,GetMagickModule(),
 
1759
          ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
 
1760
      else
 
1761
        {
 
1762
          images->blob->exempt=MagickTrue;
 
1763
          *images->filename='\0';
 
1764
          status=WriteImages(blob_info,images,images->filename,exception);
 
1765
          if ((status == MagickFalse) || (images->blob->length == 0))
 
1766
            InheritException(exception,&images->exception);
 
1767
          else
 
1768
            {
 
1769
              *length=images->blob->length;
 
1770
              blob=DetachBlob(images->blob);
 
1771
              blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
 
1772
                sizeof(*blob));
 
1773
            }
 
1774
        }
 
1775
    }
 
1776
  else
 
1777
    {
 
1778
      char
 
1779
        filename[MaxTextExtent],
 
1780
        unique[MaxTextExtent];
 
1781
 
 
1782
      int
 
1783
        file;
 
1784
 
 
1785
      /*
 
1786
        Write file to disk in blob images format.
 
1787
      */
 
1788
      file=AcquireUniqueFileResource(unique);
 
1789
      if (file == -1)
 
1790
        {
 
1791
          ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
 
1792
            image_info->filename);
 
1793
        }
 
1794
      else
 
1795
        {
 
1796
          blob_info->file=fdopen(file,"wb");
 
1797
          if (blob_info->file != (FILE *) NULL)
 
1798
            {
 
1799
              (void) FormatMagickString(filename,MaxTextExtent,"%s:%s",
 
1800
                images->magick,unique);
 
1801
              status=WriteImages(blob_info,images,filename,exception);
 
1802
              (void) fclose(blob_info->file);
 
1803
              if (status == MagickFalse)
 
1804
                InheritException(exception,&images->exception);
 
1805
              else
 
1806
                blob=FileToBlob(images->filename,~0UL,length,exception);
 
1807
            }
 
1808
          (void) RelinquishUniqueFileResource(unique);
 
1809
        }
 
1810
    }
 
1811
  blob_info=DestroyImageInfo(blob_info);
 
1812
  return(blob);
 
1813
}
 
1814
/*
 
1815
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1816
%                                                                             %
 
1817
%                                                                             %
 
1818
%                                                                             %
 
1819
%   I n j e c t I m a g e B l o b                                             %
 
1820
%                                                                             %
 
1821
%                                                                             %
 
1822
%                                                                             %
 
1823
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1824
%
 
1825
%  InjectImageBlob() injects the image with a copy of itself in the specified
 
1826
%  format (e.g. inject JPEG into a PDF image).
 
1827
%
 
1828
%  The format of the InjectImageBlob method is:
 
1829
%
 
1830
%      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
 
1831
%        Image *image,Image *inject_image,const char *format,
 
1832
%        ExceptionInfo *exception)
 
1833
%
 
1834
%  A description of each parameter follows:
 
1835
%
 
1836
%    o image_info: the image info..
 
1837
%
 
1838
%    o image: the image.
 
1839
%
 
1840
%    o inject_image: inject into the image stream.
 
1841
%
 
1842
%    o format: the image format.
 
1843
%
 
1844
%    o exception: return any errors or warnings in this structure.
 
1845
%
 
1846
*/
 
1847
MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
 
1848
  Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
 
1849
{
 
1850
  char
 
1851
    filename[MaxTextExtent];
 
1852
 
 
1853
  FILE
 
1854
    *unique_file;
 
1855
 
 
1856
  Image
 
1857
    *byte_image;
 
1858
 
 
1859
  ImageInfo
 
1860
    *write_info;
 
1861
 
 
1862
  int
 
1863
    file;
 
1864
 
 
1865
  MagickBooleanType
 
1866
    status;
 
1867
 
 
1868
  register ssize_t
 
1869
    i;
 
1870
 
 
1871
  size_t
 
1872
    quantum;
 
1873
 
 
1874
  ssize_t
 
1875
    count;
 
1876
 
 
1877
  struct stat
 
1878
    file_info;
 
1879
 
 
1880
  unsigned char
 
1881
    *buffer;
 
1882
 
 
1883
  /*
 
1884
    Write inject image to a temporary file.
 
1885
  */
 
1886
  assert(image_info != (ImageInfo *) NULL);
 
1887
  assert(image_info->signature == MagickSignature);
 
1888
  assert(image != (Image *) NULL);
 
1889
  assert(image->signature == MagickSignature);
 
1890
  if (image->debug != MagickFalse)
 
1891
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
1892
  assert(inject_image != (Image *) NULL);
 
1893
  assert(inject_image->signature == MagickSignature);
 
1894
  assert(exception != (ExceptionInfo *) NULL);
 
1895
  unique_file=(FILE *) NULL;
 
1896
  file=AcquireUniqueFileResource(filename);
 
1897
  if (file != -1)
 
1898
    unique_file=fdopen(file,"wb");
 
1899
  if ((file == -1) || (unique_file == (FILE *) NULL))
 
1900
    {
 
1901
      (void) CopyMagickString(image->filename,filename,MaxTextExtent);
 
1902
      ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
 
1903
        image->filename);
 
1904
      return(MagickFalse);
 
1905
    }
 
1906
  byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
 
1907
  if (byte_image == (Image *) NULL)
 
1908
    {
 
1909
      (void) fclose(unique_file);
 
1910
      (void) RelinquishUniqueFileResource(filename);
 
1911
      return(MagickFalse);
 
1912
    }
 
1913
  (void) FormatMagickString(byte_image->filename,MaxTextExtent,"%s:%s",format,
 
1914
    filename);
 
1915
  DestroyBlob(byte_image);
 
1916
  byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
 
1917
  write_info=CloneImageInfo(image_info);
 
1918
  SetImageInfoFile(write_info,unique_file);
 
1919
  status=WriteImage(write_info,byte_image);
 
1920
  write_info=DestroyImageInfo(write_info);
 
1921
  byte_image=DestroyImage(byte_image);
 
1922
  (void) fclose(unique_file);
 
1923
  if (status == MagickFalse)
 
1924
    {
 
1925
      (void) RelinquishUniqueFileResource(filename);
 
1926
      return(MagickFalse);
 
1927
    }
 
1928
  /*
 
1929
    Inject into image stream.
 
1930
  */
 
1931
  file=open(filename,O_RDONLY | O_BINARY);
 
1932
  if (file == -1)
 
1933
    {
 
1934
      (void) RelinquishUniqueFileResource(filename);
 
1935
      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
 
1936
        image_info->filename);
 
1937
      return(MagickFalse);
 
1938
    }
 
1939
  quantum=(size_t) MagickMaxBufferExtent;
 
1940
  if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
 
1941
    quantum=(size_t) MagickMin(file_info.st_size,MagickMaxBufferExtent);
 
1942
  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
 
1943
  if (buffer == (unsigned char *) NULL)
 
1944
    {
 
1945
      (void) RelinquishUniqueFileResource(filename);
 
1946
      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
 
1947
        image->filename);
 
1948
    }
 
1949
  for (i=0; ; i+=count)
 
1950
  {
 
1951
    count=(ssize_t) read(file,buffer,quantum);
 
1952
    if (count <= 0)
 
1953
      {
 
1954
        count=0;
 
1955
        if (errno != EINTR)
 
1956
          break;
 
1957
      }
 
1958
    status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
 
1959
      MagickFalse;
 
1960
  }
 
1961
  file=close(file);
 
1962
  if (file == -1)
 
1963
    ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
 
1964
  (void) RelinquishUniqueFileResource(filename);
 
1965
  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
 
1966
  return(status);
 
1967
}
 
1968
 
 
1969
/*
 
1970
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1971
%                                                                             %
 
1972
%                                                                             %
 
1973
%                                                                             %
 
1974
+   I s B l o b E x e m p t                                                   %
 
1975
%                                                                             %
 
1976
%                                                                             %
 
1977
%                                                                             %
 
1978
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1979
%
 
1980
%  IsBlobExempt() returns true if the blob is exempt.
 
1981
%
 
1982
%  The format of the IsBlobExempt method is:
 
1983
%
 
1984
%       MagickBooleanType IsBlobExempt(const Image *image)
 
1985
%
 
1986
%  A description of each parameter follows:
 
1987
%
 
1988
%    o image: the image.
 
1989
%
 
1990
*/
 
1991
MagickExport MagickBooleanType IsBlobExempt(const Image *image)
 
1992
{
 
1993
  assert(image != (const Image *) NULL);
 
1994
  assert(image->signature == MagickSignature);
 
1995
  if (image->debug != MagickFalse)
 
1996
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
1997
  return(image->blob->exempt);
 
1998
}
 
1999
 
 
2000
/*
 
2001
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2002
%                                                                             %
 
2003
%                                                                             %
 
2004
%                                                                             %
 
2005
+   I s B l o b S e e k a b l e                                               %
 
2006
%                                                                             %
 
2007
%                                                                             %
 
2008
%                                                                             %
 
2009
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2010
%
 
2011
%  IsBlobSeekable() returns true if the blob is seekable.
 
2012
%
 
2013
%  The format of the IsBlobSeekable method is:
 
2014
%
 
2015
%       MagickBooleanType IsBlobSeekable(const Image *image)
 
2016
%
 
2017
%  A description of each parameter follows:
 
2018
%
 
2019
%    o image: the image.
 
2020
%
 
2021
*/
 
2022
MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
 
2023
{
 
2024
  MagickBooleanType
 
2025
    seekable;
 
2026
 
 
2027
  assert(image != (const Image *) NULL);
 
2028
  assert(image->signature == MagickSignature);
 
2029
  if (image->debug != MagickFalse)
 
2030
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
2031
  seekable=(image->blob->type == FileStream) ||
 
2032
    (image->blob->type == BlobStream) ? MagickTrue : MagickFalse;
 
2033
  return(seekable);
 
2034
}
 
2035
 
 
2036
/*
 
2037
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2038
%                                                                             %
 
2039
%                                                                             %
 
2040
%                                                                             %
 
2041
+   I s B l o b T e m p o r a r y                                             %
 
2042
%                                                                             %
 
2043
%                                                                             %
 
2044
%                                                                             %
 
2045
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2046
%
 
2047
%  IsBlobTemporary() returns true if the blob is temporary.
 
2048
%
 
2049
%  The format of the IsBlobTemporary method is:
 
2050
%
 
2051
%       MagickBooleanType IsBlobTemporary(const Image *image)
 
2052
%
 
2053
%  A description of each parameter follows:
 
2054
%
 
2055
%    o image: the image.
 
2056
%
 
2057
*/
 
2058
MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
 
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);
 
2064
  return(image->blob->temporary);
 
2065
}
 
2066
 
 
2067
/*
 
2068
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2069
%                                                                             %
 
2070
%                                                                             %
 
2071
%                                                                             %
 
2072
+  M a p B l o b                                                              %
 
2073
%                                                                             %
 
2074
%                                                                             %
 
2075
%                                                                             %
 
2076
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2077
%
 
2078
%  MapBlob() creates a mapping from a file to a binary large object.
 
2079
%
 
2080
%  The format of the MapBlob method is:
 
2081
%
 
2082
%      unsigned char *MapBlob(int file,const MapMode mode,
 
2083
%        const MagickOffsetType offset,const size_t length)
 
2084
%
 
2085
%  A description of each parameter follows:
 
2086
%
 
2087
%    o file: map this file descriptor.
 
2088
%
 
2089
%    o mode: ReadMode, WriteMode, or IOMode.
 
2090
%
 
2091
%    o offset: starting at this offset within the file.
 
2092
%
 
2093
%    o length: the length of the mapping is returned in this pointer.
 
2094
%
 
2095
*/
 
2096
MagickExport unsigned char *MapBlob(int file,const MapMode mode,
 
2097
  const MagickOffsetType offset,const size_t length)
 
2098
{
 
2099
#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
 
2100
  int
 
2101
    flags,
 
2102
    protection;
 
2103
 
 
2104
  unsigned char
 
2105
    *map;
 
2106
 
 
2107
  /*
 
2108
    Map file.
 
2109
  */
 
2110
  flags=0;
 
2111
  if (file == -1)
 
2112
#if defined(MAP_ANONYMOUS)
 
2113
    flags|=MAP_ANONYMOUS;
 
2114
#else
 
2115
    return((unsigned char *) NULL);
 
2116
#endif
 
2117
  switch (mode)
 
2118
  {
 
2119
    case ReadMode:
 
2120
    default:
 
2121
    {
 
2122
      protection=PROT_READ;
 
2123
      flags|=MAP_PRIVATE;
 
2124
      map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
 
2125
        (off_t) offset);
 
2126
      break;
 
2127
    }
 
2128
    case WriteMode:
 
2129
    {
 
2130
      protection=PROT_WRITE;
 
2131
      flags|=MAP_SHARED;
 
2132
      map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
 
2133
        (off_t) offset);
 
2134
#if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
 
2135
      (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
 
2136
        POSIX_MADV_WILLNEED);
 
2137
#endif
 
2138
      break;
 
2139
    }
 
2140
    case IOMode:
 
2141
    {
 
2142
      protection=PROT_READ | PROT_WRITE;
 
2143
      flags|=MAP_SHARED;
 
2144
      map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
 
2145
        (off_t) offset);
 
2146
      break;
 
2147
    }
 
2148
  }
 
2149
  if (map == (unsigned char *) MAP_FAILED)
 
2150
    return((unsigned char *) NULL);
 
2151
  return(map);
 
2152
#else
 
2153
  (void) file;
 
2154
  (void) mode;
 
2155
  (void) offset;
 
2156
  (void) length;
 
2157
  return((unsigned char *) NULL);
 
2158
#endif
 
2159
}
 
2160
 
 
2161
/*
 
2162
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2163
%                                                                             %
 
2164
%                                                                             %
 
2165
%                                                                             %
 
2166
+  M S B O r d e r L o n g                                                    %
 
2167
%                                                                             %
 
2168
%                                                                             %
 
2169
%                                                                             %
 
2170
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2171
%
 
2172
%  MSBOrderLong() converts a least-significant byte first buffer of integers to
 
2173
%  most-significant byte first.
 
2174
%
 
2175
%  The format of the MSBOrderLong method is:
 
2176
%
 
2177
%      void MSBOrderLong(unsigned char *buffer,const size_t length)
 
2178
%
 
2179
%  A description of each parameter follows.
 
2180
%
 
2181
%   o  buffer:  Specifies a pointer to a buffer of integers.
 
2182
%
 
2183
%   o  length:  Specifies the length of the buffer.
 
2184
%
 
2185
*/
 
2186
MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
 
2187
{
 
2188
  int
 
2189
    c;
 
2190
 
 
2191
  register unsigned char
 
2192
    *p,
 
2193
    *q;
 
2194
 
 
2195
  assert(buffer != (unsigned char *) NULL);
 
2196
  q=buffer+length;
 
2197
  while (buffer < q)
 
2198
  {
 
2199
    p=buffer+3;
 
2200
    c=(int) (*p);
 
2201
    *p=(*buffer);
 
2202
    *buffer++=(unsigned char) c;
 
2203
    p=buffer+1;
 
2204
    c=(int) (*p);
 
2205
    *p=(*buffer);
 
2206
    *buffer++=(unsigned char) c;
 
2207
    buffer+=2;
 
2208
  }
 
2209
}
 
2210
 
 
2211
/*
 
2212
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2213
%                                                                             %
 
2214
%                                                                             %
 
2215
%                                                                             %
 
2216
+  M S B O r d e r S h o r t                                                  %
 
2217
%                                                                             %
 
2218
%                                                                             %
 
2219
%                                                                             %
 
2220
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2221
%
 
2222
%  MSBOrderShort() converts a least-significant byte first buffer of integers
 
2223
%  to most-significant byte first.
 
2224
%
 
2225
%  The format of the MSBOrderShort method is:
 
2226
%
 
2227
%      void MSBOrderShort(unsigned char *p,const size_t length)
 
2228
%
 
2229
%  A description of each parameter follows.
 
2230
%
 
2231
%   o  p:  Specifies a pointer to a buffer of integers.
 
2232
%
 
2233
%   o  length:  Specifies the length of the buffer.
 
2234
%
 
2235
*/
 
2236
MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
 
2237
{
 
2238
  int
 
2239
    c;
 
2240
 
 
2241
  register unsigned char
 
2242
    *q;
 
2243
 
 
2244
  assert(p != (unsigned char *) NULL);
 
2245
  q=p+length;
 
2246
  while (p < q)
 
2247
  {
 
2248
    c=(int) (*p);
 
2249
    *p=(*(p+1));
 
2250
    p++;
 
2251
    *p++=(unsigned char) c;
 
2252
  }
 
2253
}
 
2254
 
 
2255
/*
 
2256
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2257
%                                                                             %
 
2258
%                                                                             %
 
2259
%                                                                             %
 
2260
+   O p e n B l o b                                                           %
 
2261
%                                                                             %
 
2262
%                                                                             %
 
2263
%                                                                             %
 
2264
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2265
%
 
2266
%  OpenBlob() opens a file associated with the image.  A file name of '-' sets
 
2267
%  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
 
2268
%  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
 
2269
%  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
 
2270
%  from a system command.
 
2271
%
 
2272
%  The format of the OpenBlob method is:
 
2273
%
 
2274
%       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
 
2275
%        const BlobMode mode,ExceptionInfo *exception)
 
2276
%
 
2277
%  A description of each parameter follows:
 
2278
%
 
2279
%    o image_info: the image info.
 
2280
%
 
2281
%    o image: the image.
 
2282
%
 
2283
%    o mode: the mode for opening the file.
 
2284
%
 
2285
*/
 
2286
MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
 
2287
  Image *image,const BlobMode mode,ExceptionInfo *exception)
 
2288
{
 
2289
  char
 
2290
    extension[MaxTextExtent],
 
2291
    filename[MaxTextExtent];
 
2292
 
 
2293
  const char
 
2294
    *type;
 
2295
 
 
2296
  MagickBooleanType
 
2297
    status;
 
2298
 
 
2299
  PolicyRights
 
2300
    rights;
 
2301
 
 
2302
  assert(image_info != (ImageInfo *) NULL);
 
2303
  assert(image_info->signature == MagickSignature);
 
2304
  if (image_info->debug != MagickFalse)
 
2305
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
 
2306
      image_info->filename);
 
2307
  assert(image != (Image *) NULL);
 
2308
  assert(image->signature == MagickSignature);
 
2309
  if (image_info->blob != (void *) NULL)
 
2310
    {
 
2311
      if (image_info->stream != (StreamHandler) NULL)
 
2312
        image->blob->stream=(StreamHandler) image_info->stream;
 
2313
      AttachBlob(image->blob,image_info->blob,image_info->length);
 
2314
      return(MagickTrue);
 
2315
    }
 
2316
  (void) DetachBlob(image->blob);
 
2317
  switch (mode)
 
2318
  {
 
2319
    default: type="r"; break;
 
2320
    case ReadBlobMode: type="r"; break;
 
2321
    case ReadBinaryBlobMode: type="rb"; break;
 
2322
    case WriteBlobMode: type="w"; break;
 
2323
    case WriteBinaryBlobMode: type="w+b"; break;
 
2324
    case AppendBlobMode: type="a"; break;
 
2325
    case AppendBinaryBlobMode: type="a+b"; break;
 
2326
  }
 
2327
  if (*type != 'r')
 
2328
    image->blob->synchronize=image_info->synchronize;
 
2329
  if (image_info->stream != (StreamHandler) NULL)
 
2330
    {
 
2331
      image->blob->stream=(StreamHandler) image_info->stream;
 
2332
      if (*type == 'w')
 
2333
        {
 
2334
          image->blob->type=FifoStream;
 
2335
          return(MagickTrue);
 
2336
        }
 
2337
    }
 
2338
  /*
 
2339
    Open image file.
 
2340
  */
 
2341
  *filename='\0';
 
2342
  (void) CopyMagickString(filename,image->filename,MaxTextExtent);
 
2343
  rights=ReadPolicyRights;
 
2344
  if (*type == 'w')
 
2345
    rights=WritePolicyRights;
 
2346
  if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
 
2347
    {
 
2348
      errno=EPERM;
 
2349
      (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
 
2350
        "NotAuthorized","`%s'",filename);
 
2351
      return(MagickFalse);
 
2352
    }
 
2353
  if ((LocaleCompare(filename,"-") == 0) ||
 
2354
      ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
 
2355
    {
 
2356
      image->blob->file=(*type == 'r') ? stdin : stdout;
 
2357
#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
 
2358
      if (strchr(type,'b') != (char *) NULL)
 
2359
        setmode(_fileno(image->blob->file),_O_BINARY);
 
2360
#endif
 
2361
      image->blob->type=StandardStream;
 
2362
      image->blob->exempt=MagickTrue;
 
2363
      return(MagickTrue);
 
2364
    }
 
2365
  if (LocaleNCompare(filename,"fd:",3) == 0)
 
2366
    {
 
2367
      char
 
2368
        mode[MaxTextExtent];
 
2369
 
 
2370
      *mode=(*type);
 
2371
      mode[1]='\0';
 
2372
      image->blob->file=fdopen(StringToLong(filename+3),mode);
 
2373
#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
 
2374
      if (strchr(type,'b') != (char *) NULL)
 
2375
        setmode(_fileno(image->blob->file),_O_BINARY);
 
2376
#endif
 
2377
      image->blob->type=StandardStream;
 
2378
      image->blob->exempt=MagickTrue;
 
2379
      return(MagickTrue);
 
2380
    }
 
2381
#if defined(MAGICKCORE_HAVE_POPEN)
 
2382
  if (*filename == '|')
 
2383
    {
 
2384
      char
 
2385
        mode[MaxTextExtent];
 
2386
 
 
2387
      /*
 
2388
        Pipe image to or from a system command.
 
2389
      */
 
2390
#if defined(SIGPIPE)
 
2391
      if (*type == 'w')
 
2392
        (void) signal(SIGPIPE,SIG_IGN);
 
2393
#endif
 
2394
      *mode=(*type);
 
2395
      mode[1]='\0';
 
2396
      image->blob->file=(FILE *) popen(filename+1,mode);
 
2397
      if (image->blob->file == (FILE *) NULL)
 
2398
        {
 
2399
          ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
 
2400
          return(MagickFalse);
 
2401
        }
 
2402
      image->blob->type=PipeStream;
 
2403
      image->blob->exempt=MagickTrue;
 
2404
      return(MagickTrue);
 
2405
    }
 
2406
#endif
 
2407
  status=GetPathAttributes(filename,&image->blob->properties);
 
2408
#if defined(S_ISFIFO)
 
2409
  if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
 
2410
    {
 
2411
      image->blob->file=(FILE *) OpenMagickStream(filename,type);
 
2412
      if (image->blob->file == (FILE *) NULL)
 
2413
        {
 
2414
          ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
 
2415
          return(MagickFalse);
 
2416
        }
 
2417
      image->blob->type=FileStream;
 
2418
      image->blob->exempt=MagickTrue;
 
2419
      return(MagickTrue);
 
2420
    }
 
2421
#endif
 
2422
  GetPathComponent(image->filename,ExtensionPath,extension);
 
2423
  if (*type == 'w')
 
2424
    {
 
2425
      (void) CopyMagickString(filename,image->filename,MaxTextExtent);
 
2426
      if ((image_info->adjoin == MagickFalse) ||
 
2427
          (strchr(filename,'%') != (char *) NULL))
 
2428
        {
 
2429
          /*
 
2430
            Form filename for multi-part images.
 
2431
          */
 
2432
          (void) InterpretImageFilename(image_info,image,image->filename,(int)
 
2433
            image->scene,filename);
 
2434
          if ((LocaleCompare(filename,image->filename) == 0) &&
 
2435
              ((GetPreviousImageInList(image) != (Image *) NULL) ||
 
2436
               (GetNextImageInList(image) != (Image *) NULL)))
 
2437
            {
 
2438
              char
 
2439
                path[MaxTextExtent];
 
2440
 
 
2441
              GetPathComponent(image->filename,RootPath,path);
 
2442
              if (*extension == '\0')
 
2443
                (void) FormatMagickString(filename,MaxTextExtent,"%s-%.20g",
 
2444
                  path,(double) image->scene);
 
2445
              else
 
2446
                (void) FormatMagickString(filename,MaxTextExtent,"%s-%.20g.%s",
 
2447
                  path,(double) image->scene,extension);
 
2448
            }
 
2449
          (void) CopyMagickString(image->filename,filename,MaxTextExtent);
 
2450
#if defined(macintosh)
 
2451
          SetApplicationType(filename,image_info->magick,'8BIM');
 
2452
#endif
 
2453
        }
 
2454
    }
 
2455
  if (image_info->file != (FILE *) NULL)
 
2456
    {
 
2457
      image->blob->file=image_info->file;
 
2458
      image->blob->type=FileStream;
 
2459
      image->blob->exempt=MagickTrue;
 
2460
    }
 
2461
  else
 
2462
    if (*type == 'r')
 
2463
      {
 
2464
        image->blob->file=(FILE *) OpenMagickStream(filename,type);
 
2465
        if (image->blob->file != (FILE *) NULL)
 
2466
          {
 
2467
            size_t
 
2468
              count;
 
2469
 
 
2470
            unsigned char
 
2471
              magick[3];
 
2472
 
 
2473
            image->blob->type=FileStream;
 
2474
#if defined(MAGICKCORE_HAVE_SETVBUF)
 
2475
            (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,16384);
 
2476
#endif
 
2477
            (void) ResetMagickMemory(magick,0,sizeof(magick));
 
2478
            count=fread(magick,1,sizeof(magick),image->blob->file);
 
2479
            (void) rewind(image->blob->file);
 
2480
            (void) LogMagickEvent(BlobEvent,GetMagickModule(),
 
2481
               "  read %.20g magic header bytes",(double) count);
 
2482
#if defined(MAGICKCORE_ZLIB_DELEGATE)
 
2483
            if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
 
2484
                ((int) magick[2] == 0x08))
 
2485
              {
 
2486
                (void) fclose(image->blob->file);
 
2487
                image->blob->file=(FILE *) gzopen(filename,type);
 
2488
                if (image->blob->file != (FILE *) NULL)
 
2489
                  image->blob->type=ZipStream;
 
2490
               }
 
2491
#endif
 
2492
#if defined(MAGICKCORE_BZLIB_DELEGATE)
 
2493
            if (strncmp((char *) magick,"BZh",3) == 0)
 
2494
              {
 
2495
                (void) fclose(image->blob->file);
 
2496
                image->blob->file=(FILE *) BZ2_bzopen(filename,type);
 
2497
                if (image->blob->file != (FILE *) NULL)
 
2498
                  image->blob->type=BZipStream;
 
2499
              }
 
2500
#endif
 
2501
            if (image->blob->type == FileStream)
 
2502
              {
 
2503
                const MagickInfo
 
2504
                  *magick_info;
 
2505
 
 
2506
                ExceptionInfo
 
2507
                  *sans_exception;
 
2508
 
 
2509
                struct stat
 
2510
                  *properties;
 
2511
 
 
2512
                sans_exception=AcquireExceptionInfo();
 
2513
                magick_info=GetMagickInfo(image_info->magick,sans_exception);
 
2514
                sans_exception=DestroyExceptionInfo(sans_exception);
 
2515
                properties=(&image->blob->properties);
 
2516
                if ((magick_info != (const MagickInfo *) NULL) &&
 
2517
                    (GetMagickBlobSupport(magick_info) != MagickFalse) &&
 
2518
                    (properties->st_size <= MagickMaxBufferExtent))
 
2519
                  {
 
2520
                    size_t
 
2521
                      length;
 
2522
 
 
2523
                    void
 
2524
                      *blob;
 
2525
 
 
2526
                    length=(size_t) properties->st_size;
 
2527
                    blob=MapBlob(fileno(image->blob->file),ReadMode,0,length);
 
2528
                    if (blob != (void *) NULL)
 
2529
                      {
 
2530
                        /*
 
2531
                          Format supports blobs-- use memory-mapped I/O.
 
2532
                        */
 
2533
                        if (image_info->file != (FILE *) NULL)
 
2534
                          image->blob->exempt=MagickFalse;
 
2535
                        else
 
2536
                          {
 
2537
                            (void) fclose(image->blob->file);
 
2538
                            image->blob->file=(FILE *) NULL;
 
2539
                          }
 
2540
                        AttachBlob(image->blob,blob,length);
 
2541
                        image->blob->mapped=MagickTrue;
 
2542
                      }
 
2543
                  }
 
2544
              }
 
2545
          }
 
2546
        }
 
2547
      else
 
2548
#if defined(MAGICKCORE_ZLIB_DELEGATE)
 
2549
        if ((LocaleCompare(extension,"Z") == 0) ||
 
2550
            (LocaleCompare(extension,"gz") == 0) ||
 
2551
            (LocaleCompare(extension,"wmz") == 0) ||
 
2552
            (LocaleCompare(extension,"svgz") == 0))
 
2553
          {
 
2554
            if (mode == WriteBinaryBlobMode)
 
2555
              type="wb";
 
2556
            image->blob->file=(FILE *) gzopen(filename,type);
 
2557
            if (image->blob->file != (FILE *) NULL)
 
2558
              image->blob->type=ZipStream;
 
2559
          }
 
2560
        else
 
2561
#endif
 
2562
#if defined(MAGICKCORE_BZLIB_DELEGATE)
 
2563
          if (LocaleCompare(extension,".bz2") == 0)
 
2564
            {
 
2565
              image->blob->file=(FILE *) BZ2_bzopen(filename,type);
 
2566
              if (image->blob->file != (FILE *) NULL)
 
2567
                image->blob->type=BZipStream;
 
2568
            }
 
2569
          else
 
2570
#endif
 
2571
            {
 
2572
              image->blob->file=(FILE *) OpenMagickStream(filename,type);
 
2573
              if (image->blob->file != (FILE *) NULL)
 
2574
                {
 
2575
                  image->blob->type=FileStream;
 
2576
#if defined(MAGICKCORE_HAVE_SETVBUF)
 
2577
                  (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,
 
2578
                    16384);
 
2579
#endif
 
2580
                }
 
2581
       }
 
2582
  image->blob->status=MagickFalse;
 
2583
  if (image->blob->type != UndefinedStream)
 
2584
    image->blob->size=GetBlobSize(image);
 
2585
  else
 
2586
    {
 
2587
      ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
 
2588
      return(MagickFalse);
 
2589
    }
 
2590
  return(MagickTrue);
 
2591
}
 
2592
 
 
2593
/*
 
2594
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2595
%                                                                             %
 
2596
%                                                                             %
 
2597
%                                                                             %
 
2598
+   P i n g B l o b                                                           %
 
2599
%                                                                             %
 
2600
%                                                                             %
 
2601
%                                                                             %
 
2602
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2603
%
 
2604
%  PingBlob() returns all the attributes of an image or image sequence except
 
2605
%  for the pixels.  It is much faster and consumes far less memory than
 
2606
%  BlobToImage().  On failure, a NULL image is returned and exception
 
2607
%  describes the reason for the failure.
 
2608
%
 
2609
%  The format of the PingBlob method is:
 
2610
%
 
2611
%      Image *PingBlob(const ImageInfo *image_info,const void *blob,
 
2612
%        const size_t length,ExceptionInfo *exception)
 
2613
%
 
2614
%  A description of each parameter follows:
 
2615
%
 
2616
%    o image_info: the image info.
 
2617
%
 
2618
%    o blob: the address of a character stream in one of the image formats
 
2619
%      understood by ImageMagick.
 
2620
%
 
2621
%    o length: This size_t integer reflects the length in bytes of the blob.
 
2622
%
 
2623
%    o exception: return any errors or warnings in this structure.
 
2624
%
 
2625
*/
 
2626
 
 
2627
#if defined(__cplusplus) || defined(c_plusplus)
 
2628
extern "C" {
 
2629
#endif
 
2630
 
 
2631
static size_t PingStream(const Image *magick_unused(image),
 
2632
  const void *magick_unused(pixels),const size_t columns)
 
2633
{
 
2634
  return(columns);
 
2635
}
 
2636
 
 
2637
#if defined(__cplusplus) || defined(c_plusplus)
 
2638
}
 
2639
#endif
 
2640
 
 
2641
MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
 
2642
  const size_t length,ExceptionInfo *exception)
 
2643
{
 
2644
  Image
 
2645
    *image;
 
2646
 
 
2647
  ImageInfo
 
2648
    *ping_info;
 
2649
 
 
2650
  assert(image_info != (ImageInfo *) NULL);
 
2651
  assert(image_info->signature == MagickSignature);
 
2652
  if (image_info->debug != MagickFalse)
 
2653
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
 
2654
      image_info->filename);
 
2655
  assert(exception != (ExceptionInfo *) NULL);
 
2656
  if ((blob == (const void *) NULL) || (length == 0))
 
2657
    {
 
2658
      (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
 
2659
        "UnrecognizedImageFormat","`%s'",image_info->magick);
 
2660
      return((Image *) NULL);
 
2661
    }
 
2662
  ping_info=CloneImageInfo(image_info);
 
2663
  ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
 
2664
  if (ping_info->blob == (const void *) NULL)
 
2665
    {
 
2666
      (void) ThrowMagickException(exception,GetMagickModule(),
 
2667
        ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
 
2668
      return((Image *) NULL);
 
2669
    }
 
2670
  (void) memcpy(ping_info->blob,blob,length);
 
2671
  ping_info->length=length;
 
2672
  ping_info->ping=MagickTrue;
 
2673
  image=ReadStream(ping_info,&PingStream,exception);
 
2674
  ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
 
2675
  ping_info=DestroyImageInfo(ping_info);
 
2676
  return(image);
 
2677
}
 
2678
 
 
2679
/*
 
2680
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2681
%                                                                             %
 
2682
%                                                                             %
 
2683
%                                                                             %
 
2684
+  R e a d B l o b                                                            %
 
2685
%                                                                             %
 
2686
%                                                                             %
 
2687
%                                                                             %
 
2688
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2689
%
 
2690
%  ReadBlob() reads data from the blob or image file and returns it.  It
 
2691
%  returns the number of bytes read.
 
2692
%
 
2693
%  The format of the ReadBlob method is:
 
2694
%
 
2695
%      ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
 
2696
%
 
2697
%  A description of each parameter follows:
 
2698
%
 
2699
%    o image: the image.
 
2700
%
 
2701
%    o length:  Specifies an integer representing the number of bytes to read
 
2702
%      from the file.
 
2703
%
 
2704
%    o data:  Specifies an area to place the information requested from the
 
2705
%      file.
 
2706
%
 
2707
*/
 
2708
MagickExport ssize_t ReadBlob(Image *image,const size_t length,
 
2709
  unsigned char *data)
 
2710
{
 
2711
  int
 
2712
    c;
 
2713
 
 
2714
  register unsigned char
 
2715
    *q;
 
2716
 
 
2717
  ssize_t
 
2718
    count;
 
2719
 
 
2720
  assert(image != (Image *) NULL);
 
2721
  assert(image->signature == MagickSignature);
 
2722
  assert(image->blob != (BlobInfo *) NULL);
 
2723
  assert(image->blob->type != UndefinedStream);
 
2724
  if (length == 0)
 
2725
    return(0);
 
2726
  assert(data != (void *) NULL);
 
2727
  count=0;
 
2728
  q=data;
 
2729
  switch (image->blob->type)
 
2730
  {
 
2731
    case UndefinedStream:
 
2732
      break;
 
2733
    case FileStream:
 
2734
    case StandardStream:
 
2735
    case PipeStream:
 
2736
    {
 
2737
      switch (length)
 
2738
      {
 
2739
        default:
 
2740
        {
 
2741
          count=(ssize_t) fread(q,1,length,image->blob->file);
 
2742
          break;
 
2743
        }
 
2744
        case 2:
 
2745
        {
 
2746
          c=getc(image->blob->file);
 
2747
          if (c == EOF)
 
2748
            break;
 
2749
          *q++=(unsigned char) c;
 
2750
          count++;
 
2751
        }
 
2752
        case 1:
 
2753
        {
 
2754
          c=getc(image->blob->file);
 
2755
          if (c == EOF)
 
2756
            break;
 
2757
          *q++=(unsigned char) c;
 
2758
          count++;
 
2759
        }
 
2760
        case 0:
 
2761
          break;
 
2762
      }
 
2763
      break;
 
2764
    }
 
2765
    case ZipStream:
 
2766
    {
 
2767
#if defined(MAGICKCORE_ZLIB_DELEGATE)
 
2768
      switch (length)
 
2769
      {
 
2770
        default:
 
2771
        {
 
2772
          count=(ssize_t) gzread(image->blob->file,q,(unsigned int) length);
 
2773
          break;
 
2774
        }
 
2775
        case 2:
 
2776
        {
 
2777
          c=gzgetc(image->blob->file);
 
2778
          if (c == EOF)
 
2779
            break;
 
2780
          *q++=(unsigned char) c;
 
2781
          count++;
 
2782
        }
 
2783
        case 1:
 
2784
        {
 
2785
          c=gzgetc(image->blob->file);
 
2786
          if (c == EOF)
 
2787
            break;
 
2788
          *q++=(unsigned char) c;
 
2789
          count++;
 
2790
        }
 
2791
        case 0:
 
2792
          break;
 
2793
      }
 
2794
#endif
 
2795
      break;
 
2796
    }
 
2797
    case BZipStream:
 
2798
    {
 
2799
#if defined(MAGICKCORE_BZLIB_DELEGATE)
 
2800
      count=(ssize_t) BZ2_bzread((BZFILE *) image->blob->file,q,(int) length);
 
2801
#endif
 
2802
      break;
 
2803
    }
 
2804
    case FifoStream:
 
2805
      break;
 
2806
    case BlobStream:
 
2807
    {
 
2808
      register const unsigned char
 
2809
        *p;
 
2810
 
 
2811
      if (image->blob->offset >= (MagickOffsetType) image->blob->length)
 
2812
        {
 
2813
          image->blob->eof=MagickTrue;
 
2814
          break;
 
2815
        }
 
2816
      p=image->blob->data+image->blob->offset;
 
2817
      count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
 
2818
      image->blob->offset+=count;
 
2819
      if (count != (ssize_t) length)
 
2820
        image->blob->eof=MagickTrue;
 
2821
      (void) memcpy(q,p,(size_t) count);
 
2822
      break;
 
2823
    }
 
2824
  }
 
2825
  return(count);
 
2826
}
 
2827
 
 
2828
/*
 
2829
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2830
%                                                                             %
 
2831
%                                                                             %
 
2832
%                                                                             %
 
2833
+  R e a d B l o b B y t e                                                    %
 
2834
%                                                                             %
 
2835
%                                                                             %
 
2836
%                                                                             %
 
2837
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2838
%
 
2839
%  ReadBlobByte() reads a single byte from the image file and returns it.
 
2840
%
 
2841
%  The format of the ReadBlobByte method is:
 
2842
%
 
2843
%      int ReadBlobByte(Image *image)
 
2844
%
 
2845
%  A description of each parameter follows.
 
2846
%
 
2847
%    o image: the image.
 
2848
%
 
2849
*/
 
2850
MagickExport int ReadBlobByte(Image *image)
 
2851
{
 
2852
  register const unsigned char
 
2853
    *p;
 
2854
 
 
2855
  ssize_t
 
2856
    count;
 
2857
 
 
2858
  unsigned char
 
2859
    buffer[1];
 
2860
 
 
2861
  assert(image != (Image *) NULL);
 
2862
  assert(image->signature == MagickSignature);
 
2863
  p=ReadBlobStream(image,1,buffer,&count);
 
2864
  if (count != 1)
 
2865
    return(EOF);
 
2866
  return((int) (*p));
 
2867
}
 
2868
 
 
2869
/*
 
2870
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2871
%                                                                             %
 
2872
%                                                                             %
 
2873
%                                                                             %
 
2874
+  R e a d B l o b D o u b l e                                                %
 
2875
%                                                                             %
 
2876
%                                                                             %
 
2877
%                                                                             %
 
2878
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2879
%
 
2880
%  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
 
2881
%  specified by the endian member of the image structure.
 
2882
%
 
2883
%  The format of the ReadBlobDouble method is:
 
2884
%
 
2885
%      double ReadBlobDouble(Image *image)
 
2886
%
 
2887
%  A description of each parameter follows.
 
2888
%
 
2889
%    o image: the image.
 
2890
%
 
2891
*/
 
2892
MagickExport double ReadBlobDouble(Image *image)
 
2893
{
 
2894
  union
 
2895
  {
 
2896
    MagickSizeType
 
2897
      unsigned_value;
 
2898
 
 
2899
    double
 
2900
      double_value;
 
2901
  } quantum;
 
2902
 
 
2903
  quantum.double_value=0.0;
 
2904
  quantum.unsigned_value=ReadBlobLongLong(image);
 
2905
  return(quantum.double_value);
 
2906
}
 
2907
 
 
2908
/*
 
2909
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2910
%                                                                             %
 
2911
%                                                                             %
 
2912
%                                                                             %
 
2913
+  R e a d B l o b F l o a t                                                  %
 
2914
%                                                                             %
 
2915
%                                                                             %
 
2916
%                                                                             %
 
2917
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2918
%
 
2919
%  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
 
2920
%  specified by the endian member of the image structure.
 
2921
%
 
2922
%  The format of the ReadBlobFloat method is:
 
2923
%
 
2924
%      float ReadBlobFloat(Image *image)
 
2925
%
 
2926
%  A description of each parameter follows.
 
2927
%
 
2928
%    o image: the image.
 
2929
%
 
2930
*/
 
2931
MagickExport float ReadBlobFloat(Image *image)
 
2932
{
 
2933
  union
 
2934
  {
 
2935
    unsigned int
 
2936
      unsigned_value;
 
2937
 
 
2938
    float
 
2939
      float_value;
 
2940
  } quantum;
 
2941
 
 
2942
  quantum.float_value=0.0;
 
2943
  quantum.unsigned_value=ReadBlobLong(image);
 
2944
  return(quantum.float_value);
 
2945
}
 
2946
 
 
2947
/*
 
2948
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2949
%                                                                             %
 
2950
%                                                                             %
 
2951
%                                                                             %
 
2952
+  R e a d B l o b L o n g                                                    %
 
2953
%                                                                             %
 
2954
%                                                                             %
 
2955
%                                                                             %
 
2956
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
2957
%
 
2958
%  ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
 
2959
%  specified by the endian member of the image structure.
 
2960
%
 
2961
%  The format of the ReadBlobLong method is:
 
2962
%
 
2963
%      unsigned int ReadBlobLong(Image *image)
 
2964
%
 
2965
%  A description of each parameter follows.
 
2966
%
 
2967
%    o image: the image.
 
2968
%
 
2969
*/
 
2970
MagickExport unsigned int ReadBlobLong(Image *image)
 
2971
{
 
2972
  register const unsigned char
 
2973
    *p;
 
2974
 
 
2975
  ssize_t
 
2976
    count;
 
2977
 
 
2978
  unsigned char
 
2979
    buffer[4];
 
2980
 
 
2981
  unsigned int
 
2982
    value;
 
2983
 
 
2984
  assert(image != (Image *) NULL);
 
2985
  assert(image->signature == MagickSignature);
 
2986
  *buffer='\0';
 
2987
  p=ReadBlobStream(image,4,buffer,&count);
 
2988
  if (count != 4)
 
2989
    return(0UL);
 
2990
  if (image->endian == LSBEndian)
 
2991
    {
 
2992
      value=(unsigned int) (*p++);
 
2993
      value|=((unsigned int) (*p++)) << 8;
 
2994
      value|=((unsigned int) (*p++)) << 16;
 
2995
      value|=((unsigned int) (*p++)) << 24;
 
2996
      return(value);
 
2997
    }
 
2998
  value=((unsigned int) (*p++)) << 24;
 
2999
  value|=((unsigned int) (*p++)) << 16;
 
3000
  value|=((unsigned int) (*p++)) << 8;
 
3001
  value|=((unsigned int) (*p++));
 
3002
  return(value);
 
3003
}
 
3004
 
 
3005
/*
 
3006
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3007
%                                                                             %
 
3008
%                                                                             %
 
3009
%                                                                             %
 
3010
+  R e a d B l o b L o n g L o n g                                            %
 
3011
%                                                                             %
 
3012
%                                                                             %
 
3013
%                                                                             %
 
3014
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3015
%
 
3016
%  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
 
3017
%  byte-order specified by the endian member of the image structure.
 
3018
%
 
3019
%  The format of the ReadBlobLongLong method is:
 
3020
%
 
3021
%      MagickSizeType ReadBlobLongLong(Image *image)
 
3022
%
 
3023
%  A description of each parameter follows.
 
3024
%
 
3025
%    o image: the image.
 
3026
%
 
3027
*/
 
3028
MagickExport MagickSizeType ReadBlobLongLong(Image *image)
 
3029
{
 
3030
  MagickSizeType
 
3031
    value;
 
3032
 
 
3033
  register const unsigned char
 
3034
    *p;
 
3035
 
 
3036
  ssize_t
 
3037
    count;
 
3038
 
 
3039
  unsigned char
 
3040
    buffer[8];
 
3041
 
 
3042
  assert(image != (Image *) NULL);
 
3043
  assert(image->signature == MagickSignature);
 
3044
  *buffer='\0';
 
3045
  p=ReadBlobStream(image,8,buffer,&count);
 
3046
  if (count != 8)
 
3047
    return(MagickULLConstant(0));
 
3048
  if (image->endian == LSBEndian)
 
3049
    {
 
3050
      value=(MagickSizeType) (*p++);
 
3051
      value|=((MagickSizeType) (*p++)) << 8;
 
3052
      value|=((MagickSizeType) (*p++)) << 16;
 
3053
      value|=((MagickSizeType) (*p++)) << 24;
 
3054
      value|=((MagickSizeType) (*p++)) << 32;
 
3055
      value|=((MagickSizeType) (*p++)) << 40;
 
3056
      value|=((MagickSizeType) (*p++)) << 48;
 
3057
      value|=((MagickSizeType) (*p++)) << 56;
 
3058
      return(value & MagickULLConstant(0xffffffffffffffff));
 
3059
    }
 
3060
  value=((MagickSizeType) (*p++)) << 56;
 
3061
  value|=((MagickSizeType) (*p++)) << 48;
 
3062
  value|=((MagickSizeType) (*p++)) << 40;
 
3063
  value|=((MagickSizeType) (*p++)) << 32;
 
3064
  value|=((MagickSizeType) (*p++)) << 24;
 
3065
  value|=((MagickSizeType) (*p++)) << 16;
 
3066
  value|=((MagickSizeType) (*p++)) << 8;
 
3067
  value|=((MagickSizeType) (*p++));
 
3068
  return(value & MagickULLConstant(0xffffffffffffffff));
 
3069
}
 
3070
 
 
3071
/*
 
3072
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3073
%                                                                             %
 
3074
%                                                                             %
 
3075
%                                                                             %
 
3076
+  R e a d B l o b S h o r t                                                  %
 
3077
%                                                                             %
 
3078
%                                                                             %
 
3079
%                                                                             %
 
3080
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3081
%
 
3082
%  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
 
3083
%  specified by the endian member of the image structure.
 
3084
%
 
3085
%  The format of the ReadBlobShort method is:
 
3086
%
 
3087
%      unsigned short ReadBlobShort(Image *image)
 
3088
%
 
3089
%  A description of each parameter follows.
 
3090
%
 
3091
%    o image: the image.
 
3092
%
 
3093
*/
 
3094
MagickExport unsigned short ReadBlobShort(Image *image)
 
3095
{
 
3096
  register const unsigned char
 
3097
    *p;
 
3098
 
 
3099
  register unsigned int
 
3100
    value;
 
3101
 
 
3102
  ssize_t
 
3103
    count;
 
3104
 
 
3105
  unsigned char
 
3106
    buffer[2];
 
3107
 
 
3108
  assert(image != (Image *) NULL);
 
3109
  assert(image->signature == MagickSignature);
 
3110
  *buffer='\0';
 
3111
  p=ReadBlobStream(image,2,buffer,&count);
 
3112
  if (count != 2)
 
3113
    return((unsigned short) 0U);
 
3114
  if (image->endian == LSBEndian)
 
3115
    {
 
3116
      value=(unsigned int) (*p++);
 
3117
      value|=((unsigned int) (*p++)) << 8;
 
3118
      return((unsigned short) (value & 0xffff));
 
3119
    }
 
3120
  value=(unsigned int) ((*p++) << 8);
 
3121
  value|=(unsigned int) (*p++);
 
3122
  return((unsigned short) (value & 0xffff));
 
3123
}
 
3124
 
 
3125
/*
 
3126
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3127
%                                                                             %
 
3128
%                                                                             %
 
3129
%                                                                             %
 
3130
+  R e a d B l o b L S B L o n g                                              %
 
3131
%                                                                             %
 
3132
%                                                                             %
 
3133
%                                                                             %
 
3134
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3135
%
 
3136
%  ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
 
3137
%  least-significant byte first order.
 
3138
%
 
3139
%  The format of the ReadBlobLSBLong method is:
 
3140
%
 
3141
%      unsigned int ReadBlobLSBLong(Image *image)
 
3142
%
 
3143
%  A description of each parameter follows.
 
3144
%
 
3145
%    o image: the image.
 
3146
%
 
3147
*/
 
3148
MagickExport unsigned int ReadBlobLSBLong(Image *image)
 
3149
{
 
3150
  register const unsigned char
 
3151
    *p;
 
3152
 
 
3153
  register unsigned int
 
3154
    value;
 
3155
 
 
3156
  ssize_t
 
3157
    count;
 
3158
 
 
3159
  unsigned char
 
3160
    buffer[4];
 
3161
 
 
3162
  assert(image != (Image *) NULL);
 
3163
  assert(image->signature == MagickSignature);
 
3164
  *buffer='\0';
 
3165
  p=ReadBlobStream(image,4,buffer,&count);
 
3166
  if (count != 4)
 
3167
    return(0U);
 
3168
  value=(unsigned int) (*p++);
 
3169
  value|=((unsigned int) (*p++)) << 8;
 
3170
  value|=((unsigned int) (*p++)) << 16;
 
3171
  value|=((unsigned int) (*p++)) << 24;
 
3172
  return(value);
 
3173
}
 
3174
 
 
3175
/*
 
3176
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3177
%                                                                             %
 
3178
%                                                                             %
 
3179
%                                                                             %
 
3180
+  R e a d B l o b L S B S h o r t                                            %
 
3181
%                                                                             %
 
3182
%                                                                             %
 
3183
%                                                                             %
 
3184
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3185
%
 
3186
%  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
 
3187
%  least-significant byte first order.
 
3188
%
 
3189
%  The format of the ReadBlobLSBShort method is:
 
3190
%
 
3191
%      unsigned short ReadBlobLSBShort(Image *image)
 
3192
%
 
3193
%  A description of each parameter follows.
 
3194
%
 
3195
%    o image: the image.
 
3196
%
 
3197
*/
 
3198
MagickExport unsigned short ReadBlobLSBShort(Image *image)
 
3199
{
 
3200
  register const unsigned char
 
3201
    *p;
 
3202
 
 
3203
  register unsigned int
 
3204
    value;
 
3205
 
 
3206
  ssize_t
 
3207
    count;
 
3208
 
 
3209
  unsigned char
 
3210
    buffer[2];
 
3211
 
 
3212
  assert(image != (Image *) NULL);
 
3213
  assert(image->signature == MagickSignature);
 
3214
  *buffer='\0';
 
3215
  p=ReadBlobStream(image,2,buffer,&count);
 
3216
  if (count != 2)
 
3217
    return((unsigned short) 0U);
 
3218
  value=(unsigned int) (*p++);
 
3219
  value|=((unsigned int) ((*p++)) << 8);
 
3220
  return((unsigned short) (value & 0xffff));
 
3221
}
 
3222
 
 
3223
/*
 
3224
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3225
%                                                                             %
 
3226
%                                                                             %
 
3227
%                                                                             %
 
3228
+  R e a d B l o b M S B L o n g                                              %
 
3229
%                                                                             %
 
3230
%                                                                             %
 
3231
%                                                                             %
 
3232
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3233
%
 
3234
%  ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
 
3235
%  most-significant byte first order.
 
3236
%
 
3237
%  The format of the ReadBlobMSBLong method is:
 
3238
%
 
3239
%      unsigned int ReadBlobMSBLong(Image *image)
 
3240
%
 
3241
%  A description of each parameter follows.
 
3242
%
 
3243
%    o image: the image.
 
3244
%
 
3245
*/
 
3246
MagickExport unsigned int ReadBlobMSBLong(Image *image)
 
3247
{
 
3248
  register const unsigned char
 
3249
    *p;
 
3250
 
 
3251
  register unsigned int
 
3252
    value;
 
3253
 
 
3254
  ssize_t
 
3255
    count;
 
3256
 
 
3257
  unsigned char
 
3258
    buffer[4];
 
3259
 
 
3260
  assert(image != (Image *) NULL);
 
3261
  assert(image->signature == MagickSignature);
 
3262
  *buffer='\0';
 
3263
  p=ReadBlobStream(image,4,buffer,&count);
 
3264
  if (count != 4)
 
3265
    return(0UL);
 
3266
  value=((unsigned int) (*p++) << 24);
 
3267
  value|=((unsigned int) (*p++) << 16);
 
3268
  value|=((unsigned int) (*p++) << 8);
 
3269
  value|=(unsigned int) (*p++);
 
3270
  return(value);
 
3271
}
 
3272
 
 
3273
/*
 
3274
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3275
%                                                                             %
 
3276
%                                                                             %
 
3277
%                                                                             %
 
3278
+  R e a d B l o b M S B L o n g L o n g                                      %
 
3279
%                                                                             %
 
3280
%                                                                             %
 
3281
%                                                                             %
 
3282
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3283
%
 
3284
%  ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
 
3285
%  most-significant byte first order.
 
3286
%
 
3287
%  The format of the ReadBlobMSBLongLong method is:
 
3288
%
 
3289
%      unsigned int ReadBlobMSBLongLong(Image *image)
 
3290
%
 
3291
%  A description of each parameter follows.
 
3292
%
 
3293
%    o image: the image.
 
3294
%
 
3295
*/
 
3296
MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
 
3297
{
 
3298
  register const unsigned char
 
3299
    *p;
 
3300
 
 
3301
  register MagickSizeType
 
3302
    value;
 
3303
 
 
3304
  ssize_t
 
3305
    count;
 
3306
 
 
3307
  unsigned char
 
3308
    buffer[8];
 
3309
 
 
3310
  assert(image != (Image *) NULL);
 
3311
  assert(image->signature == MagickSignature);
 
3312
  *buffer='\0';
 
3313
  p=ReadBlobStream(image,8,buffer,&count);
 
3314
  if (count != 8)
 
3315
    return(MagickULLConstant(0));
 
3316
  value=((MagickSizeType) (*p++)) << 56;
 
3317
  value|=((MagickSizeType) (*p++)) << 48;
 
3318
  value|=((MagickSizeType) (*p++)) << 40;
 
3319
  value|=((MagickSizeType) (*p++)) << 32;
 
3320
  value|=((MagickSizeType) (*p++)) << 24;
 
3321
  value|=((MagickSizeType) (*p++)) << 16;
 
3322
  value|=((MagickSizeType) (*p++)) << 8;
 
3323
  value|=((MagickSizeType) (*p++));
 
3324
  return(value & MagickULLConstant(0xffffffffffffffff));
 
3325
}
 
3326
 
 
3327
/*
 
3328
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3329
%                                                                             %
 
3330
%                                                                             %
 
3331
%                                                                             %
 
3332
+  R e a d B l o b M S B S h o r t                                            %
 
3333
%                                                                             %
 
3334
%                                                                             %
 
3335
%                                                                             %
 
3336
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3337
%
 
3338
%  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
 
3339
%  most-significant byte first order.
 
3340
%
 
3341
%  The format of the ReadBlobMSBShort method is:
 
3342
%
 
3343
%      unsigned short ReadBlobMSBShort(Image *image)
 
3344
%
 
3345
%  A description of each parameter follows.
 
3346
%
 
3347
%    o image: the image.
 
3348
%
 
3349
*/
 
3350
MagickExport unsigned short ReadBlobMSBShort(Image *image)
 
3351
{
 
3352
  register const unsigned char
 
3353
    *p;
 
3354
 
 
3355
  register unsigned int
 
3356
    value;
 
3357
 
 
3358
  ssize_t
 
3359
    count;
 
3360
 
 
3361
  unsigned char
 
3362
    buffer[2];
 
3363
 
 
3364
  assert(image != (Image *) NULL);
 
3365
  assert(image->signature == MagickSignature);
 
3366
  *buffer='\0';
 
3367
  p=ReadBlobStream(image,2,buffer,&count);
 
3368
  if (count != 2)
 
3369
    return((unsigned short) 0U);
 
3370
  value=(unsigned int) ((*p++) << 8);
 
3371
  value|=(unsigned int) (*p++);
 
3372
  return((unsigned short) (value & 0xffff));
 
3373
}
 
3374
 
 
3375
/*
 
3376
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3377
%                                                                             %
 
3378
%                                                                             %
 
3379
%                                                                             %
 
3380
+   R e a d B l o b S t r i n g                                               %
 
3381
%                                                                             %
 
3382
%                                                                             %
 
3383
%                                                                             %
 
3384
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3385
%
 
3386
%  ReadBlobString() reads characters from a blob or file until a newline
 
3387
%  character is read or an end-of-file condition is encountered.
 
3388
%
 
3389
%  The format of the ReadBlobString method is:
 
3390
%
 
3391
%      char *ReadBlobString(Image *image,char *string)
 
3392
%
 
3393
%  A description of each parameter follows:
 
3394
%
 
3395
%    o image: the image.
 
3396
%
 
3397
%    o string: the address of a character buffer.
 
3398
%
 
3399
*/
 
3400
MagickExport char *ReadBlobString(Image *image,char *string)
 
3401
{
 
3402
  register const unsigned char
 
3403
    *p;
 
3404
 
 
3405
  register ssize_t
 
3406
    i;
 
3407
 
 
3408
  ssize_t
 
3409
    count;
 
3410
 
 
3411
  unsigned char
 
3412
    buffer[1];
 
3413
 
 
3414
  assert(image != (Image *) NULL);
 
3415
  assert(image->signature == MagickSignature);
 
3416
  for (i=0; i < (MaxTextExtent-1L); i++)
 
3417
  {
 
3418
    p=ReadBlobStream(image,1,buffer,&count);
 
3419
    if (count != 1)
 
3420
      {
 
3421
        if (i == 0)
 
3422
          return((char *) NULL);
 
3423
        break;
 
3424
      }
 
3425
    string[i]=(char) (*p);
 
3426
    if ((string[i] == '\r') || (string[i] == '\n'))
 
3427
      break;
 
3428
  }
 
3429
  if (string[i] == '\r')
 
3430
    (void) ReadBlobStream(image,1,buffer,&count);
 
3431
  string[i]='\0';
 
3432
  return(string);
 
3433
}
 
3434
 
 
3435
/*
 
3436
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3437
%                                                                             %
 
3438
%                                                                             %
 
3439
%                                                                             %
 
3440
+   R e f e r e n c e B l o b                                                 %
 
3441
%                                                                             %
 
3442
%                                                                             %
 
3443
%                                                                             %
 
3444
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3445
%
 
3446
%  ReferenceBlob() increments the reference count associated with the pixel
 
3447
%  blob returning a pointer to the blob.
 
3448
%
 
3449
%  The format of the ReferenceBlob method is:
 
3450
%
 
3451
%      BlobInfo ReferenceBlob(BlobInfo *blob_info)
 
3452
%
 
3453
%  A description of each parameter follows:
 
3454
%
 
3455
%    o blob_info: the blob_info.
 
3456
%
 
3457
*/
 
3458
MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
 
3459
{
 
3460
  assert(blob != (BlobInfo *) NULL);
 
3461
  assert(blob->signature == MagickSignature);
 
3462
  if (blob->debug != MagickFalse)
 
3463
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
 
3464
  LockSemaphoreInfo(blob->semaphore);
 
3465
  blob->reference_count++;
 
3466
  UnlockSemaphoreInfo(blob->semaphore);
 
3467
  return(blob);
 
3468
}
 
3469
 
 
3470
/*
 
3471
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3472
%                                                                             %
 
3473
%                                                                             %
 
3474
%                                                                             %
 
3475
+  S e e k B l o b                                                            %
 
3476
%                                                                             %
 
3477
%                                                                             %
 
3478
%                                                                             %
 
3479
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3480
%
 
3481
%  SeekBlob() sets the offset in bytes from the beginning of a blob or file
 
3482
%  and returns the resulting offset.
 
3483
%
 
3484
%  The format of the SeekBlob method is:
 
3485
%
 
3486
%      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
 
3487
%        const int whence)
 
3488
%
 
3489
%  A description of each parameter follows:
 
3490
%
 
3491
%    o image: the image.
 
3492
%
 
3493
%    o offset:  Specifies an integer representing the offset in bytes.
 
3494
%
 
3495
%    o whence:  Specifies an integer representing how the offset is
 
3496
%      treated relative to the beginning of the blob as follows:
 
3497
%
 
3498
%        SEEK_SET  Set position equal to offset bytes.
 
3499
%        SEEK_CUR  Set position to current location plus offset.
 
3500
%        SEEK_END  Set position to EOF plus offset.
 
3501
%
 
3502
*/
 
3503
MagickExport MagickOffsetType SeekBlob(Image *image,
 
3504
  const MagickOffsetType offset,const int whence)
 
3505
{
 
3506
  assert(image != (Image *) NULL);
 
3507
  assert(image->signature == MagickSignature);
 
3508
  if (image->debug != MagickFalse)
 
3509
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
3510
  assert(image->blob != (BlobInfo *) NULL);
 
3511
  assert(image->blob->type != UndefinedStream);
 
3512
  switch (image->blob->type)
 
3513
  {
 
3514
    case UndefinedStream:
 
3515
      break;
 
3516
    case FileStream:
 
3517
    {
 
3518
      if (fseek(image->blob->file,offset,whence) < 0)
 
3519
        return(-1);
 
3520
      image->blob->offset=TellBlob(image);
 
3521
      break;
 
3522
    }
 
3523
    case StandardStream:
 
3524
    case PipeStream:
 
3525
    case ZipStream:
 
3526
    {
 
3527
#if defined(MAGICKCORE_ZLIB_DELEGATE)
 
3528
      if (gzseek(image->blob->file,(off_t) offset,whence) < 0)
 
3529
        return(-1);
 
3530
#endif
 
3531
      image->blob->offset=TellBlob(image);
 
3532
      break;
 
3533
    }
 
3534
    case BZipStream:
 
3535
      return(-1);
 
3536
    case FifoStream:
 
3537
      return(-1);
 
3538
    case BlobStream:
 
3539
    {
 
3540
      switch (whence)
 
3541
      {
 
3542
        case SEEK_SET:
 
3543
        default:
 
3544
        {
 
3545
          if (offset < 0)
 
3546
            return(-1);
 
3547
          image->blob->offset=offset;
 
3548
          break;
 
3549
        }
 
3550
        case SEEK_CUR:
 
3551
        {
 
3552
          if ((image->blob->offset+offset) < 0)
 
3553
            return(-1);
 
3554
          image->blob->offset+=offset;
 
3555
          break;
 
3556
        }
 
3557
        case SEEK_END:
 
3558
        {
 
3559
          if (((MagickOffsetType) image->blob->length+offset) < 0)
 
3560
            return(-1);
 
3561
          image->blob->offset=image->blob->length+offset;
 
3562
          break;
 
3563
        }
 
3564
      }
 
3565
      if (image->blob->offset <= (MagickOffsetType)
 
3566
          ((off_t) image->blob->length))
 
3567
        image->blob->eof=MagickFalse;
 
3568
      else
 
3569
        if (image->blob->mapped != MagickFalse)
 
3570
          return(-1);
 
3571
        else
 
3572
          {
 
3573
            image->blob->extent=(size_t) (image->blob->offset+
 
3574
              image->blob->quantum);
 
3575
            image->blob->data=(unsigned char *) ResizeQuantumMemory(
 
3576
              image->blob->data,image->blob->extent+1,
 
3577
              sizeof(*image->blob->data));
 
3578
            (void) SyncBlob(image);
 
3579
            if (image->blob->data == (unsigned char *) NULL)
 
3580
              {
 
3581
                (void) DetachBlob(image->blob);
 
3582
                return(-1);
 
3583
              }
 
3584
          }
 
3585
      break;
 
3586
    }
 
3587
  }
 
3588
  return(image->blob->offset);
 
3589
}
 
3590
 
 
3591
/*
 
3592
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3593
%                                                                             %
 
3594
%                                                                             %
 
3595
%                                                                             %
 
3596
+   S e t B l o b E x e m p t                                                 %
 
3597
%                                                                             %
 
3598
%                                                                             %
 
3599
%                                                                             %
 
3600
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3601
%
 
3602
%  SetBlobExempt() sets the blob exempt status.
 
3603
%
 
3604
%  The format of the SetBlobExempt method is:
 
3605
%
 
3606
%      MagickBooleanType SetBlobExempt(const Image *image,
 
3607
%        const MagickBooleanType exempt)
 
3608
%
 
3609
%  A description of each parameter follows:
 
3610
%
 
3611
%    o image: the image.
 
3612
%
 
3613
%    o exempt: Set to true if this blob is exempt from being closed.
 
3614
%
 
3615
*/
 
3616
MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
 
3617
{
 
3618
  assert(image != (const Image *) NULL);
 
3619
  assert(image->signature == MagickSignature);
 
3620
  if (image->debug != MagickFalse)
 
3621
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
3622
  image->blob->exempt=exempt;
 
3623
}
 
3624
 
 
3625
/*
 
3626
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3627
%                                                                             %
 
3628
%                                                                             %
 
3629
%                                                                             %
 
3630
+  S e t B l o b E x t e n t                                                  %
 
3631
%                                                                             %
 
3632
%                                                                             %
 
3633
%                                                                             %
 
3634
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3635
%
 
3636
%  SetBlobExtent() ensures enough space is allocated for the blob.  If the
 
3637
%  method is successful, subsequent writes to bytes in the specified range are
 
3638
%  guaranteed not to fail.
 
3639
%
 
3640
%  The format of the SetBlobExtent method is:
 
3641
%
 
3642
%      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
 
3643
%
 
3644
%  A description of each parameter follows:
 
3645
%
 
3646
%    o image: the image.
 
3647
%
 
3648
%    o extent:  the blob maximum extent.
 
3649
%
 
3650
*/
 
3651
MagickExport MagickBooleanType SetBlobExtent(Image *image,
 
3652
  const MagickSizeType extent)
 
3653
{
 
3654
  assert(image != (Image *) NULL);
 
3655
  assert(image->signature == MagickSignature);
 
3656
  if (image->debug != MagickFalse)
 
3657
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
3658
  assert(image->blob != (BlobInfo *) NULL);
 
3659
  assert(image->blob->type != UndefinedStream);
 
3660
  switch (image->blob->type)
 
3661
  {
 
3662
    case UndefinedStream:
 
3663
      break;
 
3664
    case FileStream:
 
3665
    {
 
3666
      if (extent != (MagickSizeType) ((off_t) extent))
 
3667
        return(MagickFalse);
 
3668
#if !defined(MAGICKCORE_POSIX_FALLOCATE)
 
3669
        return(MagickFalse);
 
3670
#else
 
3671
      {
 
3672
        int
 
3673
          status;
 
3674
 
 
3675
        MagickOffsetType
 
3676
          offset;
 
3677
 
 
3678
        offset=TellBlob(image);
 
3679
        status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
 
3680
          (off_t) (extent-offset));
 
3681
        if (status != 0)
 
3682
          return(MagickFalse);
 
3683
      }
 
3684
#endif
 
3685
      break;
 
3686
    }
 
3687
    case StandardStream:
 
3688
    case PipeStream:
 
3689
    case ZipStream:
 
3690
      return(MagickFalse);
 
3691
    case BZipStream:
 
3692
      return(MagickFalse);
 
3693
    case FifoStream:
 
3694
      return(MagickFalse);
 
3695
    case BlobStream:
 
3696
    {
 
3697
      if (image->blob->mapped != MagickFalse)
 
3698
        {
 
3699
          if (image->blob->file == (FILE *) NULL)
 
3700
            return(MagickFalse);
 
3701
          (void) UnmapBlob(image->blob->data,image->blob->length);
 
3702
#if !defined(MAGICKCORE_POSIX_FALLOCATE)
 
3703
          return(MagickFalse);
 
3704
#else
 
3705
          {
 
3706
            int
 
3707
              status;
 
3708
 
 
3709
            MagickOffsetType
 
3710
              offset;
 
3711
 
 
3712
            offset=TellBlob(image);
 
3713
            status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
 
3714
              (off_t) (extent-offset));
 
3715
            if (status != 0)
 
3716
              return(MagickFalse);
 
3717
          }
 
3718
          image->blob->data=(unsigned char*) MapBlob(fileno(image->blob->file),
 
3719
            WriteMode,0,(size_t) extent);
 
3720
          image->blob->extent=(size_t) extent;
 
3721
          image->blob->length=(size_t) extent;
 
3722
          (void) SyncBlob(image);
 
3723
          break;
 
3724
#endif
 
3725
        }
 
3726
      if (extent != (MagickSizeType) ((size_t) extent))
 
3727
        return(MagickFalse);
 
3728
      image->blob->extent=(size_t) extent;
 
3729
      image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
 
3730
        image->blob->extent+1,sizeof(*image->blob->data));
 
3731
      (void) SyncBlob(image);
 
3732
      if (image->blob->data == (unsigned char *) NULL)
 
3733
        {
 
3734
          (void) DetachBlob(image->blob);
 
3735
          return(MagickFalse);
 
3736
        }
 
3737
      break;
 
3738
    }
 
3739
  }
 
3740
  return(MagickTrue);
 
3741
}
 
3742
 
 
3743
/*
 
3744
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3745
%                                                                             %
 
3746
%                                                                             %
 
3747
%                                                                             %
 
3748
+  S y n c B l o b                                                            %
 
3749
%                                                                             %
 
3750
%                                                                             %
 
3751
%                                                                             %
 
3752
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3753
%
 
3754
%  SyncBlob() flushes the datastream if it is a file or synchronizes the data
 
3755
%  attributes if it is an blob.
 
3756
%
 
3757
%  The format of the SyncBlob method is:
 
3758
%
 
3759
%      int SyncBlob(Image *image)
 
3760
%
 
3761
%  A description of each parameter follows:
 
3762
%
 
3763
%    o image: the image.
 
3764
%
 
3765
*/
 
3766
static int SyncBlob(Image *image)
 
3767
{
 
3768
  int
 
3769
    status;
 
3770
 
 
3771
  assert(image != (Image *) NULL);
 
3772
  assert(image->signature == MagickSignature);
 
3773
  if (image->debug != MagickFalse)
 
3774
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
3775
  assert(image->blob != (BlobInfo *) NULL);
 
3776
  assert(image->blob->type != UndefinedStream);
 
3777
  status=0;
 
3778
  switch (image->blob->type)
 
3779
  {
 
3780
    case UndefinedStream:
 
3781
      break;
 
3782
    case FileStream:
 
3783
    case StandardStream:
 
3784
    case PipeStream:
 
3785
    {
 
3786
      status=fflush(image->blob->file);
 
3787
      break;
 
3788
    }
 
3789
    case ZipStream:
 
3790
    {
 
3791
#if defined(MAGICKCORE_ZLIB_DELEGATE)
 
3792
      status=gzflush(image->blob->file,Z_SYNC_FLUSH);
 
3793
#endif
 
3794
      break;
 
3795
    }
 
3796
    case BZipStream:
 
3797
    {
 
3798
#if defined(MAGICKCORE_BZLIB_DELEGATE)
 
3799
      status=BZ2_bzflush((BZFILE *) image->blob->file);
 
3800
#endif
 
3801
      break;
 
3802
    }
 
3803
    case FifoStream:
 
3804
      break;
 
3805
    case BlobStream:
 
3806
    {
 
3807
#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
 
3808
      if (image->blob->mapped != MagickFalse)
 
3809
        status=msync(image->blob->data,image->blob->length,MS_SYNC);
 
3810
#endif
 
3811
      break;
 
3812
    }
 
3813
  }
 
3814
  return(status);
 
3815
}
 
3816
 
 
3817
/*
 
3818
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3819
%                                                                             %
 
3820
%                                                                             %
 
3821
%                                                                             %
 
3822
+  T e l l B l o b                                                            %
 
3823
%                                                                             %
 
3824
%                                                                             %
 
3825
%                                                                             %
 
3826
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3827
%
 
3828
%  TellBlob() obtains the current value of the blob or file position.
 
3829
%
 
3830
%  The format of the TellBlob method is:
 
3831
%
 
3832
%      MagickOffsetType TellBlob(const Image *image)
 
3833
%
 
3834
%  A description of each parameter follows:
 
3835
%
 
3836
%    o image: the image.
 
3837
%
 
3838
*/
 
3839
MagickExport MagickOffsetType TellBlob(const Image *image)
 
3840
{
 
3841
  MagickOffsetType
 
3842
    offset;
 
3843
 
 
3844
  assert(image != (Image *) NULL);
 
3845
  assert(image->signature == MagickSignature);
 
3846
  if (image->debug != MagickFalse)
 
3847
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
 
3848
  assert(image->blob != (BlobInfo *) NULL);
 
3849
  assert(image->blob->type != UndefinedStream);
 
3850
  offset=(-1);
 
3851
  switch (image->blob->type)
 
3852
  {
 
3853
    case UndefinedStream:
 
3854
      break;
 
3855
    case FileStream:
 
3856
    {
 
3857
      offset=ftell(image->blob->file);
 
3858
      break;
 
3859
    }
 
3860
    case StandardStream:
 
3861
    case PipeStream:
 
3862
      break;
 
3863
    case ZipStream:
 
3864
    {
 
3865
#if defined(MAGICKCORE_ZLIB_DELEGATE)
 
3866
      offset=(MagickOffsetType) gztell(image->blob->file);
 
3867
#endif
 
3868
      break;
 
3869
    }
 
3870
    case BZipStream:
 
3871
      break;
 
3872
    case FifoStream:
 
3873
      break;
 
3874
    case BlobStream:
 
3875
    {
 
3876
      offset=image->blob->offset;
 
3877
      break;
 
3878
    }
 
3879
  }
 
3880
  return(offset);
 
3881
}
 
3882
 
 
3883
/*
 
3884
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3885
%                                                                             %
 
3886
%                                                                             %
 
3887
%                                                                             %
 
3888
+  U n m a p B l o b                                                          %
 
3889
%                                                                             %
 
3890
%                                                                             %
 
3891
%                                                                             %
 
3892
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3893
%
 
3894
%  UnmapBlob() deallocates the binary large object previously allocated with
 
3895
%  the MapBlob method.
 
3896
%
 
3897
%  The format of the UnmapBlob method is:
 
3898
%
 
3899
%       MagickBooleanType UnmapBlob(void *map,const size_t length)
 
3900
%
 
3901
%  A description of each parameter follows:
 
3902
%
 
3903
%    o map: the address  of the binary large object.
 
3904
%
 
3905
%    o length: the length of the binary large object.
 
3906
%
 
3907
*/
 
3908
MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
 
3909
{
 
3910
#if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
 
3911
  int
 
3912
    status;
 
3913
 
 
3914
  status=munmap(map,length);
 
3915
  return(status == -1 ? MagickFalse : MagickTrue);
 
3916
#else
 
3917
  (void) map;
 
3918
  (void) length;
 
3919
  return(MagickFalse);
 
3920
#endif
 
3921
}
 
3922
 
 
3923
/*
 
3924
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3925
%                                                                             %
 
3926
%                                                                             %
 
3927
%                                                                             %
 
3928
+  W r i t e B l o b                                                          %
 
3929
%                                                                             %
 
3930
%                                                                             %
 
3931
%                                                                             %
 
3932
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3933
%
 
3934
%  WriteBlob() writes data to a blob or image file.  It returns the number of
 
3935
%  bytes written.
 
3936
%
 
3937
%  The format of the WriteBlob method is:
 
3938
%
 
3939
%      ssize_t WriteBlob(Image *image,const size_t length,
 
3940
%        const unsigned char *data)
 
3941
%
 
3942
%  A description of each parameter follows:
 
3943
%
 
3944
%    o image: the image.
 
3945
%
 
3946
%    o length:  Specifies an integer representing the number of bytes to
 
3947
%      write to the file.
 
3948
%
 
3949
%    o data:  The address of the data to write to the blob or file.
 
3950
%
 
3951
*/
 
3952
MagickExport ssize_t WriteBlob(Image *image,const size_t length,
 
3953
  const unsigned char *data)
 
3954
{
 
3955
  int
 
3956
    c;
 
3957
 
 
3958
  register const unsigned char
 
3959
    *p;
 
3960
 
 
3961
  ssize_t
 
3962
    count;
 
3963
 
 
3964
  assert(image != (Image *) NULL);
 
3965
  assert(image->signature == MagickSignature);
 
3966
  assert(data != (const unsigned char *) NULL);
 
3967
  assert(image->blob != (BlobInfo *) NULL);
 
3968
  assert(image->blob->type != UndefinedStream);
 
3969
  if (length == 0)
 
3970
    return(0);
 
3971
  count=0;
 
3972
  p=data;
 
3973
  switch (image->blob->type)
 
3974
  {
 
3975
    case UndefinedStream:
 
3976
      break;
 
3977
    case FileStream:
 
3978
    case StandardStream:
 
3979
    case PipeStream:
 
3980
    {
 
3981
      switch (length)
 
3982
      {
 
3983
        default:
 
3984
        {
 
3985
          count=(ssize_t) fwrite((const char *) data,1,length,
 
3986
            image->blob->file);
 
3987
          break;
 
3988
        }
 
3989
        case 2:
 
3990
        {
 
3991
          c=putc((int) *p++,image->blob->file);
 
3992
          if (c == EOF)
 
3993
            break;
 
3994
          count++;
 
3995
        }
 
3996
        case 1:
 
3997
        {
 
3998
          c=putc((int) *p++,image->blob->file);
 
3999
          if (c == EOF)
 
4000
            break;
 
4001
          count++;
 
4002
        }
 
4003
        case 0:
 
4004
          break;
 
4005
      }
 
4006
      break;
 
4007
    }
 
4008
    case ZipStream:
 
4009
    {
 
4010
#if defined(MAGICKCORE_ZLIB_DELEGATE)
 
4011
      switch (length)
 
4012
      {
 
4013
        default:
 
4014
        {
 
4015
          count=(ssize_t) gzwrite(image->blob->file,(void *) data,
 
4016
            (unsigned int) length);
 
4017
          break;
 
4018
        }
 
4019
        case 2:
 
4020
        {
 
4021
          c=gzputc(image->blob->file,(int) *p++);
 
4022
          if (c == EOF)
 
4023
            break;
 
4024
          count++;
 
4025
        }
 
4026
        case 1:
 
4027
        {
 
4028
          c=gzputc(image->blob->file,(int) *p++);
 
4029
          if (c == EOF)
 
4030
            break;
 
4031
          count++;
 
4032
        }
 
4033
        case 0:
 
4034
          break;
 
4035
      }
 
4036
#endif
 
4037
      break;
 
4038
    }
 
4039
    case BZipStream:
 
4040
    {
 
4041
#if defined(MAGICKCORE_BZLIB_DELEGATE)
 
4042
      count=(ssize_t) BZ2_bzwrite((BZFILE *) image->blob->file,(void *) data,
 
4043
        (int) length);
 
4044
#endif
 
4045
      break;
 
4046
    }
 
4047
    case FifoStream:
 
4048
    {
 
4049
      count=(ssize_t) image->blob->stream(image,data,length);
 
4050
      break;
 
4051
    }
 
4052
    case BlobStream:
 
4053
    {
 
4054
      register unsigned char
 
4055
        *q;
 
4056
 
 
4057
      if ((image->blob->offset+(MagickOffsetType) length) >=
 
4058
          (MagickOffsetType) image->blob->extent)
 
4059
        {
 
4060
          if (image->blob->mapped != MagickFalse)
 
4061
            return(0);
 
4062
          image->blob->quantum<<=1;
 
4063
          image->blob->extent+=length+image->blob->quantum;
 
4064
          image->blob->data=(unsigned char *) ResizeQuantumMemory(
 
4065
            image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
 
4066
          (void) SyncBlob(image);
 
4067
          if (image->blob->data == (unsigned char *) NULL)
 
4068
            {
 
4069
              (void) DetachBlob(image->blob);
 
4070
              return(0);
 
4071
            }
 
4072
        }
 
4073
      q=image->blob->data+image->blob->offset;
 
4074
      (void) memcpy(q,p,length);
 
4075
      image->blob->offset+=length;
 
4076
      if (image->blob->offset >= (MagickOffsetType) image->blob->length)
 
4077
        image->blob->length=(size_t) image->blob->offset;
 
4078
      count=(ssize_t) length;
 
4079
    }
 
4080
  }
 
4081
  return(count);
 
4082
}
 
4083
 
 
4084
/*
 
4085
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4086
%                                                                             %
 
4087
%                                                                             %
 
4088
%                                                                             %
 
4089
+  W r i t e B l o b B y t e                                                  %
 
4090
%                                                                             %
 
4091
%                                                                             %
 
4092
%                                                                             %
 
4093
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4094
%
 
4095
%  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
 
4096
%  written (either 0 or 1);
 
4097
%
 
4098
%  The format of the WriteBlobByte method is:
 
4099
%
 
4100
%      ssize_t WriteBlobByte(Image *image,const unsigned char value)
 
4101
%
 
4102
%  A description of each parameter follows.
 
4103
%
 
4104
%    o image: the image.
 
4105
%
 
4106
%    o value: Specifies the value to write.
 
4107
%
 
4108
*/
 
4109
MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
 
4110
{
 
4111
  assert(image != (Image *) NULL);
 
4112
  assert(image->signature == MagickSignature);
 
4113
  return(WriteBlobStream(image,1,&value));
 
4114
}
 
4115
 
 
4116
/*
 
4117
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4118
%                                                                             %
 
4119
%                                                                             %
 
4120
%                                                                             %
 
4121
+  W r i t e B l o b F l o a t                                                %
 
4122
%                                                                             %
 
4123
%                                                                             %
 
4124
%                                                                             %
 
4125
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4126
%
 
4127
%  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
 
4128
%  specified by the endian member of the image structure.
 
4129
%
 
4130
%  The format of the WriteBlobFloat method is:
 
4131
%
 
4132
%      ssize_t WriteBlobFloat(Image *image,const float value)
 
4133
%
 
4134
%  A description of each parameter follows.
 
4135
%
 
4136
%    o image: the image.
 
4137
%
 
4138
%    o value: Specifies the value to write.
 
4139
%
 
4140
*/
 
4141
MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
 
4142
{
 
4143
  union
 
4144
  {
 
4145
    unsigned int
 
4146
      unsigned_value;
 
4147
 
 
4148
    float
 
4149
      float_value;
 
4150
  } quantum;
 
4151
 
 
4152
  quantum.unsigned_value=0U;
 
4153
  quantum.float_value=value;
 
4154
  return(WriteBlobLong(image,quantum.unsigned_value));
 
4155
}
 
4156
 
 
4157
/*
 
4158
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4159
%                                                                             %
 
4160
%                                                                             %
 
4161
%                                                                             %
 
4162
+  W r i t e B l o b L o n g                                                  %
 
4163
%                                                                             %
 
4164
%                                                                             %
 
4165
%                                                                             %
 
4166
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4167
%
 
4168
%  WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
 
4169
%  specified by the endian member of the image structure.
 
4170
%
 
4171
%  The format of the WriteBlobLong method is:
 
4172
%
 
4173
%      ssize_t WriteBlobLong(Image *image,const unsigned int value)
 
4174
%
 
4175
%  A description of each parameter follows.
 
4176
%
 
4177
%    o image: the image.
 
4178
%
 
4179
%    o value: Specifies the value to write.
 
4180
%
 
4181
*/
 
4182
MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
 
4183
{
 
4184
  unsigned char
 
4185
    buffer[4];
 
4186
 
 
4187
  assert(image != (Image *) NULL);
 
4188
  assert(image->signature == MagickSignature);
 
4189
  if (image->endian == LSBEndian)
 
4190
    {
 
4191
      buffer[0]=(unsigned char) value;
 
4192
      buffer[1]=(unsigned char) (value >> 8);
 
4193
      buffer[2]=(unsigned char) (value >> 16);
 
4194
      buffer[3]=(unsigned char) (value >> 24);
 
4195
      return(WriteBlobStream(image,4,buffer));
 
4196
    }
 
4197
  buffer[0]=(unsigned char) (value >> 24);
 
4198
  buffer[1]=(unsigned char) (value >> 16);
 
4199
  buffer[2]=(unsigned char) (value >> 8);
 
4200
  buffer[3]=(unsigned char) value;
 
4201
  return(WriteBlobStream(image,4,buffer));
 
4202
}
 
4203
 
 
4204
/*
 
4205
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4206
%                                                                             %
 
4207
%                                                                             %
 
4208
%                                                                             %
 
4209
+   W r i t e B l o b S h o r t                                               %
 
4210
%                                                                             %
 
4211
%                                                                             %
 
4212
%                                                                             %
 
4213
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4214
%
 
4215
%  WriteBlobShort() writes a short value as a 16-bit quantity in the
 
4216
%  byte-order specified by the endian member of the image structure.
 
4217
%
 
4218
%  The format of the WriteBlobShort method is:
 
4219
%
 
4220
%      ssize_t WriteBlobShort(Image *image,const unsigned short value)
 
4221
%
 
4222
%  A description of each parameter follows.
 
4223
%
 
4224
%    o image: the image.
 
4225
%
 
4226
%    o value:  Specifies the value to write.
 
4227
%
 
4228
*/
 
4229
MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
 
4230
{
 
4231
  unsigned char
 
4232
    buffer[2];
 
4233
 
 
4234
  assert(image != (Image *) NULL);
 
4235
  assert(image->signature == MagickSignature);
 
4236
  if (image->endian == LSBEndian)
 
4237
    {
 
4238
      buffer[0]=(unsigned char) value;
 
4239
      buffer[1]=(unsigned char) (value >> 8);
 
4240
      return(WriteBlobStream(image,2,buffer));
 
4241
    }
 
4242
  buffer[0]=(unsigned char) (value >> 8);
 
4243
  buffer[1]=(unsigned char) value;
 
4244
  return(WriteBlobStream(image,2,buffer));
 
4245
}
 
4246
 
 
4247
/*
 
4248
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4249
%                                                                             %
 
4250
%                                                                             %
 
4251
%                                                                             %
 
4252
+  W r i t e B l o b L S B L o n g                                            %
 
4253
%                                                                             %
 
4254
%                                                                             %
 
4255
%                                                                             %
 
4256
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4257
%
 
4258
%  WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
 
4259
%  least-significant byte first order.
 
4260
%
 
4261
%  The format of the WriteBlobLSBLong method is:
 
4262
%
 
4263
%      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
 
4264
%
 
4265
%  A description of each parameter follows.
 
4266
%
 
4267
%    o image: the image.
 
4268
%
 
4269
%    o value: Specifies the value to write.
 
4270
%
 
4271
*/
 
4272
MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
 
4273
{
 
4274
  unsigned char
 
4275
    buffer[4];
 
4276
 
 
4277
  assert(image != (Image *) NULL);
 
4278
  assert(image->signature == MagickSignature);
 
4279
  buffer[0]=(unsigned char) value;
 
4280
  buffer[1]=(unsigned char) (value >> 8);
 
4281
  buffer[2]=(unsigned char) (value >> 16);
 
4282
  buffer[3]=(unsigned char) (value >> 24);
 
4283
  return(WriteBlobStream(image,4,buffer));
 
4284
}
 
4285
 
 
4286
/*
 
4287
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4288
%                                                                             %
 
4289
%                                                                             %
 
4290
%                                                                             %
 
4291
+   W r i t e B l o b L S B S h o r t                                         %
 
4292
%                                                                             %
 
4293
%                                                                             %
 
4294
%                                                                             %
 
4295
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4296
%
 
4297
%  WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
 
4298
%  least-significant byte first order.
 
4299
%
 
4300
%  The format of the WriteBlobLSBShort method is:
 
4301
%
 
4302
%      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
 
4303
%
 
4304
%  A description of each parameter follows.
 
4305
%
 
4306
%    o image: the image.
 
4307
%
 
4308
%    o value:  Specifies the value to write.
 
4309
%
 
4310
*/
 
4311
MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
 
4312
{
 
4313
  unsigned char
 
4314
    buffer[2];
 
4315
 
 
4316
  assert(image != (Image *) NULL);
 
4317
  assert(image->signature == MagickSignature);
 
4318
  buffer[0]=(unsigned char) value;
 
4319
  buffer[1]=(unsigned char) (value >> 8);
 
4320
  return(WriteBlobStream(image,2,buffer));
 
4321
}
 
4322
 
 
4323
/*
 
4324
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4325
%                                                                             %
 
4326
%                                                                             %
 
4327
%                                                                             %
 
4328
+  W r i t e B l o b M S B L o n g                                            %
 
4329
%                                                                             %
 
4330
%                                                                             %
 
4331
%                                                                             %
 
4332
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4333
%
 
4334
%  WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
 
4335
%  most-significant byte first order.
 
4336
%
 
4337
%  The format of the WriteBlobMSBLong method is:
 
4338
%
 
4339
%      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
 
4340
%
 
4341
%  A description of each parameter follows.
 
4342
%
 
4343
%    o value:  Specifies the value to write.
 
4344
%
 
4345
%    o image: the image.
 
4346
%
 
4347
*/
 
4348
MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
 
4349
{
 
4350
  unsigned char
 
4351
    buffer[4];
 
4352
 
 
4353
  assert(image != (Image *) NULL);
 
4354
  assert(image->signature == MagickSignature);
 
4355
  buffer[0]=(unsigned char) (value >> 24);
 
4356
  buffer[1]=(unsigned char) (value >> 16);
 
4357
  buffer[2]=(unsigned char) (value >> 8);
 
4358
  buffer[3]=(unsigned char) value;
 
4359
  return(WriteBlobStream(image,4,buffer));
 
4360
}
 
4361
 
 
4362
/*
 
4363
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4364
%                                                                             %
 
4365
%                                                                             %
 
4366
%                                                                             %
 
4367
+  W r i t e B l o b M S B L o n g L o n g                                    %
 
4368
%                                                                             %
 
4369
%                                                                             %
 
4370
%                                                                             %
 
4371
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4372
%
 
4373
%  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
 
4374
%  most-significant byte first order.
 
4375
%
 
4376
%  The format of the WriteBlobMSBLongLong method is:
 
4377
%
 
4378
%      ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
 
4379
%
 
4380
%  A description of each parameter follows.
 
4381
%
 
4382
%    o value:  Specifies the value to write.
 
4383
%
 
4384
%    o image: the image.
 
4385
%
 
4386
*/
 
4387
MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
 
4388
  const MagickSizeType value)
 
4389
{
 
4390
  unsigned char
 
4391
    buffer[8];
 
4392
 
 
4393
  assert(image != (Image *) NULL);
 
4394
  assert(image->signature == MagickSignature);
 
4395
  buffer[0]=(unsigned char) (value >> 56);
 
4396
  buffer[1]=(unsigned char) (value >> 48);
 
4397
  buffer[2]=(unsigned char) (value >> 40);
 
4398
  buffer[3]=(unsigned char) (value >> 32);
 
4399
  buffer[4]=(unsigned char) (value >> 24);
 
4400
  buffer[5]=(unsigned char) (value >> 16);
 
4401
  buffer[6]=(unsigned char) (value >> 8);
 
4402
  buffer[7]=(unsigned char) value;
 
4403
  return(WriteBlobStream(image,8,buffer));
 
4404
}
 
4405
 
 
4406
/*
 
4407
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4408
%                                                                             %
 
4409
%                                                                             %
 
4410
%                                                                             %
 
4411
+  W r i t e B l o b M S B S h o r t                                          %
 
4412
%                                                                             %
 
4413
%                                                                             %
 
4414
%                                                                             %
 
4415
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4416
%
 
4417
%  WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
 
4418
%  most-significant byte first order.
 
4419
%
 
4420
%  The format of the WriteBlobMSBShort method is:
 
4421
%
 
4422
%      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
 
4423
%
 
4424
%  A description of each parameter follows.
 
4425
%
 
4426
%   o  value:  Specifies the value to write.
 
4427
%
 
4428
%   o  file:  Specifies the file to write the data to.
 
4429
%
 
4430
*/
 
4431
MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
 
4432
{
 
4433
  unsigned char
 
4434
    buffer[2];
 
4435
 
 
4436
  assert(image != (Image *) NULL);
 
4437
  assert(image->signature == MagickSignature);
 
4438
  buffer[0]=(unsigned char) (value >> 8);
 
4439
  buffer[1]=(unsigned char) value;
 
4440
  return(WriteBlobStream(image,2,buffer));
 
4441
}
 
4442
 
 
4443
/*
 
4444
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4445
%                                                                             %
 
4446
%                                                                             %
 
4447
%                                                                             %
 
4448
+  W r i t e B l o b S t r i n g                                              %
 
4449
%                                                                             %
 
4450
%                                                                             %
 
4451
%                                                                             %
 
4452
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
4453
%
 
4454
%  WriteBlobString() write a string to a blob.  It returns the number of
 
4455
%  characters written.
 
4456
%
 
4457
%  The format of the WriteBlobString method is:
 
4458
%
 
4459
%      ssize_t WriteBlobString(Image *image,const char *string)
 
4460
%
 
4461
%  A description of each parameter follows.
 
4462
%
 
4463
%    o image: the image.
 
4464
%
 
4465
%    o string: Specifies the string to write.
 
4466
%
 
4467
*/
 
4468
MagickExport ssize_t WriteBlobString(Image *image,const char *string)
 
4469
{
 
4470
  assert(image != (Image *) NULL);
 
4471
  assert(image->signature == MagickSignature);
 
4472
  assert(string != (const char *) NULL);
 
4473
  return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
 
4474
}