Coverage Report

Created: 2026-02-14 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/fl32.c
Line
Count
Source
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                                                                             %
6
%                                                                             %
7
%                         FFFFF  L      IIIII  FFFFF                          %
8
%                         F      L        I    F                              %
9
%                         FFF    L        I    FFF                            %
10
%                         F      L        I    F                              %
11
%                         F      LLLLL  IIIII  F                              %
12
%                                                                             %
13
%                                                                             %
14
%                       Support FilmLight Image Format                        %
15
%                                                                             %
16
%                              Software Design                                %
17
%                                   Cristy                                    %
18
%                               November 2020                                 %
19
%                                                                             %
20
%                                                                             %
21
%  Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization         %
22
%  dedicated to making software imaging solutions freely available.           %
23
%                                                                             %
24
%  You may not use this file except in compliance with the License.  You may  %
25
%  obtain a copy of the License at                                            %
26
%                                                                             %
27
%    https://imagemagick.org/license/                                         %
28
%                                                                             %
29
%  Unless required by applicable law or agreed to in writing, software        %
30
%  distributed under the License is distributed on an "AS IS" BASIS,          %
31
%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
32
%  See the License for the specific language governing permissions and        %
33
%  limitations under the License.                                             %
34
%                                                                             %
35
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36
%
37
%
38
*/
39

40
/*
41
  Include declarations.
42
*/
43
#include "MagickCore/studio.h"
44
#include "MagickCore/attribute.h"
45
#include "MagickCore/blob.h"
46
#include "MagickCore/blob-private.h"
47
#include "MagickCore/cache.h"
48
#include "MagickCore/color-private.h"
49
#include "MagickCore/colormap.h"
50
#include "MagickCore/colorspace.h"
51
#include "MagickCore/colorspace-private.h"
52
#include "MagickCore/exception.h"
53
#include "MagickCore/exception-private.h"
54
#include "MagickCore/image.h"
55
#include "MagickCore/image-private.h"
56
#include "MagickCore/list.h"
57
#include "MagickCore/magick.h"
58
#include "MagickCore/memory_.h"
59
#include "MagickCore/monitor.h"
60
#include "MagickCore/monitor-private.h"
61
#include "MagickCore/quantum-private.h"
62
#include "MagickCore/static.h"
63
#include "MagickCore/string_.h"
64
#include "MagickCore/module.h"
65

66
/*
67
  Forward declarations.
68
*/
69
static MagickBooleanType
70
  WriteFL32Image(const ImageInfo *,Image *,ExceptionInfo *);
71

72
/*
73
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74
%                                                                             %
75
%                                                                             %
76
%                                                                             %
77
%   I s F L 3 2                                                               %
78
%                                                                             %
79
%                                                                             %
80
%                                                                             %
81
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82
%
83
%  IsFL32() returns MagickTrue if the image format type, identified by the
84
%  magick string, is FL32.
85
%
86
%  The format of the IsFL32 method is:
87
%
88
%      MagickBooleanType IsFL32(const unsigned char *magick,const size_t extent)
89
%
90
%  A description of each parameter follows:
91
%
92
%    o magick: compare image format pattern against these bytes.
93
%
94
%    o extent: Specifies the extent of the magick string.
95
%
96
*/
97
static MagickBooleanType IsFL32(const unsigned char *magick,const size_t extent)
98
0
{
99
0
  if (extent < 4)
100
0
    return(MagickFalse);
101
0
  if (LocaleNCompare((char *) magick,"FL32",4) == 0)
102
0
    return(MagickTrue);
103
0
  return(MagickFalse);
104
0
}
105

106
/*
107
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108
%                                                                             %
109
%                                                                             %
110
%                                                                             %
111
%   R e a d F L 3 2 I m a g e                                                 %
112
%                                                                             %
113
%                                                                             %
114
%                                                                             %
115
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116
%
117
%  ReadFL32Image() reads an image of raw bits in LSB order and returns it.
118
%  It allocates the memory necessary for the new Image structure and returns
119
%  a pointer to the new image.
120
%
121
%  The format of the ReadFL32Image method is:
122
%
123
%      Image *ReadFL32Image(const ImageInfo *image_info,
124
%        ExceptionInfo *exception)
125
%
126
%  A description of each parameter follows:
127
%
128
%    o image_info: the image info.
129
%
130
%    o exception: return any errors or warnings in this structure.
131
%
132
*/
133
static Image *ReadFL32Image(const ImageInfo *image_info,
134
  ExceptionInfo *exception)
135
962
{
136
962
  Image
137
962
    *image;
138
139
962
  MagickBooleanType
140
962
    status;
141
142
962
  QuantumInfo
143
962
    *quantum_info;
144
145
962
  QuantumType
146
962
    quantum_type;
147
148
962
  size_t
149
962
    extent;
150
151
962
  ssize_t
152
962
    count,
153
962
    y;
154
155
962
  unsigned char
156
962
    *pixels;
157
158
962
  unsigned int
159
962
    magic;
160
161
  /*
162
    Open image file.
163
  */
164
962
  assert(image_info != (const ImageInfo *) NULL);
165
962
  assert(image_info->signature == MagickCoreSignature);
166
962
  assert(exception != (ExceptionInfo *) NULL);
167
962
  assert(exception->signature == MagickCoreSignature);
168
962
  if (IsEventLogging() != MagickFalse)
169
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
170
0
      image_info->filename);
171
962
  image=AcquireImage(image_info,exception);
172
962
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
173
962
  if (status == MagickFalse)
174
119
    {
175
119
      image=DestroyImageList(image);
176
119
      return((Image *) NULL);
177
119
    }
178
843
  magic=ReadBlobLSBLong(image);
179
843
  if (magic != 842222662)
180
672
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
181
672
  image->depth=32;
182
672
  image->endian=LSBEndian;
183
672
  image->rows=(size_t) ReadBlobLSBLong(image);
184
672
  image->columns=(size_t) ReadBlobLSBLong(image);
185
672
  image->number_channels=(size_t) ReadBlobLSBLong(image);
186
672
  if ((image->columns == 0) || (image->rows == 0) ||
187
665
      (image->number_channels == 0) ||
188
621
      (image->number_channels >= MaxPixelChannels))
189
569
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
190
569
  switch (image->number_channels)
191
569
  {
192
242
    case 1:
193
242
    {
194
242
      quantum_type=GrayQuantum;
195
242
      image->colorspace=GRAYColorspace;
196
242
      break;
197
0
    }
198
61
    case 2:
199
61
    {
200
61
      image->alpha_trait=BlendPixelTrait;
201
61
      image->colorspace=GRAYColorspace;
202
61
      quantum_type=GrayAlphaQuantum;
203
61
      break;
204
0
    }
205
8
    case 3:
206
8
    {
207
8
      image->colorspace=sRGBColorspace;
208
8
      quantum_type=RGBQuantum;
209
8
      break;
210
0
    }
211
74
    case 4:
212
74
    {
213
74
      image->colorspace=sRGBColorspace;
214
74
      image->alpha_trait=BlendPixelTrait;
215
74
      quantum_type=RGBAQuantum;
216
74
      break;
217
0
    }
218
184
    default:
219
184
    {
220
184
      image->number_meta_channels=image->number_channels-3;
221
184
      quantum_type=RGBQuantum;
222
184
      break;
223
0
    }
224
569
  }
225
569
  if (image_info->ping != MagickFalse)
226
0
    {
227
0
      (void) CloseBlob(image);
228
0
      return(GetFirstImageInList(image));
229
0
    }
230
569
  status=SetImageExtent(image,image->columns,image->rows,exception);
231
569
  if (status == MagickFalse)
232
100
    return(DestroyImageList(image));
233
  /*
234
    Convert FL32 image to pixel packets.
235
  */
236
469
  quantum_info=AcquireQuantumInfo(image_info,image);
237
469
  if (quantum_info == (QuantumInfo *) NULL)
238
469
    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
239
469
  status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
240
469
  extent=GetQuantumExtent(image,quantum_info,quantum_type);
241
469
  pixels=GetQuantumPixels(quantum_info);
242
30.1k
  for (y=0; y < (ssize_t) image->rows; y++)
243
29.9k
  {
244
29.9k
    const void
245
29.9k
      *stream;
246
247
29.9k
    Quantum
248
29.9k
      *magick_restrict q;
249
250
29.9k
    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
251
29.9k
    if (q == (Quantum *) NULL)
252
0
      break;
253
29.9k
    stream=ReadBlobStream(image,extent,pixels,&count);
254
29.9k
    if (count != (ssize_t) extent)
255
248
      break;
256
29.6k
    (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
257
29.6k
      quantum_type,(unsigned char *) stream,exception);
258
29.6k
    if (SyncAuthenticPixels(image,exception) == MagickFalse)
259
0
      break;
260
29.6k
    if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
261
0
      break;
262
29.6k
  }
263
469
  SetQuantumImageType(image,quantum_type);
264
469
  quantum_info=DestroyQuantumInfo(quantum_info);
265
469
  if (y < (ssize_t) image->rows)
266
248
    ThrowReaderException(CorruptImageError,"UnableToReadImageData");
267
221
  if (EOFBlob(image) != MagickFalse)
268
0
    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
269
221
      image->filename);
270
221
  if (CloseBlob(image) == MagickFalse)
271
0
    status=MagickFalse;
272
221
  if (status == MagickFalse)
273
0
    return(DestroyImageList(image));
274
221
  return(GetFirstImageInList(image));
275
221
}
276

277
/*
278
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279
%                                                                             %
280
%                                                                             %
281
%                                                                             %
282
%   R e g i s t e r F L 3 2 I m a g e                                         %
283
%                                                                             %
284
%                                                                             %
285
%                                                                             %
286
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
287
%
288
%  RegisterFL32Image() adds attributes for the FL32 image format to
289
%  the list of supported formats.  The attributes include the image format
290
%  tag, a method to read and/or write the format, whether the format
291
%  supports the saving of more than one frame to the same file or blob,
292
%  whether the format supports native in-memory I/O, and a brief
293
%  description of the format.
294
%
295
%  The format of the RegisterFL32Image method is:
296
%
297
%      size_t RegisterFL32Image(void)
298
%
299
*/
300
ModuleExport size_t RegisterFL32Image(void)
301
8
{
302
8
  MagickInfo
303
8
    *entry;
304
305
8
  entry=AcquireMagickInfo("FL32","FL32","FilmLight");
306
8
  entry->decoder=(DecodeImageHandler *) ReadFL32Image;
307
8
  entry->encoder=(EncodeImageHandler *) WriteFL32Image;
308
8
  entry->magick=(IsImageFormatHandler *) IsFL32;
309
8
  entry->flags|=CoderRawSupportFlag;
310
8
  entry->flags^=CoderAdjoinFlag;
311
8
  (void) RegisterMagickInfo(entry);
312
8
  return(MagickImageCoderSignature);
313
8
}
314

315
/*
316
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317
%                                                                             %
318
%                                                                             %
319
%                                                                             %
320
%   U n r e g i s t e r F L 3 2 I m a g e                                     %
321
%                                                                             %
322
%                                                                             %
323
%                                                                             %
324
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325
%
326
%  UnregisterFL32Image() removes format registrations made by the
327
%  FL32 module from the list of supported formats.
328
%
329
%  The format of the UnregisterFL32Image method is:
330
%
331
%      UnregisterFL32Image(void)
332
%
333
*/
334
ModuleExport void UnregisterFL32Image(void)
335
0
{
336
0
  (void) UnregisterMagickInfo("FL32");
337
0
}
338

339
/*
340
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341
%                                                                             %
342
%                                                                             %
343
%                                                                             %
344
%   W r i t e F L 3 2 I m a g e                                               %
345
%                                                                             %
346
%                                                                             %
347
%                                                                             %
348
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349
%
350
%  WriteFL32Image() writes an image of raw bits in LSB order to a file.
351
%
352
%  The format of the WriteFL32Image method is:
353
%
354
%      MagickBooleanType WriteFL32Image(const ImageInfo *image_info,
355
%        Image *image,ExceptionInfo *exception)
356
%
357
%  A description of each parameter follows.
358
%
359
%    o image_info: the image info.
360
%
361
%    o image:  The image.
362
%
363
%    o exception: return any errors or warnings in this structure.
364
%
365
*/
366
static MagickBooleanType WriteFL32Image(const ImageInfo *image_info,
367
  Image *image,ExceptionInfo *exception)
368
221
{
369
221
  const Quantum
370
221
    *p;
371
372
221
  MagickBooleanType
373
221
    status;
374
375
221
  QuantumInfo
376
221
    *quantum_info;
377
378
221
  QuantumType
379
221
    quantum_type;
380
381
221
  size_t
382
221
    channels,
383
221
    extent;
384
385
221
  ssize_t
386
221
    count,
387
221
    y;
388
389
221
  unsigned char
390
221
    *pixels;
391
392
  /*
393
    Open output image file.
394
  */
395
221
  assert(image_info != (const ImageInfo *) NULL);
396
221
  assert(image_info->signature == MagickCoreSignature);
397
221
  assert(image != (Image *) NULL);
398
221
  assert(image->signature == MagickCoreSignature);
399
221
  assert(exception != (ExceptionInfo *) NULL);
400
221
  assert(exception->signature == MagickCoreSignature);
401
221
  if (IsEventLogging() != MagickFalse)
402
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
403
221
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
404
221
  if (status == MagickFalse)
405
0
    return(status);
406
221
  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
407
0
    (void) TransformImageColorspace(image,sRGBColorspace,exception);
408
221
  (void) WriteBlobLSBLong(image,842222662U);
409
221
  (void) WriteBlobLSBLong(image,(unsigned int) image->rows);
410
221
  (void) WriteBlobLSBLong(image,(unsigned int) image->columns);
411
221
  image->endian=LSBEndian;
412
221
  image->depth=32;
413
221
  channels=GetImageChannels(image);
414
221
  switch (channels)
415
221
  {
416
123
    case 1:
417
123
    {
418
123
      quantum_type=GrayQuantum;
419
123
      break;
420
0
    }
421
27
    case 2:
422
27
    {
423
27
      if (image->alpha_trait != UndefinedPixelTrait)
424
27
        {
425
27
          quantum_type=GrayAlphaQuantum;
426
27
          break;
427
27
        }
428
0
      quantum_type=GrayQuantum;
429
0
      channels=1;
430
0
      break;
431
27
    }
432
28
    case 4:
433
28
    {
434
28
      if (image->alpha_trait != UndefinedPixelTrait)
435
28
        {
436
28
          quantum_type=RGBAQuantum;
437
28
          break;
438
28
        }
439
0
      quantum_type=RGBQuantum;
440
0
      channels=3;
441
0
      break;
442
28
    }
443
43
    default:
444
43
    {
445
43
      quantum_type=RGBQuantum;
446
43
      channels=3;
447
43
      break;
448
28
    }
449
221
  }
450
221
  (void) WriteBlobLSBLong(image,(unsigned int) channels);
451
221
  quantum_info=AcquireQuantumInfo(image_info,image);
452
221
  if (quantum_info == (QuantumInfo *) NULL)
453
221
    ThrowWriterException(ImageError,"MemoryAllocationFailed");
454
221
  status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
455
221
  pixels=(unsigned char *) GetQuantumPixels(quantum_info);
456
15.9k
  for (y=0; y < (ssize_t) image->rows; y++)
457
15.7k
  {
458
15.7k
    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
459
15.7k
    if (p == (const Quantum *) NULL)
460
0
      break;
461
15.7k
    extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
462
15.7k
      quantum_type,pixels,exception);
463
15.7k
    count=WriteBlob(image,extent,pixels);
464
15.7k
    if (count != (ssize_t) extent)
465
0
      break;
466
15.7k
    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
467
15.7k
      image->rows);
468
15.7k
    if (status == MagickFalse)
469
0
      break;
470
15.7k
  }
471
221
  quantum_info=DestroyQuantumInfo(quantum_info);
472
221
  if (y < (ssize_t) image->rows)
473
221
    ThrowWriterException(CorruptImageError,"UnableToWriteImageData");
474
221
  if (CloseBlob(image) == MagickFalse)
475
0
    status=MagickFalse;
476
221
  return(status);
477
221
}