Coverage Report

Created: 2026-11-12 07:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/MagickCore/blob.c
Line
Count
Source
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
%                                   Cristy                                    %
17
%                                 July 1999                                   %
18
%                                                                             %
19
%                                                                             %
20
%  Copyright @ 1999 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
%    https://imagemagick.org/license/                                         %
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
#ifdef __VMS
44
#include  <types.h>
45
#include  <mman.h>
46
#endif
47
#include "MagickCore/studio.h"
48
#include "MagickCore/blob.h"
49
#include "MagickCore/blob-private.h"
50
#include "MagickCore/cache.h"
51
#include "MagickCore/client.h"
52
#include "MagickCore/constitute.h"
53
#include "MagickCore/delegate.h"
54
#include "MagickCore/exception.h"
55
#include "MagickCore/exception-private.h"
56
#include "MagickCore/geometry.h"
57
#include "MagickCore/image-private.h"
58
#include "MagickCore/list.h"
59
#include "MagickCore/locale_.h"
60
#include "MagickCore/log.h"
61
#include "MagickCore/magick.h"
62
#include "MagickCore/memory_.h"
63
#include "MagickCore/memory-private.h"
64
#include "MagickCore/nt-base-private.h"
65
#include "MagickCore/option.h"
66
#include "MagickCore/policy.h"
67
#include "MagickCore/policy-private.h"
68
#include "MagickCore/resource_.h"
69
#include "MagickCore/semaphore.h"
70
#include "MagickCore/string_.h"
71
#include "MagickCore/string-private.h"
72
#include "MagickCore/timer-private.h"
73
#include "MagickCore/token.h"
74
#include "MagickCore/utility.h"
75
#include "MagickCore/utility-private.h"
76
#if defined(MAGICKCORE_ZLIB_DELEGATE)
77
#include "zlib.h"
78
#endif
79
#if defined(MAGICKCORE_BZLIB_DELEGATE)
80
#include "bzlib.h"
81
#endif
82

83
/*
84
  Define declarations.
85
*/
86
4.31M
#define MagickMaxBlobExtent  (8*8192)
87
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
88
# define MAP_ANONYMOUS  MAP_ANON
89
#endif
90
#if !defined(MAP_FAILED)
91
#define MAP_FAILED  ((void *) -1)
92
#endif
93
#if defined(__OS2__)
94
#include <io.h>
95
#define _O_BINARY  O_BINARY
96
#endif
97
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
98
#  if !defined(fsync)
99
#    define fsync  _commit
100
#  endif
101
#  if !defined(mmap)
102
#    define MAGICKCORE_HAVE_MMAP 1
103
#    define mmap(address,length,protection,access,file,offset) \
104
  NTMapMemory(address,length,protection,access,file,offset)
105
#  endif
106
#  if !defined(munmap)
107
#    define munmap(address,length)  NTUnmapMemory(address,length)
108
#  endif
109
#  if !defined(pclose)
110
#    define pclose  _pclose
111
#  endif
112
#  if !defined(popen)
113
#    define popen  _popen
114
#  endif
115
#endif
116

117
/*
118
  Typedef declarations.
119
*/
120
typedef union FileInfo
121
{
122
  FILE
123
    *file;
124
125
#if defined(MAGICKCORE_ZLIB_DELEGATE)
126
  gzFile
127
    gzfile;
128
#endif
129
130
#if defined(MAGICKCORE_BZLIB_DELEGATE)
131
  BZFILE
132
    *bzfile;
133
#endif
134
} FileInfo;
135
136
struct _BlobInfo
137
{
138
  size_t
139
    length,
140
    extent,
141
    quantum;
142
143
  BlobMode
144
    mode;
145
146
  MagickBooleanType
147
    mapped,
148
    eof;
149
150
  int
151
    error,
152
    error_number;
153
154
  MagickOffsetType
155
    offset;
156
157
  MagickSizeType
158
    size;
159
160
  MagickBooleanType
161
    exempt,
162
    synchronize,
163
    temporary;
164
165
  int
166
    status;
167
168
  StreamType
169
    type;
170
171
  FileInfo
172
    file_info;
173
174
  struct stat
175
    properties;
176
177
  StreamHandler
178
    stream;
179
180
  CustomStreamInfo
181
    *custom_stream;
182
183
  unsigned char
184
    *data;
185
186
  MagickBooleanType
187
    debug;
188
189
  SemaphoreInfo
190
    *semaphore;
191
192
  ssize_t
193
    reference_count;
194
195
  size_t
196
    signature;
197
};
198
199
struct _CustomStreamInfo
200
{
201
  CustomStreamHandler
202
    reader,
203
    writer;
204
205
  CustomStreamSeeker
206
    seeker;
207
208
  CustomStreamTeller
209
    teller;
210
211
  void
212
    *data;
213
214
  size_t
215
    signature;
216
};
217

218
/*
219
  Forward declarations.
220
*/
221
static int
222
  SyncBlob(const Image *);
223

224
/*
225
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226
%                                                                             %
227
%                                                                             %
228
%                                                                             %
229
+   A c q u i r e C u s t o m S t r e a m I n f o                             %
230
%                                                                             %
231
%                                                                             %
232
%                                                                             %
233
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234
%
235
%  AcquireCustomStreamInfo() allocates the CustomStreamInfo structure.
236
%
237
%  The format of the AcquireCustomStreamInfo method is:
238
%
239
%      CustomStreamInfo *AcquireCustomStreamInfo(ExceptionInfo *exception)
240
%
241
%  A description of each parameter follows:
242
%
243
%    o exception: return any errors or warnings in this structure.
244
%
245
*/
246
MagickExport CustomStreamInfo *AcquireCustomStreamInfo(
247
  ExceptionInfo *magick_unused(exception))
248
396
{
249
396
  CustomStreamInfo
250
396
    *custom_stream;
251
252
396
  magick_unreferenced(exception);
253
396
  custom_stream=(CustomStreamInfo *) AcquireCriticalMemory(
254
396
    sizeof(*custom_stream));
255
396
  (void) memset(custom_stream,0,sizeof(*custom_stream));
256
396
  custom_stream->signature=MagickCoreSignature;
257
396
  return(custom_stream);
258
396
}
259

260
/*
261
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262
%                                                                             %
263
%                                                                             %
264
%                                                                             %
265
+   A t t a c h B l o b                                                       %
266
%                                                                             %
267
%                                                                             %
268
%                                                                             %
269
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270
%
271
%  AttachBlob() attaches a blob to the BlobInfo structure.
272
%
273
%  The format of the AttachBlob method is:
274
%
275
%      void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
276
%
277
%  A description of each parameter follows:
278
%
279
%    o blob_info: Specifies a pointer to a BlobInfo structure.
280
%
281
%    o blob: the address of a character stream in one of the image formats
282
%      understood by ImageMagick.
283
%
284
%    o length: This size_t integer reflects the length in bytes of the blob.
285
%
286
*/
287
MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
288
  const size_t length)
289
1.28M
{
290
1.28M
  assert(blob_info != (BlobInfo *) NULL);
291
1.28M
  if (IsEventLogging() != MagickFalse)
292
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
293
1.28M
  blob_info->length=length;
294
1.28M
  blob_info->extent=length;
295
1.28M
  blob_info->quantum=(size_t) MagickMaxBlobExtent;
296
1.28M
  blob_info->offset=0;
297
1.28M
  blob_info->type=BlobStream;
298
1.28M
  blob_info->file_info.file=(FILE *) NULL;
299
1.28M
  blob_info->data=(unsigned char *) blob;
300
1.28M
  blob_info->mapped=MagickFalse;
301
1.28M
}
302

303
/*
304
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305
%                                                                             %
306
%                                                                             %
307
%                                                                             %
308
+   A t t a c h C u s t o m S t r e a m                                       %
309
%                                                                             %
310
%                                                                             %
311
%                                                                             %
312
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313
%
314
%  AttachCustomStream() attaches a CustomStreamInfo to the BlobInfo structure.
315
%
316
%  The format of the AttachCustomStream method is:
317
%
318
%      void AttachCustomStream(BlobInfo *blob_info,
319
%        CustomStreamInfo *custom_stream)
320
%
321
%  A description of each parameter follows:
322
%
323
%    o blob_info: specifies a pointer to a BlobInfo structure.
324
%
325
%    o custom_stream: the custom stream info.
326
%
327
*/
328
MagickExport void AttachCustomStream(BlobInfo *blob_info,
329
  CustomStreamInfo *custom_stream)
330
396
{
331
396
  assert(blob_info != (BlobInfo *) NULL);
332
396
  assert(custom_stream != (CustomStreamInfo *) NULL);
333
396
  assert(custom_stream->signature == MagickCoreSignature);
334
396
  if (IsEventLogging() != MagickFalse)
335
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
336
396
  blob_info->type=CustomStream;
337
396
  blob_info->custom_stream=custom_stream;
338
396
}
339

340
/*
341
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342
%                                                                             %
343
%                                                                             %
344
%                                                                             %
345
+   B l o b T o F i l e                                                       %
346
%                                                                             %
347
%                                                                             %
348
%                                                                             %
349
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350
%
351
%  BlobToFile() writes a blob to a file.  It returns MagickFalse if an error
352
%  occurs otherwise MagickTrue.
353
%
354
%  The format of the BlobToFile method is:
355
%
356
%       MagickBooleanType BlobToFile(char *filename,const void *blob,
357
%         const size_t length,ExceptionInfo *exception)
358
%
359
%  A description of each parameter follows:
360
%
361
%    o filename: Write the blob to this file. The filename buffer length must
362
%      be a minimum of MagickPathExtent characters.
363
%
364
%    o blob: the address of a blob.
365
%
366
%    o length: This length in bytes of the blob.
367
%
368
%    o exception: return any errors or warnings in this structure.
369
%
370
*/
371
MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
372
  const size_t length,ExceptionInfo *exception)
373
201k
{
374
201k
  int
375
201k
    file;
376
377
201k
  size_t
378
201k
    i;
379
380
201k
  ssize_t
381
201k
    count;
382
383
201k
  assert(filename != (const char *) NULL);
384
201k
  assert(blob != (const void *) NULL);
385
201k
  if (IsEventLogging() != MagickFalse)
386
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
387
201k
  if (*filename == '\0')
388
201k
    file=AcquireUniqueFileResource(filename);
389
0
  else
390
0
    file=open_utf8(filename,O_WRONLY | O_CLOEXEC | O_CREAT | O_EXCL | O_BINARY,P_MODE);
391
201k
  if (file == -1)
392
0
    {
393
0
      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
394
0
      return(MagickFalse);
395
0
    }
396
402k
  for (i=0; i < length; i+=(size_t) count)
397
201k
  {
398
201k
    count=MagickWrite(file,(const char *) blob+i,MagickMin(length-i,(size_t)
399
201k
      MagickMaxBufferExtent));
400
201k
    if (count <= 0)
401
0
      break;
402
201k
  }
403
201k
  file=close_utf8(file);
404
201k
  if ((file == -1) || (i < length))
405
0
    {
406
0
      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
407
0
      return(MagickFalse);
408
0
    }
409
201k
  return(MagickTrue);
410
201k
}
411

412
/*
413
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414
%                                                                             %
415
%                                                                             %
416
%                                                                             %
417
%   B l o b T o I m a g e                                                     %
418
%                                                                             %
419
%                                                                             %
420
%                                                                             %
421
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
422
%
423
%  BlobToImage() implements direct to memory image formats.  It returns the
424
%  blob as an image.
425
%
426
%  The format of the BlobToImage method is:
427
%
428
%      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
429
%        const size_t length,ExceptionInfo *exception)
430
%
431
%  A description of each parameter follows:
432
%
433
%    o image_info: the image info.
434
%
435
%    o blob: the address of a character stream in one of the image formats
436
%      understood by ImageMagick.
437
%
438
%    o length: This size_t integer reflects the length in bytes of the blob.
439
%
440
%    o exception: return any errors or warnings in this structure.
441
%
442
*/
443
MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
444
  const size_t length,ExceptionInfo *exception)
445
724k
{
446
724k
  const MagickInfo
447
724k
    *magick_info;
448
449
724k
  Image
450
724k
    *image;
451
452
724k
  ImageInfo
453
724k
    *blob_info,
454
724k
    *clone_info;
455
456
724k
  MagickBooleanType
457
724k
    status;
458
459
724k
  assert(image_info != (ImageInfo *) NULL);
460
724k
  assert(image_info->signature == MagickCoreSignature);
461
724k
  assert(exception != (ExceptionInfo *) NULL);
462
724k
  if (IsEventLogging() != MagickFalse)
463
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
464
0
      image_info->filename);
465
724k
  if ((blob == (const void *) NULL) || (length == 0))
466
2
    {
467
2
      (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
468
2
        "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
469
2
      return((Image *) NULL);
470
2
    }
471
724k
  blob_info=CloneImageInfo(image_info);
472
724k
  blob_info->blob=(void *) blob;
473
724k
  blob_info->length=length;
474
724k
  if (*blob_info->magick == '\0')
475
32.9k
    (void) SetImageInfo(blob_info,0,exception);
476
724k
  magick_info=GetMagickInfo(blob_info->magick,exception);
477
724k
  if (magick_info == (const MagickInfo *) NULL)
478
1
    {
479
1
      (void) ThrowMagickException(exception,GetMagickModule(),
480
1
        MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
481
1
        blob_info->magick);
482
1
      blob_info=DestroyImageInfo(blob_info);
483
1
      return((Image *) NULL);
484
1
    }
485
724k
  if (GetMagickBlobSupport(magick_info) != MagickFalse)
486
531k
    {
487
531k
      char
488
531k
        filename[MagickPathExtent];
489
490
      /*
491
        Native blob support for this image format.
492
      */
493
531k
      (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
494
531k
      (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
495
531k
        blob_info->magick,filename);
496
531k
      image=ReadImage(blob_info,exception);
497
531k
      if (image != (Image *) NULL)
498
137k
        (void) DetachBlob(image->blob);
499
531k
      blob_info=DestroyImageInfo(blob_info);
500
531k
      return(image);
501
531k
    }
502
  /*
503
    Write blob to a temporary file on disk.
504
  */
505
192k
  blob_info->blob=(void *) NULL;
506
192k
  blob_info->length=0;
507
192k
  *blob_info->filename='\0';
508
192k
  status=BlobToFile(blob_info->filename,blob,length,exception);
509
192k
  if (status == MagickFalse)
510
0
    {
511
0
      (void) RelinquishUniqueFileResource(blob_info->filename);
512
0
      blob_info=DestroyImageInfo(blob_info);
513
0
      return((Image *) NULL);
514
0
    }
515
192k
  clone_info=CloneImageInfo(blob_info);
516
192k
  (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
517
192k
    blob_info->magick,blob_info->filename);
518
192k
  image=ReadImage(clone_info,exception);
519
192k
  if (image != (Image *) NULL)
520
11.5k
    {
521
11.5k
      Image
522
11.5k
        *images;
523
524
      /*
525
        Restore original filenames and image format.
526
      */
527
25.8k
      for (images=GetFirstImageInList(image); images != (Image *) NULL; )
528
14.2k
      {
529
14.2k
        (void) CopyMagickString(images->filename,image_info->filename,
530
14.2k
          MagickPathExtent);
531
14.2k
        (void) CopyMagickString(images->magick_filename,image_info->filename,
532
14.2k
          MagickPathExtent);
533
14.2k
        (void) CopyMagickString(images->magick,magick_info->name,
534
14.2k
          MagickPathExtent);
535
14.2k
        images=GetNextImageInList(images);
536
14.2k
      }
537
11.5k
    }
538
192k
  clone_info=DestroyImageInfo(clone_info);
539
192k
  (void) RelinquishUniqueFileResource(blob_info->filename);
540
192k
  blob_info=DestroyImageInfo(blob_info);
541
192k
  return(image);
542
192k
}
543

544
/*
545
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546
%                                                                             %
547
%                                                                             %
548
%                                                                             %
549
+   C l o n e B l o b I n f o                                                 %
550
%                                                                             %
551
%                                                                             %
552
%                                                                             %
553
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554
%
555
%  CloneBlobInfo() makes a duplicate of the given blob info structure, or if
556
%  blob info is NULL, a new one.
557
%
558
%  The format of the CloneBlobInfo method is:
559
%
560
%      BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
561
%
562
%  A description of each parameter follows:
563
%
564
%    o blob_info: the blob info.
565
%
566
*/
567
MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
568
2.97M
{
569
2.97M
  BlobInfo
570
2.97M
    *clone_info;
571
572
2.97M
  SemaphoreInfo
573
2.97M
    *semaphore;
574
575
2.97M
  clone_info=(BlobInfo *) AcquireCriticalMemory(sizeof(*clone_info));
576
2.97M
  GetBlobInfo(clone_info);
577
2.97M
  if (blob_info == (BlobInfo *) NULL)
578
2.97M
    return(clone_info);
579
0
  semaphore=clone_info->semaphore;
580
0
  (void) memcpy(clone_info,blob_info,sizeof(*clone_info));
581
0
  if (blob_info->mapped != MagickFalse)
582
0
    (void) AcquireMagickResource(MapResource,blob_info->length);
583
0
  clone_info->semaphore=semaphore;
584
0
  LockSemaphoreInfo(clone_info->semaphore);
585
0
  clone_info->reference_count=1;
586
0
  UnlockSemaphoreInfo(clone_info->semaphore);
587
0
  return(clone_info);
588
2.97M
}
589

590
/*
591
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592
%                                                                             %
593
%                                                                             %
594
%                                                                             %
595
+   C l o s e B l o b                                                         %
596
%                                                                             %
597
%                                                                             %
598
%                                                                             %
599
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
600
%
601
%  CloseBlob() closes a stream associated with the image.
602
%
603
%  The format of the CloseBlob method is:
604
%
605
%      MagickBooleanType CloseBlob(Image *image)
606
%
607
%  A description of each parameter follows:
608
%
609
%    o image: the image.
610
%
611
*/
612
613
static inline void ThrowBlobException(BlobInfo *blob_info)
614
17.1M
{
615
17.1M
  if ((blob_info->status == 0) && (errno != 0))
616
308
    blob_info->error_number=errno;
617
17.1M
  blob_info->status=(-1);
618
17.1M
}
619
620
MagickExport MagickBooleanType CloseBlob(Image *image)
621
4.58M
{
622
4.58M
  BlobInfo
623
4.58M
    *magick_restrict blob_info;
624
625
4.58M
  int
626
4.58M
    status;
627
628
  /*
629
    Close image file.
630
  */
631
4.58M
  assert(image != (Image *) NULL);
632
4.58M
  assert(image->signature == MagickCoreSignature);
633
4.58M
  if (IsEventLogging() != MagickFalse)
634
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
635
4.58M
  blob_info=image->blob;
636
4.58M
  if ((blob_info == (BlobInfo *) NULL) || (blob_info->type == UndefinedStream))
637
2.91M
    return(MagickTrue);
638
1.66M
  status=SyncBlob(image);
639
  /* Some platforms report an error when a read-only stream is flushed. */
640
1.66M
  if ((status != 0) &&
641
0
      ((blob_info->mode == WriteBlobMode) ||
642
0
       (blob_info->mode == WriteBinaryBlobMode) ||
643
0
       (blob_info->mode == AppendBlobMode) ||
644
0
       (blob_info->mode == AppendBinaryBlobMode)))
645
0
    ThrowBlobException(blob_info);
646
1.66M
  status=blob_info->status;
647
1.66M
  switch (blob_info->type)
648
1.66M
  {
649
0
    case UndefinedStream:
650
0
      break;
651
0
    case StandardStream:
652
313k
    case FileStream:
653
313k
    case PipeStream:
654
313k
    {
655
313k
      if (blob_info->synchronize != MagickFalse)
656
0
        {
657
0
          status=fflush(blob_info->file_info.file);
658
0
          if (status != 0)
659
0
            ThrowBlobException(blob_info);
660
0
          status=fsync(fileno(blob_info->file_info.file));
661
0
          if (status != 0)
662
0
            ThrowBlobException(blob_info);
663
0
        }
664
313k
      if ((status != 0) && (ferror(blob_info->file_info.file) != 0))
665
210
        ThrowBlobException(blob_info);
666
313k
      break;
667
313k
    }
668
70.7k
    case ZipStream:
669
70.7k
    {
670
70.7k
#if defined(MAGICKCORE_ZLIB_DELEGATE)
671
70.7k
      status=Z_OK;
672
70.7k
      (void) gzerror(blob_info->file_info.gzfile,&status);
673
70.7k
      if (status != Z_OK)
674
34.2k
        ThrowBlobException(blob_info);
675
70.7k
#endif
676
70.7k
      break;
677
313k
    }
678
0
    case BZipStream:
679
0
    {
680
#if defined(MAGICKCORE_BZLIB_DELEGATE)
681
      status=BZ_OK;
682
      (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
683
      if (status != BZ_OK)
684
        ThrowBlobException(blob_info);
685
#endif
686
0
      break;
687
313k
    }
688
0
    case FifoStream:
689
0
      break;
690
1.27M
    case BlobStream:
691
1.27M
    {
692
1.27M
      if (blob_info->file_info.file != (FILE *) NULL)
693
0
        {
694
0
          if (blob_info->synchronize != MagickFalse)
695
0
            {
696
0
              status=fflush(blob_info->file_info.file);
697
0
              if (status != 0)
698
0
                ThrowBlobException(blob_info);
699
0
              status=fsync(fileno(blob_info->file_info.file));
700
0
              if (status != 0)
701
0
                ThrowBlobException(blob_info);
702
0
            }
703
0
          if ((status != 0) && (ferror(blob_info->file_info.file) != 0))
704
0
            ThrowBlobException(blob_info);
705
0
        }
706
1.27M
      break;
707
313k
    }
708
396
    case CustomStream:
709
396
      break;
710
1.66M
  }
711
1.66M
  blob_info->size=GetBlobSize(image);
712
1.66M
  image->extent=blob_info->size;
713
1.66M
  blob_info->eof=MagickFalse;
714
1.66M
  blob_info->error=0;
715
1.66M
  blob_info->mode=UndefinedBlobMode;
716
1.66M
  if (blob_info->exempt != MagickFalse)
717
84.9k
    {
718
84.9k
      blob_info->type=UndefinedStream;
719
84.9k
      return(blob_info->status != 0 ? MagickFalse : MagickTrue);
720
84.9k
    }
721
1.57M
  switch (blob_info->type)
722
1.57M
  {
723
0
    case UndefinedStream:
724
0
    case StandardStream:
725
0
      break;
726
309k
    case FileStream:
727
309k
    {
728
309k
      if (blob_info->file_info.file != (FILE *) NULL)
729
309k
        {
730
309k
          status=fclose(blob_info->file_info.file);
731
309k
          if (status != 0)
732
0
            ThrowBlobException(blob_info);
733
309k
        }
734
309k
      break;
735
0
    }
736
0
    case PipeStream:
737
0
    {
738
0
#if defined(MAGICKCORE_HAVE_PCLOSE)
739
0
      status=pclose(blob_info->file_info.file);
740
0
      if (status != 0)
741
0
        ThrowBlobException(blob_info);
742
0
#endif
743
0
      break;
744
0
    }
745
70.7k
    case ZipStream:
746
70.7k
    {
747
70.7k
#if defined(MAGICKCORE_ZLIB_DELEGATE)
748
70.7k
      status=gzclose(blob_info->file_info.gzfile);
749
70.7k
      if (status != Z_OK)
750
23.9k
        ThrowBlobException(blob_info);
751
70.7k
#endif
752
70.7k
      break;
753
0
    }
754
0
    case BZipStream:
755
0
    {
756
#if defined(MAGICKCORE_BZLIB_DELEGATE)
757
      BZ2_bzclose(blob_info->file_info.bzfile);
758
#endif
759
0
      break;
760
0
    }
761
0
    case FifoStream:
762
0
      break;
763
1.19M
    case BlobStream:
764
1.19M
    {
765
1.19M
      if (blob_info->file_info.file != (FILE *) NULL)
766
0
        {
767
0
          status=fclose(blob_info->file_info.file);
768
0
          if (status != 0)
769
0
            ThrowBlobException(blob_info);
770
0
        }
771
1.19M
      break;
772
0
    }
773
396
    case CustomStream:
774
396
      break;
775
1.57M
  }
776
1.57M
  (void) DetachBlob(blob_info);
777
1.57M
  return(blob_info->status != 0 ? MagickFalse : MagickTrue);
778
1.57M
}
779

780
/*
781
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
782
%                                                                             %
783
%                                                                             %
784
%                                                                             %
785
%   C u s t o m S t r e a m T o I m a g e                                     %
786
%                                                                             %
787
%                                                                             %
788
%                                                                             %
789
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
790
%
791
%  CustomStreamToImage() is the equivalent of ReadImage(), but reads the
792
%  formatted "file" from the supplied method rather than to an actual file.
793
%
794
%  The format of the CustomStreamToImage method is:
795
%
796
%      Image *CustomStreamToImage(const ImageInfo *image_info,
797
%         ExceptionInfo *exception)
798
%
799
%  A description of each parameter follows:
800
%
801
%    o image_info: the image info.
802
%
803
%    o exception: return any errors or warnings in this structure.
804
%
805
*/
806
MagickExport Image *CustomStreamToImage(const ImageInfo *image_info,
807
  ExceptionInfo *exception)
808
0
{
809
0
  const MagickInfo
810
0
    *magick_info;
811
812
0
  Image
813
0
    *image;
814
815
0
  ImageInfo
816
0
    *blob_info;
817
818
0
  assert(image_info != (ImageInfo *) NULL);
819
0
  assert(image_info->signature == MagickCoreSignature);
820
0
  assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
821
0
  assert(image_info->custom_stream->signature == MagickCoreSignature);
822
0
  assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
823
0
  assert(exception != (ExceptionInfo *) NULL);
824
0
  if (IsEventLogging() != MagickFalse)
825
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
826
0
      image_info->filename);
827
0
  blob_info=CloneImageInfo(image_info);
828
0
  if (*blob_info->magick == '\0')
829
0
    (void) SetImageInfo(blob_info,0,exception);
830
0
  magick_info=GetMagickInfo(blob_info->magick,exception);
831
0
  if (magick_info == (const MagickInfo *) NULL)
832
0
    {
833
0
      (void) ThrowMagickException(exception,GetMagickModule(),
834
0
        MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
835
0
        blob_info->magick);
836
0
      blob_info=DestroyImageInfo(blob_info);
837
0
      return((Image *) NULL);
838
0
    }
839
0
  image=(Image *) NULL;
840
0
  if ((GetMagickBlobSupport(magick_info) != MagickFalse) ||
841
0
      (*blob_info->filename != '\0'))
842
0
    {
843
0
      char
844
0
        filename[MagickPathExtent];
845
846
      /*
847
        Native blob support for this image format or SetImageInfo changed the
848
        blob to a file.
849
      */
850
0
      (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
851
0
      (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
852
0
        blob_info->magick,filename);
853
0
      image=ReadImage(blob_info,exception);
854
0
    }
855
0
  else
856
0
    {
857
0
      char
858
0
        unique[MagickPathExtent];
859
860
0
      int
861
0
        file;
862
863
0
      ImageInfo
864
0
        *clone_info;
865
866
0
      unsigned char
867
0
        *blob;
868
869
      /*
870
        Write data to file on disk.
871
      */
872
0
      blob_info->custom_stream=(CustomStreamInfo *) NULL;
873
0
      blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
874
0
        sizeof(*blob));
875
0
      if (blob == (unsigned char *) NULL)
876
0
        {
877
0
          ThrowFileException(exception,BlobError,"UnableToReadBlob",
878
0
            image_info->filename);
879
0
          blob_info=DestroyImageInfo(blob_info);
880
0
          return((Image *) NULL);
881
0
        }
882
0
      file=AcquireUniqueFileResource(unique);
883
0
      if (file == -1)
884
0
        {
885
0
          ThrowFileException(exception,BlobError,"UnableToReadBlob",
886
0
            image_info->filename);
887
0
          blob=(unsigned char *) RelinquishMagickMemory(blob);
888
0
          blob_info=DestroyImageInfo(blob_info);
889
0
          return((Image *) NULL);
890
0
        }
891
0
      clone_info=CloneImageInfo(blob_info);
892
0
      blob_info->file=fdopen(file,"wb+");
893
0
      if (blob_info->file != (FILE *) NULL)
894
0
        {
895
0
          ssize_t
896
0
            count;
897
898
0
          count=(ssize_t) MagickMaxBufferExtent;
899
0
          while (count == (ssize_t) MagickMaxBufferExtent)
900
0
          {
901
0
            count=image_info->custom_stream->reader(blob,MagickMaxBufferExtent,
902
0
              image_info->custom_stream->data);
903
0
            if (count > 0)
904
0
              count=(ssize_t) write(file,(const char *) blob,(size_t) count);
905
0
          }
906
0
          (void) fclose(blob_info->file);
907
0
          (void) FormatLocaleString(clone_info->filename,MagickPathExtent,
908
0
            "%s:%s",blob_info->magick,unique);
909
0
          image=ReadImage(clone_info,exception);
910
0
          if (image != (Image *) NULL)
911
0
            {
912
0
              Image
913
0
                *images;
914
915
              /*
916
                Restore original filenames and image format.
917
              */
918
0
              for (images=GetFirstImageInList(image); images != (Image *) NULL; )
919
0
              {
920
0
                (void) CopyMagickString(images->filename,image_info->filename,
921
0
                  MagickPathExtent);
922
0
                (void) CopyMagickString(images->magick_filename,
923
0
                  image_info->filename,MagickPathExtent);
924
0
                (void) CopyMagickString(images->magick,magick_info->name,
925
0
                  MagickPathExtent);
926
0
                images=GetNextImageInList(images);
927
0
              }
928
0
            }
929
0
        }
930
0
      clone_info=DestroyImageInfo(clone_info);
931
0
      blob=(unsigned char *) RelinquishMagickMemory(blob);
932
0
      (void) RelinquishUniqueFileResource(unique);
933
0
    }
934
0
  blob_info=DestroyImageInfo(blob_info);
935
0
  if (image != (Image *) NULL)
936
0
    if (CloseBlob(image) == MagickFalse)
937
0
      image=DestroyImageList(image);
938
0
  return(image);
939
0
}
940

941
/*
942
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
943
%                                                                             %
944
%                                                                             %
945
%                                                                             %
946
+   D e s t r o y B l o b                                                     %
947
%                                                                             %
948
%                                                                             %
949
%                                                                             %
950
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
951
%
952
%  DestroyBlob() deallocates memory associated with a blob.
953
%
954
%  The format of the DestroyBlob method is:
955
%
956
%      void DestroyBlob(Image *image)
957
%
958
%  A description of each parameter follows:
959
%
960
%    o image: the image.
961
%
962
*/
963
MagickExport void DestroyBlob(Image *image)
964
3.09M
{
965
3.09M
  BlobInfo
966
3.09M
    *magick_restrict blob_info;
967
968
3.09M
  MagickBooleanType
969
3.09M
    destroy;
970
971
3.09M
  assert(image != (Image *) NULL);
972
3.09M
  assert(image->signature == MagickCoreSignature);
973
3.09M
  assert(image->blob != (BlobInfo *) NULL);
974
3.09M
  assert(image->blob->signature == MagickCoreSignature);
975
3.09M
  if (IsEventLogging() != MagickFalse)
976
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
977
3.09M
  blob_info=image->blob;
978
3.09M
  destroy=MagickFalse;
979
3.09M
  LockSemaphoreInfo(blob_info->semaphore);
980
3.09M
  blob_info->reference_count--;
981
3.09M
  assert(blob_info->reference_count >= 0);
982
3.09M
  if (blob_info->reference_count == 0)
983
2.97M
    destroy=MagickTrue;
984
3.09M
  UnlockSemaphoreInfo(blob_info->semaphore);
985
3.09M
  if (destroy == MagickFalse)
986
118k
    {
987
118k
      image->blob=(BlobInfo *) NULL;
988
118k
      return;
989
118k
    }
990
2.97M
  (void) CloseBlob(image);
991
2.97M
  if (blob_info->mapped != MagickFalse)
992
0
    {
993
0
      (void) UnmapBlob(blob_info->data,blob_info->length);
994
0
      RelinquishMagickResource(MapResource,blob_info->length);
995
0
    }
996
2.97M
  if (blob_info->semaphore != (SemaphoreInfo *) NULL)
997
2.97M
    RelinquishSemaphoreInfo(&blob_info->semaphore);
998
2.97M
  blob_info->signature=(~MagickCoreSignature);
999
2.97M
  image->blob=(BlobInfo *) RelinquishMagickMemory(blob_info);
1000
2.97M
}
1001

1002
/*
1003
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004
%                                                                             %
1005
%                                                                             %
1006
%                                                                             %
1007
+   D e s t r o y C u s t o m S t r e a m I n f o                             %
1008
%                                                                             %
1009
%                                                                             %
1010
%                                                                             %
1011
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1012
%
1013
%  DestroyCustomStreamInfo() destroys memory associated with the
1014
%  CustomStreamInfo structure.
1015
%
1016
%  The format of the DestroyCustomStreamInfo method is:
1017
%
1018
%      CustomStreamInfo *DestroyCustomStreamInfo(CustomStreamInfo *stream_info)
1019
%
1020
%  A description of each parameter follows:
1021
%
1022
%    o custom_stream: the custom stream info.
1023
%
1024
*/
1025
MagickExport CustomStreamInfo *DestroyCustomStreamInfo(
1026
  CustomStreamInfo *custom_stream)
1027
396
{
1028
396
  assert(custom_stream != (CustomStreamInfo *) NULL);
1029
396
  assert(custom_stream->signature == MagickCoreSignature);
1030
396
  if (IsEventLogging() != MagickFalse)
1031
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1032
396
  custom_stream->signature=(~MagickCoreSignature);
1033
396
  custom_stream=(CustomStreamInfo *) RelinquishMagickMemory(custom_stream);
1034
396
  return(custom_stream);
1035
396
}
1036

1037
/*
1038
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1039
%                                                                             %
1040
%                                                                             %
1041
%                                                                             %
1042
+   D e t a c h B l o b                                                       %
1043
%                                                                             %
1044
%                                                                             %
1045
%                                                                             %
1046
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1047
%
1048
%  DetachBlob() detaches a blob from the BlobInfo structure.
1049
%
1050
%  The format of the DetachBlob method is:
1051
%
1052
%      void *DetachBlob(BlobInfo *blob_info)
1053
%
1054
%  A description of each parameter follows:
1055
%
1056
%    o blob_info: Specifies a pointer to a BlobInfo structure.
1057
%
1058
*/
1059
MagickExport void *DetachBlob(BlobInfo *blob_info)
1060
2.29M
{
1061
2.29M
  void
1062
2.29M
    *data;
1063
1064
2.29M
  assert(blob_info != (BlobInfo *) NULL);
1065
2.29M
  if (IsEventLogging() != MagickFalse)
1066
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1067
2.29M
  if (blob_info->mapped != MagickFalse)
1068
125k
    {
1069
125k
      (void) UnmapBlob(blob_info->data,blob_info->length);
1070
125k
      blob_info->data=NULL;
1071
125k
      RelinquishMagickResource(MapResource,blob_info->length);
1072
125k
    }
1073
2.29M
  blob_info->mapped=MagickFalse;
1074
2.29M
  blob_info->length=0;
1075
  /*
1076
    We should not reset blob_info->extent because we use it to check if the
1077
    blob was opened inside ImagesToBlob and ImagesToBlob.
1078
  */
1079
2.29M
  blob_info->offset=0;
1080
2.29M
  blob_info->mode=UndefinedBlobMode;
1081
2.29M
  blob_info->eof=MagickFalse;
1082
2.29M
  blob_info->error=0;
1083
2.29M
  blob_info->exempt=MagickFalse;
1084
2.29M
  blob_info->type=UndefinedStream;
1085
2.29M
  blob_info->file_info.file=(FILE *) NULL;
1086
2.29M
  data=blob_info->data;
1087
2.29M
  blob_info->data=(unsigned char *) NULL;
1088
2.29M
  blob_info->stream=(StreamHandler) NULL;
1089
2.29M
  blob_info->custom_stream=(CustomStreamInfo *) NULL;
1090
2.29M
  return(data);
1091
2.29M
}
1092

1093
/*
1094
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1095
%                                                                             %
1096
%                                                                             %
1097
%                                                                             %
1098
+   D i s a s s o c i a t e B l o b                                           %
1099
%                                                                             %
1100
%                                                                             %
1101
%                                                                             %
1102
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1103
%
1104
%  DisassociateBlob() disassociates the image stream.  It checks if the
1105
%  blob of the specified image is referenced by other images. If the reference
1106
%  count is higher then 1 a new blob is assigned to the specified image.
1107
%
1108
%  The format of the DisassociateBlob method is:
1109
%
1110
%      void DisassociateBlob(const Image *image)
1111
%
1112
%  A description of each parameter follows:
1113
%
1114
%    o image: the image.
1115
%
1116
*/
1117
1118
static inline void ResetDisassociatedBlobStorage(BlobInfo *blob_info)
1119
0
{
1120
0
  assert(blob_info != (BlobInfo *) NULL);
1121
0
  assert(blob_info->signature == MagickCoreSignature);
1122
0
  if (blob_info->mapped != MagickFalse)
1123
0
    {
1124
0
      RelinquishMagickResource(MapResource,blob_info->length);
1125
0
      blob_info->mapped=MagickFalse;
1126
0
    }
1127
0
  blob_info->data=(unsigned char *) NULL;
1128
0
  blob_info->length=0;
1129
0
  blob_info->offset=0;
1130
0
  blob_info->mode=UndefinedBlobMode;
1131
0
  blob_info->type=UndefinedStream;
1132
0
}
1133
1134
MagickExport void DisassociateBlob(Image *image)
1135
63.0k
{
1136
63.0k
  BlobInfo
1137
63.0k
    *magick_restrict blob_info,
1138
63.0k
    *clone_info;
1139
1140
63.0k
  MagickBooleanType
1141
63.0k
    clone;
1142
1143
63.0k
  assert(image != (Image *) NULL);
1144
63.0k
  assert(image->signature == MagickCoreSignature);
1145
63.0k
  assert(image->blob != (BlobInfo *) NULL);
1146
63.0k
  assert(image->blob->signature == MagickCoreSignature);
1147
63.0k
  if (IsEventLogging() != MagickFalse)
1148
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1149
63.0k
  blob_info=image->blob;
1150
63.0k
  clone=MagickFalse;
1151
63.0k
  LockSemaphoreInfo(blob_info->semaphore);
1152
63.0k
  assert(blob_info->reference_count >= 0);
1153
63.0k
  if (blob_info->reference_count > 1)
1154
0
    clone=MagickTrue;
1155
63.0k
  UnlockSemaphoreInfo(blob_info->semaphore);
1156
63.0k
  if (clone == MagickFalse)
1157
63.0k
    return;
1158
0
  clone_info=CloneBlobInfo(blob_info);
1159
0
  ResetDisassociatedBlobStorage(clone_info);
1160
0
  DestroyBlob(image);
1161
0
  image->blob=clone_info;
1162
0
}
1163

1164
/*
1165
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1166
%                                                                             %
1167
%                                                                             %
1168
%                                                                             %
1169
+  D i s c a r d B l o b B y t e s                                            %
1170
%                                                                             %
1171
%                                                                             %
1172
%                                                                             %
1173
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1174
%
1175
%  DiscardBlobBytes() discards bytes in a blob.
1176
%
1177
%  The format of the DiscardBlobBytes method is:
1178
%
1179
%      MagickBooleanType DiscardBlobBytes(Image *image,
1180
%        const MagickSizeType length)
1181
%
1182
%  A description of each parameter follows.
1183
%
1184
%    o image: the image.
1185
%
1186
%    o length:  the number of bytes to skip.
1187
%
1188
*/
1189
MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
1190
  const MagickSizeType length)
1191
8.44k
{
1192
8.44k
  MagickSizeType
1193
8.44k
    i;
1194
1195
8.44k
  size_t
1196
8.44k
    quantum;
1197
1198
8.44k
  ssize_t
1199
8.44k
    count;
1200
1201
8.44k
  unsigned char
1202
8.44k
    buffer[MagickMinBufferExtent >> 1];
1203
1204
8.44k
  assert(image != (Image *) NULL);
1205
8.44k
  assert(image->signature == MagickCoreSignature);
1206
8.44k
  if (length != (MagickSizeType) ((MagickOffsetType) length))
1207
0
    return(MagickFalse);
1208
8.44k
  count=0;
1209
13.2k
  for (i=0; i < length; i+=(MagickSizeType) count)
1210
5.84k
  {
1211
5.84k
    quantum=(size_t) MagickMin(length-i,sizeof(buffer));
1212
5.84k
    (void) ReadBlobStream(image,quantum,buffer,&count);
1213
5.84k
    if (count <= 0)
1214
1.06k
      {
1215
1.06k
        if (count == 0)
1216
1.06k
          break; /* EOF is terminal, errno may hold a stale EINTR */
1217
0
        count=0;
1218
0
        if (errno != EINTR)
1219
0
          break;
1220
0
      }
1221
5.84k
  }
1222
8.44k
  return(i < (MagickSizeType) length ? MagickFalse : MagickTrue);
1223
8.44k
}
1224

1225
/*
1226
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1227
%                                                                             %
1228
%                                                                             %
1229
%                                                                             %
1230
+   D u p l i c a t e s B l o b                                               %
1231
%                                                                             %
1232
%                                                                             %
1233
%                                                                             %
1234
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1235
%
1236
%  DuplicateBlob() duplicates a blob descriptor.
1237
%
1238
%  The format of the DuplicateBlob method is:
1239
%
1240
%      void DuplicateBlob(Image *image,const Image *duplicate)
1241
%
1242
%  A description of each parameter follows:
1243
%
1244
%    o image: the image.
1245
%
1246
%    o duplicate: the duplicate image.
1247
%
1248
*/
1249
MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
1250
8.89k
{
1251
8.89k
  assert(image != (Image *) NULL);
1252
8.89k
  assert(image->signature == MagickCoreSignature);
1253
8.89k
  assert(duplicate != (Image *) NULL);
1254
8.89k
  assert(duplicate->signature == MagickCoreSignature);
1255
8.89k
  if (IsEventLogging() != MagickFalse)
1256
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1257
8.89k
  DestroyBlob(image);
1258
8.89k
  image->blob=ReferenceBlob(duplicate->blob);
1259
8.89k
}
1260

1261
/*
1262
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1263
%                                                                             %
1264
%                                                                             %
1265
%                                                                             %
1266
+  E O F B l o b                                                              %
1267
%                                                                             %
1268
%                                                                             %
1269
%                                                                             %
1270
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1271
%
1272
%  EOFBlob() returns a non-zero value when EOF has been detected reading from
1273
%  a blob or file.
1274
%
1275
%  The format of the EOFBlob method is:
1276
%
1277
%      int EOFBlob(const Image *image)
1278
%
1279
%  A description of each parameter follows:
1280
%
1281
%    o image: the image.
1282
%
1283
*/
1284
MagickExport int EOFBlob(const Image *image)
1285
8.44M
{
1286
8.44M
  BlobInfo
1287
8.44M
    *magick_restrict blob_info;
1288
1289
8.44M
  assert(image != (Image *) NULL);
1290
8.44M
  assert(image->signature == MagickCoreSignature);
1291
8.44M
  assert(image->blob != (BlobInfo *) NULL);
1292
8.44M
  assert(image->blob->type != UndefinedStream);
1293
8.44M
  if (IsEventLogging() != MagickFalse)
1294
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1295
8.44M
  blob_info=image->blob;
1296
8.44M
  switch (blob_info->type)
1297
8.44M
  {
1298
0
    case UndefinedStream:
1299
0
    case StandardStream:
1300
0
      break;
1301
426k
    case FileStream:
1302
426k
    case PipeStream:
1303
426k
    {
1304
426k
      blob_info->eof=feof(blob_info->file_info.file) != 0 ? MagickTrue :
1305
426k
        MagickFalse;
1306
426k
      break;
1307
426k
    }
1308
4.29M
    case ZipStream:
1309
4.29M
    {
1310
4.29M
#if defined(MAGICKCORE_ZLIB_DELEGATE)
1311
4.29M
      blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
1312
4.29M
        MagickFalse;
1313
4.29M
#endif
1314
4.29M
      break;
1315
426k
    }
1316
0
    case BZipStream:
1317
0
    {
1318
#if defined(MAGICKCORE_BZLIB_DELEGATE)
1319
      int
1320
        status;
1321
1322
      status=0;
1323
      (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
1324
      if (status == BZ_UNEXPECTED_EOF)
1325
        blob_info->eof=MagickTrue;
1326
#endif
1327
0
      break;
1328
426k
    }
1329
0
    case FifoStream:
1330
0
    {
1331
0
      blob_info->eof=MagickFalse;
1332
0
      break;
1333
426k
    }
1334
3.72M
    case BlobStream:
1335
3.72M
      break;
1336
396
    case CustomStream:
1337
396
      break;
1338
8.44M
  }
1339
8.44M
  return((int) blob_info->eof);
1340
8.44M
}
1341

1342
/*
1343
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1344
%                                                                             %
1345
%                                                                             %
1346
%                                                                             %
1347
+  E r r o r B l o b                                                          %
1348
%                                                                             %
1349
%                                                                             %
1350
%                                                                             %
1351
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1352
%
1353
%  ErrorBlob() returns a non-zero value when an error has been detected reading
1354
%  from a blob or file.
1355
%
1356
%  The format of the ErrorBlob method is:
1357
%
1358
%      int ErrorBlob(const Image *image)
1359
%
1360
%  A description of each parameter follows:
1361
%
1362
%    o image: the image.
1363
%
1364
*/
1365
MagickExport int ErrorBlob(const Image *image)
1366
0
{
1367
0
  BlobInfo
1368
0
    *magick_restrict blob_info;
1369
1370
0
  assert(image != (Image *) NULL);
1371
0
  assert(image->signature == MagickCoreSignature);
1372
0
  assert(image->blob != (BlobInfo *) NULL);
1373
0
  assert(image->blob->type != UndefinedStream);
1374
0
  if (IsEventLogging() != MagickFalse)
1375
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1376
0
  blob_info=image->blob;
1377
0
  switch (blob_info->type)
1378
0
  {
1379
0
    case UndefinedStream:
1380
0
    case StandardStream:
1381
0
      break;
1382
0
    case FileStream:
1383
0
    case PipeStream:
1384
0
    {
1385
0
      blob_info->error=ferror(blob_info->file_info.file);
1386
0
      break;
1387
0
    }
1388
0
    case ZipStream:
1389
0
    {
1390
0
#if defined(MAGICKCORE_ZLIB_DELEGATE)
1391
0
      (void) gzerror(blob_info->file_info.gzfile,&blob_info->error);
1392
0
#endif
1393
0
      break;
1394
0
    }
1395
0
    case BZipStream:
1396
0
    {
1397
#if defined(MAGICKCORE_BZLIB_DELEGATE)
1398
      (void) BZ2_bzerror(blob_info->file_info.bzfile,&blob_info->error);
1399
#endif
1400
0
      break;
1401
0
    }
1402
0
    case FifoStream:
1403
0
    {
1404
0
      blob_info->error=0;
1405
0
      break;
1406
0
    }
1407
0
    case BlobStream:
1408
0
      break;
1409
0
    case CustomStream:
1410
0
      break;
1411
0
  }
1412
0
  return(blob_info->error);
1413
0
}
1414

1415
/*
1416
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1417
%                                                                             %
1418
%                                                                             %
1419
%                                                                             %
1420
%   F i l e T o B l o b                                                       %
1421
%                                                                             %
1422
%                                                                             %
1423
%                                                                             %
1424
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1425
%
1426
%  FileToBlob() returns the contents of a file as a buffer terminated with
1427
%  the '\0' character.  The length of the buffer (not including the extra
1428
%  terminating '\0' character) is returned via the 'length' parameter.  Free
1429
%  the buffer with RelinquishMagickMemory().
1430
%
1431
%  The format of the FileToBlob method is:
1432
%
1433
%      void *FileToBlob(const char *filename,const size_t extent,
1434
%        size_t *length,ExceptionInfo *exception)
1435
%
1436
%  A description of each parameter follows:
1437
%
1438
%    o blob:  FileToBlob() returns the contents of a file as a blob.  If
1439
%      an error occurs NULL is returned.
1440
%
1441
%    o filename: the filename.
1442
%
1443
%    o extent:  The maximum length of the blob.
1444
%
1445
%    o length: On return, this reflects the actual length of the blob.
1446
%
1447
%    o exception: return any errors or warnings in this structure.
1448
%
1449
*/
1450
MagickExport void *FileToBlob(const char *filename,const size_t extent,
1451
  size_t *length,ExceptionInfo *exception)
1452
863
{
1453
863
  int
1454
863
    file;
1455
1456
863
  MagickBooleanType
1457
863
    status;
1458
1459
863
  MagickOffsetType
1460
863
    offset;
1461
1462
863
  size_t
1463
863
    i;
1464
1465
863
  ssize_t
1466
863
    count;
1467
1468
863
  struct stat
1469
863
    attributes;
1470
1471
863
  unsigned char
1472
863
    *blob;
1473
1474
863
  void
1475
863
    *map;
1476
1477
863
  assert(filename != (const char *) NULL);
1478
863
  assert(exception != (ExceptionInfo *) NULL);
1479
863
  assert(exception->signature == MagickCoreSignature);
1480
863
  if (IsEventLogging() != MagickFalse)
1481
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1482
863
  *length=0;
1483
863
  if (IsPathAuthorized(ReadPolicyRights,filename) == MagickFalse)
1484
863
    ThrowPolicyException(filename,NULL);
1485
863
  file=fileno(stdin);
1486
863
  if (LocaleCompare(filename,"-") != 0)
1487
830
    {
1488
830
      int
1489
830
        flags = O_RDONLY | O_CLOEXEC | O_BINARY;
1490
1491
830
      status=GetPathAttributes(filename,&attributes);
1492
830
      if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
1493
55
        {
1494
55
          ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1495
55
          return(NULL);
1496
55
        }
1497
775
      file=open_utf8(filename,flags,0);
1498
775
    }
1499
808
  if (file == -1)
1500
0
    {
1501
0
      ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1502
0
      return(NULL);
1503
0
    }
1504
808
  if (IsPathAuthorized(ReadPolicyRights,filename) == MagickFalse)
1505
0
    {
1506
0
      file=close_utf8(file)-1;
1507
0
      ThrowPolicyException(filename,NULL);
1508
0
    }
1509
808
  offset=(MagickOffsetType) lseek(file,0,SEEK_END);
1510
808
  count=0;
1511
808
  if ((file == fileno(stdin)) || (offset < 0) ||
1512
775
      (offset != (MagickOffsetType) ((ssize_t) offset)))
1513
33
    {
1514
33
      size_t
1515
33
        quantum;
1516
1517
33
      struct stat
1518
33
        file_stats;
1519
1520
      /*
1521
        Stream is not seekable.
1522
      */
1523
33
      offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1524
33
      quantum=(size_t) MagickMaxBufferExtent;
1525
33
      if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1526
0
        quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1527
33
      blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1528
33
      for (i=0; blob != (unsigned char *) NULL; i+=(size_t) count)
1529
33
      {
1530
33
        count=MagickRead(file,blob+i,quantum);
1531
33
        if (count <= 0)
1532
33
          break;
1533
0
        if (~i < ((size_t) count+quantum+1))
1534
0
          {
1535
0
            blob=(unsigned char *) RelinquishMagickMemory(blob);
1536
0
            break;
1537
0
          }
1538
0
        blob=(unsigned char *) ResizeQuantumMemory(blob,i+(size_t) count+
1539
0
          quantum+1,sizeof(*blob));
1540
0
        if ((i+(size_t) count) >= extent)
1541
0
          break;
1542
0
      }
1543
33
      if (LocaleCompare(filename,"-") != 0)
1544
0
        file=close_utf8(file);
1545
33
      if (blob == (unsigned char *) NULL)
1546
0
        {
1547
0
          (void) ThrowMagickException(exception,GetMagickModule(),
1548
0
            ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1549
0
          return(NULL);
1550
0
        }
1551
33
      if ((count < 0) || (file == -1))
1552
0
        {
1553
0
          blob=(unsigned char *) RelinquishMagickMemory(blob);
1554
0
          ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1555
0
          return(NULL);
1556
0
        }
1557
33
      *length=(size_t) MagickMin(i+(size_t) count,extent);
1558
33
      blob[*length]='\0';
1559
33
      return(blob);
1560
33
    }
1561
775
  *length=(size_t) MagickMin(offset,(MagickOffsetType)
1562
775
    MagickMin(extent,(size_t) MAGICK_SSIZE_MAX));
1563
775
  blob=(unsigned char *) NULL;
1564
775
  if (~(*length) >= (MagickPathExtent-1))
1565
775
    blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
1566
775
      sizeof(*blob));
1567
775
  if (blob == (unsigned char *) NULL)
1568
0
    {
1569
0
      file=close_utf8(file);
1570
0
      (void) ThrowMagickException(exception,GetMagickModule(),
1571
0
        ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1572
0
      return(NULL);
1573
0
    }
1574
775
  map=MapBlob(file,ReadMode,0,*length);
1575
775
  if (map != (unsigned char *) NULL)
1576
775
    {
1577
775
      (void) memcpy(blob,map,*length);
1578
775
      (void) UnmapBlob(map,*length);
1579
775
    }
1580
0
  else
1581
0
    {
1582
0
      (void) lseek(file,0,SEEK_SET);
1583
0
      for (i=0; i < *length; i+=(size_t) count)
1584
0
      {
1585
0
        count=MagickRead(file,blob+i,(size_t) MagickMin(*length-i,(size_t)
1586
0
          MagickMaxBufferExtent));
1587
0
        if (count <= 0)
1588
0
          break;
1589
0
      }
1590
0
      if (i < *length)
1591
0
        {
1592
0
          file=close_utf8(file)-1;
1593
0
          blob=(unsigned char *) RelinquishMagickMemory(blob);
1594
0
          ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1595
0
          return(NULL);
1596
0
        }
1597
0
    }
1598
775
  blob[*length]='\0';
1599
775
  if (LocaleCompare(filename,"-") != 0)
1600
775
    file=close_utf8(file);
1601
775
  if (file == -1)
1602
0
    {
1603
0
      blob=(unsigned char *) RelinquishMagickMemory(blob);
1604
0
      ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1605
0
    }
1606
775
  return(blob);
1607
775
}
1608

1609
/*
1610
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1611
%                                                                             %
1612
%                                                                             %
1613
%                                                                             %
1614
%   F i l e T o I m a g e                                                     %
1615
%                                                                             %
1616
%                                                                             %
1617
%                                                                             %
1618
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1619
%
1620
%  FileToImage() write the contents of a file to an image.
1621
%
1622
%  The format of the FileToImage method is:
1623
%
1624
%      MagickBooleanType FileToImage(Image *,const char *filename)
1625
%
1626
%  A description of each parameter follows:
1627
%
1628
%    o image: the image.
1629
%
1630
%    o filename: the filename.
1631
%
1632
*/
1633
1634
static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1635
  const void *magick_restrict data)
1636
386M
{
1637
386M
  BlobInfo
1638
386M
    *magick_restrict blob_info;
1639
1640
386M
  MagickSizeType
1641
386M
    extent;
1642
1643
386M
  unsigned char
1644
386M
    *magick_restrict q;
1645
1646
386M
  assert(image->blob != (BlobInfo *) NULL);
1647
386M
  assert(image->blob->type != UndefinedStream);
1648
386M
  assert(data != NULL);
1649
386M
  blob_info=image->blob;
1650
386M
  if (blob_info->type != BlobStream)
1651
12.3k
    return(WriteBlob(image,length,(const unsigned char *) data));
1652
386M
  if (blob_info->offset > (MagickOffsetType) (MAGICK_SSIZE_MAX-length))
1653
0
    {
1654
0
      errno=EOVERFLOW;
1655
0
      return(0);
1656
0
    }
1657
386M
  extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
1658
386M
  if (extent >= blob_info->extent)
1659
18.0k
    {
1660
18.0k
      extent+=blob_info->quantum+length;
1661
18.0k
      blob_info->quantum<<=1;
1662
18.0k
      if (SetBlobExtent(image,extent) == MagickFalse)
1663
0
        return(0);
1664
18.0k
    }
1665
386M
  q=blob_info->data+blob_info->offset;
1666
386M
  (void) memcpy(q,data,length);
1667
386M
  blob_info->offset+=(MagickOffsetType) length;
1668
386M
  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
1669
386M
    blob_info->length=(size_t) blob_info->offset;
1670
386M
  return((ssize_t) length);
1671
386M
}
1672
1673
MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1674
  ExceptionInfo *exception)
1675
0
{
1676
0
  int
1677
0
    file;
1678
1679
0
  size_t
1680
0
    length,
1681
0
    quantum;
1682
1683
0
  ssize_t
1684
0
    count;
1685
1686
0
  struct stat
1687
0
    file_stats;
1688
1689
0
  unsigned char
1690
0
    *blob;
1691
1692
0
  assert(image != (const Image *) NULL);
1693
0
  assert(image->signature == MagickCoreSignature);
1694
0
  assert(filename != (const char *) NULL);
1695
0
  if (IsEventLogging() != MagickFalse)
1696
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1697
0
  if (IsPathAuthorized(ReadPolicyRights,filename) == MagickFalse)
1698
0
    ThrowPolicyException(filename,MagickFalse);
1699
0
  file=fileno(stdin);
1700
0
  if (LocaleCompare(filename,"-") != 0)
1701
0
    {
1702
0
      int
1703
0
        flags = O_RDONLY | O_CLOEXEC | O_BINARY;
1704
1705
0
      file=open_utf8(filename,flags,0);
1706
0
    }
1707
0
  if (file == -1)
1708
0
    {
1709
0
      ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1710
0
      return(MagickFalse);
1711
0
    }
1712
0
  if (IsPathAuthorized(ReadPolicyRights,filename) == MagickFalse)
1713
0
    ThrowPolicyException(filename,MagickFalse);
1714
0
  quantum=(size_t) MagickMaxBufferExtent;
1715
0
  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1716
0
    quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1717
0
  blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1718
0
  if (blob == (unsigned char *) NULL)
1719
0
    {
1720
0
      file=close_utf8(file);
1721
0
      ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1722
0
        filename);
1723
0
      return(MagickFalse);
1724
0
    }
1725
0
  for ( ; ; )
1726
0
  {
1727
0
    count=MagickRead(file,blob,quantum);
1728
0
    if (count <= 0)
1729
0
      break;
1730
0
    length=(size_t) count;
1731
0
    count=WriteBlobStream(image,length,blob);
1732
0
    if (count != (ssize_t) length)
1733
0
      {
1734
0
        ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1735
0
        break;
1736
0
      }
1737
0
  }
1738
0
  file=close_utf8(file);
1739
0
  if (file == -1)
1740
0
    ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1741
0
  blob=(unsigned char *) RelinquishMagickMemory(blob);
1742
0
  return(MagickTrue);
1743
0
}
1744

1745
/*
1746
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1747
%                                                                             %
1748
%                                                                             %
1749
%                                                                             %
1750
+   G e t B l o b E r r o r                                                   %
1751
%                                                                             %
1752
%                                                                             %
1753
%                                                                             %
1754
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1755
%
1756
%  GetBlobError() returns MagickTrue if the blob associated with the specified
1757
%  image encountered an error.
1758
%
1759
%  The format of the GetBlobError method is:
1760
%
1761
%       MagickBooleanType GetBlobError(const Image *image)
1762
%
1763
%  A description of each parameter follows:
1764
%
1765
%    o image: the image.
1766
%
1767
*/
1768
MagickExport MagickBooleanType GetBlobError(const Image *image)
1769
258k
{
1770
258k
  assert(image != (const Image *) NULL);
1771
258k
  assert(image->signature == MagickCoreSignature);
1772
258k
  if (IsEventLogging() != MagickFalse)
1773
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1774
258k
  if ((image->blob->status != 0) && (image->blob->error_number != 0))
1775
258k
    errno=image->blob->error_number;
1776
258k
  return(image->blob->status == 0 ? MagickFalse : MagickTrue);
1777
258k
}
1778

1779
/*
1780
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781
%                                                                             %
1782
%                                                                             %
1783
%                                                                             %
1784
+   G e t B l o b F i l e H a n d l e                                         %
1785
%                                                                             %
1786
%                                                                             %
1787
%                                                                             %
1788
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1789
%
1790
%  GetBlobFileHandle() returns the stdio file handle associated with the image
1791
%  blob. If the blob is not backed by a FILE object, NULL is returned.
1792
%
1793
%  The format of the GetBlobFile method is:
1794
%
1795
%      FILE *GetBlobFileHandle(const Image *image)
1796
%
1797
%  A description of each parameter follows:
1798
%
1799
%    o image: the image.
1800
%
1801
*/
1802
MagickExport FILE *GetBlobFileHandle(const Image *image)
1803
0
{
1804
0
  assert(image != (const Image *) NULL);
1805
0
  assert(image->signature == MagickCoreSignature);
1806
0
  assert(image->blob != (BlobInfo *) NULL);
1807
0
  assert(image->blob->signature == MagickCoreSignature);
1808
0
  switch (image->blob->type)
1809
0
  {
1810
0
    case StandardStream:
1811
0
    case FileStream:
1812
0
    case PipeStream:
1813
0
     return(image->blob->file_info.file);
1814
0
    case UndefinedStream:
1815
0
    case ZipStream:
1816
0
    case BZipStream:
1817
0
    case FifoStream:
1818
0
    case BlobStream:
1819
0
    case CustomStream:
1820
0
      break;
1821
0
  }
1822
0
  return((FILE *) NULL);
1823
0
}
1824

1825
/*
1826
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1827
%                                                                             %
1828
%                                                                             %
1829
%                                                                             %
1830
+   G e t B l o b I n f o                                                     %
1831
%                                                                             %
1832
%                                                                             %
1833
%                                                                             %
1834
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1835
%
1836
%  GetBlobInfo() initializes the BlobInfo structure.
1837
%
1838
%  The format of the GetBlobInfo method is:
1839
%
1840
%      void GetBlobInfo(BlobInfo *blob_info)
1841
%
1842
%  A description of each parameter follows:
1843
%
1844
%    o blob_info: Specifies a pointer to a BlobInfo structure.
1845
%
1846
*/
1847
MagickExport void GetBlobInfo(BlobInfo *blob_info)
1848
2.97M
{
1849
2.97M
  assert(blob_info != (BlobInfo *) NULL);
1850
2.97M
  (void) memset(blob_info,0,sizeof(*blob_info));
1851
2.97M
  blob_info->type=UndefinedStream;
1852
2.97M
  blob_info->quantum=(size_t) MagickMaxBlobExtent;
1853
2.97M
  blob_info->properties.st_mtime=GetMagickTime();
1854
2.97M
  blob_info->properties.st_ctime=blob_info->properties.st_mtime;
1855
2.97M
  blob_info->debug=GetLogEventMask() & BlobEvent ? MagickTrue : MagickFalse;
1856
2.97M
  blob_info->reference_count=1;
1857
2.97M
  blob_info->semaphore=AcquireSemaphoreInfo();
1858
2.97M
  blob_info->signature=MagickCoreSignature;
1859
2.97M
}
1860

1861
/*
1862
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1863
%                                                                             %
1864
%                                                                             %
1865
%                                                                             %
1866
%  G e t B l o b P r o p e r t i e s                                          %
1867
%                                                                             %
1868
%                                                                             %
1869
%                                                                             %
1870
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1871
%
1872
%  GetBlobProperties() returns information about an image blob.
1873
%
1874
%  The format of the GetBlobProperties method is:
1875
%
1876
%      const struct stat *GetBlobProperties(const Image *image)
1877
%
1878
%  A description of each parameter follows:
1879
%
1880
%    o image: the image.
1881
%
1882
*/
1883
MagickExport const struct stat *GetBlobProperties(const Image *image)
1884
444k
{
1885
444k
  assert(image != (Image *) NULL);
1886
444k
  assert(image->signature == MagickCoreSignature);
1887
444k
  if (IsEventLogging() != MagickFalse)
1888
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1889
444k
  return(&image->blob->properties);
1890
444k
}
1891

1892
/*
1893
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1894
%                                                                             %
1895
%                                                                             %
1896
%                                                                             %
1897
+  G e t B l o b S i z e                                                      %
1898
%                                                                             %
1899
%                                                                             %
1900
%                                                                             %
1901
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1902
%
1903
%  GetBlobSize() returns the current length of the image file or blob; zero is
1904
%  returned if the size cannot be determined.
1905
%
1906
%  The format of the GetBlobSize method is:
1907
%
1908
%      MagickSizeType GetBlobSize(const Image *image)
1909
%
1910
%  A description of each parameter follows:
1911
%
1912
%    o image: the image.
1913
%
1914
*/
1915
MagickExport MagickSizeType GetBlobSize(const Image *image)
1916
94.6M
{
1917
94.6M
  BlobInfo
1918
94.6M
    *magick_restrict blob_info;
1919
1920
94.6M
  MagickSizeType
1921
94.6M
    extent;
1922
1923
94.6M
  assert(image != (Image *) NULL);
1924
94.6M
  assert(image->signature == MagickCoreSignature);
1925
94.6M
  assert(image->blob != (BlobInfo *) NULL);
1926
94.6M
  if (IsEventLogging() != MagickFalse)
1927
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1928
94.6M
  blob_info=image->blob;
1929
94.6M
  extent=0;
1930
94.6M
  switch (blob_info->type)
1931
94.6M
  {
1932
4.88k
    case UndefinedStream:
1933
4.88k
    case StandardStream:
1934
4.88k
    {
1935
4.88k
      extent=blob_info->size;
1936
4.88k
      break;
1937
4.88k
    }
1938
835k
    case FileStream:
1939
835k
    {
1940
835k
      int
1941
835k
        file_descriptor;
1942
1943
835k
      extent=(MagickSizeType) blob_info->properties.st_size;
1944
835k
      if (extent == 0)
1945
45.9k
        extent=blob_info->size;
1946
835k
      file_descriptor=fileno(blob_info->file_info.file);
1947
835k
      if (file_descriptor == -1)
1948
0
        break;
1949
835k
      if (fstat(file_descriptor,&blob_info->properties) == 0)
1950
835k
        extent=(MagickSizeType) blob_info->properties.st_size;
1951
835k
      break;
1952
835k
    }
1953
0
    case PipeStream:
1954
0
    {
1955
0
      extent=blob_info->size;
1956
0
      break;
1957
835k
    }
1958
166k
    case ZipStream:
1959
166k
    case BZipStream:
1960
166k
    {
1961
166k
      MagickBooleanType
1962
166k
        status;
1963
1964
166k
      status=GetPathAttributes(image->filename,&blob_info->properties);
1965
166k
      if (status != MagickFalse)
1966
166k
        extent=(MagickSizeType) blob_info->properties.st_size;
1967
166k
      break;
1968
166k
    }
1969
0
    case FifoStream:
1970
0
      break;
1971
93.6M
    case BlobStream:
1972
93.6M
    {
1973
93.6M
      extent=(MagickSizeType) blob_info->length;
1974
93.6M
      break;
1975
166k
    }
1976
631
    case CustomStream:
1977
631
    {
1978
631
      if ((blob_info->custom_stream->teller != (CustomStreamTeller) NULL) &&
1979
631
          (blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL))
1980
631
        {
1981
631
          MagickOffsetType
1982
631
            offset;
1983
1984
631
          offset=blob_info->custom_stream->teller(
1985
631
            blob_info->custom_stream->data);
1986
631
          extent=(MagickSizeType) blob_info->custom_stream->seeker(0,SEEK_END,
1987
631
            blob_info->custom_stream->data);
1988
631
          (void) blob_info->custom_stream->seeker(offset,SEEK_SET,
1989
631
            blob_info->custom_stream->data);
1990
631
        }
1991
631
      break;
1992
166k
    }
1993
94.6M
  }
1994
94.6M
  return(extent);
1995
94.6M
}
1996

1997
/*
1998
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1999
%                                                                             %
2000
%                                                                             %
2001
%                                                                             %
2002
+   G e t B l o b S t r e a m D a t a                                         %
2003
%                                                                             %
2004
%                                                                             %
2005
%                                                                             %
2006
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2007
%
2008
%  GetBlobStreamData() returns the stream data for the image.
2009
%
2010
%  The format of the GetBlobStreamData method is:
2011
%
2012
%      void *GetBlobStreamData(const Image *image)
2013
%
2014
%  A description of each parameter follows:
2015
%
2016
%    o image: the image.
2017
%
2018
*/
2019
MagickExport void *GetBlobStreamData(const Image *image)
2020
123k
{
2021
123k
  assert(image != (const Image *) NULL);
2022
123k
  assert(image->signature == MagickCoreSignature);
2023
123k
  return(image->blob->data);
2024
123k
}
2025

2026
/*
2027
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2028
%                                                                             %
2029
%                                                                             %
2030
%                                                                             %
2031
+   G e t B l o b S t r e a m H a n d l e r                                   %
2032
%                                                                             %
2033
%                                                                             %
2034
%                                                                             %
2035
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2036
%
2037
%  GetBlobStreamHandler() returns the stream handler for the image.
2038
%
2039
%  The format of the GetBlobStreamHandler method is:
2040
%
2041
%      StreamHandler GetBlobStreamHandler(const Image *image)
2042
%
2043
%  A description of each parameter follows:
2044
%
2045
%    o image: the image.
2046
%
2047
*/
2048
MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
2049
4.43M
{
2050
4.43M
  assert(image != (const Image *) NULL);
2051
4.43M
  assert(image->signature == MagickCoreSignature);
2052
4.43M
  if (IsEventLogging() != MagickFalse)
2053
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2054
4.43M
  return(image->blob->stream);
2055
4.43M
}
2056

2057
/*
2058
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2059
%                                                                             %
2060
%                                                                             %
2061
%                                                                             %
2062
%   I m a g e T o B l o b                                                     %
2063
%                                                                             %
2064
%                                                                             %
2065
%                                                                             %
2066
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2067
%
2068
%  ImageToBlob() implements direct to memory image formats.  It returns the
2069
%  image as a formatted blob and its length.  The magick member of the Image
2070
%  structure determines the format of the returned blob (GIF, JPEG, PNG,
2071
%  etc.).  This method is the equivalent of WriteImage(), but writes the
2072
%  formatted "file" to a memory buffer rather than to an actual file.
2073
%
2074
%  The format of the ImageToBlob method is:
2075
%
2076
%      void *ImageToBlob(const ImageInfo *image_info,Image *image,
2077
%        size_t *length,ExceptionInfo *exception)
2078
%
2079
%  A description of each parameter follows:
2080
%
2081
%    o image_info: the image info.
2082
%
2083
%    o image: the image.
2084
%
2085
%    o length: return the actual length of the blob.
2086
%
2087
%    o exception: return any errors or warnings in this structure.
2088
%
2089
*/
2090
MagickExport void *ImageToBlob(const ImageInfo *image_info,
2091
  Image *image,size_t *length,ExceptionInfo *exception)
2092
25.1k
{
2093
25.1k
  const MagickInfo
2094
25.1k
    *magick_info;
2095
2096
25.1k
  ImageInfo
2097
25.1k
    *blob_info;
2098
2099
25.1k
  MagickBooleanType
2100
25.1k
    status;
2101
2102
25.1k
  void
2103
25.1k
    *blob;
2104
2105
25.1k
  assert(image_info != (const ImageInfo *) NULL);
2106
25.1k
  assert(image_info->signature == MagickCoreSignature);
2107
25.1k
  assert(image != (Image *) NULL);
2108
25.1k
  assert(image->signature == MagickCoreSignature);
2109
25.1k
  assert(exception != (ExceptionInfo *) NULL);
2110
25.1k
  assert(exception->signature == MagickCoreSignature);
2111
25.1k
  if (IsEventLogging() != MagickFalse)
2112
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2113
0
      image_info->filename);
2114
25.1k
  *length=0;
2115
25.1k
  blob=(unsigned char *) NULL;
2116
25.1k
  blob_info=CloneImageInfo(image_info);
2117
25.1k
  blob_info->adjoin=MagickFalse;
2118
25.1k
  (void) SetImageInfo(blob_info,1,exception);
2119
25.1k
  if (*blob_info->magick != '\0')
2120
25.1k
    (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
2121
25.1k
  magick_info=GetMagickInfo(image->magick,exception);
2122
25.1k
  if (magick_info == (const MagickInfo *) NULL)
2123
0
    {
2124
0
      (void) ThrowMagickException(exception,GetMagickModule(),
2125
0
        MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2126
0
        image->magick);
2127
0
      blob_info=DestroyImageInfo(blob_info);
2128
0
      return(blob);
2129
0
    }
2130
25.1k
  (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
2131
25.1k
  if (GetMagickBlobSupport(magick_info) != MagickFalse)
2132
25.1k
    {
2133
      /*
2134
        Native blob support for this image format.
2135
      */
2136
25.1k
      blob_info->length=0;
2137
25.1k
      blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
2138
25.1k
        sizeof(unsigned char));
2139
25.1k
      if (blob_info->blob == NULL)
2140
0
        (void) ThrowMagickException(exception,GetMagickModule(),
2141
0
          ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
2142
25.1k
      else
2143
25.1k
        {
2144
25.1k
          (void) CloseBlob(image);
2145
25.1k
          image->blob->exempt=MagickTrue;
2146
25.1k
          image->blob->extent=0;
2147
25.1k
          *image->filename='\0';
2148
25.1k
          status=WriteImage(blob_info,image,exception);
2149
25.1k
          SyncBlobStream(blob_info,image,image);
2150
25.1k
          *length=image->blob->length;
2151
25.1k
          blob=DetachBlob(image->blob);
2152
25.1k
          if (blob != (void *) NULL)
2153
25.1k
            {
2154
25.1k
              if (status == MagickFalse)
2155
140
                blob=RelinquishMagickMemory(blob);
2156
24.9k
              else
2157
24.9k
                blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2158
25.1k
            }
2159
0
          else
2160
0
            if ((status == MagickFalse) && (image->blob->extent == 0))
2161
0
              blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2162
25.1k
        }
2163
25.1k
    }
2164
0
  else
2165
0
    {
2166
0
      char
2167
0
        unique[MagickPathExtent];
2168
2169
0
      int
2170
0
        file;
2171
2172
      /*
2173
        Write file to disk in blob image format.
2174
      */
2175
0
      file=AcquireUniqueFileResource(unique);
2176
0
      if (file == -1)
2177
0
        {
2178
0
          ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2179
0
            image_info->filename);
2180
0
        }
2181
0
      else
2182
0
        {
2183
0
          blob_info->file=fdopen(file,"wb");
2184
0
          if (blob_info->file != (FILE *) NULL)
2185
0
            {
2186
0
              (void) FormatLocaleString(image->filename,MagickPathExtent,
2187
0
                "%s:%s",image->magick,unique);
2188
0
              status=WriteImage(blob_info,image,exception);
2189
0
              (void) fclose(blob_info->file);
2190
0
              if (status != MagickFalse)
2191
0
                blob=FileToBlob(unique,SIZE_MAX,length,exception);
2192
0
            }
2193
0
          (void) RelinquishUniqueFileResource(unique);
2194
0
        }
2195
0
    }
2196
25.1k
  blob_info=DestroyImageInfo(blob_info);
2197
25.1k
  return(blob);
2198
25.1k
}
2199

2200
/*
2201
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2202
%                                                                             %
2203
%                                                                             %
2204
%                                                                             %
2205
+  I m a g e T o C u s t o m S t r e a m                                      %
2206
%                                                                             %
2207
%                                                                             %
2208
%                                                                             %
2209
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2210
%
2211
%  ImageToCustomStream() is the equivalent of WriteImage(), but writes the
2212
%  formatted "file" to the custom stream rather than to an actual file.
2213
%
2214
%  The format of the ImageToCustomStream method is:
2215
%
2216
%      void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2217
%        ExceptionInfo *exception)
2218
%
2219
%  A description of each parameter follows:
2220
%
2221
%    o image_info: the image info.
2222
%
2223
%    o image: the image.
2224
%
2225
%    o exception: return any errors or warnings in this structure.
2226
%
2227
*/
2228
MagickExport void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2229
  ExceptionInfo *exception)
2230
0
{
2231
0
  const MagickInfo
2232
0
    *magick_info;
2233
2234
0
  ImageInfo
2235
0
    *clone_info;
2236
2237
0
  MagickBooleanType
2238
0
    blob_support,
2239
0
    status;
2240
2241
0
  assert(image_info != (const ImageInfo *) NULL);
2242
0
  assert(image_info->signature == MagickCoreSignature);
2243
0
  assert(image != (Image *) NULL);
2244
0
  assert(image->signature == MagickCoreSignature);
2245
0
  assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2246
0
  assert(image_info->custom_stream->signature == MagickCoreSignature);
2247
0
  assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2248
0
  assert(exception != (ExceptionInfo *) NULL);
2249
0
  if (IsEventLogging() != MagickFalse)
2250
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2251
0
      image_info->filename);
2252
0
  clone_info=CloneImageInfo(image_info);
2253
0
  clone_info->adjoin=MagickFalse;
2254
0
  (void) SetImageInfo(clone_info,1,exception);
2255
0
  if (*clone_info->magick != '\0')
2256
0
    (void) CopyMagickString(image->magick,clone_info->magick,MagickPathExtent);
2257
0
  magick_info=GetMagickInfo(image->magick,exception);
2258
0
  if (magick_info == (const MagickInfo *) NULL)
2259
0
    {
2260
0
      (void) ThrowMagickException(exception,GetMagickModule(),
2261
0
        MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2262
0
        image->magick);
2263
0
      clone_info=DestroyImageInfo(clone_info);
2264
0
      return;
2265
0
    }
2266
0
  (void) CopyMagickString(clone_info->magick,image->magick,MagickPathExtent);
2267
0
  blob_support=GetMagickBlobSupport(magick_info);
2268
0
  if ((blob_support != MagickFalse) &&
2269
0
      (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2270
0
    {
2271
0
      if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2272
0
          (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2273
0
        blob_support=MagickFalse;
2274
0
    }
2275
0
  if (blob_support != MagickFalse)
2276
0
    {
2277
      /*
2278
        Native blob support for this image format.
2279
      */
2280
0
      (void) CloseBlob(image);
2281
0
      *image->filename='\0';
2282
0
      if (WriteImage(clone_info,image,exception) == MagickFalse)
2283
0
        {
2284
0
          (void) ThrowMagickException(exception,GetMagickModule(),
2285
0
            BlobError,"UnableToWriteBlob","`%s'",image_info->filename);
2286
0
        }
2287
0
    }
2288
0
  else
2289
0
    {
2290
0
      char
2291
0
        unique[MagickPathExtent];
2292
2293
0
      int
2294
0
        file;
2295
2296
0
      unsigned char
2297
0
        *blob;
2298
2299
      /*
2300
        Write file to disk in blob image format.
2301
      */
2302
0
      clone_info->custom_stream=(CustomStreamInfo *) NULL;
2303
0
      blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2304
0
        sizeof(*blob));
2305
0
      if (blob == (unsigned char *) NULL)
2306
0
        {
2307
0
          ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2308
0
            image_info->filename);
2309
0
          clone_info=DestroyImageInfo(clone_info);
2310
0
          return;
2311
0
        }
2312
0
      file=AcquireUniqueFileResource(unique);
2313
0
      if (file == -1)
2314
0
        {
2315
0
          ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2316
0
            image_info->filename);
2317
0
          blob=(unsigned char *) RelinquishMagickMemory(blob);
2318
0
          clone_info=DestroyImageInfo(clone_info);
2319
0
          return;
2320
0
        }
2321
0
      clone_info->file=fdopen(file,"wb+");
2322
0
      if (clone_info->file != (FILE *) NULL)
2323
0
        {
2324
0
          ssize_t
2325
0
            count;
2326
2327
0
          (void) FormatLocaleString(image->filename,MagickPathExtent,"%s:%s",
2328
0
            image->magick,unique);
2329
0
          status=WriteImage(clone_info,image,exception);
2330
0
          if (status != MagickFalse)
2331
0
            {
2332
0
              (void) fseek(clone_info->file,0,SEEK_SET);
2333
0
              count=(ssize_t) MagickMaxBufferExtent;
2334
0
              while (count == (ssize_t) MagickMaxBufferExtent)
2335
0
              {
2336
0
                count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2337
0
                  clone_info->file);
2338
0
                if (image_info->custom_stream->writer(blob,(size_t) count,
2339
0
                      image_info->custom_stream->data) != count)
2340
0
                  {
2341
0
                    (void) ThrowMagickException(exception,GetMagickModule(),
2342
0
                      BlobError,"UnableToWriteBlob","`%s'",image_info->filename);
2343
0
                    break;
2344
0
                  }
2345
0
              }
2346
0
            }
2347
0
          (void) fclose(clone_info->file);
2348
0
        }
2349
0
      blob=(unsigned char *) RelinquishMagickMemory(blob);
2350
0
      (void) RelinquishUniqueFileResource(unique);
2351
0
    }
2352
0
  clone_info=DestroyImageInfo(clone_info);
2353
0
}
2354

2355
/*
2356
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2357
%                                                                             %
2358
%                                                                             %
2359
%                                                                             %
2360
%   I m a g e T o F i l e                                                     %
2361
%                                                                             %
2362
%                                                                             %
2363
%                                                                             %
2364
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2365
%
2366
%  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
2367
%  occurs otherwise MagickTrue.
2368
%
2369
%  The format of the ImageToFile method is:
2370
%
2371
%       MagickBooleanType ImageToFile(Image *image,char *filename,
2372
%         ExceptionInfo *exception)
2373
%
2374
%  A description of each parameter follows:
2375
%
2376
%    o image: the image.
2377
%
2378
%    o filename: Write the image to this file.
2379
%
2380
%    o exception: return any errors or warnings in this structure.
2381
%
2382
*/
2383
MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
2384
  ExceptionInfo *exception)
2385
8.93k
{
2386
8.93k
  int
2387
8.93k
    file;
2388
2389
8.93k
  const unsigned char
2390
8.93k
    *p;
2391
2392
8.93k
  size_t
2393
8.93k
    i;
2394
2395
8.93k
  size_t
2396
8.93k
    length,
2397
8.93k
    quantum;
2398
2399
8.93k
  ssize_t
2400
8.93k
    count;
2401
2402
8.93k
  struct stat
2403
8.93k
    file_stats;
2404
2405
8.93k
  unsigned char
2406
8.93k
    *buffer;
2407
2408
8.93k
  assert(image != (Image *) NULL);
2409
8.93k
  assert(image->signature == MagickCoreSignature);
2410
8.93k
  assert(image->blob != (BlobInfo *) NULL);
2411
8.93k
  assert(image->blob->type != UndefinedStream);
2412
8.93k
  assert(filename != (const char *) NULL);
2413
8.93k
  if (IsEventLogging() != MagickFalse)
2414
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
2415
8.93k
  if (*filename == '\0')
2416
8.93k
    file=AcquireUniqueFileResource(filename);
2417
0
  else
2418
0
    if (LocaleCompare(filename,"-") == 0)
2419
0
      file=fileno(stdout);
2420
0
    else
2421
0
      file=open_utf8(filename,O_RDWR | O_CLOEXEC | O_CREAT | O_EXCL | O_BINARY,P_MODE);
2422
8.93k
  if (file == -1)
2423
0
    {
2424
0
      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2425
0
      return(MagickFalse);
2426
0
    }
2427
8.93k
  quantum=(size_t) MagickMaxBufferExtent;
2428
8.93k
  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2429
0
    quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2430
8.93k
  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2431
8.93k
  if (buffer == (unsigned char *) NULL)
2432
0
    {
2433
0
      file=close_utf8(file)-1;
2434
0
      (void) ThrowMagickException(exception,GetMagickModule(),
2435
0
        ResourceLimitError,"MemoryAllocationError","`%s'",filename);
2436
0
      return(MagickFalse);
2437
0
    }
2438
8.93k
  length=0;
2439
8.93k
  p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2440
17.7k
  for (i=0; count > 0; )
2441
8.83k
  {
2442
8.83k
    length=(size_t) count;
2443
17.6k
    for (i=0; i < length; i+=(size_t) count)
2444
8.83k
    {
2445
8.83k
      count=MagickWrite(file,p+i,(size_t) (length-i));
2446
8.83k
      if (count <= 0)
2447
0
        break;
2448
8.83k
    }
2449
8.83k
    if (i < length)
2450
0
      break;
2451
8.83k
    p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2452
8.83k
  }
2453
8.93k
  if (LocaleCompare(filename,"-") != 0)
2454
8.93k
    file=close_utf8(file);
2455
8.93k
  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2456
8.93k
  if ((file == -1) || (i < length))
2457
0
    {
2458
0
      if (file != -1)
2459
0
        file=close_utf8(file);
2460
0
      ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2461
0
      return(MagickFalse);
2462
0
    }
2463
8.93k
  return(MagickTrue);
2464
8.93k
}
2465

2466
/*
2467
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2468
%                                                                             %
2469
%                                                                             %
2470
%                                                                             %
2471
%   I m a g e s T o B l o b                                                   %
2472
%                                                                             %
2473
%                                                                             %
2474
%                                                                             %
2475
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2476
%
2477
%  ImagesToBlob() implements direct to memory image formats.  It returns the
2478
%  image sequence as a blob and its length.  The magick member of the ImageInfo
2479
%  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
2480
%
2481
%  Note, some image formats do not permit multiple images to the same image
2482
%  stream (e.g. JPEG).  in this instance, just the first image of the
2483
%  sequence is returned as a blob.
2484
%
2485
%  The format of the ImagesToBlob method is:
2486
%
2487
%      void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2488
%        size_t *length,ExceptionInfo *exception)
2489
%
2490
%  A description of each parameter follows:
2491
%
2492
%    o image_info: the image info.
2493
%
2494
%    o images: the image list.
2495
%
2496
%    o length: return the actual length of the blob.
2497
%
2498
%    o exception: return any errors or warnings in this structure.
2499
%
2500
*/
2501
MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2502
  size_t *length,ExceptionInfo *exception)
2503
62.9k
{
2504
62.9k
  const MagickInfo
2505
62.9k
    *magick_info;
2506
2507
62.9k
  ImageInfo
2508
62.9k
    *blob_info;
2509
2510
62.9k
  MagickBooleanType
2511
62.9k
    status;
2512
2513
62.9k
  void
2514
62.9k
    *blob;
2515
2516
62.9k
  assert(image_info != (const ImageInfo *) NULL);
2517
62.9k
  assert(image_info->signature == MagickCoreSignature);
2518
62.9k
  assert(images != (Image *) NULL);
2519
62.9k
  assert(images->signature == MagickCoreSignature);
2520
62.9k
  assert(exception != (ExceptionInfo *) NULL);
2521
62.9k
  if (IsEventLogging() != MagickFalse)
2522
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2523
0
      image_info->filename);
2524
62.9k
  *length=0;
2525
62.9k
  blob=(unsigned char *) NULL;
2526
62.9k
  blob_info=CloneImageInfo(image_info);
2527
62.9k
  (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
2528
62.9k
    exception);
2529
62.9k
  if (*blob_info->magick != '\0')
2530
62.9k
    (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
2531
62.9k
  magick_info=GetMagickInfo(images->magick,exception);
2532
62.9k
  if (magick_info == (const MagickInfo *) NULL)
2533
0
    {
2534
0
      (void) ThrowMagickException(exception,GetMagickModule(),
2535
0
        MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2536
0
        images->magick);
2537
0
      blob_info=DestroyImageInfo(blob_info);
2538
0
      return(blob);
2539
0
    }
2540
62.9k
  if (GetMagickAdjoin(magick_info) == MagickFalse)
2541
25.0k
    {
2542
25.0k
      blob_info=DestroyImageInfo(blob_info);
2543
25.0k
      return(ImageToBlob(image_info,images,length,exception));
2544
25.0k
    }
2545
37.9k
  (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
2546
37.9k
  if (GetMagickBlobSupport(magick_info) != MagickFalse)
2547
36.0k
    {
2548
      /*
2549
        Native blob support for this images format.
2550
      */
2551
36.0k
      blob_info->length=0;
2552
36.0k
      blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
2553
36.0k
        sizeof(unsigned char));
2554
36.0k
      if (blob_info->blob == (void *) NULL)
2555
0
        (void) ThrowMagickException(exception,GetMagickModule(),
2556
0
          ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2557
36.0k
      else
2558
36.0k
        {
2559
36.0k
          (void) CloseBlob(images);
2560
36.0k
          images->blob->exempt=MagickTrue;
2561
36.0k
          images->blob->extent=0;
2562
36.0k
          *images->filename='\0';
2563
36.0k
          status=WriteImages(blob_info,images,images->filename,exception);
2564
36.0k
          SyncBlobStream(blob_info,images,images);
2565
36.0k
          *length=images->blob->length;
2566
36.0k
          blob=DetachBlob(images->blob);
2567
36.0k
          if (blob != (void *) NULL)
2568
35.9k
            {
2569
35.9k
              if (status == MagickFalse)
2570
298
                blob=RelinquishMagickMemory(blob);
2571
35.7k
              else
2572
35.7k
                blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2573
35.9k
            }
2574
12
          else if ((status == MagickFalse) && (images->blob->extent == 0))
2575
0
            blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2576
36.0k
        }
2577
36.0k
    }
2578
1.92k
  else
2579
1.92k
    {
2580
1.92k
      char
2581
1.92k
        filename[MagickPathExtent],
2582
1.92k
        unique[MagickPathExtent];
2583
2584
1.92k
      int
2585
1.92k
        file;
2586
2587
      /*
2588
        Write file to disk in blob images format.
2589
      */
2590
1.92k
      file=AcquireUniqueFileResource(unique);
2591
1.92k
      if (file == -1)
2592
0
        {
2593
0
          ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2594
0
            image_info->filename);
2595
0
        }
2596
1.92k
      else
2597
1.92k
        {
2598
1.92k
          blob_info->file=fdopen(file,"wb");
2599
1.92k
          if (blob_info->file != (FILE *) NULL)
2600
1.92k
            {
2601
1.92k
              (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2602
1.92k
                images->magick,unique);
2603
1.92k
              status=WriteImages(blob_info,images,filename,exception);
2604
1.92k
              (void) fclose(blob_info->file);
2605
1.92k
              if (status != MagickFalse)
2606
771
                blob=FileToBlob(unique,SIZE_MAX,length,exception);
2607
1.92k
            }
2608
1.92k
          (void) RelinquishUniqueFileResource(unique);
2609
1.92k
        }
2610
1.92k
    }
2611
37.9k
  blob_info=DestroyImageInfo(blob_info);
2612
37.9k
  return(blob);
2613
62.9k
}
2614

2615
/*
2616
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2617
%                                                                             %
2618
%                                                                             %
2619
%                                                                             %
2620
+  I m a g e s T o C u s t o m B l o b                                        %
2621
%                                                                             %
2622
%                                                                             %
2623
%                                                                             %
2624
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2625
%
2626
%  ImagesToCustomStream() is the equivalent of WriteImages(), but writes the
2627
%  formatted "file" to the custom stream rather than to an actual file.
2628
%
2629
%  The format of the ImageToCustomStream method is:
2630
%
2631
%      void ImagesToCustomStream(const ImageInfo *image_info,Image *images,
2632
%        ExceptionInfo *exception)
2633
%
2634
%  A description of each parameter follows:
2635
%
2636
%    o image_info: the image info.
2637
%
2638
%    o images: the image list.
2639
%
2640
%    o exception: return any errors or warnings in this structure.
2641
%
2642
*/
2643
MagickExport void ImagesToCustomStream(const ImageInfo *image_info,
2644
  Image *images,ExceptionInfo *exception)
2645
0
{
2646
0
  const MagickInfo
2647
0
    *magick_info;
2648
2649
0
  ImageInfo
2650
0
    *clone_info;
2651
2652
0
  MagickBooleanType
2653
0
    blob_support,
2654
0
    status;
2655
2656
0
  assert(image_info != (const ImageInfo *) NULL);
2657
0
  assert(image_info->signature == MagickCoreSignature);
2658
0
  assert(images != (Image *) NULL);
2659
0
  assert(images->signature == MagickCoreSignature);
2660
0
  assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2661
0
  assert(image_info->custom_stream->signature == MagickCoreSignature);
2662
0
  assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2663
0
  assert(exception != (ExceptionInfo *) NULL);
2664
0
  if (IsEventLogging() != MagickFalse)
2665
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2666
0
      image_info->filename);
2667
0
  clone_info=CloneImageInfo(image_info);
2668
0
  (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
2669
0
    exception);
2670
0
  if (*clone_info->magick != '\0')
2671
0
    (void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
2672
0
  magick_info=GetMagickInfo(images->magick,exception);
2673
0
  if (magick_info == (const MagickInfo *) NULL)
2674
0
    {
2675
0
      (void) ThrowMagickException(exception,GetMagickModule(),
2676
0
        MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2677
0
        images->magick);
2678
0
      clone_info=DestroyImageInfo(clone_info);
2679
0
      return;
2680
0
    }
2681
0
  (void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
2682
0
  blob_support=GetMagickBlobSupport(magick_info);
2683
0
  if ((blob_support != MagickFalse) &&
2684
0
      (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2685
0
    {
2686
0
      if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2687
0
          (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2688
0
        blob_support=MagickFalse;
2689
0
    }
2690
0
  if (blob_support != MagickFalse)
2691
0
    {
2692
      /*
2693
        Native blob support for this image format.
2694
      */
2695
0
      (void) CloseBlob(images);
2696
0
      *images->filename='\0';
2697
0
      (void) WriteImages(clone_info,images,images->filename,exception);
2698
0
    }
2699
0
  else
2700
0
    {
2701
0
      char
2702
0
        filename[MagickPathExtent],
2703
0
        unique[MagickPathExtent];
2704
2705
0
      int
2706
0
        file;
2707
2708
0
      unsigned char
2709
0
        *blob;
2710
2711
      /*
2712
        Write file to disk in blob image format.
2713
      */
2714
0
      clone_info->custom_stream=(CustomStreamInfo *) NULL;
2715
0
      blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2716
0
        sizeof(*blob));
2717
0
      if (blob == (unsigned char *) NULL)
2718
0
        {
2719
0
          ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2720
0
            image_info->filename);
2721
0
          clone_info=DestroyImageInfo(clone_info);
2722
0
          return;
2723
0
        }
2724
0
      file=AcquireUniqueFileResource(unique);
2725
0
      if (file == -1)
2726
0
        {
2727
0
          ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2728
0
            image_info->filename);
2729
0
          blob=(unsigned char *) RelinquishMagickMemory(blob);
2730
0
          clone_info=DestroyImageInfo(clone_info);
2731
0
          return;
2732
0
        }
2733
0
      clone_info->file=fdopen(file,"wb+");
2734
0
      if (clone_info->file != (FILE *) NULL)
2735
0
        {
2736
0
          ssize_t
2737
0
            count;
2738
2739
0
          (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2740
0
            images->magick,unique);
2741
0
          status=WriteImages(clone_info,images,filename,exception);
2742
0
          if (status != MagickFalse)
2743
0
            {
2744
0
              (void) fseek(clone_info->file,0,SEEK_SET);
2745
0
              count=(ssize_t) MagickMaxBufferExtent;
2746
0
              while (count == (ssize_t) MagickMaxBufferExtent)
2747
0
              {
2748
0
                count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2749
0
                  clone_info->file);
2750
0
                (void) image_info->custom_stream->writer(blob,(size_t) count,
2751
0
                  image_info->custom_stream->data);
2752
0
              }
2753
0
            }
2754
0
          (void) fclose(clone_info->file);
2755
0
        }
2756
0
      blob=(unsigned char *) RelinquishMagickMemory(blob);
2757
0
      (void) RelinquishUniqueFileResource(unique);
2758
0
    }
2759
0
  clone_info=DestroyImageInfo(clone_info);
2760
0
}
2761

2762
/*
2763
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2764
%                                                                             %
2765
%                                                                             %
2766
%                                                                             %
2767
%   I n j e c t I m a g e B l o b                                             %
2768
%                                                                             %
2769
%                                                                             %
2770
%                                                                             %
2771
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2772
%
2773
%  InjectImageBlob() injects the image with a copy of itself in the specified
2774
%  format (e.g. inject JPEG into a PDF image).
2775
%
2776
%  The format of the InjectImageBlob method is:
2777
%
2778
%      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2779
%        Image *image,Image *inject_image,const char *format,
2780
%        ExceptionInfo *exception)
2781
%
2782
%  A description of each parameter follows:
2783
%
2784
%    o image_info: the image info..
2785
%
2786
%    o image: the image.
2787
%
2788
%    o inject_image: inject into the image stream.
2789
%
2790
%    o format: the image format.
2791
%
2792
%    o exception: return any errors or warnings in this structure.
2793
%
2794
*/
2795
MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2796
  Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2797
0
{
2798
0
  char
2799
0
    filename[MagickPathExtent];
2800
2801
0
  FILE
2802
0
    *unique_file;
2803
2804
0
  Image
2805
0
    *byte_image;
2806
2807
0
  ImageInfo
2808
0
    *write_info;
2809
2810
0
  int
2811
0
    file;
2812
2813
0
  MagickBooleanType
2814
0
    status;
2815
2816
0
  size_t
2817
0
    quantum;
2818
2819
0
  struct stat
2820
0
    file_stats;
2821
2822
0
  unsigned char
2823
0
    *buffer;
2824
2825
  /*
2826
    Write inject image to a temporary file.
2827
  */
2828
0
  assert(image_info != (ImageInfo *) NULL);
2829
0
  assert(image_info->signature == MagickCoreSignature);
2830
0
  assert(image != (Image *) NULL);
2831
0
  assert(image->signature == MagickCoreSignature);
2832
0
  assert(inject_image != (Image *) NULL);
2833
0
  assert(inject_image->signature == MagickCoreSignature);
2834
0
  assert(exception != (ExceptionInfo *) NULL);
2835
0
  if (IsEventLogging() != MagickFalse)
2836
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2837
0
  unique_file=(FILE *) NULL;
2838
0
  file=AcquireUniqueFileResource(filename);
2839
0
  if (file != -1)
2840
0
    unique_file=fdopen(file,"wb");
2841
0
  if ((file == -1) || (unique_file == (FILE *) NULL))
2842
0
    {
2843
0
      (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2844
0
      ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2845
0
        image->filename);
2846
0
      return(MagickFalse);
2847
0
    }
2848
0
  byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2849
0
  if (byte_image == (Image *) NULL)
2850
0
    {
2851
0
      (void) fclose(unique_file);
2852
0
      (void) RelinquishUniqueFileResource(filename);
2853
0
      return(MagickFalse);
2854
0
    }
2855
0
  (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
2856
0
    format,filename);
2857
0
  DestroyBlob(byte_image);
2858
0
  byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2859
0
  write_info=CloneImageInfo(image_info);
2860
0
  SetImageInfoFile(write_info,unique_file);
2861
0
  status=WriteImage(write_info,byte_image,exception);
2862
0
  write_info=DestroyImageInfo(write_info);
2863
0
  byte_image=DestroyImage(byte_image);
2864
0
  (void) fclose(unique_file);
2865
0
  if (status == MagickFalse)
2866
0
    {
2867
0
      (void) RelinquishUniqueFileResource(filename);
2868
0
      return(MagickFalse);
2869
0
    }
2870
  /*
2871
    Inject into image stream.
2872
  */
2873
0
  file=open_utf8(filename,O_RDONLY | O_CLOEXEC | O_BINARY,0);
2874
0
  if (file == -1)
2875
0
    {
2876
0
      (void) RelinquishUniqueFileResource(filename);
2877
0
      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2878
0
        image_info->filename);
2879
0
      return(MagickFalse);
2880
0
    }
2881
0
  quantum=(size_t) MagickMaxBufferExtent;
2882
0
  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2883
0
    quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2884
0
  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2885
0
  if (buffer == (unsigned char *) NULL)
2886
0
    {
2887
0
      (void) RelinquishUniqueFileResource(filename);
2888
0
      file=close_utf8(file);
2889
0
      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2890
0
        image->filename);
2891
0
    }
2892
0
  for ( ; ; )
2893
0
  {
2894
0
    ssize_t count = read(file,buffer,quantum);
2895
0
    if (count <= 0)
2896
0
      {
2897
0
        count=0;
2898
0
        if (errno != EINTR)
2899
0
          break;
2900
0
      }
2901
0
    status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2902
0
      MagickFalse;
2903
0
  }
2904
0
  file=close_utf8(file);
2905
0
  if (file == -1)
2906
0
    ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2907
0
  (void) RelinquishUniqueFileResource(filename);
2908
0
  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2909
0
  return(status);
2910
0
}
2911

2912
/*
2913
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2914
%                                                                             %
2915
%                                                                             %
2916
%                                                                             %
2917
%   I s B l o b E x e m p t                                                   %
2918
%                                                                             %
2919
%                                                                             %
2920
%                                                                             %
2921
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2922
%
2923
%  IsBlobExempt() returns true if the blob is exempt.
2924
%
2925
%  The format of the IsBlobExempt method is:
2926
%
2927
%       MagickBooleanType IsBlobExempt(const Image *image)
2928
%
2929
%  A description of each parameter follows:
2930
%
2931
%    o image: the image.
2932
%
2933
*/
2934
MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2935
84.8k
{
2936
84.8k
  assert(image != (const Image *) NULL);
2937
84.8k
  assert(image->signature == MagickCoreSignature);
2938
84.8k
  if (IsEventLogging() != MagickFalse)
2939
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2940
84.8k
  return(image->blob->exempt);
2941
84.8k
}
2942

2943
/*
2944
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2945
%                                                                             %
2946
%                                                                             %
2947
%                                                                             %
2948
%   I s B l o b S e e k a b l e                                               %
2949
%                                                                             %
2950
%                                                                             %
2951
%                                                                             %
2952
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2953
%
2954
%  IsBlobSeekable() returns true if the blob is seekable.
2955
%
2956
%  The format of the IsBlobSeekable method is:
2957
%
2958
%       MagickBooleanType IsBlobSeekable(const Image *image)
2959
%
2960
%  A description of each parameter follows:
2961
%
2962
%    o image: the image.
2963
%
2964
*/
2965
MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2966
804k
{
2967
804k
  BlobInfo
2968
804k
    *magick_restrict blob_info;
2969
2970
804k
  assert(image != (const Image *) NULL);
2971
804k
  assert(image->signature == MagickCoreSignature);
2972
804k
  if (IsEventLogging() != MagickFalse)
2973
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2974
804k
  blob_info=image->blob;
2975
804k
  switch (blob_info->type)
2976
804k
  {
2977
595k
    case BlobStream:
2978
595k
      return(MagickTrue);
2979
173k
    case FileStream:
2980
173k
    {
2981
173k
      int
2982
173k
        status;
2983
2984
173k
      if (blob_info->file_info.file == (FILE *) NULL)
2985
0
        return(MagickFalse);
2986
173k
      status=fseek(blob_info->file_info.file,0,SEEK_CUR);
2987
173k
      return(status == -1 ? MagickFalse : MagickTrue);
2988
173k
    }
2989
35.2k
    case ZipStream:
2990
35.2k
    {
2991
35.2k
#if defined(MAGICKCORE_ZLIB_DELEGATE)
2992
35.2k
      MagickOffsetType
2993
35.2k
        offset;
2994
2995
35.2k
      if (blob_info->file_info.gzfile == (gzFile) NULL)
2996
0
        return(MagickFalse);
2997
35.2k
      offset=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
2998
35.2k
      return(offset < 0 ? MagickFalse : MagickTrue);
2999
#else
3000
      break;
3001
#endif
3002
35.2k
    }
3003
0
    case UndefinedStream:
3004
0
    case BZipStream:
3005
0
    case FifoStream:
3006
0
    case PipeStream:
3007
0
    case StandardStream:
3008
0
      break;
3009
0
    case CustomStream:
3010
0
    {
3011
0
      if ((blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL) &&
3012
0
          (blob_info->custom_stream->teller != (CustomStreamTeller) NULL))
3013
0
        return(MagickTrue);
3014
0
      break;
3015
0
    }
3016
0
    default:
3017
0
      break;
3018
804k
  }
3019
0
  return(MagickFalse);
3020
804k
}
3021

3022
/*
3023
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3024
%                                                                             %
3025
%                                                                             %
3026
%                                                                             %
3027
%   I s B l o b T e m p o r a r y                                             %
3028
%                                                                             %
3029
%                                                                             %
3030
%                                                                             %
3031
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3032
%
3033
%  IsBlobTemporary() returns true if the blob is temporary.
3034
%
3035
%  The format of the IsBlobTemporary method is:
3036
%
3037
%       MagickBooleanType IsBlobTemporary(const Image *image)
3038
%
3039
%  A description of each parameter follows:
3040
%
3041
%    o image: the image.
3042
%
3043
*/
3044
MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
3045
512k
{
3046
512k
  assert(image != (const Image *) NULL);
3047
512k
  assert(image->signature == MagickCoreSignature);
3048
512k
  if (IsEventLogging() != MagickFalse)
3049
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3050
512k
  return(image->blob->temporary);
3051
512k
}
3052

3053
/*
3054
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3055
%                                                                             %
3056
%                                                                             %
3057
%                                                                             %
3058
+  M a p B l o b                                                              %
3059
%                                                                             %
3060
%                                                                             %
3061
%                                                                             %
3062
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3063
%
3064
%  MapBlob() creates a mapping from a file to a binary large object.
3065
%
3066
%  The format of the MapBlob method is:
3067
%
3068
%      void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
3069
%        const size_t length)
3070
%
3071
%  A description of each parameter follows:
3072
%
3073
%    o file: map this file descriptor.
3074
%
3075
%    o mode: ReadMode, WriteMode, or IOMode.
3076
%
3077
%    o offset: starting at this offset within the file.
3078
%
3079
%    o length: the length of the mapping is returned in this pointer.
3080
%
3081
*/
3082
MagickExport void *MapBlob(int file,const MapMode mode,
3083
  const MagickOffsetType offset,const size_t length)
3084
126k
{
3085
126k
#if defined(MAGICKCORE_HAVE_MMAP)
3086
126k
  int
3087
126k
    flags,
3088
126k
    protection;
3089
3090
126k
  void
3091
126k
    *map;
3092
3093
  /*
3094
    Map file.
3095
  */
3096
126k
  flags=0;
3097
126k
  if (file == -1)
3098
0
#if defined(MAP_ANONYMOUS)
3099
0
    flags|=MAP_ANONYMOUS;
3100
#else
3101
    return(NULL);
3102
#endif
3103
126k
  switch (mode)
3104
126k
  {
3105
125k
    case ReadMode:
3106
125k
    default:
3107
125k
    {
3108
125k
      protection=PROT_READ;
3109
125k
      flags|=MAP_PRIVATE;
3110
125k
      break;
3111
125k
    }
3112
0
    case WriteMode:
3113
0
    {
3114
0
      protection=PROT_WRITE;
3115
0
      flags|=MAP_SHARED;
3116
0
      break;
3117
125k
    }
3118
625
    case IOMode:
3119
625
    {
3120
625
      protection=PROT_READ | PROT_WRITE;
3121
625
      flags|=MAP_SHARED;
3122
625
      break;
3123
125k
    }
3124
126k
  }
3125
126k
#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
3126
126k
  map=mmap((char *) NULL,length,protection,flags,file,offset);
3127
#else
3128
  map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,offset);
3129
  if (map == MAP_FAILED)
3130
    map=mmap((char *) NULL,length,protection,flags,file,offset);
3131
#endif
3132
126k
  if (map == MAP_FAILED)
3133
14
    return(NULL);
3134
126k
  return(map);
3135
#else
3136
  (void) file;
3137
  (void) mode;
3138
  (void) offset;
3139
  (void) length;
3140
  return(NULL);
3141
#endif
3142
126k
}
3143

3144
/*
3145
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3146
%                                                                             %
3147
%                                                                             %
3148
%                                                                             %
3149
+  M S B O r d e r L o n g                                                    %
3150
%                                                                             %
3151
%                                                                             %
3152
%                                                                             %
3153
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3154
%
3155
%  MSBOrderLong() converts a least-significant byte first buffer of integers to
3156
%  most-significant byte first.
3157
%
3158
%  The format of the MSBOrderLong method is:
3159
%
3160
%      void MSBOrderLong(unsigned char *buffer,const size_t length)
3161
%
3162
%  A description of each parameter follows.
3163
%
3164
%   o  buffer:  Specifies a pointer to a buffer of integers.
3165
%
3166
%   o  length:  Specifies the length of the buffer.
3167
%
3168
*/
3169
MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
3170
281
{
3171
281
  int
3172
281
    c;
3173
3174
281
  unsigned char
3175
281
    *p,
3176
281
    *q;
3177
3178
281
  assert(buffer != (unsigned char *) NULL);
3179
281
  q=buffer+length;
3180
428M
  while (buffer < q)
3181
428M
  {
3182
428M
    p=buffer+3;
3183
428M
    c=(int) (*p);
3184
428M
    *p=(*buffer);
3185
428M
    *buffer++=(unsigned char) c;
3186
428M
    p=buffer+1;
3187
428M
    c=(int) (*p);
3188
428M
    *p=(*buffer);
3189
428M
    *buffer++=(unsigned char) c;
3190
428M
    buffer+=2;
3191
428M
  }
3192
281
}
3193

3194
/*
3195
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3196
%                                                                             %
3197
%                                                                             %
3198
%                                                                             %
3199
+  M S B O r d e r S h o r t                                                  %
3200
%                                                                             %
3201
%                                                                             %
3202
%                                                                             %
3203
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3204
%
3205
%  MSBOrderShort() converts a least-significant byte first buffer of integers
3206
%  to most-significant byte first.
3207
%
3208
%  The format of the MSBOrderShort method is:
3209
%
3210
%      void MSBOrderShort(unsigned char *p,const size_t length)
3211
%
3212
%  A description of each parameter follows.
3213
%
3214
%   o  p:  Specifies a pointer to a buffer of integers.
3215
%
3216
%   o  length:  Specifies the length of the buffer.
3217
%
3218
*/
3219
MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
3220
167
{
3221
167
  int
3222
167
    c;
3223
3224
167
  unsigned char
3225
167
    *q;
3226
3227
167
  assert(p != (unsigned char *) NULL);
3228
167
  q=p+length;
3229
541M
  while (p < q)
3230
541M
  {
3231
541M
    c=(int) (*p);
3232
541M
    *p=(*(p+1));
3233
541M
    p++;
3234
541M
    *p++=(unsigned char) c;
3235
541M
  }
3236
167
}
3237

3238
/*
3239
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3240
%                                                                             %
3241
%                                                                             %
3242
%                                                                             %
3243
+   O p e n B l o b                                                           %
3244
%                                                                             %
3245
%                                                                             %
3246
%                                                                             %
3247
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3248
%
3249
%  OpenBlob() opens a file associated with the image.  A file name of '-' sets
3250
%  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
3251
%  suffix is '.gz', the image is decompressed for type 'r' and compressed for
3252
%  type 'w'.  If the filename prefix is '|', it is piped to or from a system
3253
%  command.
3254
%
3255
%  The format of the OpenBlob method is:
3256
%
3257
%       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
3258
%        const BlobMode mode,ExceptionInfo *exception)
3259
%
3260
%  A description of each parameter follows:
3261
%
3262
%    o image_info: the image info.
3263
%
3264
%    o image: the image.
3265
%
3266
%    o mode: the mode for opening the file.
3267
%
3268
*/
3269
3270
static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
3271
  const BlobInfo *blob_info)
3272
505k
{
3273
505k
  const char
3274
505k
    *option;
3275
3276
505k
  int
3277
505k
    status;
3278
3279
505k
  size_t
3280
505k
    size;
3281
3282
505k
  size=MagickMinBufferExtent;
3283
505k
  option=GetImageOption(image_info,"stream:buffer-size");
3284
505k
  if (option != (const char *) NULL)
3285
0
    size=StringToUnsignedLong(option);
3286
505k
  status=setvbuf(blob_info->file_info.file,(char *) NULL,size == 0 ?
3287
505k
    _IONBF : _IOFBF,size);
3288
505k
  return(status == 0 ? MagickTrue : MagickFalse);
3289
505k
}
3290
3291
#if defined(MAGICKCORE_ZLIB_DELEGATE)
3292
static inline gzFile gzopen_utf8(const char *path,const char *mode)
3293
71.7k
{
3294
71.7k
#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
3295
71.7k
  return(gzopen(path,mode));
3296
#else
3297
   gzFile
3298
     file;
3299
3300
   wchar_t
3301
     *path_wide;
3302
3303
   path_wide=NTCreateWidePath(path);
3304
   if (path_wide == (wchar_t *) NULL)
3305
     return((gzFile) NULL);
3306
   file=gzopen_w(path_wide,mode);
3307
   path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
3308
   return(file);
3309
#endif
3310
71.7k
}
3311
#endif
3312
3313
MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
3314
  Image *image,const BlobMode mode,ExceptionInfo *exception)
3315
1.66M
{
3316
1.66M
  BlobInfo
3317
1.66M
    *magick_restrict blob_info;
3318
3319
1.66M
  char
3320
1.66M
    extension[MagickPathExtent],
3321
1.66M
    filename[MagickPathExtent];
3322
3323
1.66M
  const char
3324
1.66M
    *type;
3325
3326
1.66M
  int
3327
1.66M
    flags = O_RDONLY | O_CLOEXEC;
3328
3329
1.66M
  MagickBooleanType
3330
1.66M
    status;
3331
3332
1.66M
  PolicyRights
3333
1.66M
    rights;
3334
3335
1.66M
  assert(image_info != (ImageInfo *) NULL);
3336
1.66M
  assert(image_info->signature == MagickCoreSignature);
3337
1.66M
  assert(image != (Image *) NULL);
3338
1.66M
  assert(image->signature == MagickCoreSignature);
3339
1.66M
  if (IsEventLogging() != MagickFalse)
3340
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3341
0
      image_info->filename);
3342
1.66M
  blob_info=image->blob;
3343
1.66M
  if (image_info->blob != (void *) NULL)
3344
1.15M
    {
3345
1.15M
      if (image_info->stream != (StreamHandler) NULL)
3346
34.7k
        blob_info->stream=(StreamHandler) image_info->stream;
3347
1.15M
      AttachBlob(blob_info,image_info->blob,image_info->length);
3348
1.15M
      return(MagickTrue);
3349
1.15M
    }
3350
509k
  if ((image_info->custom_stream != (CustomStreamInfo *) NULL) &&
3351
0
      (*image->filename == '\0'))
3352
0
    {
3353
0
      blob_info->type=CustomStream;
3354
0
      blob_info->custom_stream=image_info->custom_stream;
3355
0
      if (blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL)
3356
0
        blob_info->custom_stream->seeker(0,SEEK_SET,
3357
0
          blob_info->custom_stream->data);
3358
0
      return(MagickTrue);
3359
0
    }
3360
509k
  (void) DetachBlob(blob_info);
3361
509k
  blob_info->mode=mode;
3362
509k
  switch (mode)
3363
509k
  {
3364
0
    case ReadBlobMode:
3365
0
    {
3366
0
      flags=O_RDONLY | O_CLOEXEC;
3367
0
      type="r";
3368
0
      break;
3369
0
    }
3370
487k
    case ReadBinaryBlobMode:
3371
487k
    {
3372
487k
      flags=O_RDONLY | O_CLOEXEC | O_BINARY;
3373
487k
      type="rb";
3374
487k
      break;
3375
0
    }
3376
0
    case WriteBlobMode:
3377
0
    {
3378
0
      flags=O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC;
3379
0
      type="w";
3380
0
      break;
3381
0
    }
3382
22.1k
    case WriteBinaryBlobMode:
3383
22.1k
    {
3384
22.1k
      flags=O_RDWR | O_CLOEXEC | O_CREAT | O_TRUNC | O_BINARY;
3385
22.1k
      type="w+b";
3386
22.1k
      break;
3387
0
    }
3388
0
    case AppendBlobMode:
3389
0
    {
3390
0
      flags=O_WRONLY | O_CLOEXEC | O_CREAT | O_APPEND;
3391
0
      type="a";
3392
0
      break;
3393
0
    }
3394
0
    case AppendBinaryBlobMode:
3395
0
    {
3396
0
      flags=O_RDWR | O_CLOEXEC | O_CREAT | O_APPEND | O_BINARY;
3397
0
      type="a+b";
3398
0
      break;
3399
0
    }
3400
0
    default:
3401
0
    {
3402
0
      flags=O_RDONLY | O_CLOEXEC;
3403
0
      type="r";
3404
0
      break;
3405
0
    }
3406
509k
  }
3407
509k
  if (*type != 'r')
3408
22.1k
    blob_info->synchronize=image_info->synchronize;
3409
509k
  if (image_info->stream != (StreamHandler) NULL)
3410
16.9k
    {
3411
16.9k
      blob_info->stream=image_info->stream;
3412
16.9k
      if (*type == 'w')
3413
0
        {
3414
0
          blob_info->type=FifoStream;
3415
0
          return(MagickTrue);
3416
0
        }
3417
16.9k
    }
3418
  /*
3419
    Open image file.
3420
  */
3421
509k
  *filename='\0';
3422
509k
  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3423
509k
  rights=ReadPolicyRights;
3424
509k
  if (*type == 'w')
3425
22.1k
    rights=WritePolicyRights;
3426
509k
  if (IsPathAuthorized(rights,filename) == MagickFalse)
3427
509k
    ThrowPolicyException(filename,MagickFalse);
3428
509k
  if ((LocaleCompare(filename,"-") == 0) ||
3429
509k
      ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
3430
0
    {
3431
0
      blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
3432
#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3433
      if (strchr(type,'b') != (char *) NULL)
3434
        (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
3435
#endif
3436
0
      blob_info->type=StandardStream;
3437
0
      blob_info->exempt=MagickTrue;
3438
0
      return(SetStreamBuffering(image_info,blob_info));
3439
0
    }
3440
509k
  if ((LocaleNCompare(filename,"fd:",3) == 0) &&
3441
0
      (IsGeometry(filename+3) != MagickFalse))
3442
0
    {
3443
0
      char
3444
0
        fileMode[2];
3445
3446
0
      *fileMode=(*type);
3447
0
      fileMode[1]='\0';
3448
0
      blob_info->file_info.file=fdopen(StringToInteger(filename+3),fileMode);
3449
0
      if (blob_info->file_info.file == (FILE *) NULL)
3450
0
        {
3451
0
          ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3452
0
          return(MagickFalse);
3453
0
        }
3454
#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3455
      if (strchr(type,'b') != (char *) NULL)
3456
        (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
3457
#endif
3458
0
      blob_info->type=FileStream;
3459
0
      blob_info->exempt=MagickTrue;
3460
0
      return(SetStreamBuffering(image_info,blob_info));
3461
0
    }
3462
#if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
3463
  if (*filename == '|')
3464
    {
3465
      char
3466
        fileMode[MagickPathExtent],
3467
        *sanitize_command;
3468
3469
      /*
3470
        Pipe image to or from a system command.
3471
      */
3472
#if defined(SIGPIPE)
3473
      if (*type == 'w')
3474
        (void) signal(SIGPIPE,SIG_IGN);
3475
#endif
3476
      *fileMode=(*type);
3477
      fileMode[1]='\0';
3478
      sanitize_command=SanitizeString(filename+1);
3479
      blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,fileMode);
3480
      sanitize_command=DestroyString(sanitize_command);
3481
      if (blob_info->file_info.file == (FILE *) NULL)
3482
        {
3483
          ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3484
          return(MagickFalse);
3485
        }
3486
      blob_info->type=PipeStream;
3487
      blob_info->exempt=MagickTrue;
3488
      return(SetStreamBuffering(image_info,blob_info));
3489
    }
3490
#endif
3491
509k
  status=GetPathAttributes(filename,&blob_info->properties);
3492
509k
#if defined(S_ISFIFO)
3493
509k
  if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
3494
0
    {
3495
0
      blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3496
0
      if (blob_info->file_info.file == (FILE *) NULL)
3497
0
        {
3498
0
          ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3499
0
          return(MagickFalse);
3500
0
        }
3501
0
      blob_info->type=FileStream;
3502
0
      blob_info->exempt=MagickTrue;
3503
0
      return(SetStreamBuffering(image_info,blob_info));
3504
0
    }
3505
509k
#endif
3506
509k
  GetPathComponent(image->filename,ExtensionPath,extension);
3507
509k
  if (*type == 'w')
3508
22.1k
    {
3509
22.1k
      (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3510
22.1k
      if ((image_info->adjoin == MagickFalse) ||
3511
22.1k
          (strchr(filename,'%') != (char *) NULL))
3512
0
        {
3513
          /*
3514
            Form filename for multi-part images.
3515
          */
3516
0
          (void) InterpretImageFilename(image_info,image,image->filename,(int)
3517
0
            image->scene,filename,exception);
3518
0
          if ((LocaleCompare(filename,image->filename) == 0) &&
3519
0
              ((GetPreviousImageInList(image) != (Image *) NULL) ||
3520
0
               (GetNextImageInList(image) != (Image *) NULL)))
3521
0
            {
3522
0
              char
3523
0
                path[MagickPathExtent];
3524
3525
0
              GetPathComponent(image->filename,RootPath,path);
3526
0
              if (*extension == '\0')
3527
0
                (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.17g",
3528
0
                  path,(double) image->scene);
3529
0
              else
3530
0
                (void) FormatLocaleString(filename,MagickPathExtent,
3531
0
                  "%s-%.17g.%s",path,(double) image->scene,extension);
3532
0
            }
3533
0
          (void) CopyMagickString(image->filename,filename,MagickPathExtent);
3534
0
        }
3535
22.1k
      if (IsPathAuthorized(rights,filename) == MagickFalse)
3536
22.1k
        ThrowPolicyException(filename,MagickFalse);
3537
22.1k
    }
3538
509k
  if (image_info->file != (FILE *) NULL)
3539
4.21k
    {
3540
4.21k
      blob_info->file_info.file=image_info->file;
3541
4.21k
      blob_info->type=FileStream;
3542
4.21k
      blob_info->exempt=MagickTrue;
3543
4.21k
    }
3544
505k
  else
3545
505k
    if (*type == 'r')
3546
484k
      {
3547
484k
        int
3548
484k
          file;
3549
3550
484k
        blob_info->file_info.file=(FILE *) NULL;
3551
484k
        file=open_utf8(filename,flags,0);
3552
484k
        if (file >= 0)
3553
484k
          blob_info->file_info.file=fdopen(file,type);
3554
484k
        if (blob_info->file_info.file != (FILE *) NULL)
3555
484k
          {
3556
484k
            size_t
3557
484k
              count;
3558
3559
484k
            unsigned char
3560
484k
              magick[3];
3561
3562
484k
            blob_info->type=FileStream;
3563
484k
            (void) SetStreamBuffering(image_info,blob_info);
3564
484k
            (void) memset(magick,0,sizeof(magick));
3565
484k
            count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
3566
484k
            (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
3567
484k
#if defined(MAGICKCORE_POSIX_SUPPORT)
3568
484k
            (void) fflush(blob_info->file_info.file);
3569
484k
#endif
3570
484k
            (void) LogMagickEvent(BlobEvent,GetMagickModule(),
3571
484k
               "  read %.17g magic header bytes",(double) count);
3572
484k
#if defined(MAGICKCORE_ZLIB_DELEGATE)
3573
484k
            if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
3574
72.2k
                ((int) magick[2] == 0x08))
3575
71.7k
              {
3576
71.7k
                gzFile
3577
71.7k
                  gzfile = gzopen_utf8(filename,"rb");
3578
3579
71.7k
                if (gzfile != (gzFile) NULL)
3580
70.7k
                  {
3581
70.7k
                    if (blob_info->file_info.file != (FILE *) NULL)
3582
70.7k
                      (void) fclose(blob_info->file_info.file);
3583
70.7k
                    blob_info->file_info.file=(FILE *) NULL;
3584
70.7k
                    blob_info->file_info.gzfile=gzfile;
3585
70.7k
                    blob_info->type=ZipStream;
3586
70.7k
                  }
3587
71.7k
              }
3588
484k
#endif
3589
#if defined(MAGICKCORE_BZLIB_DELEGATE)
3590
            if (strncmp((char *) magick,"BZh",3) == 0)
3591
              {
3592
                BZFILE
3593
                  *bzfile = BZ2_bzopen(filename,"r");
3594
3595
                if (bzfile != (BZFILE *) NULL)
3596
                  {
3597
                    if (blob_info->file_info.file != (FILE *) NULL)
3598
                      (void) fclose(blob_info->file_info.file);
3599
                    blob_info->file_info.file=(FILE *) NULL;
3600
                    blob_info->file_info.bzfile=bzfile;
3601
                    blob_info->type=BZipStream;
3602
                  }
3603
              }
3604
#endif
3605
484k
            if (blob_info->type == FileStream)
3606
413k
              {
3607
413k
                const MagickInfo
3608
413k
                  *magick_info;
3609
3610
413k
                ExceptionInfo
3611
413k
                  *sans_exception;
3612
3613
413k
                size_t
3614
413k
                  length;
3615
3616
413k
                sans_exception=AcquireExceptionInfo();
3617
413k
                magick_info=GetMagickInfo(image_info->magick,sans_exception);
3618
413k
                sans_exception=DestroyExceptionInfo(sans_exception);
3619
413k
                length=(size_t) blob_info->properties.st_size;
3620
413k
                if ((magick_info != (const MagickInfo *) NULL) &&
3621
353k
                    (GetMagickBlobSupport(magick_info) != MagickFalse) &&
3622
125k
                    (AcquireMagickResource(MapResource,length) != MagickFalse))
3623
125k
                  {
3624
125k
                    void
3625
125k
                      *blob;
3626
3627
125k
                    blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
3628
125k
                      length);
3629
125k
                    if (blob == (void *) NULL)
3630
14
                      RelinquishMagickResource(MapResource,length);
3631
125k
                    else
3632
125k
                      {
3633
                        /*
3634
                          Format supports blobs-- use memory-mapped I/O.
3635
                        */
3636
125k
                        if (image_info->file != (FILE *) NULL)
3637
0
                          blob_info->exempt=MagickFalse;
3638
125k
                        else
3639
125k
                          {
3640
125k
                            (void) fclose(blob_info->file_info.file);
3641
125k
                            blob_info->file_info.file=(FILE *) NULL;
3642
125k
                          }
3643
125k
                        AttachBlob(blob_info,blob,length);
3644
125k
                        blob_info->mapped=MagickTrue;
3645
125k
                      }
3646
125k
                  }
3647
413k
              }
3648
484k
          }
3649
484k
      }
3650
21.3k
    else
3651
21.3k
#if defined(MAGICKCORE_ZLIB_DELEGATE)
3652
21.3k
      if ((LocaleCompare(extension,"gz") == 0) ||
3653
21.3k
          (LocaleCompare(extension,"wmz") == 0) ||
3654
21.3k
          (LocaleCompare(extension,"svgz") == 0))
3655
0
        {
3656
0
          blob_info->file_info.gzfile=gzopen_utf8(filename,"wb");
3657
0
          if (blob_info->file_info.gzfile != (gzFile) NULL)
3658
0
            blob_info->type=ZipStream;
3659
0
        }
3660
21.3k
      else
3661
21.3k
#endif
3662
#if defined(MAGICKCORE_BZLIB_DELEGATE)
3663
        if (LocaleCompare(extension,"bz2") == 0)
3664
          {
3665
            blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
3666
            if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3667
              blob_info->type=BZipStream;
3668
          }
3669
        else
3670
#endif
3671
21.3k
          {
3672
21.3k
            int
3673
21.3k
              file;
3674
3675
21.3k
            blob_info->file_info.file=(FILE *) NULL;
3676
21.3k
            file=open_utf8(filename,flags,P_MODE);
3677
21.3k
            if (file >= 0)
3678
21.3k
              blob_info->file_info.file=fdopen(file,type);
3679
21.3k
            if (blob_info->file_info.file != (FILE *) NULL)
3680
21.3k
              {
3681
21.3k
                blob_info->type=FileStream;
3682
21.3k
                (void) SetStreamBuffering(image_info,blob_info);
3683
21.3k
              }
3684
21.3k
          }
3685
509k
  if (IsPathAuthorized(rights,filename) == MagickFalse)
3686
509k
    ThrowPolicyException(filename,MagickFalse);
3687
509k
  blob_info->status=0;
3688
509k
  blob_info->error_number=0;
3689
509k
  if (blob_info->type != UndefinedStream)
3690
509k
    blob_info->size=GetBlobSize(image);
3691
6
  else
3692
6
    {
3693
6
      ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3694
6
      return(MagickFalse);
3695
6
    }
3696
509k
  return(MagickTrue);
3697
509k
}
3698

3699
/*
3700
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3701
%                                                                             %
3702
%                                                                             %
3703
%                                                                             %
3704
+   P i n g B l o b                                                           %
3705
%                                                                             %
3706
%                                                                             %
3707
%                                                                             %
3708
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3709
%
3710
%  PingBlob() returns all the attributes of an image or image sequence except
3711
%  for the pixels.  It is much faster and consumes far less memory than
3712
%  BlobToImage().  On failure, a NULL image is returned and exception
3713
%  describes the reason for the failure.
3714
%
3715
%  The format of the PingBlob method is:
3716
%
3717
%      Image *PingBlob(const ImageInfo *image_info,const void *blob,
3718
%        const size_t length,ExceptionInfo *exception)
3719
%
3720
%  A description of each parameter follows:
3721
%
3722
%    o image_info: the image info.
3723
%
3724
%    o blob: the address of a character stream in one of the image formats
3725
%      understood by ImageMagick.
3726
%
3727
%    o length: This size_t integer reflects the length in bytes of the blob.
3728
%
3729
%    o exception: return any errors or warnings in this structure.
3730
%
3731
*/
3732
3733
#if defined(__cplusplus) || defined(c_plusplus)
3734
extern "C" {
3735
#endif
3736
3737
static size_t PingStream(const Image *magick_unused(image),
3738
  const void *magick_unused(pixels),const size_t columns)
3739
2.21M
{
3740
2.21M
  magick_unreferenced(image);
3741
2.21M
  magick_unreferenced(pixels);
3742
2.21M
  return(columns);
3743
2.21M
}
3744
3745
#if defined(__cplusplus) || defined(c_plusplus)
3746
}
3747
#endif
3748
3749
MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3750
  const size_t length,ExceptionInfo *exception)
3751
29.5k
{
3752
29.5k
  const MagickInfo
3753
29.5k
    *magick_info;
3754
3755
29.5k
  Image
3756
29.5k
    *image;
3757
3758
29.5k
  ImageInfo
3759
29.5k
    *clone_info,
3760
29.5k
    *ping_info;
3761
3762
29.5k
  MagickBooleanType
3763
29.5k
    status;
3764
3765
29.5k
  assert(image_info != (ImageInfo *) NULL);
3766
29.5k
  assert(image_info->signature == MagickCoreSignature);
3767
29.5k
  assert(exception != (ExceptionInfo *) NULL);
3768
29.5k
  if (IsEventLogging() != MagickFalse)
3769
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3770
0
      image_info->filename);
3771
29.5k
  if ((blob == (const void *) NULL) || (length == 0))
3772
0
    {
3773
0
      (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3774
0
        "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
3775
0
      return((Image *) NULL);
3776
0
    }
3777
29.5k
  ping_info=CloneImageInfo(image_info);
3778
29.5k
  ping_info->blob=(void *) blob;
3779
29.5k
  ping_info->length=length;
3780
29.5k
  ping_info->ping=MagickTrue;
3781
29.5k
  if (*ping_info->magick == '\0')
3782
29.5k
    (void) SetImageInfo(ping_info,0,exception);
3783
29.5k
  magick_info=GetMagickInfo(ping_info->magick,exception);
3784
29.5k
  if (magick_info == (const MagickInfo *) NULL)
3785
19
    {
3786
19
      (void) ThrowMagickException(exception,GetMagickModule(),
3787
19
        MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
3788
19
        ping_info->magick);
3789
19
      ping_info=DestroyImageInfo(ping_info);
3790
19
      return((Image *) NULL);
3791
19
    }
3792
29.5k
  if (GetMagickBlobSupport(magick_info) != MagickFalse)
3793
21.0k
    {
3794
21.0k
      char
3795
21.0k
        filename[MagickPathExtent];
3796
3797
      /*
3798
        Native blob support for this image format.
3799
      */
3800
21.0k
      (void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
3801
21.0k
      (void) FormatLocaleString(ping_info->filename,MagickPathExtent,"%s:%s",
3802
21.0k
        ping_info->magick,filename);
3803
21.0k
      image=ReadStream(ping_info,&PingStream,exception);
3804
21.0k
      if (image != (Image *) NULL)
3805
3.47k
        (void) DetachBlob(image->blob);
3806
21.0k
      ping_info=DestroyImageInfo(ping_info);
3807
21.0k
      return(image);
3808
21.0k
    }
3809
  /*
3810
    Write blob to a temporary file on disk.
3811
  */
3812
8.42k
  ping_info->blob=(void *) NULL;
3813
8.42k
  ping_info->length=0;
3814
8.42k
  *ping_info->filename='\0';
3815
8.42k
  status=BlobToFile(ping_info->filename,blob,length,exception);
3816
8.42k
  if (status == MagickFalse)
3817
0
    {
3818
0
      (void) RelinquishUniqueFileResource(ping_info->filename);
3819
0
      ping_info=DestroyImageInfo(ping_info);
3820
0
      return((Image *) NULL);
3821
0
    }
3822
8.42k
  clone_info=CloneImageInfo(ping_info);
3823
8.42k
  (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
3824
8.42k
    ping_info->magick,ping_info->filename);
3825
8.42k
  image=ReadStream(clone_info,&PingStream,exception);
3826
8.42k
  if (image != (Image *) NULL)
3827
124
    {
3828
124
      Image
3829
124
        *images;
3830
3831
      /*
3832
        Restore original filenames and image format.
3833
      */
3834
248
      for (images=GetFirstImageInList(image); images != (Image *) NULL; )
3835
124
      {
3836
124
        (void) CopyMagickString(images->filename,image_info->filename,
3837
124
          MagickPathExtent);
3838
124
        (void) CopyMagickString(images->magick_filename,image_info->filename,
3839
124
          MagickPathExtent);
3840
124
        (void) CopyMagickString(images->magick,magick_info->name,
3841
124
          MagickPathExtent);
3842
124
        images=GetNextImageInList(images);
3843
124
      }
3844
124
    }
3845
8.42k
  clone_info=DestroyImageInfo(clone_info);
3846
8.42k
  (void) RelinquishUniqueFileResource(ping_info->filename);
3847
8.42k
  ping_info=DestroyImageInfo(ping_info);
3848
8.42k
  return(image);
3849
8.42k
}
3850

3851
/*
3852
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3853
%                                                                             %
3854
%                                                                             %
3855
%                                                                             %
3856
+  R e a d B l o b                                                            %
3857
%                                                                             %
3858
%                                                                             %
3859
%                                                                             %
3860
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3861
%
3862
%  ReadBlob() reads data from the blob or image file and returns it.  It
3863
%  returns the number of bytes read. If length is zero, ReadBlob() returns
3864
%  zero and has no other results. If length is greater than MAGICK_SSIZE_MAX,
3865
%  the result is unspecified.
3866
%
3867
%  The format of the ReadBlob method is:
3868
%
3869
%      ssize_t ReadBlob(Image *image,const size_t length,void *data)
3870
%
3871
%  A description of each parameter follows:
3872
%
3873
%    o image: the image.
3874
%
3875
%    o length:  Specifies an integer representing the number of bytes to read
3876
%      from the file.
3877
%
3878
%    o data:  Specifies an area to place the information requested from the
3879
%      file.
3880
%
3881
*/
3882
MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
3883
437M
{
3884
437M
  BlobInfo
3885
437M
    *magick_restrict blob_info;
3886
3887
437M
  int
3888
437M
    c;
3889
3890
437M
  ssize_t
3891
437M
    count;
3892
3893
437M
  unsigned char
3894
437M
    *q;
3895
3896
437M
  assert(image != (Image *) NULL);
3897
437M
  assert(image->signature == MagickCoreSignature);
3898
437M
  assert(image->blob != (BlobInfo *) NULL);
3899
437M
  assert(image->blob->type != UndefinedStream);
3900
437M
  if (length == 0)
3901
56.0k
    return(0);
3902
437M
  assert(data != (void *) NULL);
3903
437M
  blob_info=image->blob;
3904
437M
  count=0;
3905
437M
  q=(unsigned char *) data;
3906
437M
  switch (blob_info->type)
3907
437M
  {
3908
0
    case UndefinedStream:
3909
0
      break;
3910
0
    case StandardStream:
3911
780k
    case FileStream:
3912
780k
    case PipeStream:
3913
780k
    {
3914
780k
      switch (length)
3915
780k
      {
3916
218k
        default:
3917
218k
        {
3918
218k
          count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
3919
218k
          break;
3920
0
        }
3921
435k
        case 4:
3922
435k
        {
3923
435k
          c=getc(blob_info->file_info.file);
3924
435k
          if (c == EOF)
3925
5.07k
            break;
3926
430k
          *q++=(unsigned char) c;
3927
430k
          count++;
3928
430k
          magick_fallthrough;
3929
430k
        }
3930
432k
        case 3:
3931
432k
        {
3932
432k
          c=getc(blob_info->file_info.file);
3933
432k
          if (c == EOF)
3934
735
            break;
3935
431k
          *q++=(unsigned char) c;
3936
431k
          count++;
3937
431k
          magick_fallthrough;
3938
431k
        }
3939
503k
        case 2:
3940
503k
        {
3941
503k
          c=getc(blob_info->file_info.file);
3942
503k
          if (c == EOF)
3943
2.30k
            break;
3944
500k
          *q++=(unsigned char) c;
3945
500k
          count++;
3946
500k
          magick_fallthrough;
3947
500k
        }
3948
554k
        case 1:
3949
554k
        {
3950
554k
          c=getc(blob_info->file_info.file);
3951
554k
          if (c == EOF)
3952
1.10k
            break;
3953
553k
          *q++=(unsigned char) c;
3954
553k
          count++;
3955
553k
          magick_fallthrough;
3956
553k
        }
3957
553k
        case 0:
3958
553k
          break;
3959
780k
      }
3960
780k
      if ((count != (ssize_t) length) &&
3961
181k
          (ferror(blob_info->file_info.file) != 0))
3962
210
        ThrowBlobException(blob_info);
3963
780k
      break;
3964
780k
    }
3965
191M
    case ZipStream:
3966
191M
    {
3967
191M
#if defined(MAGICKCORE_ZLIB_DELEGATE)
3968
191M
      int
3969
191M
        status;
3970
3971
191M
      switch (length)
3972
191M
      {
3973
458k
        default:
3974
458k
        {
3975
458k
          size_t
3976
458k
            i;
3977
3978
688k
          for (i=0; i < length; i+=(size_t) count)
3979
478k
          {
3980
478k
            count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
3981
478k
              (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3982
478k
            if (count <= 0)
3983
249k
              {
3984
249k
                count=0;
3985
249k
                if (errno != EINTR)
3986
249k
                  break;
3987
249k
              }
3988
478k
          }
3989
458k
          count=(ssize_t) i;
3990
458k
          break;
3991
0
        }
3992
19.8k
        case 4:
3993
19.8k
        {
3994
19.8k
          c=gzgetc(blob_info->file_info.gzfile);
3995
19.8k
          if (c == EOF)
3996
3.40k
            break;
3997
16.4k
          *q++=(unsigned char) c;
3998
16.4k
          count++;
3999
16.4k
          magick_fallthrough;
4000
16.4k
        }
4001
20.7k
        case 3:
4002
20.7k
        {
4003
20.7k
          c=gzgetc(blob_info->file_info.gzfile);
4004
20.7k
          if (c == EOF)
4005
1.12k
            break;
4006
19.5k
          *q++=(unsigned char) c;
4007
19.5k
          count++;
4008
19.5k
          magick_fallthrough;
4009
19.5k
        }
4010
24.6k
        case 2:
4011
24.6k
        {
4012
24.6k
          c=gzgetc(blob_info->file_info.gzfile);
4013
24.6k
          if (c == EOF)
4014
749
            break;
4015
23.8k
          *q++=(unsigned char) c;
4016
23.8k
          count++;
4017
23.8k
          magick_fallthrough;
4018
23.8k
        }
4019
190M
        case 1:
4020
190M
        {
4021
190M
          c=gzgetc(blob_info->file_info.gzfile);
4022
190M
          if (c == EOF)
4023
16.8M
            break;
4024
173M
          *q++=(unsigned char) c;
4025
173M
          count++;
4026
173M
          magick_fallthrough;
4027
173M
        }
4028
173M
        case 0:
4029
173M
          break;
4030
191M
      }
4031
191M
      status=Z_OK;
4032
191M
      (void) gzerror(blob_info->file_info.gzfile,&status);
4033
191M
      if ((count != (ssize_t) length) && (status != Z_OK))
4034
17.1M
        ThrowBlobException(blob_info);
4035
191M
      if (blob_info->eof == MagickFalse)
4036
190M
        blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
4037
190M
          MagickFalse;
4038
191M
#endif
4039
191M
      break;
4040
191M
    }
4041
0
    case BZipStream:
4042
0
    {
4043
#if defined(MAGICKCORE_BZLIB_DELEGATE)
4044
      int
4045
        status;
4046
4047
      size_t
4048
        i;
4049
4050
      if (blob_info->status != 0)
4051
        break;
4052
      for (i=0; i < length; i+=(size_t) count)
4053
      {
4054
        count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,(int)
4055
          MagickMin(length-i,MagickMaxBufferExtent));
4056
        if (count <= 0)
4057
          {
4058
            count=0;
4059
            if (errno != EINTR)
4060
              break;
4061
          }
4062
      }
4063
      count=(ssize_t) i;
4064
      status=BZ_OK;
4065
      (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
4066
      if ((count != (ssize_t) length) && (status != BZ_OK))
4067
        ThrowBlobException(blob_info);
4068
      if ((count != (ssize_t) length) && (status == BZ_OK))
4069
        blob_info->eof=MagickTrue;
4070
#endif
4071
0
      break;
4072
191M
    }
4073
0
    case FifoStream:
4074
0
      break;
4075
245M
    case BlobStream:
4076
245M
    {
4077
245M
      const unsigned char
4078
245M
        *p;
4079
4080
245M
      if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4081
70.1M
        {
4082
70.1M
          blob_info->eof=MagickTrue;
4083
70.1M
          break;
4084
70.1M
        }
4085
175M
      p=blob_info->data+blob_info->offset;
4086
175M
      count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4087
175M
        blob_info->length-blob_info->offset);
4088
175M
      blob_info->offset+=count;
4089
175M
      if (count != (ssize_t) length)
4090
269k
        blob_info->eof=MagickTrue;
4091
175M
      (void) memcpy(q,p,(size_t) count);
4092
175M
      break;
4093
245M
    }
4094
16.0k
    case CustomStream:
4095
16.0k
    {
4096
16.0k
      if (blob_info->custom_stream->reader != (CustomStreamHandler) NULL)
4097
16.0k
        {
4098
16.0k
          count=blob_info->custom_stream->reader(q,length,
4099
16.0k
            blob_info->custom_stream->data);
4100
16.0k
          if (count <= 0)
4101
1.46k
            {
4102
1.46k
              blob_info->eof=MagickTrue;
4103
1.46k
              count=0;
4104
1.46k
            }
4105
16.0k
        }
4106
16.0k
      break;
4107
245M
    }
4108
437M
  }
4109
437M
  return(count);
4110
437M
}
4111

4112
/*
4113
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4114
%                                                                             %
4115
%                                                                             %
4116
%                                                                             %
4117
+  R e a d B l o b B y t e                                                    %
4118
%                                                                             %
4119
%                                                                             %
4120
%                                                                             %
4121
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4122
%
4123
%  ReadBlobByte() reads a single byte from the image file and returns it.
4124
%
4125
%  The format of the ReadBlobByte method is:
4126
%
4127
%      int ReadBlobByte(Image *image)
4128
%
4129
%  A description of each parameter follows.
4130
%
4131
%    o image: the image.
4132
%
4133
*/
4134
MagickExport int ReadBlobByte(Image *image)
4135
361M
{
4136
361M
  BlobInfo
4137
361M
    *magick_restrict blob_info;
4138
4139
361M
  int
4140
361M
    c;
4141
4142
361M
  assert(image != (Image *) NULL);
4143
361M
  assert(image->signature == MagickCoreSignature);
4144
361M
  assert(image->blob != (BlobInfo *) NULL);
4145
361M
  assert(image->blob->type != UndefinedStream);
4146
361M
  blob_info=image->blob;
4147
361M
  switch (blob_info->type)
4148
361M
  {
4149
0
    case StandardStream:
4150
444k
    case FileStream:
4151
444k
    case PipeStream:
4152
444k
    {
4153
444k
      c=getc(blob_info->file_info.file);
4154
444k
      if (c == EOF)
4155
841
        {
4156
841
          if (ferror(blob_info->file_info.file) != 0)
4157
0
            ThrowBlobException(blob_info);
4158
841
          return(EOF);
4159
841
        }
4160
443k
      break;
4161
444k
    }
4162
170M
    case BlobStream:
4163
170M
    {
4164
170M
      if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4165
130M
        {
4166
130M
          blob_info->eof=MagickTrue;
4167
130M
          return(EOF);
4168
130M
        }
4169
39.9M
      c=(int) (*((unsigned char *) blob_info->data+blob_info->offset));
4170
39.9M
      blob_info->offset++;
4171
39.9M
      break;
4172
170M
    }
4173
190M
    default:
4174
190M
    {
4175
190M
      ssize_t
4176
190M
        count;
4177
4178
190M
      unsigned char
4179
190M
        buffer[1];
4180
4181
190M
      count=ReadBlob(image,1,buffer);
4182
190M
      if (count != 1)
4183
16.8M
        return(EOF);
4184
173M
      c=(int) *buffer;
4185
173M
      break;
4186
190M
    }
4187
361M
  }
4188
214M
  return(c);
4189
361M
}
4190

4191
/*
4192
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4193
%                                                                             %
4194
%                                                                             %
4195
%                                                                             %
4196
+  R e a d B l o b D o u b l e                                                %
4197
%                                                                             %
4198
%                                                                             %
4199
%                                                                             %
4200
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4201
%
4202
%  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
4203
%  specified by the endian member of the image structure.
4204
%
4205
%  The format of the ReadBlobDouble method is:
4206
%
4207
%      double ReadBlobDouble(Image *image)
4208
%
4209
%  A description of each parameter follows.
4210
%
4211
%    o image: the image.
4212
%
4213
*/
4214
MagickExport double ReadBlobDouble(Image *image)
4215
51.5M
{
4216
51.5M
  union
4217
51.5M
  {
4218
51.5M
    MagickSizeType
4219
51.5M
      unsigned_value;
4220
4221
51.5M
    double
4222
51.5M
      double_value;
4223
51.5M
  } quantum;
4224
4225
51.5M
  quantum.double_value=0.0;
4226
51.5M
  quantum.unsigned_value=ReadBlobLongLong(image);
4227
51.5M
  return(quantum.double_value);
4228
51.5M
}
4229

4230
/*
4231
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4232
%                                                                             %
4233
%                                                                             %
4234
%                                                                             %
4235
+  R e a d B l o b F l o a t                                                  %
4236
%                                                                             %
4237
%                                                                             %
4238
%                                                                             %
4239
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4240
%
4241
%  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
4242
%  specified by the endian member of the image structure.
4243
%
4244
%  The format of the ReadBlobFloat method is:
4245
%
4246
%      float ReadBlobFloat(Image *image)
4247
%
4248
%  A description of each parameter follows.
4249
%
4250
%    o image: the image.
4251
%
4252
*/
4253
MagickExport float ReadBlobFloat(Image *image)
4254
38.0M
{
4255
38.0M
  union
4256
38.0M
  {
4257
38.0M
    unsigned int
4258
38.0M
      unsigned_value;
4259
4260
38.0M
    float
4261
38.0M
      float_value;
4262
38.0M
  } quantum;
4263
4264
38.0M
  quantum.float_value=0.0;
4265
38.0M
  quantum.unsigned_value=ReadBlobLong(image);
4266
38.0M
  return(quantum.float_value);
4267
38.0M
}
4268

4269
/*
4270
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4271
%                                                                             %
4272
%                                                                             %
4273
%                                                                             %
4274
+  R e a d B l o b L o n g                                                    %
4275
%                                                                             %
4276
%                                                                             %
4277
%                                                                             %
4278
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4279
%
4280
%  ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
4281
%  byte-order specified by the endian member of the image structure.
4282
%
4283
%  The format of the ReadBlobLong method is:
4284
%
4285
%      unsigned int ReadBlobLong(Image *image)
4286
%
4287
%  A description of each parameter follows.
4288
%
4289
%    o image: the image.
4290
%
4291
*/
4292
MagickExport unsigned int ReadBlobLong(Image *image)
4293
197M
{
4294
197M
  const unsigned char
4295
197M
    *p;
4296
4297
197M
  ssize_t
4298
197M
    count;
4299
4300
197M
  unsigned char
4301
197M
    buffer[4];
4302
4303
197M
  unsigned int
4304
197M
    value;
4305
4306
197M
  assert(image != (Image *) NULL);
4307
197M
  assert(image->signature == MagickCoreSignature);
4308
197M
  *buffer='\0';
4309
197M
  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4310
197M
  if (count != 4)
4311
196M
    return(0UL);
4312
482k
  if (image->endian == LSBEndian)
4313
189k
    {
4314
189k
      value=(unsigned int) (*p++);
4315
189k
      value|=(unsigned int) (*p++) << 8;
4316
189k
      value|=(unsigned int) (*p++) << 16;
4317
189k
      value|=(unsigned int) (*p++) << 24;
4318
189k
      return(value);
4319
189k
    }
4320
292k
  value=(unsigned int) (*p++) << 24;
4321
292k
  value|=(unsigned int) (*p++) << 16;
4322
292k
  value|=(unsigned int) (*p++) << 8;
4323
292k
  value|=(unsigned int) (*p++);
4324
292k
  return(value);
4325
482k
}
4326

4327
/*
4328
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4329
%                                                                             %
4330
%                                                                             %
4331
%                                                                             %
4332
+  R e a d B l o b L o n g L o n g                                            %
4333
%                                                                             %
4334
%                                                                             %
4335
%                                                                             %
4336
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4337
%
4338
%  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
4339
%  byte-order specified by the endian member of the image structure.
4340
%
4341
%  The format of the ReadBlobLongLong method is:
4342
%
4343
%      MagickSizeType ReadBlobLongLong(Image *image)
4344
%
4345
%  A description of each parameter follows.
4346
%
4347
%    o image: the image.
4348
%
4349
*/
4350
MagickExport MagickSizeType ReadBlobLongLong(Image *image)
4351
51.5M
{
4352
51.5M
  MagickSizeType
4353
51.5M
    value;
4354
4355
51.5M
  const unsigned char
4356
51.5M
    *p;
4357
4358
51.5M
  ssize_t
4359
51.5M
    count;
4360
4361
51.5M
  unsigned char
4362
51.5M
    buffer[8];
4363
4364
51.5M
  assert(image != (Image *) NULL);
4365
51.5M
  assert(image->signature == MagickCoreSignature);
4366
51.5M
  *buffer='\0';
4367
51.5M
  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4368
51.5M
  if (count != 8)
4369
51.5M
    return(MagickULLConstant(0));
4370
38.4k
  if (image->endian == LSBEndian)
4371
24.4k
    {
4372
24.4k
      value=(MagickSizeType) (*p++);
4373
24.4k
      value|=(MagickSizeType) (*p++) << 8;
4374
24.4k
      value|=(MagickSizeType) (*p++) << 16;
4375
24.4k
      value|=(MagickSizeType) (*p++) << 24;
4376
24.4k
      value|=(MagickSizeType) (*p++) << 32;
4377
24.4k
      value|=(MagickSizeType) (*p++) << 40;
4378
24.4k
      value|=(MagickSizeType) (*p++) << 48;
4379
24.4k
      value|=(MagickSizeType) (*p++) << 56;
4380
24.4k
      return(value);
4381
24.4k
    }
4382
13.9k
  value=(MagickSizeType) (*p++) << 56;
4383
13.9k
  value|=(MagickSizeType) (*p++) << 48;
4384
13.9k
  value|=(MagickSizeType) (*p++) << 40;
4385
13.9k
  value|=(MagickSizeType) (*p++) << 32;
4386
13.9k
  value|=(MagickSizeType) (*p++) << 24;
4387
13.9k
  value|=(MagickSizeType) (*p++) << 16;
4388
13.9k
  value|=(MagickSizeType) (*p++) << 8;
4389
13.9k
  value|=(MagickSizeType) (*p++);
4390
13.9k
  return(value);
4391
38.4k
}
4392

4393
/*
4394
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4395
%                                                                             %
4396
%                                                                             %
4397
%                                                                             %
4398
+  R e a d B l o b S h o r t                                                  %
4399
%                                                                             %
4400
%                                                                             %
4401
%                                                                             %
4402
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4403
%
4404
%  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
4405
%  specified by the endian member of the image structure.
4406
%
4407
%  The format of the ReadBlobShort method is:
4408
%
4409
%      unsigned short ReadBlobShort(Image *image)
4410
%
4411
%  A description of each parameter follows.
4412
%
4413
%    o image: the image.
4414
%
4415
*/
4416
MagickExport unsigned short ReadBlobShort(Image *image)
4417
103M
{
4418
103M
  const unsigned char
4419
103M
    *p;
4420
4421
103M
  unsigned short
4422
103M
    value;
4423
4424
103M
  ssize_t
4425
103M
    count;
4426
4427
103M
  unsigned char
4428
103M
    buffer[2];
4429
4430
103M
  assert(image != (Image *) NULL);
4431
103M
  assert(image->signature == MagickCoreSignature);
4432
103M
  *buffer='\0';
4433
103M
  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4434
103M
  if (count != 2)
4435
103M
    return((unsigned short) 0U);
4436
120k
  if (image->endian == LSBEndian)
4437
52.3k
    {
4438
52.3k
      value=(unsigned short) (*p++);
4439
52.3k
      value|=(unsigned short) (*p++) << 8;
4440
52.3k
      return(value);
4441
52.3k
    }
4442
67.6k
  value=(unsigned short) ((unsigned short) (*p++) << 8);
4443
67.6k
  value|=(unsigned short) (*p++);
4444
67.6k
  return(value);
4445
120k
}
4446

4447
/*
4448
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4449
%                                                                             %
4450
%                                                                             %
4451
%                                                                             %
4452
+  R e a d B l o b L S B L o n g                                              %
4453
%                                                                             %
4454
%                                                                             %
4455
%                                                                             %
4456
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4457
%
4458
%  ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
4459
%  least-significant byte first order.
4460
%
4461
%  The format of the ReadBlobLSBLong method is:
4462
%
4463
%      unsigned int ReadBlobLSBLong(Image *image)
4464
%
4465
%  A description of each parameter follows.
4466
%
4467
%    o image: the image.
4468
%
4469
*/
4470
MagickExport unsigned int ReadBlobLSBLong(Image *image)
4471
1.86M
{
4472
1.86M
  const unsigned char
4473
1.86M
    *p;
4474
4475
1.86M
  unsigned int
4476
1.86M
    value;
4477
4478
1.86M
  ssize_t
4479
1.86M
    count;
4480
4481
1.86M
  unsigned char
4482
1.86M
    buffer[4];
4483
4484
1.86M
  assert(image != (Image *) NULL);
4485
1.86M
  assert(image->signature == MagickCoreSignature);
4486
1.86M
  *buffer='\0';
4487
1.86M
  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4488
1.86M
  if (count != 4)
4489
78.4k
    return(0U);
4490
1.78M
  value=(unsigned int) (*p++);
4491
1.78M
  value|=(unsigned int) (*p++) << 8;
4492
1.78M
  value|=(unsigned int) (*p++) << 16;
4493
1.78M
  value|=(unsigned int) (*p++) << 24;
4494
1.78M
  return(value);
4495
1.86M
}
4496

4497
/*
4498
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4499
%                                                                             %
4500
%                                                                             %
4501
%                                                                             %
4502
+  R e a d B l o b L S B S i g n e d L o n g                                  %
4503
%                                                                             %
4504
%                                                                             %
4505
%                                                                             %
4506
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4507
%
4508
%  ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
4509
%  least-significant byte first order.
4510
%
4511
%  The format of the ReadBlobLSBSignedLong method is:
4512
%
4513
%      signed int ReadBlobLSBSignedLong(Image *image)
4514
%
4515
%  A description of each parameter follows.
4516
%
4517
%    o image: the image.
4518
%
4519
*/
4520
MagickExport signed int ReadBlobLSBSignedLong(Image *image)
4521
618k
{
4522
618k
  union
4523
618k
  {
4524
618k
    unsigned int
4525
618k
      unsigned_value;
4526
4527
618k
    signed int
4528
618k
      signed_value;
4529
618k
  } quantum;
4530
4531
618k
  quantum.unsigned_value=ReadBlobLSBLong(image);
4532
618k
  return(quantum.signed_value);
4533
618k
}
4534

4535
/*
4536
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4537
%                                                                             %
4538
%                                                                             %
4539
%                                                                             %
4540
+  R e a d B l o b L S B S h o r t                                            %
4541
%                                                                             %
4542
%                                                                             %
4543
%                                                                             %
4544
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4545
%
4546
%  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
4547
%  least-significant byte first order.
4548
%
4549
%  The format of the ReadBlobLSBShort method is:
4550
%
4551
%      unsigned short ReadBlobLSBShort(Image *image)
4552
%
4553
%  A description of each parameter follows.
4554
%
4555
%    o image: the image.
4556
%
4557
*/
4558
MagickExport unsigned short ReadBlobLSBShort(Image *image)
4559
1.14M
{
4560
1.14M
  const unsigned char
4561
1.14M
    *p;
4562
4563
1.14M
  unsigned short
4564
1.14M
    value;
4565
4566
1.14M
  ssize_t
4567
1.14M
    count;
4568
4569
1.14M
  unsigned char
4570
1.14M
    buffer[2];
4571
4572
1.14M
  assert(image != (Image *) NULL);
4573
1.14M
  assert(image->signature == MagickCoreSignature);
4574
1.14M
  *buffer='\0';
4575
1.14M
  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4576
1.14M
  if (count != 2)
4577
12.7k
    return((unsigned short) 0U);
4578
1.13M
  value=(unsigned short) (*p++);
4579
1.13M
  value|=(unsigned short) (*p++) << 8;
4580
1.13M
  return(value);
4581
1.14M
}
4582

4583
/*
4584
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4585
%                                                                             %
4586
%                                                                             %
4587
%                                                                             %
4588
+  R e a d B l o b L S B S i g n e d S h o r t                                %
4589
%                                                                             %
4590
%                                                                             %
4591
%                                                                             %
4592
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4593
%
4594
%  ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
4595
%  least-significant byte-order.
4596
%
4597
%  The format of the ReadBlobLSBSignedShort method is:
4598
%
4599
%      signed short ReadBlobLSBSignedShort(Image *image)
4600
%
4601
%  A description of each parameter follows.
4602
%
4603
%    o image: the image.
4604
%
4605
*/
4606
MagickExport signed short ReadBlobLSBSignedShort(Image *image)
4607
284k
{
4608
284k
  union
4609
284k
  {
4610
284k
    unsigned short
4611
284k
      unsigned_value;
4612
4613
284k
    signed short
4614
284k
      signed_value;
4615
284k
  } quantum;
4616
4617
284k
  quantum.unsigned_value=ReadBlobLSBShort(image);
4618
284k
  return(quantum.signed_value);
4619
284k
}
4620

4621
/*
4622
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4623
%                                                                             %
4624
%                                                                             %
4625
%                                                                             %
4626
+  R e a d B l o b M S B L o n g                                              %
4627
%                                                                             %
4628
%                                                                             %
4629
%                                                                             %
4630
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4631
%
4632
%  ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
4633
%  most-significant byte first order.
4634
%
4635
%  The format of the ReadBlobMSBLong method is:
4636
%
4637
%      unsigned int ReadBlobMSBLong(Image *image)
4638
%
4639
%  A description of each parameter follows.
4640
%
4641
%    o image: the image.
4642
%
4643
*/
4644
MagickExport unsigned int ReadBlobMSBLong(Image *image)
4645
182M
{
4646
182M
  const unsigned char
4647
182M
    *p;
4648
4649
182M
  unsigned int
4650
182M
    value;
4651
4652
182M
  ssize_t
4653
182M
    count;
4654
4655
182M
  unsigned char
4656
182M
    buffer[4];
4657
4658
182M
  assert(image != (Image *) NULL);
4659
182M
  assert(image->signature == MagickCoreSignature);
4660
182M
  *buffer='\0';
4661
182M
  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4662
182M
  if (count != 4)
4663
39.9M
    return(0UL);
4664
142M
  value=(unsigned int) (*p++) << 24;
4665
142M
  value|=(unsigned int) (*p++) << 16;
4666
142M
  value|=(unsigned int) (*p++) << 8;
4667
142M
  value|=(unsigned int) (*p++);
4668
142M
  return(value);
4669
182M
}
4670

4671
/*
4672
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4673
%                                                                             %
4674
%                                                                             %
4675
%                                                                             %
4676
+  R e a d B l o b M S B L o n g L o n g                                      %
4677
%                                                                             %
4678
%                                                                             %
4679
%                                                                             %
4680
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4681
%
4682
%  ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
4683
%  in most-significant byte first order.
4684
%
4685
%  The format of the ReadBlobMSBLongLong method is:
4686
%
4687
%      unsigned int ReadBlobMSBLongLong(Image *image)
4688
%
4689
%  A description of each parameter follows.
4690
%
4691
%    o image: the image.
4692
%
4693
*/
4694
MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
4695
7.68k
{
4696
7.68k
  const unsigned char
4697
7.68k
    *p;
4698
4699
7.68k
  MagickSizeType
4700
7.68k
    value;
4701
4702
7.68k
  ssize_t
4703
7.68k
    count;
4704
4705
7.68k
  unsigned char
4706
7.68k
    buffer[8];
4707
4708
7.68k
  assert(image != (Image *) NULL);
4709
7.68k
  assert(image->signature == MagickCoreSignature);
4710
7.68k
  *buffer='\0';
4711
7.68k
  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4712
7.68k
  if (count != 8)
4713
1.12k
    return(MagickULLConstant(0));
4714
6.55k
  value=(MagickSizeType) (*p++) << 56;
4715
6.55k
  value|=(MagickSizeType) (*p++) << 48;
4716
6.55k
  value|=(MagickSizeType) (*p++) << 40;
4717
6.55k
  value|=(MagickSizeType) (*p++) << 32;
4718
6.55k
  value|=(MagickSizeType) (*p++) << 24;
4719
6.55k
  value|=(MagickSizeType) (*p++) << 16;
4720
6.55k
  value|=(MagickSizeType) (*p++) << 8;
4721
6.55k
  value|=(MagickSizeType) (*p++);
4722
6.55k
  return(value);
4723
7.68k
}
4724

4725
/*
4726
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4727
%                                                                             %
4728
%                                                                             %
4729
%                                                                             %
4730
+  R e a d B l o b M S B S h o r t                                            %
4731
%                                                                             %
4732
%                                                                             %
4733
%                                                                             %
4734
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4735
%
4736
%  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
4737
%  most-significant byte first order.
4738
%
4739
%  The format of the ReadBlobMSBShort method is:
4740
%
4741
%      unsigned short ReadBlobMSBShort(Image *image)
4742
%
4743
%  A description of each parameter follows.
4744
%
4745
%    o image: the image.
4746
%
4747
*/
4748
MagickExport unsigned short ReadBlobMSBShort(Image *image)
4749
6.46M
{
4750
6.46M
  const unsigned char
4751
6.46M
    *p;
4752
4753
6.46M
  unsigned short
4754
6.46M
    value;
4755
4756
6.46M
  ssize_t
4757
6.46M
    count;
4758
4759
6.46M
  unsigned char
4760
6.46M
    buffer[2];
4761
4762
6.46M
  assert(image != (Image *) NULL);
4763
6.46M
  assert(image->signature == MagickCoreSignature);
4764
6.46M
  *buffer='\0';
4765
6.46M
  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4766
6.46M
  if (count != 2)
4767
5.99M
    return((unsigned short) 0U);
4768
469k
  value=(unsigned short) ((*p++) << 8);
4769
469k
  value|=(unsigned short) (*p++);
4770
469k
  return((unsigned short) (value & 0xffff));
4771
6.46M
}
4772

4773
/*
4774
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4775
%                                                                             %
4776
%                                                                             %
4777
%                                                                             %
4778
+  R e a d B l o b M S B S i g n e d L o n g                                  %
4779
%                                                                             %
4780
%                                                                             %
4781
%                                                                             %
4782
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4783
%
4784
%  ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4785
%  most-significant byte-order.
4786
%
4787
%  The format of the ReadBlobMSBSignedLong method is:
4788
%
4789
%      signed int ReadBlobMSBSignedLong(Image *image)
4790
%
4791
%  A description of each parameter follows.
4792
%
4793
%    o image: the image.
4794
%
4795
*/
4796
MagickExport signed int ReadBlobMSBSignedLong(Image *image)
4797
215k
{
4798
215k
  union
4799
215k
  {
4800
215k
    unsigned int
4801
215k
      unsigned_value;
4802
4803
215k
    signed int
4804
215k
      signed_value;
4805
215k
  } quantum;
4806
4807
215k
  quantum.unsigned_value=ReadBlobMSBLong(image);
4808
215k
  return(quantum.signed_value);
4809
215k
}
4810

4811
/*
4812
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4813
%                                                                             %
4814
%                                                                             %
4815
%                                                                             %
4816
+  R e a d B l o b M S B S i g n e d S h o r t                                %
4817
%                                                                             %
4818
%                                                                             %
4819
%                                                                             %
4820
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4821
%
4822
%  ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4823
%  most-significant byte-order.
4824
%
4825
%  The format of the ReadBlobMSBSignedShort method is:
4826
%
4827
%      signed short ReadBlobMSBSignedShort(Image *image)
4828
%
4829
%  A description of each parameter follows.
4830
%
4831
%    o image: the image.
4832
%
4833
*/
4834
MagickExport signed short ReadBlobMSBSignedShort(Image *image)
4835
84.1k
{
4836
84.1k
  union
4837
84.1k
  {
4838
84.1k
    unsigned short
4839
84.1k
      unsigned_value;
4840
4841
84.1k
    signed short
4842
84.1k
      signed_value;
4843
84.1k
  } quantum;
4844
4845
84.1k
  quantum.unsigned_value=ReadBlobMSBShort(image);
4846
84.1k
  return(quantum.signed_value);
4847
84.1k
}
4848

4849
/*
4850
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4851
%                                                                             %
4852
%                                                                             %
4853
%                                                                             %
4854
+  R e a d B l o b S i g n e d L o n g                                        %
4855
%                                                                             %
4856
%                                                                             %
4857
%                                                                             %
4858
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4859
%
4860
%  ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4861
%  byte-order specified by the endian member of the image structure.
4862
%
4863
%  The format of the ReadBlobSignedLong method is:
4864
%
4865
%      signed int ReadBlobSignedLong(Image *image)
4866
%
4867
%  A description of each parameter follows.
4868
%
4869
%    o image: the image.
4870
%
4871
*/
4872
MagickExport signed int ReadBlobSignedLong(Image *image)
4873
26.6k
{
4874
26.6k
  union
4875
26.6k
  {
4876
26.6k
    unsigned int
4877
26.6k
      unsigned_value;
4878
4879
26.6k
    signed int
4880
26.6k
      signed_value;
4881
26.6k
  } quantum;
4882
4883
26.6k
  quantum.unsigned_value=ReadBlobLong(image);
4884
26.6k
  return(quantum.signed_value);
4885
26.6k
}
4886

4887
/*
4888
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4889
%                                                                             %
4890
%                                                                             %
4891
%                                                                             %
4892
+  R e a d B l o b S i g n e d S h o r t                                      %
4893
%                                                                             %
4894
%                                                                             %
4895
%                                                                             %
4896
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4897
%
4898
%  ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4899
%  byte-order specified by the endian member of the image structure.
4900
%
4901
%  The format of the ReadBlobSignedShort method is:
4902
%
4903
%      signed short ReadBlobSignedShort(Image *image)
4904
%
4905
%  A description of each parameter follows.
4906
%
4907
%    o image: the image.
4908
%
4909
*/
4910
MagickExport signed short ReadBlobSignedShort(Image *image)
4911
24.8k
{
4912
24.8k
  union
4913
24.8k
  {
4914
24.8k
    unsigned short
4915
24.8k
      unsigned_value;
4916
4917
24.8k
    signed short
4918
24.8k
      signed_value;
4919
24.8k
  } quantum;
4920
4921
24.8k
  quantum.unsigned_value=ReadBlobShort(image);
4922
24.8k
  return(quantum.signed_value);
4923
24.8k
}
4924

4925
/*
4926
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4927
%                                                                             %
4928
%                                                                             %
4929
%                                                                             %
4930
+  R e a d B l o b S t r e a m                                                %
4931
%                                                                             %
4932
%                                                                             %
4933
%                                                                             %
4934
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4935
%
4936
%  ReadBlobStream() reads data from the blob or image file and returns it.  It
4937
%  returns a pointer to the data buffer you supply or to the image memory
4938
%  buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4939
%  returns a count of zero and has no other results. If length is greater than
4940
%  MAGICK_SSIZE_MAX, the result is unspecified.
4941
%
4942
%  The format of the ReadBlobStream method is:
4943
%
4944
%      const void *ReadBlobStream(Image *image,const size_t length,
4945
%        void *magick_restrict data,ssize_t *count)
4946
%
4947
%  A description of each parameter follows:
4948
%
4949
%    o image: the image.
4950
%
4951
%    o length:  Specifies an integer representing the number of bytes to read
4952
%      from the file.
4953
%
4954
%    o count: returns the number of bytes read.
4955
%
4956
%    o data:  Specifies an area to place the information requested from the
4957
%      file.
4958
%
4959
*/
4960
MagickExport magick_hot_spot const void *ReadBlobStream(Image *image,
4961
  const size_t length,void *magick_restrict data,ssize_t *count)
4962
545M
{
4963
545M
  BlobInfo
4964
545M
    *magick_restrict blob_info;
4965
4966
545M
  assert(image != (Image *) NULL);
4967
545M
  assert(image->signature == MagickCoreSignature);
4968
545M
  assert(image->blob != (BlobInfo *) NULL);
4969
545M
  assert(image->blob->type != UndefinedStream);
4970
545M
  assert(count != (ssize_t *) NULL);
4971
545M
  blob_info=image->blob;
4972
545M
  if (blob_info->type != BlobStream)
4973
617k
    {
4974
617k
      assert(data != NULL);
4975
617k
      *count=ReadBlob(image,length,(unsigned char *) data);
4976
617k
      return(data);
4977
617k
    }
4978
544M
  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4979
393M
    {
4980
393M
      *count=0;
4981
393M
      blob_info->eof=MagickTrue;
4982
393M
      return(data);
4983
393M
    }
4984
150M
  data=blob_info->data+blob_info->offset;
4985
150M
  *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4986
150M
    blob_info->length-blob_info->offset);
4987
150M
  blob_info->offset+=(*count);
4988
150M
  if (*count != (ssize_t) length)
4989
3.96M
    blob_info->eof=MagickTrue;
4990
150M
  return(data);
4991
544M
}
4992

4993
/*
4994
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4995
%                                                                             %
4996
%                                                                             %
4997
%                                                                             %
4998
+   R e a d B l o b S t r i n g                                               %
4999
%                                                                             %
5000
%                                                                             %
5001
%                                                                             %
5002
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5003
%
5004
%  ReadBlobString() reads characters from a blob or file until a newline
5005
%  character is read or an end-of-file condition is encountered.
5006
%
5007
%  The format of the ReadBlobString method is:
5008
%
5009
%      char *ReadBlobString(Image *image,char *string)
5010
%
5011
%  A description of each parameter follows:
5012
%
5013
%    o image: the image.
5014
%
5015
%    o string: the address of a character buffer.
5016
%
5017
*/
5018
MagickExport char *ReadBlobString(Image *image,char *string)
5019
83.5k
{
5020
83.5k
  BlobInfo
5021
83.5k
    *magick_restrict blob_info;
5022
5023
83.5k
  int
5024
83.5k
    c = -1;
5025
5026
83.5k
  size_t
5027
83.5k
    i = 0;
5028
5029
83.5k
  assert(image != (Image *) NULL);
5030
83.5k
  assert(image->signature == MagickCoreSignature);
5031
83.5k
  assert(image->blob != (BlobInfo *) NULL);
5032
83.5k
  assert(image->blob->type != UndefinedStream);
5033
83.5k
  if (IsEventLogging() != MagickFalse)
5034
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5035
83.5k
  *string='\0';
5036
83.5k
  blob_info=image->blob;
5037
83.5k
  switch (blob_info->type)
5038
83.5k
  {
5039
0
    case UndefinedStream:
5040
0
      break;
5041
0
    case StandardStream:
5042
0
    case FileStream:
5043
0
    {
5044
0
      char *p = fgets(string,MagickPathExtent,blob_info->file_info.file);
5045
0
      if (p == (char *) NULL)
5046
0
        {
5047
0
          if (ferror(blob_info->file_info.file) != 0)
5048
0
            ThrowBlobException(blob_info);
5049
0
          return((char *) NULL);
5050
0
        }
5051
0
      i=strlen(string);
5052
0
      break;
5053
0
    }
5054
4.44k
    case ZipStream:
5055
4.44k
    {
5056
4.44k
#if defined(MAGICKCORE_ZLIB_DELEGATE)
5057
4.44k
      char *p = gzgets(blob_info->file_info.gzfile,string,MagickPathExtent);
5058
4.44k
      if (p == (char *) NULL)
5059
87
        {
5060
87
          int status = Z_OK;
5061
87
          (void) gzerror(blob_info->file_info.gzfile,&status);
5062
87
          if (status != Z_OK)
5063
87
            ThrowBlobException(blob_info);
5064
87
          return((char *) NULL);
5065
87
        }
5066
4.35k
      i=strlen(string);
5067
4.35k
      break;
5068
4.44k
#endif
5069
4.44k
    }
5070
79.1k
    default:
5071
79.1k
    {
5072
79.1k
      do
5073
4.31M
      {
5074
4.31M
        c=ReadBlobByte(image);
5075
4.31M
        if (c == EOF)
5076
14.8k
          {
5077
14.8k
            blob_info->eof=MagickTrue;
5078
14.8k
            break;
5079
14.8k
          }
5080
4.30M
        string[i++]=(char) c;
5081
4.30M
        if (c == '\n')
5082
64.1k
          break;
5083
4.30M
      } while (i < (MaxTextExtent-2));
5084
79.1k
      string[i]='\0';
5085
79.1k
      break;
5086
4.44k
    }
5087
83.5k
  }
5088
  /*
5089
    Strip trailing newline.
5090
  */
5091
83.4k
  if ((string[i] == '\r') || (string[i] == '\n'))
5092
0
    string[i]='\0';
5093
83.4k
  if (i >= 1)
5094
75.7k
    if ((string[i-1] == '\r') || (string[i-1] == '\n'))
5095
66.6k
      string[i-1]='\0';
5096
83.4k
  if ((*string == '\0') && (blob_info->eof != MagickFalse))
5097
7.32k
    return((char *) NULL);
5098
76.1k
  return(string);
5099
83.4k
}
5100

5101
/*
5102
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5103
%                                                                             %
5104
%                                                                             %
5105
%                                                                             %
5106
+   R e f e r e n c e B l o b                                                 %
5107
%                                                                             %
5108
%                                                                             %
5109
%                                                                             %
5110
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5111
%
5112
%  ReferenceBlob() increments the reference count associated with the pixel
5113
%  blob returning a pointer to the blob.
5114
%
5115
%  The format of the ReferenceBlob method is:
5116
%
5117
%      BlobInfo ReferenceBlob(BlobInfo *blob_info)
5118
%
5119
%  A description of each parameter follows:
5120
%
5121
%    o blob_info: the blob_info.
5122
%
5123
*/
5124
MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
5125
118k
{
5126
118k
  assert(blob != (BlobInfo *) NULL);
5127
118k
  assert(blob->signature == MagickCoreSignature);
5128
118k
  if (IsEventLogging() != MagickFalse)
5129
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5130
118k
  LockSemaphoreInfo(blob->semaphore);
5131
118k
  blob->reference_count++;
5132
118k
  UnlockSemaphoreInfo(blob->semaphore);
5133
118k
  return(blob);
5134
118k
}
5135

5136
/*
5137
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5138
%                                                                             %
5139
%                                                                             %
5140
%                                                                             %
5141
+  S e e k B l o b                                                            %
5142
%                                                                             %
5143
%                                                                             %
5144
%                                                                             %
5145
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5146
%
5147
%  SeekBlob() sets the offset in bytes from the beginning of a blob or file
5148
%  and returns the resulting offset.
5149
%
5150
%  The format of the SeekBlob method is:
5151
%
5152
%      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
5153
%        const int whence)
5154
%
5155
%  A description of each parameter follows:
5156
%
5157
%    o image: the image.
5158
%
5159
%    o offset:  Specifies an integer representing the offset in bytes.
5160
%
5161
%    o whence:  Specifies an integer representing how the offset is
5162
%      treated relative to the beginning of the blob as follows:
5163
%
5164
%        SEEK_SET  Set position equal to offset bytes.
5165
%        SEEK_CUR  Set position to current location plus offset.
5166
%        SEEK_END  Set position to EOF plus offset.
5167
%
5168
*/
5169
MagickExport MagickOffsetType SeekBlob(Image *image,
5170
  const MagickOffsetType offset,const int whence)
5171
44.2M
{
5172
44.2M
  BlobInfo
5173
44.2M
    *magick_restrict blob_info;
5174
5175
44.2M
  assert(image != (Image *) NULL);
5176
44.2M
  assert(image->signature == MagickCoreSignature);
5177
44.2M
  assert(image->blob != (BlobInfo *) NULL);
5178
44.2M
  assert(image->blob->type != UndefinedStream);
5179
44.2M
  if (IsEventLogging() != MagickFalse)
5180
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5181
44.2M
  blob_info=image->blob;
5182
44.2M
  switch (blob_info->type)
5183
44.2M
  {
5184
0
    case UndefinedStream:
5185
0
      break;
5186
0
    case StandardStream:
5187
0
    case PipeStream:
5188
0
      return(-1);
5189
173k
    case FileStream:
5190
173k
    {
5191
173k
      if ((offset < 0) && (whence == SEEK_SET))
5192
0
        return(-1);
5193
173k
      if (fseek(blob_info->file_info.file,offset,whence) < 0)
5194
0
        return(-1);
5195
173k
      blob_info->offset=TellBlob(image);
5196
173k
      break;
5197
173k
    }
5198
9.28k
    case ZipStream:
5199
9.28k
    {
5200
9.28k
#if defined(MAGICKCORE_ZLIB_DELEGATE)
5201
9.28k
      if (gzseek(blob_info->file_info.gzfile,(long) offset,whence) < 0)
5202
660
        return(-1);
5203
8.62k
#endif
5204
8.62k
      blob_info->offset=TellBlob(image);
5205
8.62k
      break;
5206
9.28k
    }
5207
0
    case BZipStream:
5208
0
      return(-1);
5209
0
    case FifoStream:
5210
0
      return(-1);
5211
44.0M
    case BlobStream:
5212
44.0M
    {
5213
44.0M
      switch (whence)
5214
44.0M
      {
5215
43.8M
        case SEEK_SET:
5216
43.8M
        default:
5217
43.8M
        {
5218
43.8M
          if (offset < 0)
5219
11.2k
            return(-1);
5220
43.8M
          blob_info->offset=offset;
5221
43.8M
          break;
5222
43.8M
        }
5223
146k
        case SEEK_CUR:
5224
146k
        {
5225
146k
          if (((offset > 0) && (blob_info->offset > (MAGICK_SSIZE_MAX-offset))) ||
5226
146k
              ((offset < 0) && (blob_info->offset < (MAGICK_SSIZE_MIN-offset))))
5227
0
            {
5228
0
              errno=EOVERFLOW;
5229
0
              return(-1);
5230
0
            }
5231
146k
          if ((blob_info->offset+offset) < 0)
5232
0
            return(-1);
5233
146k
          blob_info->offset+=offset;
5234
146k
          break;
5235
146k
        }
5236
13.6k
        case SEEK_END:
5237
13.6k
        {
5238
13.6k
          if (((MagickOffsetType) blob_info->length+offset) < 0)
5239
268
            return(-1);
5240
13.4k
          blob_info->offset=(MagickOffsetType) blob_info->length+offset;
5241
13.4k
          break;
5242
13.6k
        }
5243
44.0M
      }
5244
44.0M
      if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
5245
43.9M
        {
5246
43.9M
          blob_info->eof=MagickFalse;
5247
43.9M
          break;
5248
43.9M
        }
5249
93.1k
      break;
5250
44.0M
    }
5251
93.1k
    case CustomStream:
5252
396
    {
5253
396
      if (blob_info->custom_stream->seeker == (CustomStreamSeeker) NULL)
5254
0
        return(-1);
5255
396
      blob_info->offset=blob_info->custom_stream->seeker(offset,whence,
5256
396
        blob_info->custom_stream->data);
5257
396
      break;
5258
396
    }
5259
44.2M
  }
5260
44.1M
  return(blob_info->offset);
5261
44.2M
}
5262

5263
/*
5264
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5265
%                                                                             %
5266
%                                                                             %
5267
%                                                                             %
5268
+   S e t B l o b E x e m p t                                                 %
5269
%                                                                             %
5270
%                                                                             %
5271
%                                                                             %
5272
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5273
%
5274
%  SetBlobExempt() sets the blob exempt status.
5275
%
5276
%  The format of the SetBlobExempt method is:
5277
%
5278
%      MagickBooleanType SetBlobExempt(const Image *image,
5279
%        const MagickBooleanType exempt)
5280
%
5281
%  A description of each parameter follows:
5282
%
5283
%    o image: the image.
5284
%
5285
%    o exempt: Set to true if this blob is exempt from being closed.
5286
%
5287
*/
5288
MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
5289
2.86M
{
5290
2.86M
  assert(image != (const Image *) NULL);
5291
2.86M
  assert(image->signature == MagickCoreSignature);
5292
2.86M
  if (IsEventLogging() != MagickFalse)
5293
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5294
2.86M
  image->blob->exempt=exempt;
5295
2.86M
}
5296

5297
/*
5298
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5299
%                                                                             %
5300
%                                                                             %
5301
%                                                                             %
5302
+  S e t B l o b E x t e n t                                                  %
5303
%                                                                             %
5304
%                                                                             %
5305
%                                                                             %
5306
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5307
%
5308
%  SetBlobExtent() ensures enough space is allocated for the blob.  If the
5309
%  method is successful, subsequent writes to bytes in the specified range are
5310
%  guaranteed not to fail.
5311
%
5312
%  The format of the SetBlobExtent method is:
5313
%
5314
%      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
5315
%
5316
%  A description of each parameter follows:
5317
%
5318
%    o image: the image.
5319
%
5320
%    o extent:  the blob maximum extent.
5321
%
5322
*/
5323
MagickExport MagickBooleanType SetBlobExtent(Image *image,
5324
  const MagickSizeType extent)
5325
72.5k
{
5326
72.5k
  BlobInfo
5327
72.5k
    *magick_restrict blob_info;
5328
5329
72.5k
  assert(image != (Image *) NULL);
5330
72.5k
  assert(image->signature == MagickCoreSignature);
5331
72.5k
  assert(image->blob != (BlobInfo *) NULL);
5332
72.5k
  assert(image->blob->type != UndefinedStream);
5333
72.5k
  if (IsEventLogging() != MagickFalse)
5334
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5335
72.5k
  blob_info=image->blob;
5336
72.5k
  switch (blob_info->type)
5337
72.5k
  {
5338
0
    case UndefinedStream:
5339
0
      break;
5340
0
    case StandardStream:
5341
0
      return(MagickFalse);
5342
0
    case FileStream:
5343
0
    {
5344
0
      MagickOffsetType
5345
0
        offset;
5346
5347
0
      ssize_t
5348
0
        count;
5349
5350
0
      if (extent != (MagickSizeType) ((off_t) extent))
5351
0
        return(MagickFalse);
5352
0
      offset=SeekBlob(image,0,SEEK_END);
5353
0
      if (offset < 0)
5354
0
        return(MagickFalse);
5355
0
      if ((MagickSizeType) offset >= extent)
5356
0
        break;
5357
0
      offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5358
0
      if (offset < 0)
5359
0
        break;
5360
0
      count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5361
0
        blob_info->file_info.file);
5362
0
#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5363
0
      if (blob_info->synchronize != MagickFalse)
5364
0
        {
5365
0
          int
5366
0
            file;
5367
5368
0
          file=fileno(blob_info->file_info.file);
5369
0
          if ((file == -1) || (offset < 0))
5370
0
            return(MagickFalse);
5371
0
          (void) posix_fallocate(file,offset,(MagickOffsetType) extent-offset);
5372
0
        }
5373
0
#endif
5374
0
      offset=SeekBlob(image,offset,SEEK_SET);
5375
0
      if (count != 1)
5376
0
        return(MagickFalse);
5377
0
      break;
5378
0
    }
5379
0
    case PipeStream:
5380
0
    case ZipStream:
5381
0
      return(MagickFalse);
5382
0
    case BZipStream:
5383
0
      return(MagickFalse);
5384
0
    case FifoStream:
5385
0
      return(MagickFalse);
5386
72.5k
    case BlobStream:
5387
72.5k
    {
5388
72.5k
      if (extent != (MagickSizeType) ((size_t) extent))
5389
0
        return(MagickFalse);
5390
72.5k
      if (blob_info->mapped != MagickFalse)
5391
0
        {
5392
0
          MagickOffsetType
5393
0
            offset;
5394
5395
0
          ssize_t
5396
0
            count;
5397
5398
0
          (void) UnmapBlob(blob_info->data,blob_info->length);
5399
0
          RelinquishMagickResource(MapResource,blob_info->length);
5400
0
          if (extent != (MagickSizeType) ((off_t) extent))
5401
0
            return(MagickFalse);
5402
0
          offset=SeekBlob(image,0,SEEK_END);
5403
0
          if (offset < 0)
5404
0
            return(MagickFalse);
5405
0
          if ((MagickSizeType) offset >= extent)
5406
0
            break;
5407
0
          offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5408
0
          count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5409
0
            blob_info->file_info.file);
5410
0
#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5411
0
          if (blob_info->synchronize != MagickFalse)
5412
0
            {
5413
0
              int
5414
0
                file;
5415
5416
0
              file=fileno(blob_info->file_info.file);
5417
0
              if ((file == -1) || (offset < 0))
5418
0
                return(MagickFalse);
5419
0
              (void) posix_fallocate(file,offset,(MagickOffsetType) extent-
5420
0
                offset);
5421
0
            }
5422
0
#endif
5423
0
          offset=SeekBlob(image,offset,SEEK_SET);
5424
0
          if (count != 1)
5425
0
            return(MagickFalse);
5426
0
          (void) AcquireMagickResource(MapResource,extent);
5427
0
          blob_info->data=(unsigned char*) MapBlob(fileno(
5428
0
            blob_info->file_info.file),WriteMode,0,(size_t) extent);
5429
0
          blob_info->extent=(size_t) extent;
5430
0
          blob_info->length=(size_t) extent;
5431
0
          (void) SyncBlob(image);
5432
0
          break;
5433
0
        }
5434
72.5k
      blob_info->extent=(size_t) extent;
5435
72.5k
      blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
5436
72.5k
        blob_info->extent+1,sizeof(*blob_info->data));
5437
72.5k
      (void) SyncBlob(image);
5438
72.5k
      if (blob_info->data == (unsigned char *) NULL)
5439
12
        {
5440
12
          (void) DetachBlob(blob_info);
5441
12
          return(MagickFalse);
5442
12
        }
5443
72.5k
      break;
5444
72.5k
    }
5445
72.5k
    case CustomStream:
5446
0
      break;
5447
72.5k
  }
5448
72.5k
  return(MagickTrue);
5449
72.5k
}
5450

5451
/*
5452
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5453
%                                                                             %
5454
%                                                                             %
5455
%                                                                             %
5456
+  S e t C u s t o m S t r e a m D a t a                                      %
5457
%                                                                             %
5458
%                                                                             %
5459
%                                                                             %
5460
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5461
%
5462
%  SetCustomStreamData() sets the stream info data member.
5463
%
5464
%  The format of the SetCustomStreamData method is:
5465
%
5466
%      void SetCustomStreamData(CustomStreamInfo *custom_stream,void *)
5467
%
5468
%  A description of each parameter follows:
5469
%
5470
%    o custom_stream: the custom stream info.
5471
%
5472
%    o data: an object containing information about the custom stream.
5473
%
5474
*/
5475
MagickExport void SetCustomStreamData(CustomStreamInfo *custom_stream,
5476
  void *data)
5477
396
{
5478
396
  assert(custom_stream != (CustomStreamInfo *) NULL);
5479
396
  assert(custom_stream->signature == MagickCoreSignature);
5480
396
  custom_stream->data=data;
5481
396
}
5482

5483
/*
5484
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5485
%                                                                             %
5486
%                                                                             %
5487
%                                                                             %
5488
+  S e t C u s t o m S t r e a m R e a d e r                                  %
5489
%                                                                             %
5490
%                                                                             %
5491
%                                                                             %
5492
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5493
%
5494
%  SetCustomStreamReader() sets the stream info reader member.
5495
%
5496
%  The format of the SetCustomStreamReader method is:
5497
%
5498
%      void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5499
%        CustomStreamHandler reader)
5500
%
5501
%  A description of each parameter follows:
5502
%
5503
%    o custom_stream: the custom stream info.
5504
%
5505
%    o reader: a function to read from the stream.
5506
%
5507
*/
5508
MagickExport void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5509
  CustomStreamHandler reader)
5510
396
{
5511
396
  assert(custom_stream != (CustomStreamInfo *) NULL);
5512
396
  assert(custom_stream->signature == MagickCoreSignature);
5513
396
  custom_stream->reader=reader;
5514
396
}
5515

5516
/*
5517
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5518
%                                                                             %
5519
%                                                                             %
5520
%                                                                             %
5521
+  S e t C u s t o m S t r e a m S e e k e r                                  %
5522
%                                                                             %
5523
%                                                                             %
5524
%                                                                             %
5525
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5526
%
5527
%  SetCustomStreamSeeker() sets the stream info seeker member.
5528
%
5529
%  The format of the SetCustomStreamReader method is:
5530
%
5531
%      void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5532
%        CustomStreamSeeker seeker)
5533
%
5534
%  A description of each parameter follows:
5535
%
5536
%    o custom_stream: the custom stream info.
5537
%
5538
%    o seeker: a function to seek in the custom stream.
5539
%
5540
*/
5541
MagickExport void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5542
  CustomStreamSeeker seeker)
5543
396
{
5544
396
  assert(custom_stream != (CustomStreamInfo *) NULL);
5545
396
  assert(custom_stream->signature == MagickCoreSignature);
5546
396
  custom_stream->seeker=seeker;
5547
396
}
5548

5549
/*
5550
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5551
%                                                                             %
5552
%                                                                             %
5553
%                                                                             %
5554
+  S e t C u s t o m S t r e a m T e l l e r                                  %
5555
%                                                                             %
5556
%                                                                             %
5557
%                                                                             %
5558
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5559
%
5560
%  SetCustomStreamTeller() sets the stream info teller member.
5561
%
5562
%  The format of the SetCustomStreamTeller method is:
5563
%
5564
%      void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5565
%        CustomStreamTeller *teller)
5566
%
5567
%  A description of each parameter follows:
5568
%
5569
%    o custom_stream: the custom stream info.
5570
%
5571
%    o teller: a function to set the position in the stream.
5572
%
5573
*/
5574
MagickExport void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5575
  CustomStreamTeller teller)
5576
396
{
5577
396
  assert(custom_stream != (CustomStreamInfo *) NULL);
5578
396
  assert(custom_stream->signature == MagickCoreSignature);
5579
396
  custom_stream->teller=teller;
5580
396
}
5581

5582
/*
5583
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5584
%                                                                             %
5585
%                                                                             %
5586
%                                                                             %
5587
+  S e t C u s t o m S t r e a m W r i t e r                                  %
5588
%                                                                             %
5589
%                                                                             %
5590
%                                                                             %
5591
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5592
%
5593
%  SetCustomStreamWriter() sets the stream info writer member.
5594
%
5595
%  The format of the SetCustomStreamWriter method is:
5596
%
5597
%      void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5598
%        CustomStreamHandler *writer)
5599
%
5600
%  A description of each parameter follows:
5601
%
5602
%    o custom_stream: the custom stream info.
5603
%
5604
%    o writer: a function to write to the custom stream.
5605
%
5606
*/
5607
MagickExport void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5608
  CustomStreamHandler writer)
5609
0
{
5610
0
  assert(custom_stream != (CustomStreamInfo *) NULL);
5611
0
  assert(custom_stream->signature == MagickCoreSignature);
5612
0
  custom_stream->writer=writer;
5613
0
}
5614

5615
/*
5616
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5617
%                                                                             %
5618
%                                                                             %
5619
%                                                                             %
5620
+  S y n c B l o b                                                            %
5621
%                                                                             %
5622
%                                                                             %
5623
%                                                                             %
5624
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5625
%
5626
%  SyncBlob() flushes the datastream if it is a file or synchronizes the data
5627
%  attributes if it is an blob.  It returns 0 on success; otherwise, it returns
5628
%  -1 and set errno to indicate the error.
5629
%
5630
%  The format of the SyncBlob method is:
5631
%
5632
%      int SyncBlob(const Image *image)
5633
%
5634
%  A description of each parameter follows:
5635
%
5636
%    o image: the image.
5637
%
5638
*/
5639
static int SyncBlob(const Image *image)
5640
1.73M
{
5641
1.73M
  BlobInfo
5642
1.73M
    *magick_restrict blob_info;
5643
5644
1.73M
  int
5645
1.73M
    status;
5646
5647
1.73M
  assert(image != (Image *) NULL);
5648
1.73M
  assert(image->signature == MagickCoreSignature);
5649
1.73M
  assert(image->blob != (BlobInfo *) NULL);
5650
1.73M
  if (IsEventLogging() != MagickFalse)
5651
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5652
1.73M
  if (EOFBlob(image) != 0)
5653
418k
    return(0);
5654
1.31M
  blob_info=image->blob;
5655
1.31M
  status=0;
5656
1.31M
  switch (blob_info->type)
5657
1.31M
  {
5658
0
    case UndefinedStream:
5659
0
      break;
5660
0
    case StandardStream:
5661
0
    {
5662
0
      if ((blob_info->mode == WriteBlobMode) ||
5663
0
          (blob_info->mode == WriteBinaryBlobMode) ||
5664
0
          (blob_info->mode == AppendBlobMode) ||
5665
0
          (blob_info->mode == AppendBinaryBlobMode))
5666
0
        status=fflush(blob_info->file_info.file);
5667
0
      break;
5668
0
    }
5669
293k
    case FileStream:
5670
293k
    case PipeStream:
5671
293k
    {
5672
293k
      status=fflush(blob_info->file_info.file);
5673
293k
      break;
5674
293k
    }
5675
37.9k
    case ZipStream:
5676
37.9k
    {
5677
37.9k
#if defined(MAGICKCORE_ZLIB_DELEGATE)
5678
37.9k
      (void) gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
5679
37.9k
#endif
5680
37.9k
      break;
5681
293k
    }
5682
0
    case BZipStream:
5683
0
    {
5684
#if defined(MAGICKCORE_BZLIB_DELEGATE)
5685
      status=BZ2_bzflush(blob_info->file_info.bzfile);
5686
#endif
5687
0
      break;
5688
293k
    }
5689
0
    case FifoStream:
5690
0
      break;
5691
987k
    case BlobStream:
5692
987k
      break;
5693
253
    case CustomStream:
5694
253
      break;
5695
1.31M
  }
5696
1.31M
  return(status);
5697
1.31M
}
5698

5699
/*
5700
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5701
%                                                                             %
5702
%                                                                             %
5703
%                                                                             %
5704
+  S y n c B l o b S t r e a m                                                %
5705
%                                                                             %
5706
%                                                                             %
5707
%                                                                             %
5708
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5709
%
5710
%  SyncBlobStream() transfers ownership of an in-memory blob stream from the
5711
%  image that has just been written back to the owner image and to image info.
5712
%  The method copies the current buffer state onto the owner, refreshes
5713
%  image info, and detaches the borrower so exactly one object owns the memory.
5714
%
5715
%  The format of the SyncBlobStream method is:
5716
%
5717
%      void SyncBlobStream(ImageInfo *image,const Image *image,Image *owner)
5718
%
5719
%  A description of each parameter follows:
5720
%
5721
%    o image_info: image info whose blob/length members are refreshed; may be
5722
%      NULL.
5723
%
5724
%    o owner: the image ImagesToBlob()/ImageToBlob() harvests the blob from
5725
%      (the head of the list).
5726
%
5727
%    o image: the image that was just written; may be the owner.
5728
%
5729
*/
5730
MagickPrivate void SyncBlobStream(ImageInfo *image_info,Image *image,
5731
  Image *owner)
5732
97.1k
{
5733
97.1k
  assert(owner != (Image *) NULL);
5734
97.1k
  assert(image != (Image *) NULL);
5735
97.1k
  assert(image->signature == MagickCoreSignature);
5736
97.1k
  if (image->blob == (BlobInfo *) NULL)
5737
0
    return;
5738
97.1k
  if (image->blob->data == (unsigned char *) NULL)
5739
24
    return;
5740
97.1k
  if (image_info != (ImageInfo *) NULL)
5741
97.1k
    {
5742
97.1k
      image_info->blob=(void *) image->blob->data;
5743
97.1k
      image_info->length=image->blob->length;
5744
97.1k
    }
5745
97.1k
  if ((image == owner) || (owner->blob == (BlobInfo *) NULL))
5746
97.1k
    return;
5747
0
  if (owner->blob == (BlobInfo *) NULL)
5748
0
    return;
5749
  /*
5750
    Promote the live buffer onto the owner before detaching the borrower;
5751
    DetachBlob() clears image->blob->data.
5752
  */
5753
0
  owner->blob->data=image->blob->data;
5754
0
  owner->blob->extent=image->blob->extent;
5755
0
  owner->blob->length=image->blob->length;
5756
0
  owner->blob->offset=image->blob->offset;
5757
0
  owner->blob->quantum=image->blob->quantum;
5758
0
  owner->blob->type=BlobStream;
5759
0
  owner->blob->exempt=MagickTrue;
5760
0
  (void) DetachBlob(image->blob);
5761
0
}
5762

5763
/*
5764
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5765
%                                                                             %
5766
%                                                                             %
5767
%                                                                             %
5768
+  T e l l B l o b                                                            %
5769
%                                                                             %
5770
%                                                                             %
5771
%                                                                             %
5772
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5773
%
5774
%  TellBlob() obtains the current value of the blob or file position.
5775
%
5776
%  The format of the TellBlob method is:
5777
%
5778
%      MagickOffsetType TellBlob(const Image *image)
5779
%
5780
%  A description of each parameter follows:
5781
%
5782
%    o image: the image.
5783
%
5784
*/
5785
MagickExport MagickOffsetType TellBlob(const Image *image)
5786
3.71M
{
5787
3.71M
  BlobInfo
5788
3.71M
    *magick_restrict blob_info;
5789
5790
3.71M
  MagickOffsetType
5791
3.71M
    offset;
5792
5793
3.71M
  assert(image != (Image *) NULL);
5794
3.71M
  assert(image->signature == MagickCoreSignature);
5795
3.71M
  assert(image->blob != (BlobInfo *) NULL);
5796
3.71M
  assert(image->blob->type != UndefinedStream);
5797
3.71M
  if (IsEventLogging() != MagickFalse)
5798
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5799
3.71M
  blob_info=image->blob;
5800
3.71M
  offset=(-1);
5801
3.71M
  switch (blob_info->type)
5802
3.71M
  {
5803
0
    case UndefinedStream:
5804
0
    case StandardStream:
5805
0
      break;
5806
181k
    case FileStream:
5807
181k
    {
5808
181k
      offset=ftell(blob_info->file_info.file);
5809
181k
      break;
5810
0
    }
5811
0
    case PipeStream:
5812
0
      break;
5813
13.3k
    case ZipStream:
5814
13.3k
    {
5815
13.3k
#if defined(MAGICKCORE_ZLIB_DELEGATE)
5816
13.3k
      offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
5817
13.3k
#endif
5818
13.3k
      break;
5819
0
    }
5820
0
    case BZipStream:
5821
0
      break;
5822
0
    case FifoStream:
5823
0
      break;
5824
3.51M
    case BlobStream:
5825
3.51M
    {
5826
3.51M
      offset=blob_info->offset;
5827
3.51M
      break;
5828
0
    }
5829
0
    case CustomStream:
5830
0
    {
5831
0
      if (blob_info->custom_stream->teller != (CustomStreamTeller) NULL)
5832
0
        offset=blob_info->custom_stream->teller(blob_info->custom_stream->data);
5833
0
      break;
5834
0
    }
5835
3.71M
  }
5836
3.71M
  return(offset);
5837
3.71M
}
5838

5839
/*
5840
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5841
%                                                                             %
5842
%                                                                             %
5843
%                                                                             %
5844
+  U n m a p B l o b                                                          %
5845
%                                                                             %
5846
%                                                                             %
5847
%                                                                             %
5848
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5849
%
5850
%  UnmapBlob() deallocates the binary large object previously allocated with
5851
%  the MapBlob method.
5852
%
5853
%  The format of the UnmapBlob method is:
5854
%
5855
%       MagickBooleanType UnmapBlob(void *map,const size_t length)
5856
%
5857
%  A description of each parameter follows:
5858
%
5859
%    o map: the address  of the binary large object.
5860
%
5861
%    o length: the length of the binary large object.
5862
%
5863
*/
5864
MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
5865
126k
{
5866
126k
#if defined(MAGICKCORE_HAVE_MMAP)
5867
126k
  int
5868
126k
    status;
5869
5870
126k
  status=munmap(map,length);
5871
126k
  return(status == -1 ? MagickFalse : MagickTrue);
5872
#else
5873
  (void) map;
5874
  (void) length;
5875
  return(MagickFalse);
5876
#endif
5877
126k
}
5878

5879
/*
5880
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5881
%                                                                             %
5882
%                                                                             %
5883
%                                                                             %
5884
+  W r i t e B l o b                                                          %
5885
%                                                                             %
5886
%                                                                             %
5887
%                                                                             %
5888
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5889
%
5890
%  WriteBlob() writes data to a blob or image file.  It returns the number of
5891
%  bytes written.
5892
%
5893
%  The format of the WriteBlob method is:
5894
%
5895
%      ssize_t WriteBlob(Image *image,const size_t length,const void *data)
5896
%
5897
%  A description of each parameter follows:
5898
%
5899
%    o image: the image.
5900
%
5901
%    o length:  Specifies an integer representing the number of bytes to
5902
%      write to the file.
5903
%
5904
%    o data:  The address of the data to write to the blob or file.
5905
%
5906
*/
5907
MagickExport ssize_t WriteBlob(Image *image,const size_t length,
5908
  const void *data)
5909
12.0M
{
5910
12.0M
  BlobInfo
5911
12.0M
    *magick_restrict blob_info;
5912
5913
12.0M
  int
5914
12.0M
    c;
5915
5916
12.0M
  const unsigned char
5917
12.0M
    *p;
5918
5919
12.0M
  unsigned char
5920
12.0M
    *q;
5921
5922
12.0M
  ssize_t
5923
12.0M
    count;
5924
5925
12.0M
  assert(image != (Image *) NULL);
5926
12.0M
  assert(image->signature == MagickCoreSignature);
5927
12.0M
  assert(image->blob != (BlobInfo *) NULL);
5928
12.0M
  assert(image->blob->type != UndefinedStream);
5929
12.0M
  if (length == 0)
5930
20.2k
    return(0);
5931
12.0M
  assert(data != (const void *) NULL);
5932
12.0M
  blob_info=image->blob;
5933
12.0M
  count=0;
5934
12.0M
  p=(const unsigned char *) data;
5935
12.0M
  q=(unsigned char *) data;
5936
12.0M
  switch (blob_info->type)
5937
12.0M
  {
5938
0
    case UndefinedStream:
5939
0
      break;
5940
0
    case StandardStream:
5941
121k
    case FileStream:
5942
121k
    case PipeStream:
5943
121k
    {
5944
121k
      switch (length)
5945
121k
      {
5946
34.1k
        default:
5947
34.1k
        {
5948
34.1k
          count=(ssize_t) fwrite((const char *) data,1,length,
5949
34.1k
            blob_info->file_info.file);
5950
34.1k
          break;
5951
0
        }
5952
32.8k
        case 4:
5953
32.8k
        {
5954
32.8k
          c=putc((int) *p++,blob_info->file_info.file);
5955
32.8k
          if (c == EOF)
5956
0
            break;
5957
32.8k
          count++;
5958
32.8k
          magick_fallthrough;
5959
32.8k
        }
5960
35.2k
        case 3:
5961
35.2k
        {
5962
35.2k
          c=putc((int) *p++,blob_info->file_info.file);
5963
35.2k
          if (c == EOF)
5964
0
            break;
5965
35.2k
          count++;
5966
35.2k
          magick_fallthrough;
5967
35.2k
        }
5968
48.6k
        case 2:
5969
48.6k
        {
5970
48.6k
          c=putc((int) *p++,blob_info->file_info.file);
5971
48.6k
          if (c == EOF)
5972
0
            break;
5973
48.6k
          count++;
5974
48.6k
          magick_fallthrough;
5975
48.6k
        }
5976
87.3k
        case 1:
5977
87.3k
        {
5978
87.3k
          c=putc((int) *p++,blob_info->file_info.file);
5979
87.3k
          if (c == EOF)
5980
0
            break;
5981
87.3k
          count++;
5982
87.3k
          magick_fallthrough;
5983
87.3k
        }
5984
87.3k
        case 0:
5985
87.3k
          break;
5986
121k
      }
5987
121k
      if ((count != (ssize_t) length) &&
5988
0
          (ferror(blob_info->file_info.file) != 0))
5989
0
        ThrowBlobException(blob_info);
5990
121k
      break;
5991
121k
    }
5992
0
    case ZipStream:
5993
0
    {
5994
0
#if defined(MAGICKCORE_ZLIB_DELEGATE)
5995
0
      int
5996
0
        status;
5997
5998
0
      switch (length)
5999
0
      {
6000
0
        default:
6001
0
        {
6002
0
          size_t
6003
0
            i;
6004
6005
0
          for (i=0; i < length; i+=(size_t) count)
6006
0
          {
6007
0
            count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
6008
0
              (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
6009
0
            if (count <= 0)
6010
0
              {
6011
0
                count=0;
6012
0
                if (errno != EINTR)
6013
0
                  break;
6014
0
              }
6015
0
          }
6016
0
          count=(ssize_t) i;
6017
0
          break;
6018
0
        }
6019
0
        case 4:
6020
0
        {
6021
0
          c=gzputc(blob_info->file_info.gzfile,(int) *p++);
6022
0
          if (c == EOF)
6023
0
            break;
6024
0
          count++;
6025
0
          magick_fallthrough;
6026
0
        }
6027
0
        case 3:
6028
0
        {
6029
0
          c=gzputc(blob_info->file_info.gzfile,(int) *p++);
6030
0
          if (c == EOF)
6031
0
            break;
6032
0
          count++;
6033
0
          magick_fallthrough;
6034
0
        }
6035
0
        case 2:
6036
0
        {
6037
0
          c=gzputc(blob_info->file_info.gzfile,(int) *p++);
6038
0
          if (c == EOF)
6039
0
            break;
6040
0
          count++;
6041
0
          magick_fallthrough;
6042
0
        }
6043
0
        case 1:
6044
0
        {
6045
0
          c=gzputc(blob_info->file_info.gzfile,(int) *p++);
6046
0
          if (c == EOF)
6047
0
            break;
6048
0
          count++;
6049
0
          magick_fallthrough;
6050
0
        }
6051
0
        case 0:
6052
0
          break;
6053
0
      }
6054
0
      status=Z_OK;
6055
0
      (void) gzerror(blob_info->file_info.gzfile,&status);
6056
0
      if ((count != (ssize_t) length) && (status != Z_OK))
6057
0
        ThrowBlobException(blob_info);
6058
0
#endif
6059
0
      break;
6060
0
    }
6061
0
    case BZipStream:
6062
0
    {
6063
#if defined(MAGICKCORE_BZLIB_DELEGATE)
6064
      int
6065
        status;
6066
6067
      size_t
6068
        i;
6069
6070
      for (i=0; i < length; i+=(size_t) count)
6071
      {
6072
        count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
6073
          (int) MagickMin(length-i,MagickMaxBufferExtent));
6074
        if (count <= 0)
6075
          {
6076
            count=0;
6077
            if (errno != EINTR)
6078
              break;
6079
          }
6080
      }
6081
      count=(ssize_t) i;
6082
      status=BZ_OK;
6083
      (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
6084
      if ((count != (ssize_t) length) && (status != BZ_OK))
6085
        ThrowBlobException(blob_info);
6086
#endif
6087
0
      break;
6088
0
    }
6089
0
    case FifoStream:
6090
0
    {
6091
0
      count=(ssize_t) blob_info->stream(image,data,length);
6092
0
      break;
6093
0
    }
6094
11.9M
    case BlobStream:
6095
11.9M
    {
6096
11.9M
      MagickSizeType
6097
11.9M
        extent;
6098
6099
11.9M
      if (blob_info->offset > (MagickOffsetType) (MAGICK_SSIZE_MAX-length))
6100
0
        {
6101
0
          errno=EOVERFLOW;
6102
0
          return(0);
6103
0
        }
6104
11.9M
      extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
6105
11.9M
      if (extent >= blob_info->extent)
6106
54.5k
        {
6107
54.5k
          extent+=blob_info->quantum+length;
6108
54.5k
          blob_info->quantum<<=1;
6109
54.5k
          if (SetBlobExtent(image,extent) == MagickFalse)
6110
12
            return(0);
6111
54.5k
        }
6112
11.9M
      q=blob_info->data+blob_info->offset;
6113
11.9M
      (void) memcpy(q,p,length);
6114
11.9M
      blob_info->offset+=(MagickOffsetType) length;
6115
11.9M
      if (blob_info->offset >= (MagickOffsetType) blob_info->length)
6116
11.8M
        blob_info->length=(size_t) blob_info->offset;
6117
11.9M
      count=(ssize_t) length;
6118
11.9M
      break;
6119
11.9M
    }
6120
0
    case CustomStream:
6121
0
    {
6122
0
      if (blob_info->custom_stream->writer != (CustomStreamHandler) NULL)
6123
0
        count=blob_info->custom_stream->writer((unsigned char *) data,
6124
0
          length,blob_info->custom_stream->data);
6125
0
      break;
6126
11.9M
    }
6127
12.0M
  }
6128
12.0M
  return(count);
6129
12.0M
}
6130

6131
/*
6132
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6133
%                                                                             %
6134
%                                                                             %
6135
%                                                                             %
6136
+  W r i t e B l o b B y t e                                                  %
6137
%                                                                             %
6138
%                                                                             %
6139
%                                                                             %
6140
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6141
%
6142
%  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
6143
%  written (either 0 or 1);
6144
%
6145
%  The format of the WriteBlobByte method is:
6146
%
6147
%      ssize_t WriteBlobByte(Image *image,const unsigned char value)
6148
%
6149
%  A description of each parameter follows.
6150
%
6151
%    o image: the image.
6152
%
6153
%    o value: Specifies the value to write.
6154
%
6155
*/
6156
MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
6157
280M
{
6158
280M
  BlobInfo
6159
280M
    *magick_restrict blob_info;
6160
6161
280M
  ssize_t
6162
280M
    count;
6163
6164
280M
  assert(image != (Image *) NULL);
6165
280M
  assert(image->signature == MagickCoreSignature);
6166
280M
  assert(image->blob != (BlobInfo *) NULL);
6167
280M
  assert(image->blob->type != UndefinedStream);
6168
280M
  blob_info=image->blob;
6169
280M
  count=0;
6170
280M
  switch (blob_info->type)
6171
280M
  {
6172
0
    case StandardStream:
6173
0
    case FileStream:
6174
0
    case PipeStream:
6175
0
    {
6176
0
      int
6177
0
        c;
6178
6179
0
      c=putc((int) value,blob_info->file_info.file);
6180
0
      if (c == EOF)
6181
0
        {
6182
0
          if (ferror(blob_info->file_info.file) != 0)
6183
0
            ThrowBlobException(blob_info);
6184
0
          break;
6185
0
        }
6186
0
      count++;
6187
0
      break;
6188
0
    }
6189
280M
    default:
6190
280M
    {
6191
280M
      count=WriteBlobStream(image,1,&value);
6192
280M
      break;
6193
0
    }
6194
280M
  }
6195
280M
  return(count);
6196
280M
}
6197
6198
/*
6199
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6200
%                                                                             %
6201
%                                                                             %
6202
%                                                                             %
6203
+   W r i t e B l o b P a d d i n g                                           %
6204
%                                                                             %
6205
%                                                                             %
6206
%                                                                             %
6207
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6208
%
6209
%  WriteBlobPadding() writes length copies of a byte value to a blob.  It
6210
%  returns the number of bytes written, stopping on a short or failed write.
6211
%  Lengths greater than MAGICK_SSIZE_MAX return zero and set errno to EOVERFLOW.
6212
%
6213
%  The format of the WriteBlobPadding method is:
6214
%
6215
%      ssize_t WriteBlobPadding(Image *image,const size_t length,
6216
%        const char value)
6217
%
6218
%  A description of each parameter follows.
6219
%
6220
%    o image: the image.
6221
%
6222
%    o length: the number of bytes to write.
6223
%
6224
%    o value: the byte value to repeat.
6225
%
6226
*/
6227
MagickExport ssize_t WriteBlobPadding(Image *image,const size_t length,
6228
  const char value)
6229
25.0k
{
6230
25.0k
  size_t
6231
25.0k
    extent;
6232
6233
25.0k
  ssize_t
6234
25.0k
    count,
6235
25.0k
    total;
6236
6237
25.0k
  unsigned char
6238
25.0k
    padding[1024];
6239
6240
25.0k
  assert(image != (Image *) NULL);
6241
25.0k
  assert(image->signature == MagickCoreSignature);
6242
25.0k
  assert(image->blob != (BlobInfo *) NULL);
6243
25.0k
  assert(image->blob->type != UndefinedStream);
6244
25.0k
  if (length == 0)
6245
5.82k
    return(0);
6246
19.2k
  if (length > (size_t) MAGICK_SSIZE_MAX)
6247
0
    {
6248
0
      errno=EOVERFLOW;
6249
0
      return(0);
6250
0
    }
6251
19.2k
  (void) memset(padding,value,sizeof(padding));
6252
19.2k
  total=0;
6253
43.5k
  while ((size_t) total < length)
6254
24.3k
  {
6255
24.3k
    extent=MagickMin(sizeof(padding),length-(size_t) total);
6256
24.3k
    count=WriteBlob(image,extent,padding);
6257
24.3k
    if (count <= 0)
6258
0
      break;
6259
24.3k
    total+=count;
6260
24.3k
    if (count != (ssize_t) extent)
6261
0
      break;
6262
24.3k
  }
6263
19.2k
  return(total);
6264
19.2k
}
6265

6266
/*
6267
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6268
%                                                                             %
6269
%                                                                             %
6270
%                                                                             %
6271
+  W r i t e B l o b F l o a t                                                %
6272
%                                                                             %
6273
%                                                                             %
6274
%                                                                             %
6275
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6276
%
6277
%  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
6278
%  specified by the endian member of the image structure.
6279
%
6280
%  The format of the WriteBlobFloat method is:
6281
%
6282
%      ssize_t WriteBlobFloat(Image *image,const float value)
6283
%
6284
%  A description of each parameter follows.
6285
%
6286
%    o image: the image.
6287
%
6288
%    o value: Specifies the value to write.
6289
%
6290
*/
6291
MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
6292
60.5k
{
6293
60.5k
  union
6294
60.5k
  {
6295
60.5k
    unsigned int
6296
60.5k
      unsigned_value;
6297
6298
60.5k
    float
6299
60.5k
      float_value;
6300
60.5k
  } quantum;
6301
6302
60.5k
  quantum.unsigned_value=0U;
6303
60.5k
  quantum.float_value=value;
6304
60.5k
  return(WriteBlobLong(image,quantum.unsigned_value));
6305
60.5k
}
6306

6307
/*
6308
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6309
%                                                                             %
6310
%                                                                             %
6311
%                                                                             %
6312
+  W r i t e B l o b L o n g                                                  %
6313
%                                                                             %
6314
%                                                                             %
6315
%                                                                             %
6316
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6317
%
6318
%  WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
6319
%  byte-order specified by the endian member of the image structure.
6320
%
6321
%  The format of the WriteBlobLong method is:
6322
%
6323
%      ssize_t WriteBlobLong(Image *image,const unsigned int value)
6324
%
6325
%  A description of each parameter follows.
6326
%
6327
%    o image: the image.
6328
%
6329
%    o value: Specifies the value to write.
6330
%
6331
*/
6332
MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
6333
197k
{
6334
197k
  unsigned char
6335
197k
    buffer[4];
6336
6337
197k
  assert(image != (Image *) NULL);
6338
197k
  assert(image->signature == MagickCoreSignature);
6339
197k
  if (image->endian == LSBEndian)
6340
61.9k
    {
6341
61.9k
      buffer[0]=(unsigned char) value;
6342
61.9k
      buffer[1]=(unsigned char) (value >> 8);
6343
61.9k
      buffer[2]=(unsigned char) (value >> 16);
6344
61.9k
      buffer[3]=(unsigned char) (value >> 24);
6345
61.9k
      return(WriteBlobStream(image,4,buffer));
6346
61.9k
    }
6347
135k
  buffer[0]=(unsigned char) (value >> 24);
6348
135k
  buffer[1]=(unsigned char) (value >> 16);
6349
135k
  buffer[2]=(unsigned char) (value >> 8);
6350
135k
  buffer[3]=(unsigned char) value;
6351
135k
  return(WriteBlobStream(image,4,buffer));
6352
197k
}
6353

6354
/*
6355
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6356
%                                                                             %
6357
%                                                                             %
6358
%                                                                             %
6359
+  W r i t e B l o b L o n g L o n g                                          %
6360
%                                                                             %
6361
%                                                                             %
6362
%                                                                             %
6363
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6364
%
6365
%  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in the
6366
%  byte-order specified by the endian member of the image structure.
6367
%
6368
%  The format of the WriteBlobLongLong method is:
6369
%
6370
%      ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
6371
%
6372
%  A description of each parameter follows.
6373
%
6374
%    o value:  Specifies the value to write.
6375
%
6376
%    o image: the image.
6377
%
6378
*/
6379
MagickExport ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
6380
150
{
6381
150
  unsigned char
6382
150
    buffer[8];
6383
6384
150
  assert(image != (Image *) NULL);
6385
150
  assert(image->signature == MagickCoreSignature);
6386
150
  if (image->endian == LSBEndian)
6387
0
    {
6388
0
      buffer[0]=(unsigned char) value;
6389
0
      buffer[1]=(unsigned char) (value >> 8);
6390
0
      buffer[2]=(unsigned char) (value >> 16);
6391
0
      buffer[3]=(unsigned char) (value >> 24);
6392
0
      buffer[4]=(unsigned char) (value >> 32);
6393
0
      buffer[5]=(unsigned char) (value >> 40);
6394
0
      buffer[6]=(unsigned char) (value >> 48);
6395
0
      buffer[7]=(unsigned char) (value >> 56);
6396
0
      return(WriteBlobStream(image,8,buffer));
6397
0
    }
6398
150
  buffer[0]=(unsigned char) (value >> 56);
6399
150
  buffer[1]=(unsigned char) (value >> 48);
6400
150
  buffer[2]=(unsigned char) (value >> 40);
6401
150
  buffer[3]=(unsigned char) (value >> 32);
6402
150
  buffer[4]=(unsigned char) (value >> 24);
6403
150
  buffer[5]=(unsigned char) (value >> 16);
6404
150
  buffer[6]=(unsigned char) (value >> 8);
6405
150
  buffer[7]=(unsigned char) value;
6406
150
  return(WriteBlobStream(image,8,buffer));
6407
150
}
6408

6409
/*
6410
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6411
%                                                                             %
6412
%                                                                             %
6413
%                                                                             %
6414
+   W r i t e B l o b S h o r t                                               %
6415
%                                                                             %
6416
%                                                                             %
6417
%                                                                             %
6418
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6419
%
6420
%  WriteBlobShort() writes a short value as a 16-bit quantity in the
6421
%  byte-order specified by the endian member of the image structure.
6422
%
6423
%  The format of the WriteBlobShort method is:
6424
%
6425
%      ssize_t WriteBlobShort(Image *image,const unsigned short value)
6426
%
6427
%  A description of each parameter follows.
6428
%
6429
%    o image: the image.
6430
%
6431
%    o value:  Specifies the value to write.
6432
%
6433
*/
6434
MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
6435
102M
{
6436
102M
  unsigned char
6437
102M
    buffer[2];
6438
6439
102M
  assert(image != (Image *) NULL);
6440
102M
  assert(image->signature == MagickCoreSignature);
6441
102M
  if (image->endian == LSBEndian)
6442
58.4M
    {
6443
58.4M
      buffer[0]=(unsigned char) value;
6444
58.4M
      buffer[1]=(unsigned char) (value >> 8);
6445
58.4M
      return(WriteBlobStream(image,2,buffer));
6446
58.4M
    }
6447
43.5M
  buffer[0]=(unsigned char) (value >> 8);
6448
43.5M
  buffer[1]=(unsigned char) value;
6449
43.5M
  return(WriteBlobStream(image,2,buffer));
6450
102M
}
6451

6452
/*
6453
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6454
%                                                                             %
6455
%                                                                             %
6456
%                                                                             %
6457
+  W r i t e B l o b S i g n e d L o n g                                      %
6458
%                                                                             %
6459
%                                                                             %
6460
%                                                                             %
6461
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6462
%
6463
%  WriteBlobSignedLong() writes a signed value as a 32-bit quantity in the
6464
%  byte-order specified by the endian member of the image structure.
6465
%
6466
%  The format of the WriteBlobSignedLong method is:
6467
%
6468
%      ssize_t WriteBlobSignedLong(Image *image,const signed int value)
6469
%
6470
%  A description of each parameter follows.
6471
%
6472
%    o image: the image.
6473
%
6474
%    o value: Specifies the value to write.
6475
%
6476
*/
6477
MagickExport ssize_t WriteBlobSignedLong(Image *image,const signed int value)
6478
12.6k
{
6479
12.6k
  union
6480
12.6k
  {
6481
12.6k
    unsigned int
6482
12.6k
      unsigned_value;
6483
6484
12.6k
    signed int
6485
12.6k
      signed_value;
6486
12.6k
  } quantum;
6487
6488
12.6k
  unsigned char
6489
12.6k
    buffer[4];
6490
6491
12.6k
  assert(image != (Image *) NULL);
6492
12.6k
  assert(image->signature == MagickCoreSignature);
6493
12.6k
  quantum.signed_value=value;
6494
12.6k
  if (image->endian == LSBEndian)
6495
0
    {
6496
0
      buffer[0]=(unsigned char) quantum.unsigned_value;
6497
0
      buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6498
0
      buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6499
0
      buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6500
0
      return(WriteBlobStream(image,4,buffer));
6501
0
    }
6502
12.6k
  buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
6503
12.6k
  buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
6504
12.6k
  buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
6505
12.6k
  buffer[3]=(unsigned char) quantum.unsigned_value;
6506
12.6k
  return(WriteBlobStream(image,4,buffer));
6507
12.6k
}
6508

6509
/*
6510
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6511
%                                                                             %
6512
%                                                                             %
6513
%                                                                             %
6514
+  W r i t e B l o b L S B L o n g                                            %
6515
%                                                                             %
6516
%                                                                             %
6517
%                                                                             %
6518
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6519
%
6520
%  WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
6521
%  least-significant byte first order.
6522
%
6523
%  The format of the WriteBlobLSBLong method is:
6524
%
6525
%      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6526
%
6527
%  A description of each parameter follows.
6528
%
6529
%    o image: the image.
6530
%
6531
%    o value: Specifies the value to write.
6532
%
6533
*/
6534
MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6535
104k
{
6536
104k
  unsigned char
6537
104k
    buffer[4];
6538
6539
104k
  assert(image != (Image *) NULL);
6540
104k
  assert(image->signature == MagickCoreSignature);
6541
104k
  buffer[0]=(unsigned char) value;
6542
104k
  buffer[1]=(unsigned char) (value >> 8);
6543
104k
  buffer[2]=(unsigned char) (value >> 16);
6544
104k
  buffer[3]=(unsigned char) (value >> 24);
6545
104k
  return(WriteBlobStream(image,4,buffer));
6546
104k
}
6547

6548
/*
6549
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6550
%                                                                             %
6551
%                                                                             %
6552
%                                                                             %
6553
+   W r i t e B l o b L S B S h o r t                                         %
6554
%                                                                             %
6555
%                                                                             %
6556
%                                                                             %
6557
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6558
%
6559
%  WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
6560
%  least-significant byte first order.
6561
%
6562
%  The format of the WriteBlobLSBShort method is:
6563
%
6564
%      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6565
%
6566
%  A description of each parameter follows.
6567
%
6568
%    o image: the image.
6569
%
6570
%    o value:  Specifies the value to write.
6571
%
6572
*/
6573
MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6574
189k
{
6575
189k
  unsigned char
6576
189k
    buffer[2];
6577
6578
189k
  assert(image != (Image *) NULL);
6579
189k
  assert(image->signature == MagickCoreSignature);
6580
189k
  buffer[0]=(unsigned char) value;
6581
189k
  buffer[1]=(unsigned char) (value >> 8);
6582
189k
  return(WriteBlobStream(image,2,buffer));
6583
189k
}
6584

6585
/*
6586
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6587
%                                                                             %
6588
%                                                                             %
6589
%                                                                             %
6590
+  W r i t e B l o b L S B S i g n e d L o n g                                %
6591
%                                                                             %
6592
%                                                                             %
6593
%                                                                             %
6594
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6595
%
6596
%  WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
6597
%  least-significant byte first order.
6598
%
6599
%  The format of the WriteBlobLSBSignedLong method is:
6600
%
6601
%      ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6602
%
6603
%  A description of each parameter follows.
6604
%
6605
%    o image: the image.
6606
%
6607
%    o value: Specifies the value to write.
6608
%
6609
*/
6610
MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6611
1.43k
{
6612
1.43k
  union
6613
1.43k
  {
6614
1.43k
    unsigned int
6615
1.43k
      unsigned_value;
6616
6617
1.43k
    signed int
6618
1.43k
      signed_value;
6619
1.43k
  } quantum;
6620
6621
1.43k
  unsigned char
6622
1.43k
    buffer[4];
6623
6624
1.43k
  assert(image != (Image *) NULL);
6625
1.43k
  assert(image->signature == MagickCoreSignature);
6626
1.43k
  quantum.signed_value=value;
6627
1.43k
  buffer[0]=(unsigned char) quantum.unsigned_value;
6628
1.43k
  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6629
1.43k
  buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6630
1.43k
  buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6631
1.43k
  return(WriteBlobStream(image,4,buffer));
6632
1.43k
}
6633

6634
/*
6635
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6636
%                                                                             %
6637
%                                                                             %
6638
%                                                                             %
6639
+   W r i t e B l o b L S B S i g n e d S h o r t                             %
6640
%                                                                             %
6641
%                                                                             %
6642
%                                                                             %
6643
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6644
%
6645
%  WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
6646
%  in least-significant byte first order.
6647
%
6648
%  The format of the WriteBlobLSBSignedShort method is:
6649
%
6650
%      ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
6651
%
6652
%  A description of each parameter follows.
6653
%
6654
%    o image: the image.
6655
%
6656
%    o value:  Specifies the value to write.
6657
%
6658
*/
6659
MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
6660
  const signed short value)
6661
496
{
6662
496
  union
6663
496
  {
6664
496
    unsigned short
6665
496
      unsigned_value;
6666
6667
496
    signed short
6668
496
      signed_value;
6669
496
  } quantum;
6670
6671
496
  unsigned char
6672
496
    buffer[2];
6673
6674
496
  assert(image != (Image *) NULL);
6675
496
  assert(image->signature == MagickCoreSignature);
6676
496
  quantum.signed_value=value;
6677
496
  buffer[0]=(unsigned char) quantum.unsigned_value;
6678
496
  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6679
496
  return(WriteBlobStream(image,2,buffer));
6680
496
}
6681

6682
/*
6683
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6684
%                                                                             %
6685
%                                                                             %
6686
%                                                                             %
6687
+  W r i t e B l o b M S B L o n g                                            %
6688
%                                                                             %
6689
%                                                                             %
6690
%                                                                             %
6691
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6692
%
6693
%  WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
6694
%  most-significant byte first order.
6695
%
6696
%  The format of the WriteBlobMSBLong method is:
6697
%
6698
%      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6699
%
6700
%  A description of each parameter follows.
6701
%
6702
%    o value:  Specifies the value to write.
6703
%
6704
%    o image: the image.
6705
%
6706
*/
6707
MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6708
61.8k
{
6709
61.8k
  unsigned char
6710
61.8k
    buffer[4];
6711
6712
61.8k
  assert(image != (Image *) NULL);
6713
61.8k
  assert(image->signature == MagickCoreSignature);
6714
61.8k
  buffer[0]=(unsigned char) (value >> 24);
6715
61.8k
  buffer[1]=(unsigned char) (value >> 16);
6716
61.8k
  buffer[2]=(unsigned char) (value >> 8);
6717
61.8k
  buffer[3]=(unsigned char) value;
6718
61.8k
  return(WriteBlobStream(image,4,buffer));
6719
61.8k
}
6720

6721
/*
6722
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6723
%                                                                             %
6724
%                                                                             %
6725
%                                                                             %
6726
+   W r i t e B l o b M S B S i g n e d S h o r t                             %
6727
%                                                                             %
6728
%                                                                             %
6729
%                                                                             %
6730
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6731
%
6732
%  WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
6733
%  in most-significant byte first order.
6734
%
6735
%  The format of the WriteBlobMSBSignedShort method is:
6736
%
6737
%      ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
6738
%
6739
%  A description of each parameter follows.
6740
%
6741
%    o image: the image.
6742
%
6743
%    o value:  Specifies the value to write.
6744
%
6745
*/
6746
MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
6747
  const signed short value)
6748
0
{
6749
0
  union
6750
0
  {
6751
0
    unsigned short
6752
0
      unsigned_value;
6753
6754
0
    signed short
6755
0
      signed_value;
6756
0
  } quantum;
6757
6758
0
  unsigned char
6759
0
    buffer[2];
6760
6761
0
  assert(image != (Image *) NULL);
6762
0
  assert(image->signature == MagickCoreSignature);
6763
0
  quantum.signed_value=value;
6764
0
  buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
6765
0
  buffer[1]=(unsigned char) quantum.unsigned_value;
6766
0
  return(WriteBlobStream(image,2,buffer));
6767
0
}
6768

6769
/*
6770
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6771
%                                                                             %
6772
%                                                                             %
6773
%                                                                             %
6774
+  W r i t e B l o b M S B S h o r t                                          %
6775
%                                                                             %
6776
%                                                                             %
6777
%                                                                             %
6778
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6779
%
6780
%  WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
6781
%  most-significant byte first order.
6782
%
6783
%  The format of the WriteBlobMSBShort method is:
6784
%
6785
%      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6786
%
6787
%  A description of each parameter follows.
6788
%
6789
%   o  value:  Specifies the value to write.
6790
%
6791
%   o  file:  Specifies the file to write the data to.
6792
%
6793
*/
6794
MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6795
3.27M
{
6796
3.27M
  unsigned char
6797
3.27M
    buffer[2];
6798
6799
3.27M
  assert(image != (Image *) NULL);
6800
3.27M
  assert(image->signature == MagickCoreSignature);
6801
3.27M
  buffer[0]=(unsigned char) (value >> 8);
6802
3.27M
  buffer[1]=(unsigned char) value;
6803
3.27M
  return(WriteBlobStream(image,2,buffer));
6804
3.27M
}
6805

6806
/*
6807
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6808
%                                                                             %
6809
%                                                                             %
6810
%                                                                             %
6811
+  W r i t e B l o b S t r i n g                                              %
6812
%                                                                             %
6813
%                                                                             %
6814
%                                                                             %
6815
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6816
%
6817
%  WriteBlobString() write a string to a blob.  It returns the number of
6818
%  characters written.
6819
%
6820
%  The format of the WriteBlobString method is:
6821
%
6822
%      ssize_t WriteBlobString(Image *image,const char *string)
6823
%
6824
%  A description of each parameter follows.
6825
%
6826
%    o image: the image.
6827
%
6828
%    o string: Specifies the string to write.
6829
%
6830
*/
6831
MagickExport ssize_t WriteBlobString(Image *image,const char *string)
6832
217k
{
6833
217k
  assert(image != (Image *) NULL);
6834
217k
  assert(image->signature == MagickCoreSignature);
6835
217k
  assert(string != (const char *) NULL);
6836
217k
  return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
6837
217k
}