Coverage Report

Created: 2026-07-20 07:19

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
803
{
136
803
  Image
137
803
    *image;
138
139
803
  MagickBooleanType
140
803
    status;
141
142
803
  QuantumInfo
143
803
    *quantum_info;
144
145
803
  QuantumType
146
803
    quantum_type;
147
148
803
  size_t
149
803
    extent;
150
151
803
  ssize_t
152
803
    count,
153
803
    y;
154
155
803
  unsigned char
156
803
    *pixels;
157
158
803
  unsigned int
159
803
    magic;
160
161
  /*
162
    Open image file.
163
  */
164
803
  assert(image_info != (const ImageInfo *) NULL);
165
803
  assert(image_info->signature == MagickCoreSignature);
166
803
  assert(exception != (ExceptionInfo *) NULL);
167
803
  assert(exception->signature == MagickCoreSignature);
168
803
  if (IsEventLogging() != MagickFalse)
169
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
170
0
      image_info->filename);
171
803
  image=AcquireImage(image_info,exception);
172
803
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
173
803
  if (status == MagickFalse)
174
0
    {
175
0
      image=DestroyImageList(image);
176
0
      return((Image *) NULL);
177
0
    }
178
803
  magic=ReadBlobLSBLong(image);
179
803
  if (magic != 842222662)
180
745
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
181
745
  image->depth=32;
182
745
  image->endian=LSBEndian;
183
745
  image->rows=(size_t) ReadBlobLSBLong(image);
184
745
  image->columns=(size_t) ReadBlobLSBLong(image);
185
745
  image->number_channels=(size_t) ReadBlobLSBLong(image);
186
745
  if ((image->columns == 0) || (image->rows == 0) ||
187
736
      (image->number_channels == 0) ||
188
688
      (image->number_channels >= MaxPixelChannels))
189
623
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
190
623
  switch (image->number_channels)
191
623
  {
192
209
    case 1:
193
209
    {
194
209
      quantum_type=GrayQuantum;
195
209
      image->colorspace=GRAYColorspace;
196
209
      break;
197
0
    }
198
68
    case 2:
199
68
    {
200
68
      image->alpha_trait=BlendPixelTrait;
201
68
      image->colorspace=GRAYColorspace;
202
68
      quantum_type=GrayAlphaQuantum;
203
68
      break;
204
0
    }
205
12
    case 3:
206
12
    {
207
12
      image->colorspace=sRGBColorspace;
208
12
      quantum_type=RGBQuantum;
209
12
      break;
210
0
    }
211
67
    case 4:
212
67
    {
213
67
      image->colorspace=sRGBColorspace;
214
67
      image->alpha_trait=BlendPixelTrait;
215
67
      quantum_type=RGBAQuantum;
216
67
      break;
217
0
    }
218
267
    default:
219
267
    {
220
267
      image->number_meta_channels=image->number_channels-3;
221
267
      quantum_type=RGBQuantum;
222
267
      break;
223
0
    }
224
623
  }
225
623
  if (image_info->ping != MagickFalse)
226
10
    {
227
10
      (void) CloseBlob(image);
228
10
      return(GetFirstImageInList(image));
229
10
    }
230
613
  status=SetImageExtent(image,image->columns,image->rows,exception);
231
613
  if (status == MagickFalse)
232
105
    return(DestroyImageList(image));
233
  /*
234
    Convert FL32 image to pixel packets.
235
  */
236
508
  quantum_info=AcquireQuantumInfo(image_info,image);
237
508
  if (quantum_info == (QuantumInfo *) NULL)
238
508
    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
239
508
  status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
240
508
  extent=GetQuantumExtent(image,quantum_info,quantum_type);
241
508
  pixels=GetQuantumPixels(quantum_info);
242
22.0k
  for (y=0; y < (ssize_t) image->rows; y++)
243
21.8k
  {
244
21.8k
    const void
245
21.8k
      *stream;
246
247
21.8k
    Quantum
248
21.8k
      *magick_restrict q;
249
250
21.8k
    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
251
21.8k
    if (q == (Quantum *) NULL)
252
0
      break;
253
21.8k
    stream=ReadBlobStream(image,extent,pixels,&count);
254
21.8k
    if (count != (ssize_t) extent)
255
298
      break;
256
21.5k
    (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
257
21.5k
      quantum_type,(unsigned char *) stream,exception);
258
21.5k
    if (SyncAuthenticPixels(image,exception) == MagickFalse)
259
0
      break;
260
21.5k
    if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
261
0
      break;
262
21.5k
  }
263
508
  SetQuantumImageType(image,quantum_type);
264
508
  quantum_info=DestroyQuantumInfo(quantum_info);
265
508
  if (y < (ssize_t) image->rows)
266
298
    ThrowReaderException(CorruptImageError,"UnableToReadImageData");
267
210
  if (EOFBlob(image) != MagickFalse)
268
0
    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
269
210
      image->filename);
270
210
  if (CloseBlob(image) == MagickFalse)
271
0
    status=MagickFalse;
272
210
  if (status == MagickFalse)
273
0
    return(DestroyImageList(image));
274
210
  return(GetFirstImageInList(image));
275
210
}
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
9
{
302
9
  MagickInfo
303
9
    *entry;
304
305
9
  entry=AcquireMagickInfo("FL32","FL32","FilmLight");
306
9
  entry->decoder=(DecodeImageHandler *) ReadFL32Image;
307
9
  entry->encoder=(EncodeImageHandler *) WriteFL32Image;
308
9
  entry->magick=(IsImageFormatHandler *) IsFL32;
309
9
  entry->flags|=CoderRawSupportFlag;
310
9
  entry->flags^=CoderAdjoinFlag;
311
9
  (void) RegisterMagickInfo(entry);
312
9
  return(MagickImageCoderSignature);
313
9
}
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
210
{
369
210
  const Quantum
370
210
    *p;
371
372
210
  MagickBooleanType
373
210
    status;
374
375
210
  QuantumInfo
376
210
    *quantum_info;
377
378
210
  QuantumType
379
210
    quantum_type;
380
381
210
  size_t
382
210
    channels,
383
210
    extent;
384
385
210
  ssize_t
386
210
    count,
387
210
    y;
388
389
210
  unsigned char
390
210
    *pixels;
391
392
  /*
393
    Open output image file.
394
  */
395
210
  assert(image_info != (const ImageInfo *) NULL);
396
210
  assert(image_info->signature == MagickCoreSignature);
397
210
  assert(image != (Image *) NULL);
398
210
  assert(image->signature == MagickCoreSignature);
399
210
  assert(exception != (ExceptionInfo *) NULL);
400
210
  assert(exception->signature == MagickCoreSignature);
401
210
  if (IsEventLogging() != MagickFalse)
402
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
403
210
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
404
210
  if (status == MagickFalse)
405
0
    return(status);
406
210
  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
407
0
    (void) TransformImageColorspace(image,sRGBColorspace,exception);
408
210
  (void) WriteBlobLSBLong(image,842222662U);
409
210
  (void) WriteBlobLSBLong(image,(unsigned int) image->rows);
410
210
  (void) WriteBlobLSBLong(image,(unsigned int) image->columns);
411
210
  image->endian=LSBEndian;
412
210
  image->depth=32;
413
210
  channels=GetImageChannels(image);
414
210
  switch (channels)
415
210
  {
416
110
    case 1:
417
110
    {
418
110
      quantum_type=GrayQuantum;
419
110
      break;
420
0
    }
421
36
    case 2:
422
36
    {
423
36
      if (image->alpha_trait != UndefinedPixelTrait)
424
36
        {
425
36
          quantum_type=GrayAlphaQuantum;
426
36
          break;
427
36
        }
428
0
      quantum_type=GrayQuantum;
429
0
      channels=1;
430
0
      break;
431
36
    }
432
25
    case 4:
433
25
    {
434
25
      if (image->alpha_trait != UndefinedPixelTrait)
435
25
        {
436
25
          quantum_type=RGBAQuantum;
437
25
          break;
438
25
        }
439
0
      quantum_type=RGBQuantum;
440
0
      channels=3;
441
0
      break;
442
25
    }
443
39
    default:
444
39
    {
445
39
      quantum_type=RGBQuantum;
446
39
      channels=3;
447
39
      break;
448
25
    }
449
210
  }
450
210
  (void) WriteBlobLSBLong(image,(unsigned int) channels);
451
210
  quantum_info=AcquireQuantumInfo(image_info,image);
452
210
  if (quantum_info == (QuantumInfo *) NULL)
453
210
    ThrowWriterException(ImageError,"MemoryAllocationFailed");
454
210
  status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
455
210
  pixels=(unsigned char *) GetQuantumPixels(quantum_info);
456
12.1k
  for (y=0; y < (ssize_t) image->rows; y++)
457
11.9k
  {
458
11.9k
    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
459
11.9k
    if (p == (const Quantum *) NULL)
460
0
      break;
461
11.9k
    extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
462
11.9k
      quantum_type,pixels,exception);
463
11.9k
    count=WriteBlob(image,extent,pixels);
464
11.9k
    if (count != (ssize_t) extent)
465
0
      break;
466
11.9k
    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
467
11.9k
      image->rows);
468
11.9k
    if (status == MagickFalse)
469
0
      break;
470
11.9k
  }
471
210
  quantum_info=DestroyQuantumInfo(quantum_info);
472
210
  if (y < (ssize_t) image->rows)
473
210
    ThrowWriterException(CorruptImageError,"UnableToWriteImageData");
474
210
  if (CloseBlob(image) == MagickFalse)
475
0
    status=MagickFalse;
476
210
  return(status);
477
210
}