Coverage Report

Created: 2026-05-16 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/viff.c
Line
Count
Source
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                                                                             %
6
%                        V   V  IIIII  FFFFF  FFFFF                           %
7
%                        V   V    I    F      F                               %
8
%                        V   V    I    FFF    FFF                             %
9
%                         V V     I    F      F                               %
10
%                          V    IIIII  F      F                               %
11
%                                                                             %
12
%                                                                             %
13
%                Read/Write Khoros Visualization Image Format                 %
14
%                                                                             %
15
%                              Software Design                                %
16
%                                   Cristy                                    %
17
%                                 July 1992                                   %
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
  Include declarations.
41
*/
42
#include "MagickCore/studio.h"
43
#include "MagickCore/attribute.h"
44
#include "MagickCore/blob.h"
45
#include "MagickCore/blob-private.h"
46
#include "MagickCore/cache.h"
47
#include "MagickCore/color.h"
48
#include "MagickCore/color-private.h"
49
#include "MagickCore/colormap.h"
50
#include "MagickCore/colormap-private.h"
51
#include "MagickCore/colorspace.h"
52
#include "MagickCore/colorspace-private.h"
53
#include "MagickCore/exception.h"
54
#include "MagickCore/exception-private.h"
55
#include "MagickCore/image.h"
56
#include "MagickCore/image-private.h"
57
#include "MagickCore/list.h"
58
#include "MagickCore/magick.h"
59
#include "MagickCore/memory_.h"
60
#include "MagickCore/module.h"
61
#include "MagickCore/monitor.h"
62
#include "MagickCore/monitor-private.h"
63
#include "MagickCore/pixel-accessor.h"
64
#include "MagickCore/property.h"
65
#include "MagickCore/quantum-private.h"
66
#include "MagickCore/static.h"
67
#include "MagickCore/string_.h"
68
#include "coders/coders-private.h"
69

70
/*
71
  Forward declarations.
72
*/
73
static MagickBooleanType
74
  WriteVIFFImage(const ImageInfo *,Image *,ExceptionInfo *);
75

76
/*
77
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78
%                                                                             %
79
%                                                                             %
80
%                                                                             %
81
%   I s V I F F                                                               %
82
%                                                                             %
83
%                                                                             %
84
%                                                                             %
85
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
86
%
87
%  IsVIFF() returns MagickTrue if the image format type, identified by the
88
%  magick string, is VIFF.
89
%
90
%  The format of the IsVIFF method is:
91
%
92
%      MagickBooleanType IsVIFF(const unsigned char *magick,const size_t length)
93
%
94
%  A description of each parameter follows:
95
%
96
%    o magick: compare image format pattern against these bytes.
97
%
98
%    o length: Specifies the length of the magick string.
99
%
100
*/
101
static MagickBooleanType IsVIFF(const unsigned char *magick,const size_t length)
102
0
{
103
0
  if (length < 2)
104
0
    return(MagickFalse);
105
0
  if (memcmp(magick,"\253\001",2) == 0)
106
0
    return(MagickTrue);
107
0
  return(MagickFalse);
108
0
}
109

110
/*
111
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112
%                                                                             %
113
%                                                                             %
114
%                                                                             %
115
%   R e a d V I F F I m a g e                                                 %
116
%                                                                             %
117
%                                                                             %
118
%                                                                             %
119
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120
%
121
%  ReadVIFFImage() reads a Khoros Visualization image file and returns
122
%  it.  It allocates the memory necessary for the new Image structure and
123
%  returns a pointer to the new image.
124
%
125
%  The format of the ReadVIFFImage method is:
126
%
127
%      Image *ReadVIFFImage(const ImageInfo *image_info,
128
%        ExceptionInfo *exception)
129
%
130
%  A description of each parameter follows:
131
%
132
%    o image: Method ReadVIFFImage returns a pointer to the image after
133
%      reading.  A null image is returned if there is a memory shortage or if
134
%      the image cannot be read.
135
%
136
%    o image_info: the image info.
137
%
138
%    o exception: return any errors or warnings in this structure.
139
%
140
*/
141
static Image *ReadVIFFImage(const ImageInfo *image_info,
142
  ExceptionInfo *exception)
143
1.67k
{
144
1.67k
#define VFF_CM_genericRGB  15
145
1.67k
#define VFF_CM_ntscRGB  1
146
1.67k
#define VFF_CM_NONE  0
147
3.91k
#define VFF_DEP_DECORDER  0x4
148
3.65k
#define VFF_DEP_NSORDER  0x8
149
1.77k
#define VFF_DES_RAW  0
150
1.67k
#define VFF_LOC_IMPLICIT  1
151
1.72k
#define VFF_MAPTYP_NONE  0
152
1.67k
#define VFF_MAPTYP_1_BYTE  1
153
466M
#define VFF_MAPTYP_2_BYTE  2
154
364M
#define VFF_MAPTYP_4_BYTE  4
155
113M
#define VFF_MAPTYP_FLOAT  5
156
32.9M
#define VFF_MAPTYP_DOUBLE  7
157
153k
#define VFF_MS_NONE  0
158
1.67k
#define VFF_MS_ONEPERBAND  1
159
1.67k
#define VFF_MS_SHARED  3
160
6.15k
#define VFF_TYP_BIT  0
161
2.29k
#define VFF_TYP_1_BYTE  1
162
1.67k
#define VFF_TYP_2_BYTE  2
163
1.67k
#define VFF_TYP_4_BYTE  4
164
2.73k
#define VFF_TYP_FLOAT  5
165
1.67k
#define VFF_TYP_DOUBLE  9
166
167
1.67k
  typedef struct _ViffInfo
168
1.67k
  {
169
1.67k
    unsigned char
170
1.67k
      identifier,
171
1.67k
      file_type,
172
1.67k
      release,
173
1.67k
      version,
174
1.67k
      machine_dependency,
175
1.67k
      reserve[3];
176
177
1.67k
    char
178
1.67k
      comment[512];
179
180
1.67k
    unsigned int
181
1.67k
      rows,
182
1.67k
      columns,
183
1.67k
      subrows;
184
185
1.67k
    int
186
1.67k
      x_offset,
187
1.67k
      y_offset;
188
189
1.67k
    float
190
1.67k
      x_bits_per_pixel,
191
1.67k
      y_bits_per_pixel;
192
193
1.67k
    unsigned int
194
1.67k
      location_type,
195
1.67k
      location_dimension,
196
1.67k
      number_of_images,
197
1.67k
      number_data_bands,
198
1.67k
      data_storage_type,
199
1.67k
      data_encode_scheme,
200
1.67k
      map_scheme,
201
1.67k
      map_storage_type,
202
1.67k
      map_rows,
203
1.67k
      map_columns,
204
1.67k
      map_subrows,
205
1.67k
      map_enable,
206
1.67k
      maps_per_cycle,
207
1.67k
      color_space_model;
208
1.67k
  } ViffInfo;
209
210
1.67k
  double
211
1.67k
    min_value,
212
1.67k
    scale_factor,
213
1.67k
    value;
214
215
1.67k
  Image
216
1.67k
    *image;
217
218
1.67k
  int
219
1.67k
    bit;
220
221
1.67k
  MagickBooleanType
222
1.67k
    status;
223
224
1.67k
  MagickSizeType
225
1.67k
    number_pixels;
226
227
1.67k
  Quantum
228
1.67k
    *q;
229
230
1.67k
  size_t
231
1.67k
    bytes_per_pixel,
232
1.67k
    max_packets,
233
1.67k
    quantum;
234
235
1.67k
  ssize_t
236
1.67k
    count,
237
1.67k
    i,
238
1.67k
    x,
239
1.67k
    y;
240
241
1.67k
  unsigned char
242
1.67k
    *p,
243
1.67k
    *pixels;
244
245
1.67k
  unsigned long
246
1.67k
    lsb_first;
247
248
1.67k
  ViffInfo
249
1.67k
    viff_info;
250
251
  /*
252
    Open image file.
253
  */
254
1.67k
  assert(image_info != (const ImageInfo *) NULL);
255
1.67k
  assert(image_info->signature == MagickCoreSignature);
256
1.67k
  assert(exception != (ExceptionInfo *) NULL);
257
1.67k
  assert(exception->signature == MagickCoreSignature);
258
1.67k
  if (IsEventLogging() != MagickFalse)
259
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
260
0
      image_info->filename);
261
1.67k
  image=AcquireImage(image_info,exception);
262
1.67k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
263
1.67k
  if (status == MagickFalse)
264
0
    {
265
0
      image=DestroyImageList(image);
266
0
      return((Image *) NULL);
267
0
    }
268
  /*
269
    Read VIFF header (1024 bytes).
270
  */
271
1.67k
  count=ReadBlob(image,1,&viff_info.identifier);
272
1.67k
  do
273
2.21k
  {
274
    /*
275
      Verify VIFF identifier.
276
    */
277
2.21k
    if ((count != 1) || ((unsigned char) viff_info.identifier != 0xab))
278
2.20k
      ThrowReaderException(CorruptImageError,"NotAVIFFImage");
279
    /*
280
      Initialize VIFF image.
281
    */
282
2.20k
    (void) ReadBlob(image,sizeof(viff_info.file_type),&viff_info.file_type);
283
2.20k
    (void) ReadBlob(image,sizeof(viff_info.release),&viff_info.release);
284
2.20k
    (void) ReadBlob(image,sizeof(viff_info.version),&viff_info.version);
285
2.20k
    (void) ReadBlob(image,sizeof(viff_info.machine_dependency),
286
2.20k
      &viff_info.machine_dependency);
287
2.20k
    (void) ReadBlob(image,sizeof(viff_info.reserve),viff_info.reserve);
288
2.20k
    count=ReadBlob(image,512,(unsigned char *) viff_info.comment);
289
2.20k
    if (count != 512)
290
2.14k
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
291
2.14k
    viff_info.comment[511]='\0';
292
2.14k
    if (strlen(viff_info.comment) > 4)
293
1.13k
      (void) SetImageProperty(image,"comment",viff_info.comment,exception);
294
2.14k
    if ((viff_info.machine_dependency == VFF_DEP_DECORDER) ||
295
2.02k
        (viff_info.machine_dependency == VFF_DEP_NSORDER))
296
389
      image->endian=LSBEndian;
297
1.75k
    else
298
1.75k
      image->endian=MSBEndian;
299
2.14k
    viff_info.rows=ReadBlobLong(image);
300
2.14k
    viff_info.columns=ReadBlobLong(image);
301
2.14k
    viff_info.subrows=ReadBlobLong(image);
302
2.14k
    viff_info.x_offset=ReadBlobSignedLong(image);
303
2.14k
    viff_info.y_offset=ReadBlobSignedLong(image);
304
2.14k
    viff_info.x_bits_per_pixel=(float) ReadBlobLong(image);
305
2.14k
    viff_info.y_bits_per_pixel=(float) ReadBlobLong(image);
306
2.14k
    viff_info.location_type=ReadBlobLong(image);
307
2.14k
    viff_info.location_dimension=ReadBlobLong(image);
308
2.14k
    viff_info.number_of_images=ReadBlobLong(image);
309
2.14k
    viff_info.number_data_bands=ReadBlobLong(image);
310
2.14k
    viff_info.data_storage_type=ReadBlobLong(image);
311
2.14k
    viff_info.data_encode_scheme=ReadBlobLong(image);
312
2.14k
    viff_info.map_scheme=ReadBlobLong(image);
313
2.14k
    viff_info.map_storage_type=ReadBlobLong(image);
314
2.14k
    viff_info.map_rows=ReadBlobLong(image);
315
2.14k
    viff_info.map_columns=ReadBlobLong(image);
316
2.14k
    viff_info.map_subrows=ReadBlobLong(image);
317
2.14k
    viff_info.map_enable=ReadBlobLong(image);
318
2.14k
    viff_info.maps_per_cycle=ReadBlobLong(image);
319
2.14k
    viff_info.color_space_model=ReadBlobLong(image);
320
903k
    for (i=0; i < 420; i++)
321
901k
      (void) ReadBlobByte(image);
322
2.14k
    if (EOFBlob(image) != MagickFalse)
323
2.04k
      ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
324
2.04k
    number_pixels=(MagickSizeType) viff_info.columns*viff_info.rows;
325
2.04k
    if (HeapOverflowSanityCheck(viff_info.columns,viff_info.rows) != MagickFalse)
326
2.03k
        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
327
2.03k
    if (number_pixels > 8*GetBlobSize(image))
328
1.92k
      ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
329
1.92k
    if (number_pixels == 0)
330
1.92k
      ThrowReaderException(CoderError,"ImageColumnOrRowSizeIsNotSupported");
331
1.92k
    image->columns=viff_info.rows;
332
1.92k
    image->rows=viff_info.columns;
333
1.92k
    image->depth=viff_info.x_bits_per_pixel <= 8 ? 8UL :
334
1.92k
      MAGICKCORE_QUANTUM_DEPTH;
335
1.92k
    image->alpha_trait=viff_info.number_data_bands == 4 ? BlendPixelTrait :
336
1.92k
      UndefinedPixelTrait;
337
1.92k
    status=SetImageExtent(image,image->columns,image->rows,exception);
338
1.92k
    if (status == MagickFalse)
339
36
      return(DestroyImageList(image));
340
1.88k
    (void) SetImageBackgroundColor(image,exception);
341
    /*
342
      Verify that we can read this VIFF image.
343
    */
344
1.88k
    if ((viff_info.number_data_bands < 1) || (viff_info.number_data_bands > 4))
345
1.82k
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
346
1.82k
    if ((viff_info.data_storage_type != VFF_TYP_BIT) &&
347
1.15k
        (viff_info.data_storage_type != VFF_TYP_1_BYTE) &&
348
375
        (viff_info.data_storage_type != VFF_TYP_2_BYTE) &&
349
284
        (viff_info.data_storage_type != VFF_TYP_4_BYTE) &&
350
193
        (viff_info.data_storage_type != VFF_TYP_FLOAT) &&
351
110
        (viff_info.data_storage_type != VFF_TYP_DOUBLE))
352
1.77k
      ThrowReaderException(CoderError,"DataStorageTypeIsNotSupported");
353
1.77k
    if (viff_info.data_encode_scheme != VFF_DES_RAW)
354
1.72k
      ThrowReaderException(CoderError,"DataEncodingSchemeIsNotSupported");
355
1.72k
    if ((viff_info.map_storage_type != VFF_MAPTYP_NONE) &&
356
694
        (viff_info.map_storage_type != VFF_MAPTYP_1_BYTE) &&
357
599
        (viff_info.map_storage_type != VFF_MAPTYP_2_BYTE) &&
358
353
        (viff_info.map_storage_type != VFF_MAPTYP_4_BYTE) &&
359
260
        (viff_info.map_storage_type != VFF_MAPTYP_FLOAT) &&
360
153
        (viff_info.map_storage_type != VFF_MAPTYP_DOUBLE))
361
1.67k
      ThrowReaderException(CoderError,"MapStorageTypeIsNotSupported");
362
1.67k
    if ((viff_info.color_space_model != VFF_CM_NONE) &&
363
227
        (viff_info.color_space_model != VFF_CM_ntscRGB) &&
364
110
        (viff_info.color_space_model != VFF_CM_genericRGB))
365
1.61k
      ThrowReaderException(CoderError,"ColorspaceModelIsNotSupported");
366
1.61k
    if (viff_info.location_type != VFF_LOC_IMPLICIT)
367
1.57k
      ThrowReaderException(CoderError,"LocationTypeIsNotSupported");
368
1.57k
    if (viff_info.number_of_images != 1)
369
1.54k
      ThrowReaderException(CoderError,"NumberOfImagesIsNotSupported");
370
1.54k
    if (viff_info.map_rows == 0)
371
416
      viff_info.map_scheme=VFF_MS_NONE;
372
1.54k
    switch ((int) viff_info.map_scheme)
373
1.54k
    {
374
742
      case VFF_MS_NONE:
375
742
      {
376
742
        if (viff_info.number_data_bands < 3)
377
449
          {
378
            /*
379
              Create linear color ramp.
380
            */
381
449
            if (viff_info.data_storage_type == VFF_TYP_BIT)
382
223
              image->colors=2;
383
226
            else
384
226
              if (viff_info.data_storage_type == VFF_MAPTYP_1_BYTE)
385
101
                image->colors=256UL;
386
125
              else
387
125
                image->colors=image->depth <= 8 ? 256UL : 65536UL;
388
449
            status=AcquireImageColormap(image,image->colors,exception);
389
449
            if (status == MagickFalse)
390
449
              ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
391
449
          }
392
742
        break;
393
742
      }
394
742
      case VFF_MS_ONEPERBAND:
395
797
      case VFF_MS_SHARED:
396
797
      {
397
797
        unsigned char
398
797
          *viff_colormap;
399
400
        /*
401
          Allocate VIFF colormap.
402
        */
403
797
        switch ((int) viff_info.map_storage_type)
404
797
        {
405
28
          case VFF_MAPTYP_1_BYTE: bytes_per_pixel=1; break;
406
92
          case VFF_MAPTYP_2_BYTE: bytes_per_pixel=2; break;
407
77
          case VFF_MAPTYP_4_BYTE: bytes_per_pixel=4; break;
408
98
          case VFF_MAPTYP_FLOAT: bytes_per_pixel=4; break;
409
52
          case VFF_MAPTYP_DOUBLE: bytes_per_pixel=8; break;
410
450
          default: bytes_per_pixel=1; break;
411
797
        }
412
797
        image->colors=viff_info.map_columns;
413
797
        count=(ssize_t) (bytes_per_pixel*image->colors*viff_info.map_rows);
414
797
        if ((MagickSizeType) count > GetBlobSize(image))
415
704
          ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
416
704
        if ((MagickSizeType) viff_info.map_rows >
417
704
            (viff_info.map_rows*bytes_per_pixel*sizeof(*viff_colormap)))
418
704
          ThrowReaderException(CorruptImageError,"ImproperImageHeader");
419
704
        if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
420
699
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
421
699
        viff_colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
422
699
          viff_info.map_rows*bytes_per_pixel*sizeof(*viff_colormap));
423
699
        if (viff_colormap == (unsigned char *) NULL)
424
662
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
425
        /*
426
          Read VIFF raster colormap.
427
        */
428
662
        if (ReadBlob(image,(size_t) count,viff_colormap) != count)
429
33
          {
430
33
            viff_colormap=(unsigned char *) RelinquishMagickMemory(
431
33
              viff_colormap);
432
33
            ThrowReaderException(CorruptImageError,
433
33
              "InsufficientImageDataInFile");
434
0
          }
435
629
        lsb_first=1;
436
629
        if (*(char *) &lsb_first &&
437
629
            ((viff_info.machine_dependency != VFF_DEP_DECORDER) &&
438
568
             (viff_info.machine_dependency != VFF_DEP_NSORDER)))
439
473
          switch ((int) viff_info.map_storage_type)
440
473
          {
441
81
            case VFF_MAPTYP_2_BYTE:
442
81
            {
443
81
              MSBOrderShort(viff_colormap,(bytes_per_pixel*image->colors*
444
81
                viff_info.map_rows));
445
81
              break;
446
0
            }
447
67
            case VFF_MAPTYP_4_BYTE:
448
147
            case VFF_MAPTYP_FLOAT:
449
147
            {
450
147
              MSBOrderLong(viff_colormap,(bytes_per_pixel*image->colors*
451
147
                viff_info.map_rows));
452
147
              break;
453
67
            }
454
245
            default: break;
455
473
          }
456
2.56G
        for (i=0; i < (ssize_t) (viff_info.map_rows*image->colors); i++)
457
2.56G
        {
458
2.56G
          switch ((int) viff_info.map_storage_type)
459
2.56G
          {
460
466M
            case VFF_MAPTYP_2_BYTE: value=1.0*((short *) viff_colormap)[i]; break;
461
364M
            case VFF_MAPTYP_4_BYTE: value=1.0*((int *) viff_colormap)[i]; break;
462
113M
            case VFF_MAPTYP_FLOAT: value=((float *) viff_colormap)[i]; break;
463
32.9M
            case VFF_MAPTYP_DOUBLE: value=((double *) viff_colormap)[i]; break;
464
1.58G
            default: value=1.0*viff_colormap[i]; break;
465
2.56G
          }
466
2.56G
          if (i < (ssize_t) image->colors)
467
41.7k
            {
468
41.7k
              image->colormap[i].red=(MagickRealType)
469
41.7k
                ScaleCharToQuantum(CastDoubleToUChar(value));
470
41.7k
              image->colormap[i].green=(MagickRealType)
471
41.7k
                ScaleCharToQuantum(CastDoubleToUChar(value));
472
41.7k
              image->colormap[i].blue=(MagickRealType)
473
41.7k
                ScaleCharToQuantum(CastDoubleToUChar(value));
474
41.7k
            }
475
2.56G
          else
476
2.56G
            if (i < (ssize_t) (2*image->colors))
477
18.0k
              image->colormap[i % (ssize_t) image->colors].green=
478
18.0k
                (MagickRealType) ScaleCharToQuantum(CastDoubleToUChar(value));
479
2.56G
            else
480
2.56G
              if (i < (ssize_t) (3*image->colors))
481
2.89k
                image->colormap[i % (ssize_t) image->colors].blue=
482
2.89k
                  (MagickRealType) ScaleCharToQuantum(CastDoubleToUChar(value));
483
2.56G
        }
484
629
        viff_colormap=(unsigned char *) RelinquishMagickMemory(viff_colormap);
485
629
        break;
486
629
      }
487
3
      default:
488
3
        ThrowReaderException(CoderError,"ColormapTypeNotSupported");
489
1.54k
    }
490
1.37k
    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
491
0
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
492
0
        break;
493
1.37k
    if (viff_info.data_storage_type == VFF_TYP_BIT)
494
534
      {
495
        /*
496
          Create bi-level colormap.
497
        */
498
534
        image->colors=2;
499
534
        if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
500
534
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
501
534
        image->colorspace=GRAYColorspace;
502
534
      }
503
    /*
504
      Allocate VIFF pixels.
505
    */
506
1.37k
    switch ((int) viff_info.data_storage_type)
507
1.37k
    {
508
69
      case VFF_TYP_2_BYTE: bytes_per_pixel=2; break;
509
77
      case VFF_TYP_4_BYTE: bytes_per_pixel=4; break;
510
67
      case VFF_TYP_FLOAT: bytes_per_pixel=4; break;
511
37
      case VFF_TYP_DOUBLE: bytes_per_pixel=8; break;
512
1.12k
      default: bytes_per_pixel=1; break;
513
1.37k
    }
514
1.37k
    if (viff_info.data_storage_type == VFF_TYP_BIT)
515
534
      {
516
534
        if (HeapOverflowSanityCheckGetSize((image->columns+7UL) >> 3UL,image->rows,&max_packets) != MagickFalse)
517
534
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
518
534
      }
519
837
    else
520
837
      {
521
837
        if (HeapOverflowSanityCheckGetSize((size_t) number_pixels,viff_info.number_data_bands,&max_packets) != MagickFalse)
522
837
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
523
837
      }
524
1.37k
    count=(ssize_t) (bytes_per_pixel*max_packets);
525
1.37k
    if ((MagickSizeType) count > GetBlobSize(image))
526
1.33k
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
527
1.33k
    pixels=(unsigned char *) AcquireQuantumMemory((size_t) MagickMax(
528
1.33k
      number_pixels,max_packets),bytes_per_pixel*sizeof(*pixels));
529
1.33k
    if (pixels == (unsigned char *) NULL)
530
1.33k
      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
531
1.33k
    (void) memset(pixels,0,(size_t) MagickMax(number_pixels,max_packets)*
532
1.33k
      bytes_per_pixel*sizeof(*pixels));
533
1.33k
    if (ReadBlob(image,(size_t) count,pixels) != count)
534
203
      {
535
203
        pixels=(unsigned char *) RelinquishMagickMemory(pixels);
536
203
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
537
0
      }
538
1.13k
    lsb_first=1;
539
1.13k
    if (*(char *) &lsb_first &&
540
1.13k
        ((viff_info.machine_dependency != VFF_DEP_DECORDER) &&
541
1.06k
         (viff_info.machine_dependency != VFF_DEP_NSORDER)))
542
913
      switch ((int) viff_info.data_storage_type)
543
913
      {
544
45
        case VFF_TYP_2_BYTE:
545
45
        {
546
45
          MSBOrderShort(pixels,bytes_per_pixel*max_packets);
547
45
          break;
548
0
        }
549
62
        case VFF_TYP_4_BYTE:
550
109
        case VFF_TYP_FLOAT:
551
109
        {
552
109
          MSBOrderLong(pixels,bytes_per_pixel*max_packets);
553
109
          break;
554
62
        }
555
759
        default: break;
556
913
      }
557
1.13k
    min_value=0.0;
558
1.13k
    scale_factor=1.0;
559
1.13k
    if ((viff_info.data_storage_type != VFF_TYP_1_BYTE) &&
560
619
        (viff_info.map_scheme == VFF_MS_NONE))
561
485
      {
562
485
        double
563
485
          max_value;
564
565
        /*
566
          Determine scale factor.
567
        */
568
485
        switch ((int) viff_info.data_storage_type)
569
485
        {
570
28
          case VFF_TYP_2_BYTE: value=1.0*((short *) pixels)[0]; break;
571
38
          case VFF_TYP_4_BYTE: value=1.0*((int *) pixels)[0]; break;
572
39
          case VFF_TYP_FLOAT: value=((float *) pixels)[0]; break;
573
26
          case VFF_TYP_DOUBLE: value=((double *) pixels)[0]; break;
574
354
          default: value=1.0*pixels[0]; break;
575
485
        }
576
485
        max_value=value;
577
485
        min_value=value;
578
95.4k
        for (i=0; i < (ssize_t) max_packets; i++)
579
94.9k
        {
580
94.9k
          switch ((int) viff_info.data_storage_type)
581
94.9k
          {
582
479
            case VFF_TYP_2_BYTE: value=1.0*((short *) pixels)[i]; break;
583
267
            case VFF_TYP_4_BYTE: value=1.0*((int *) pixels)[i]; break;
584
1.01k
            case VFF_TYP_FLOAT: value=((float *) pixels)[i]; break;
585
276
            case VFF_TYP_DOUBLE: value=((double *) pixels)[i]; break;
586
92.9k
            default: value=1.0*pixels[i]; break;
587
94.9k
          }
588
94.9k
          if (value > max_value)
589
555
            max_value=value;
590
94.4k
          else
591
94.4k
            if (value < min_value)
592
378
              min_value=value;
593
94.9k
        }
594
485
        if ((min_value == 0) && (max_value == 0))
595
85
          scale_factor=0;
596
400
        else
597
400
          if (min_value == max_value)
598
217
            {
599
217
              scale_factor=(double) QuantumRange/min_value;
600
217
              min_value=0;
601
217
            }
602
183
          else
603
183
            scale_factor=(double) QuantumRange/(max_value-min_value);
604
485
      }
605
    /*
606
      Convert pixels to Quantum size.
607
    */
608
1.13k
    p=(unsigned char *) pixels;
609
153k
    for (i=0; i < (ssize_t) max_packets; i++)
610
152k
    {
611
152k
      switch ((int) viff_info.data_storage_type)
612
152k
      {
613
527
        case VFF_TYP_2_BYTE: value=1.0*((short *) pixels)[i]; break;
614
323
        case VFF_TYP_4_BYTE: value=1.0*((int *) pixels)[i]; break;
615
1.31k
        case VFF_TYP_FLOAT: value=((float *) pixels)[i]; break;
616
301
        case VFF_TYP_DOUBLE: value=((double *) pixels)[i]; break;
617
149k
        default: value=1.0*pixels[i]; break;
618
152k
      }
619
152k
      if (viff_info.map_scheme == VFF_MS_NONE)
620
126k
        value=(value-min_value)*scale_factor;
621
152k
      *p=(unsigned char) ClampToQuantum(value);
622
152k
      p++;
623
152k
    }
624
    /*
625
      Convert VIFF raster image to pixel packets.
626
    */
627
1.13k
    p=(unsigned char *) pixels;
628
1.13k
    if (viff_info.data_storage_type == VFF_TYP_BIT)
629
436
      {
630
        /*
631
          Convert bitmap scanline.
632
        */
633
16.6k
        for (y=0; y < (ssize_t) image->rows; y++)
634
16.1k
        {
635
16.1k
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
636
16.1k
          if (q == (Quantum *) NULL)
637
0
            break;
638
104k
          for (x=0; x < (ssize_t) (image->columns-7); x+=8)
639
88.7k
          {
640
798k
            for (bit=0; bit < 8; bit++)
641
709k
            {
642
709k
              quantum=(size_t) ((*p) & (0x01 << bit) ? 0 : 1);
643
709k
              SetPixelRed(image,quantum == 0 ? 0 : QuantumRange,q);
644
709k
              SetPixelGreen(image,quantum == 0 ? 0 : QuantumRange,q);
645
709k
              SetPixelBlue(image,quantum == 0 ? 0 : QuantumRange,q);
646
709k
              if (image->storage_class == PseudoClass)
647
709k
                SetPixelIndex(image,(Quantum) quantum,q);
648
709k
              q+=(ptrdiff_t) GetPixelChannels(image);
649
709k
            }
650
88.7k
            p++;
651
88.7k
          }
652
16.1k
          if ((image->columns % 8) != 0)
653
10.7k
            {
654
68.4k
              for (bit=0; bit < (int) (image->columns % 8); bit++)
655
57.7k
              {
656
57.7k
                quantum=(size_t) ((*p) & (0x01 << bit) ? 0 : 1);
657
57.7k
                SetPixelRed(image,quantum == 0 ? 0 : QuantumRange,q);
658
57.7k
                SetPixelGreen(image,quantum == 0 ? 0 : QuantumRange,q);
659
57.7k
                SetPixelBlue(image,quantum == 0 ? 0 : QuantumRange,q);
660
57.7k
                if (image->storage_class == PseudoClass)
661
57.7k
                  SetPixelIndex(image,(Quantum) quantum,q);
662
57.7k
                q+=(ptrdiff_t) GetPixelChannels(image);
663
57.7k
              }
664
10.7k
              p++;
665
10.7k
            }
666
16.1k
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
667
0
            break;
668
16.1k
          if (image->previous == (Image *) NULL)
669
15.8k
            {
670
15.8k
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
671
15.8k
                image->rows);
672
15.8k
              if (status == MagickFalse)
673
0
                break;
674
15.8k
            }
675
16.1k
        }
676
436
      }
677
698
    else
678
698
      if (image->storage_class == PseudoClass)
679
14.8k
        for (y=0; y < (ssize_t) image->rows; y++)
680
14.2k
        {
681
14.2k
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
682
14.2k
          if (q == (Quantum *) NULL)
683
0
            break;
684
47.8k
          for (x=0; x < (ssize_t) image->columns; x++)
685
33.5k
          {
686
33.5k
            SetPixelIndex(image,*p++,q);
687
33.5k
            q+=(ptrdiff_t) GetPixelChannels(image);
688
33.5k
          }
689
14.2k
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
690
0
            break;
691
14.2k
          if (image->previous == (Image *) NULL)
692
13.8k
            {
693
13.8k
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
694
13.8k
                image->rows);
695
13.8k
              if (status == MagickFalse)
696
0
                break;
697
13.8k
            }
698
14.2k
        }
699
107
      else
700
107
        {
701
          /*
702
            Convert DirectColor scanline.
703
          */
704
107
          number_pixels=(MagickSizeType) image->columns*image->rows;
705
1.01k
          for (y=0; y < (ssize_t) image->rows; y++)
706
910
          {
707
910
            q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
708
910
            if (q == (Quantum *) NULL)
709
0
              break;
710
7.08k
            for (x=0; x < (ssize_t) image->columns; x++)
711
6.17k
            {
712
6.17k
              SetPixelRed(image,ScaleCharToQuantum(*p),q);
713
6.17k
              SetPixelGreen(image,ScaleCharToQuantum(*(p+number_pixels)),q);
714
6.17k
              SetPixelBlue(image,ScaleCharToQuantum(*(p+2*number_pixels)),q);
715
6.17k
              if (image->colors != 0)
716
0
                {
717
0
                  ssize_t
718
0
                    index;
719
720
0
                  index=(ssize_t) GetPixelRed(image,q);
721
0
                  SetPixelRed(image,ClampToQuantum(image->colormap[
722
0
                    ConstrainColormapIndex(image,index,exception)].red),q);
723
0
                  index=(ssize_t) GetPixelGreen(image,q);
724
0
                  SetPixelGreen(image,ClampToQuantum(image->colormap[
725
0
                    ConstrainColormapIndex(image,index,exception)].green),q);
726
0
                  index=(ssize_t) GetPixelBlue(image,q);
727
0
                  SetPixelBlue(image,ClampToQuantum(image->colormap[
728
0
                    ConstrainColormapIndex(image,index,exception)].blue),q);
729
0
                }
730
6.17k
              SetPixelAlpha(image,image->alpha_trait != UndefinedPixelTrait ?
731
5.60k
                ScaleCharToQuantum(*(p+number_pixels*3)) : OpaqueAlpha,q);
732
6.17k
              p++;
733
6.17k
              q+=(ptrdiff_t) GetPixelChannels(image);
734
6.17k
            }
735
910
            if (SyncAuthenticPixels(image,exception) == MagickFalse)
736
0
              break;
737
910
            if (image->previous == (Image *) NULL)
738
694
              {
739
694
                status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
740
694
                image->rows);
741
694
                if (status == MagickFalse)
742
0
                  break;
743
694
              }
744
910
          }
745
107
        }
746
1.13k
    pixels=(unsigned char *) RelinquishMagickMemory(pixels);
747
1.13k
    if (image->storage_class == PseudoClass)
748
1.02k
      (void) SyncImage(image,exception);
749
1.13k
    if (EOFBlob(image) != MagickFalse)
750
1.13k
      ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
751
    /*
752
      Proceed to next image.
753
    */
754
1.13k
    if (image_info->number_scenes != 0)
755
0
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
756
0
        break;
757
1.13k
    count=ReadBlob(image,1,&viff_info.identifier);
758
1.13k
    if ((count == 1) && (viff_info.identifier == 0xab))
759
539
      {
760
        /*
761
          Allocate next image structure.
762
        */
763
539
        AcquireNextImage(image_info,image,exception);
764
539
        if (GetNextImageInList(image) == (Image *) NULL)
765
0
          {
766
0
            status=MagickFalse;
767
0
            break;
768
0
          }
769
539
        image=SyncNextImageInList(image);
770
539
        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
771
539
          GetBlobSize(image));
772
539
        if (status == MagickFalse)
773
0
          break;
774
539
      }
775
1.13k
  } while ((count != 0) && (viff_info.identifier == 0xab));
776
595
  if (CloseBlob(image) == MagickFalse)
777
0
    status=MagickFalse;
778
595
  if (status == MagickFalse)
779
0
    return(DestroyImageList(image));
780
595
  return(GetFirstImageInList(image));
781
595
}
782

783
/*
784
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
785
%                                                                             %
786
%                                                                             %
787
%                                                                             %
788
%   R e g i s t e r V I F F I m a g e                                         %
789
%                                                                             %
790
%                                                                             %
791
%                                                                             %
792
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
793
%
794
%  RegisterVIFFImage() adds properties for the VIFF image format to
795
%  the list of supported formats.  The properties include the image format
796
%  tag, a method to read and/or write the format, whether the format
797
%  supports the saving of more than one frame to the same file or blob,
798
%  whether the format supports native in-memory I/O, and a brief
799
%  description of the format.
800
%
801
%  The format of the RegisterVIFFImage method is:
802
%
803
%      size_t RegisterVIFFImage(void)
804
%
805
*/
806
ModuleExport size_t RegisterVIFFImage(void)
807
9
{
808
9
  MagickInfo
809
9
    *entry;
810
811
9
  entry=AcquireMagickInfo("VIFF","VIFF","Khoros Visualization image");
812
9
  entry->decoder=(DecodeImageHandler *) ReadVIFFImage;
813
9
  entry->encoder=(EncodeImageHandler *) WriteVIFFImage;
814
9
  entry->magick=(IsImageFormatHandler *) IsVIFF;
815
9
  entry->flags|=CoderDecoderSeekableStreamFlag;
816
9
  (void) RegisterMagickInfo(entry);
817
9
  entry=AcquireMagickInfo("VIFF","XV","Khoros Visualization image");
818
9
  entry->decoder=(DecodeImageHandler *) ReadVIFFImage;
819
9
  entry->encoder=(EncodeImageHandler *) WriteVIFFImage;
820
9
  entry->flags|=CoderDecoderSeekableStreamFlag;
821
9
  (void) RegisterMagickInfo(entry);
822
9
  return(MagickImageCoderSignature);
823
9
}
824

825
/*
826
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827
%                                                                             %
828
%                                                                             %
829
%                                                                             %
830
%   U n r e g i s t e r V I F F I m a g e                                     %
831
%                                                                             %
832
%                                                                             %
833
%                                                                             %
834
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835
%
836
%  UnregisterVIFFImage() removes format registrations made by the
837
%  VIFF module from the list of supported formats.
838
%
839
%  The format of the UnregisterVIFFImage method is:
840
%
841
%      UnregisterVIFFImage(void)
842
%
843
*/
844
ModuleExport void UnregisterVIFFImage(void)
845
0
{
846
0
  (void) UnregisterMagickInfo("VIFF");
847
0
  (void) UnregisterMagickInfo("XV");
848
0
}
849

850
/*
851
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
852
%                                                                             %
853
%                                                                             %
854
%                                                                             %
855
%   W r i t e V I F F I m a g e                                               %
856
%                                                                             %
857
%                                                                             %
858
%                                                                             %
859
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860
%
861
%  WriteVIFFImage() writes an image to a file in the VIFF image format.
862
%
863
%  The format of the WriteVIFFImage method is:
864
%
865
%      MagickBooleanType WriteVIFFImage(const ImageInfo *image_info,
866
%        Image *image,ExceptionInfo *exception)
867
%
868
%  A description of each parameter follows.
869
%
870
%    o image_info: the image info.
871
%
872
%    o image:  The image.
873
%
874
%    o exception: return any errors or warnings in this structure.
875
%
876
*/
877
static MagickBooleanType WriteVIFFImage(const ImageInfo *image_info,
878
  Image *image,ExceptionInfo *exception)
879
516
{
880
516
#define VFF_CM_genericRGB  15
881
516
#define VFF_CM_NONE  0
882
516
#define VFF_DEP_IEEEORDER  0x2
883
516
#define VFF_DES_RAW  0
884
516
#define VFF_LOC_IMPLICIT  1
885
516
#define VFF_MAPTYP_NONE  0
886
516
#define VFF_MAPTYP_1_BYTE  1
887
516
#define VFF_MS_NONE  0
888
516
#define VFF_MS_ONEPERBAND  1
889
516
#define VFF_TYP_BIT  0
890
516
#define VFF_TYP_1_BYTE  1
891
892
516
  typedef struct _ViffInfo
893
516
  {
894
516
    char
895
516
      identifier,
896
516
      file_type,
897
516
      release,
898
516
      version,
899
516
      machine_dependency,
900
516
      reserve[3],
901
516
      comment[512];
902
903
516
    size_t
904
516
      rows,
905
516
      columns,
906
516
      subrows;
907
908
516
    int
909
516
      x_offset,
910
516
      y_offset;
911
912
516
    unsigned int
913
516
      x_bits_per_pixel,
914
516
      y_bits_per_pixel,
915
516
      location_type,
916
516
      location_dimension,
917
516
      number_of_images,
918
516
      number_data_bands,
919
516
      data_storage_type,
920
516
      data_encode_scheme,
921
516
      map_scheme,
922
516
      map_storage_type,
923
516
      map_rows,
924
516
      map_columns,
925
516
      map_subrows,
926
516
      map_enable,
927
516
      maps_per_cycle,
928
516
      color_space_model;
929
516
  } ViffInfo;
930
931
516
  const char
932
516
    *value;
933
934
516
  const Quantum
935
516
    *p;
936
937
516
  MagickBooleanType
938
516
    status;
939
940
516
  MagickOffsetType
941
516
    scene;
942
943
516
  MagickSizeType
944
516
    number_pixels,
945
516
    packets;
946
947
516
  MemoryInfo
948
516
    *pixel_info;
949
950
516
  size_t
951
516
    number_scenes;
952
953
516
  ssize_t
954
516
    i,
955
516
    x,
956
516
    y;
957
958
516
  unsigned char
959
516
    *pixels,
960
516
    *q;
961
962
516
  ViffInfo
963
516
    viff_info;
964
965
  /*
966
    Open output image file.
967
  */
968
516
  assert(image_info != (const ImageInfo *) NULL);
969
516
  assert(image_info->signature == MagickCoreSignature);
970
516
  assert(image != (Image *) NULL);
971
516
  assert(image->signature == MagickCoreSignature);
972
516
  assert(exception != (ExceptionInfo *) NULL);
973
516
  assert(exception->signature == MagickCoreSignature);
974
516
  if (IsEventLogging() != MagickFalse)
975
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
976
516
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
977
516
  if (status == MagickFalse)
978
0
    return(status);
979
516
  (void) memset(&viff_info,0,sizeof(ViffInfo));
980
516
  scene=0;
981
516
  number_scenes=GetImageListLength(image);
982
516
  do
983
516
  {
984
516
    MagickBooleanType
985
516
      is_gray;
986
987
    /*
988
      Initialize VIFF image structure.
989
    */
990
516
    (void) TransformImageColorspace(image,sRGBColorspace,exception);
991
516
    viff_info.identifier=(char) -85;
992
516
    viff_info.file_type=1;
993
516
    viff_info.release=1;
994
516
    viff_info.version=3;
995
516
    viff_info.machine_dependency=VFF_DEP_IEEEORDER;  /* IEEE byte ordering */
996
516
    *viff_info.comment='\0';
997
516
    value=GetImageProperty(image,"comment",exception);
998
516
    if (value != (const char *) NULL)
999
273
      (void) CopyMagickString(viff_info.comment,value,MagickMin(strlen(value),
1000
273
        511)+1);
1001
516
    viff_info.rows=image->columns;
1002
516
    viff_info.columns=image->rows;
1003
516
    viff_info.subrows=0;
1004
516
    viff_info.x_offset=(~0);
1005
516
    viff_info.y_offset=(~0);
1006
516
    viff_info.x_bits_per_pixel=0;
1007
516
    viff_info.y_bits_per_pixel=0;
1008
516
    viff_info.location_type=VFF_LOC_IMPLICIT;
1009
516
    viff_info.location_dimension=0;
1010
516
    viff_info.number_of_images=1;
1011
516
    viff_info.data_encode_scheme=VFF_DES_RAW;
1012
516
    viff_info.map_scheme=VFF_MS_NONE;
1013
516
    viff_info.map_storage_type=VFF_MAPTYP_NONE;
1014
516
    viff_info.map_rows=0;
1015
516
    viff_info.map_columns=0;
1016
516
    viff_info.map_subrows=0;
1017
516
    viff_info.map_enable=1;  /* no colormap */
1018
516
    viff_info.maps_per_cycle=0;
1019
516
    number_pixels=(MagickSizeType) image->columns*image->rows;
1020
516
    is_gray=IdentifyImageCoderGray(image,exception);
1021
516
    if (image->storage_class == DirectClass)
1022
289
      {
1023
        /*
1024
          Full color VIFF raster.
1025
        */
1026
289
        viff_info.number_data_bands=image->alpha_trait ? 4U : 3U;
1027
289
        viff_info.color_space_model=VFF_CM_genericRGB;
1028
289
        viff_info.data_storage_type=VFF_TYP_1_BYTE;
1029
289
        packets=viff_info.number_data_bands*number_pixels;
1030
289
      }
1031
227
    else
1032
227
      {
1033
227
        viff_info.number_data_bands=1;
1034
227
        viff_info.color_space_model=VFF_CM_NONE;
1035
227
        viff_info.data_storage_type=VFF_TYP_1_BYTE;
1036
227
        packets=number_pixels;
1037
227
        if (is_gray == MagickFalse)
1038
96
          {
1039
            /*
1040
              Colormapped VIFF raster.
1041
            */
1042
96
            viff_info.map_scheme=VFF_MS_ONEPERBAND;
1043
96
            viff_info.map_storage_type=VFF_MAPTYP_1_BYTE;
1044
96
            viff_info.map_rows=3;
1045
96
            viff_info.map_columns=(unsigned int) image->colors;
1046
96
          }
1047
131
        else
1048
131
          if (image->colors <= 2)
1049
25
            {
1050
              /*
1051
                Monochrome VIFF raster.
1052
              */
1053
25
              viff_info.data_storage_type=VFF_TYP_BIT;
1054
25
              packets=((image->columns+7) >> 3)*image->rows;
1055
25
            }
1056
227
      }
1057
    /*
1058
      Write VIFF image header (pad to 1024 bytes).
1059
    */
1060
516
    (void) WriteBlob(image,sizeof(viff_info.identifier),(unsigned char *)
1061
516
      &viff_info.identifier);
1062
516
    (void) WriteBlob(image,sizeof(viff_info.file_type),(unsigned char *)
1063
516
      &viff_info.file_type);
1064
516
    (void) WriteBlob(image,sizeof(viff_info.release),(unsigned char *)
1065
516
      &viff_info.release);
1066
516
    (void) WriteBlob(image,sizeof(viff_info.version),(unsigned char *)
1067
516
      &viff_info.version);
1068
516
    (void) WriteBlob(image,sizeof(viff_info.machine_dependency),
1069
516
      (unsigned char *) &viff_info.machine_dependency);
1070
516
    (void) WriteBlob(image,sizeof(viff_info.reserve),(unsigned char *)
1071
516
      viff_info.reserve);
1072
516
    (void) WriteBlob(image,512,(unsigned char *) viff_info.comment);
1073
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.rows);
1074
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.columns);
1075
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.subrows);
1076
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.x_offset);
1077
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.y_offset);
1078
516
    viff_info.x_bits_per_pixel=(unsigned int) ((63 << 24) | (128 << 16));
1079
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.x_bits_per_pixel);
1080
516
    viff_info.y_bits_per_pixel=(unsigned int) ((63 << 24) | (128 << 16));
1081
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.y_bits_per_pixel);
1082
516
    (void) WriteBlobMSBLong(image,viff_info.location_type);
1083
516
    (void) WriteBlobMSBLong(image,viff_info.location_dimension);
1084
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.number_of_images);
1085
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.number_data_bands);
1086
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.data_storage_type);
1087
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.data_encode_scheme);
1088
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_scheme);
1089
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_storage_type);
1090
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_rows);
1091
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_columns);
1092
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_subrows);
1093
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_enable);
1094
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.maps_per_cycle);
1095
516
    (void) WriteBlobMSBLong(image,(unsigned int) viff_info.color_space_model);
1096
217k
    for (i=0; i < 420; i++)
1097
216k
      (void) WriteBlobByte(image,'\0');
1098
    /*
1099
      Convert MIFF to VIFF raster pixels.
1100
    */
1101
516
    if (packets != (MagickSizeType) ((size_t) packets))
1102
516
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1103
516
    pixel_info=AcquireVirtualMemory((size_t) packets,sizeof(*pixels));
1104
516
    if (pixel_info == (MemoryInfo *) NULL)
1105
516
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1106
516
    pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
1107
516
    q=pixels;
1108
516
    if (image->storage_class == DirectClass)
1109
289
      {
1110
        /*
1111
          Convert DirectClass packet to VIFF RGB pixel.
1112
        */
1113
289
        number_pixels=(MagickSizeType) image->columns*image->rows;
1114
16.5k
        for (y=0; y < (ssize_t) image->rows; y++)
1115
16.3k
        {
1116
16.3k
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1117
16.3k
          if (p == (const Quantum *) NULL)
1118
0
            break;
1119
755k
          for (x=0; x < (ssize_t) image->columns; x++)
1120
738k
          {
1121
738k
            *q=ScaleQuantumToChar(GetPixelRed(image,p));
1122
738k
            *(q+number_pixels)=ScaleQuantumToChar(GetPixelGreen(image,p));
1123
738k
            *(q+number_pixels*2)=ScaleQuantumToChar(GetPixelBlue(image,p));
1124
738k
            if (image->alpha_trait != UndefinedPixelTrait)
1125
540k
              *(q+number_pixels*3)=ScaleQuantumToChar((Quantum)
1126
540k
                (GetPixelAlpha(image,p)));
1127
738k
            p+=(ptrdiff_t) GetPixelChannels(image);
1128
738k
            q++;
1129
738k
          }
1130
16.3k
          if (image->previous == (Image *) NULL)
1131
16.3k
            {
1132
16.3k
              status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1133
16.3k
                image->rows);
1134
16.3k
              if (status == MagickFalse)
1135
0
                break;
1136
16.3k
            }
1137
16.3k
        }
1138
289
      }
1139
227
    else
1140
227
      if (is_gray == MagickFalse)
1141
96
        {
1142
96
          unsigned char
1143
96
            *viff_colormap;
1144
1145
          /*
1146
            Dump colormap to file.
1147
          */
1148
96
          viff_colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
1149
96
            3*sizeof(*viff_colormap));
1150
96
          if (viff_colormap == (unsigned char *) NULL)
1151
96
            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1152
96
          q=viff_colormap;
1153
14.2k
          for (i=0; i < (ssize_t) image->colors; i++)
1154
14.1k
            *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
1155
14.2k
          for (i=0; i < (ssize_t) image->colors; i++)
1156
14.1k
            *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
1157
14.2k
          for (i=0; i < (ssize_t) image->colors; i++)
1158
14.1k
            *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));
1159
96
          (void) WriteBlob(image,3*image->colors,viff_colormap);
1160
96
          viff_colormap=(unsigned char *) RelinquishMagickMemory(viff_colormap);
1161
          /*
1162
            Convert PseudoClass packet to VIFF colormapped pixels.
1163
          */
1164
96
          q=pixels;
1165
7.39k
          for (y=0; y < (ssize_t) image->rows; y++)
1166
7.30k
          {
1167
7.30k
            p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1168
7.30k
            if (p == (const Quantum *) NULL)
1169
0
              break;
1170
20.3k
            for (x=0; x < (ssize_t) image->columns; x++)
1171
13.0k
            {
1172
13.0k
              *q++=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
1173
13.0k
              p+=(ptrdiff_t) GetPixelChannels(image);
1174
13.0k
            }
1175
7.30k
            if (image->previous == (Image *) NULL)
1176
7.30k
              {
1177
7.30k
                status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1178
7.30k
                image->rows);
1179
7.30k
                if (status == MagickFalse)
1180
0
                  break;
1181
7.30k
              }
1182
7.30k
          }
1183
96
        }
1184
131
      else
1185
131
        if (image->colors <= 2)
1186
25
          {
1187
25
            unsigned char
1188
25
              bit,
1189
25
              byte;
1190
1191
            /*
1192
              Convert PseudoClass image to a VIFF monochrome image.
1193
            */
1194
533
            for (y=0; y < (ssize_t) image->rows; y++)
1195
508
            {
1196
508
              p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1197
508
              if (p == (const Quantum *) NULL)
1198
0
                break;
1199
508
              bit=0;
1200
508
              byte=0;
1201
3.61k
              for (x=0; x < (ssize_t) image->columns; x++)
1202
3.10k
              {
1203
3.10k
                byte>>=1;
1204
3.10k
                if (GetPixelLuma(image,p) < ((double) QuantumRange/2.0))
1205
2.84k
                  byte|=0x80;
1206
3.10k
                bit++;
1207
3.10k
                if (bit == 8)
1208
346
                  {
1209
346
                    *q++=byte;
1210
346
                    bit=0;
1211
346
                    byte=0;
1212
346
                  }
1213
3.10k
                p+=(ptrdiff_t) GetPixelChannels(image);
1214
3.10k
              }
1215
508
              if (bit != 0)
1216
314
                *q++=byte >> (8-bit);
1217
508
              if (image->previous == (Image *) NULL)
1218
508
                {
1219
508
                  status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1220
508
                    y,image->rows);
1221
508
                  if (status == MagickFalse)
1222
0
                    break;
1223
508
                }
1224
508
            }
1225
25
          }
1226
106
        else
1227
106
          {
1228
            /*
1229
              Convert PseudoClass packet to VIFF grayscale pixel.
1230
            */
1231
5.44k
            for (y=0; y < (ssize_t) image->rows; y++)
1232
5.33k
            {
1233
5.33k
              p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1234
5.33k
              if (p == (const Quantum *) NULL)
1235
0
                break;
1236
20.3k
              for (x=0; x < (ssize_t) image->columns; x++)
1237
14.9k
              {
1238
14.9k
                *q++=(unsigned char) ClampToQuantum(GetPixelLuma(image,p));
1239
14.9k
                p+=(ptrdiff_t) GetPixelChannels(image);
1240
14.9k
              }
1241
5.33k
              if (image->previous == (Image *) NULL)
1242
5.33k
                {
1243
5.33k
                  status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1244
5.33k
                    y,image->rows);
1245
5.33k
                  if (status == MagickFalse)
1246
0
                    break;
1247
5.33k
                }
1248
5.33k
            }
1249
106
          }
1250
516
    (void) WriteBlob(image,(size_t) packets,pixels);
1251
516
    pixel_info=RelinquishVirtualMemory(pixel_info);
1252
516
    if (GetNextImageInList(image) == (Image *) NULL)
1253
516
      break;
1254
0
    image=SyncNextImageInList(image);
1255
0
    status=SetImageProgress(image,SaveImagesTag,scene++,number_scenes);
1256
0
    if (status == MagickFalse)
1257
0
      break;
1258
0
  } while (image_info->adjoin != MagickFalse);
1259
516
  if (CloseBlob(image) == MagickFalse)
1260
0
    status=MagickFalse;
1261
516
  return(status);
1262
516
}