Coverage Report

Created: 2025-10-12 07:48

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