/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 | } |