Coverage Report

Created: 2025-12-03 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/fax.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2024 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
5
%
6
% This program is covered by multiple licenses, which are described in
7
% Copyright.txt. You should have received a copy of Copyright.txt with this
8
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9
%
10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11
%                                                                             %
12
%                                                                             %
13
%                                                                             %
14
%                            FFFFF   AAA   X   X                              %
15
%                            F      A   A   X X                               %
16
%                            FFF    AAAAA    X                                %
17
%                            F      A   A   X X                               %
18
%                            F      A   A  X   X                              %
19
%                                                                             %
20
%                                                                             %
21
%                   Read/Write Group 3 FIX Image Format.                      %
22
%                                                                             %
23
%                                                                             %
24
%                              Software Design                                %
25
%                                John Cristy                                  %
26
%                                 July 1992                                   %
27
%                                                                             %
28
%                                                                             %
29
%                                                                             %
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31
%
32
%
33
*/
34

35
/*
36
  Include declarations.
37
*/
38
#include "magick/studio.h"
39
#include "magick/blob.h"
40
#include "magick/colormap.h"
41
#include "magick/compress.h"
42
#include "magick/magick.h"
43
#include "magick/monitor.h"
44
#include "magick/pixel_cache.h"
45
#include "magick/utility.h"
46

47
/*
48
  Forward declarations.
49
*/
50
static unsigned int
51
  WriteFAXImage(const ImageInfo *,Image *);
52

53
/*
54
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55
%                                                                             %
56
%                                                                             %
57
%                                                                             %
58
%   I s F A X                                                                 %
59
%                                                                             %
60
%                                                                             %
61
%                                                                             %
62
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63
%
64
%  Method IsFAX returns True if the image format type, identified by the
65
%  magick string, is FAX.
66
%
67
%  The format of the IsFAX method is:
68
%
69
%      unsigned int IsFAX(const unsigned char *magick,const size_t length)
70
%
71
%  A description of each parameter follows:
72
%
73
%    o status:  Method IsFAX returns True if the image format type is FAX.
74
%
75
%    o magick: This string is generally the first few bytes of an image file
76
%      or blob.
77
%
78
%    o length: Specifies the length of the magick string.
79
%
80
%
81
*/
82
static unsigned int IsFAX(const unsigned char *magick,const size_t length)
83
0
{
84
0
  if (length < 4)
85
0
    return(False);
86
0
  if (LocaleNCompare((char *) magick,"DFAX",4) == 0)
87
0
    return(True);
88
0
  return(False);
89
0
}
90

91
/*
92
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93
%                                                                             %
94
%                                                                             %
95
%                                                                             %
96
%   R e a d F A X I m a g e                                                   %
97
%                                                                             %
98
%                                                                             %
99
%                                                                             %
100
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101
%
102
%  Method ReadFAXImage reads a Group 3 FAX image file and returns it.  It
103
%  allocates the memory necessary for the new Image structure and returns a
104
%  pointer to the new image.
105
%
106
%  The format of the ReadFAXImage method is:
107
%
108
%      Image *ReadFAXImage(const ImageInfo *image_info,ExceptionInfo *exception)
109
%
110
%  A description of each parameter follows:
111
%
112
%    o image:  Method ReadFAXImage returns a pointer to the image after
113
%      reading.  A null image is returned if there is a memory shortage or
114
%      if the image cannot be read.
115
%
116
%    o image_info: Specifies a pointer to a ImageInfo structure.
117
%
118
%    o exception: return any errors or warnings in this structure.
119
%
120
%
121
*/
122
static Image *ReadFAXImage(const ImageInfo *image_info,ExceptionInfo *exception)
123
1.56k
{
124
1.56k
  Image
125
1.56k
    *image;
126
127
1.56k
  unsigned int
128
1.56k
    status;
129
130
  /*
131
    Open image file.
132
  */
133
1.56k
  assert(image_info != (const ImageInfo *) NULL);
134
1.56k
  assert(image_info->signature == MagickSignature);
135
1.56k
  assert(exception != (ExceptionInfo *) NULL);
136
1.56k
  assert(exception->signature == MagickSignature);
137
1.56k
  image=AllocateImage(image_info);
138
1.56k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
139
1.56k
  if (status == False)
140
1.56k
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
141
  /*
142
    Initialize image structure.
143
  */
144
1.56k
  image->storage_class=PseudoClass;
145
1.56k
  if (image->columns == 0)
146
1.56k
    image->columns=2592;
147
1.56k
  if (image->rows == 0)
148
1.56k
    image->rows=3508;
149
1.56k
  image->depth=8;
150
1.56k
  if (!AllocateImageColormap(image,2))
151
1.56k
    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
152
  /*
153
    Monochrome colormap.
154
  */
155
1.56k
  image->colormap[0].red=MaxRGB;
156
1.56k
  image->colormap[0].green=MaxRGB;
157
1.56k
  image->colormap[0].blue=MaxRGB;
158
1.56k
  image->colormap[1].red=0;
159
1.56k
  image->colormap[1].green=0;
160
1.56k
  image->colormap[1].blue=0;
161
1.56k
  if (image_info->ping)
162
0
    {
163
0
      CloseBlob(image);
164
0
      StopTimer(&image->timer);
165
0
      return(image);
166
0
    }
167
168
1.56k
  if (CheckImagePixelLimits(image, exception) != MagickPass)
169
1.56k
    ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
170
171
0
  status=HuffmanDecodeImage(image);
172
0
  if (status == False)
173
0
    ThrowReaderException(CorruptImageError,UnableToReadImageData,image);
174
0
  if (EOFBlob(image))
175
0
    ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
176
0
      image->filename);
177
0
  CloseBlob(image);
178
0
  StopTimer(&image->timer);
179
0
  return(image);
180
0
}
181

182
/*
183
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
184
%                                                                             %
185
%                                                                             %
186
%                                                                             %
187
%   R e g i s t e r F A X I m a g e                                           %
188
%                                                                             %
189
%                                                                             %
190
%                                                                             %
191
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192
%
193
%  Method RegisterFAXImage adds attributes for the FAX image format to
194
%  the list of supported formats.  The attributes include the image format
195
%  tag, a method to read and/or write the format, whether the format
196
%  supports the saving of more than one frame to the same file or blob,
197
%  whether the format supports native in-memory I/O, and a brief
198
%  description of the format.
199
%
200
%  The format of the RegisterFAXImage method is:
201
%
202
%      RegisterFAXImage(void)
203
%
204
*/
205
ModuleExport void RegisterFAXImage(void)
206
4
{
207
4
  MagickInfo
208
4
    *entry;
209
210
4
  entry=SetMagickInfo("FAX");
211
4
  entry->decoder=(DecoderHandler) ReadFAXImage;
212
4
  entry->encoder=(EncoderHandler) WriteFAXImage;
213
4
  entry->magick=(MagickHandler) IsFAX;
214
4
  entry->description="Group 3 FAX (Not TIFF Group3 FAX!)";
215
4
  entry->module="FAX";
216
4
  entry->coder_class=PrimaryCoderClass;
217
4
  (void) RegisterMagickInfo(entry);
218
219
4
  entry=SetMagickInfo("G3");
220
4
  entry->decoder=(DecoderHandler) ReadFAXImage;
221
4
  entry->encoder=(EncoderHandler) WriteFAXImage;
222
4
  entry->magick=(MagickHandler) IsFAX;
223
4
  entry->adjoin=False;
224
4
  entry->description="Group 3 FAX (same as \"FAX\")";
225
4
  entry->stealth=MagickTrue; /* Don't list in '-list format' output */
226
4
  entry->module="FAX";
227
4
  entry->coder_class=PrimaryCoderClass;
228
4
  (void) RegisterMagickInfo(entry);
229
4
}
230

231
/*
232
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233
%                                                                             %
234
%                                                                             %
235
%                                                                             %
236
%   U n r e g i s t e r F A X I m a g e                                       %
237
%                                                                             %
238
%                                                                             %
239
%                                                                             %
240
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241
%
242
%  Method UnregisterFAXImage removes format registrations made by the
243
%  FAX module from the list of supported formats.
244
%
245
%  The format of the UnregisterFAXImage method is:
246
%
247
%      UnregisterFAXImage(void)
248
%
249
*/
250
ModuleExport void UnregisterFAXImage(void)
251
0
{
252
0
  (void) UnregisterMagickInfo("FAX");
253
0
  (void) UnregisterMagickInfo("G3");
254
0
}
255

256
/*
257
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258
%                                                                             %
259
%                                                                             %
260
%                                                                             %
261
%   W r i t e F A X I m a g e                                                 %
262
%                                                                             %
263
%                                                                             %
264
%                                                                             %
265
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266
%
267
%  Procedure WriteFAXImage writes an image to a file in 1 dimensional Huffman
268
%  encoded format.
269
%
270
%  The format of the WriteFAXImage method is:
271
%
272
%      unsigned int WriteFAXImage(const ImageInfo *image_info,Image *image)
273
%
274
%  A description of each parameter follows.
275
%
276
%    o status: Method WriteFAXImage return MagickPass if the image is written.
277
%      MagickFail is returned is there is a memory shortage or if the image file
278
%      fails to write.
279
%
280
%    o image_info: Specifies a pointer to a ImageInfo structure.
281
%
282
%    o image:  A pointer to an Image structure.
283
%
284
%
285
*/
286
static MagickPassFail WriteFAXImage(const ImageInfo *image_info,Image *image)
287
0
{
288
0
  ImageInfo
289
0
    *clone_info;
290
291
0
  MagickPassFail
292
0
    status;
293
294
0
  unsigned long
295
0
    scene;
296
297
0
  size_t
298
0
    image_list_length;
299
300
  /*
301
    Open output image file.
302
  */
303
0
  assert(image_info != (const ImageInfo *) NULL);
304
0
  assert(image_info->signature == MagickSignature);
305
0
  assert(image != (Image *) NULL);
306
0
  assert(image->signature == MagickSignature);
307
0
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
308
0
  if (status == MagickFail)
309
0
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
310
0
  image_list_length=GetImageListLength(image);
311
0
  clone_info=CloneImageInfo(image_info);
312
0
  (void) strlcpy(clone_info->magick,"FAX",sizeof(clone_info->magick));
313
0
  scene=0;
314
0
  do
315
0
  {
316
    /*
317
      Convert MIFF to monochrome.
318
    */
319
0
    status &= TransformColorspace(image,RGBColorspace);
320
0
    if (status != MagickPass)
321
0
      break;
322
0
    status &= HuffmanEncodeImage(clone_info,image);
323
0
    if (status != MagickPass)
324
0
      break;
325
0
    if (image->next == (Image *) NULL)
326
0
      break;
327
0
    image=SyncNextImageInList(image);
328
0
    status &= MagickMonitorFormatted(scene++,image_list_length,
329
0
                                     &image->exception,SaveImagesText,
330
0
                                     image->filename);
331
0
    if (status != MagickPass)
332
0
      break;
333
0
  } while (clone_info->adjoin);
334
0
  DestroyImageInfo(clone_info);
335
0
  if (image_info->adjoin)
336
0
    while (image->previous != (Image *) NULL)
337
0
      image=image->previous;
338
0
  status &= CloseBlob(image);
339
0
  return(status);
340
0
}