Coverage Report

Created: 2026-04-01 07:49

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