xref: /plan9/sys/src/cmd/gs/src/gdevtfax.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gdevtfax.c,v 1.10 2005/04/08 23:31:24 dan Exp $ */
18 /* TIFF and TIFF/fax devices */
19 #include "gdevprn.h"
20 #include "gdevtifs.h"
21 #include "strimpl.h"
22 #include "scfx.h"
23 #include "gdevfax.h"
24 #include "gdevtfax.h"		/* for gdev_fax_print_page_stripped proto */
25 
26 /* ---------------- TIFF/fax output ---------------- */
27 
28 /* The device descriptors */
29 
30 private dev_proc_get_params(tfax_get_params);
31 private dev_proc_put_params(tfax_put_params);
32 private dev_proc_print_page(tiffcrle_print_page);
33 private dev_proc_print_page(tiffg3_print_page);
34 private dev_proc_print_page(tiffg32d_print_page);
35 private dev_proc_print_page(tiffg4_print_page);
36 
37 struct gx_device_tfax_s {
38     gx_device_common;
39     gx_prn_device_common;
40     gx_fax_device_common;
41     long MaxStripSize;		/* 0 = no limit, other is UNCOMPRESSED limit */
42                                 /* The type and range of FillOrder follows TIFF 6 spec  */
43     int  FillOrder;             /* 1 = lowest column in the high-order bit, 2 = reverse */
44     gdev_tiff_state tiff;	/* for TIFF output only */
45 };
46 typedef struct gx_device_tfax_s gx_device_tfax;
47 
48 /* Define procedures that adjust the paper size. */
49 private const gx_device_procs gdev_tfax_std_procs =
50     prn_params_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
51 		     tfax_get_params, tfax_put_params);
52 
53 #define TFAX_DEVICE(dname, print_page)\
54 {\
55     FAX_DEVICE_BODY(gx_device_tfax, gdev_tfax_std_procs, dname, print_page),\
56     0				/* unlimited strip size byte count */,\
57     1                           /* lowest column in the high-order bit */\
58 }
59 
60 const gx_device_tfax gs_tiffcrle_device =
61     TFAX_DEVICE("tiffcrle", tiffcrle_print_page);
62 
63 const gx_device_tfax gs_tiffg3_device =
64     TFAX_DEVICE("tiffg3", tiffg3_print_page);
65 
66 const gx_device_tfax gs_tiffg32d_device =
67     TFAX_DEVICE("tiffg32d", tiffg32d_print_page);
68 
69 const gx_device_tfax gs_tiffg4_device =
70     TFAX_DEVICE("tiffg4", tiffg4_print_page);
71 
72 /* Get/put the MaxStripSize parameter. */
73 private int
tfax_get_params(gx_device * dev,gs_param_list * plist)74 tfax_get_params(gx_device * dev, gs_param_list * plist)
75 {
76     gx_device_tfax *const tfdev = (gx_device_tfax *)dev;
77     int code = gdev_fax_get_params(dev, plist);
78     int ecode = code;
79 
80     if ((code = param_write_long(plist, "MaxStripSize", &tfdev->MaxStripSize)) < 0)
81         ecode = code;
82     if ((code = param_write_int(plist, "FillOrder", &tfdev->FillOrder)) < 0)
83         ecode = code;
84     return ecode;
85 }
86 private int
tfax_put_params(gx_device * dev,gs_param_list * plist)87 tfax_put_params(gx_device * dev, gs_param_list * plist)
88 {
89     gx_device_tfax *const tfdev = (gx_device_tfax *)dev;
90     int ecode = 0;
91     int code;
92     long mss = tfdev->MaxStripSize;
93     int fill_order = tfdev->FillOrder;
94     const char *param_name;
95 
96     switch (code = param_read_long(plist, (param_name = "MaxStripSize"), &mss)) {
97         case 0:
98 	    /*
99 	     * Strip must be large enough to accommodate a raster line.
100 	     * If the max strip size is too small, we still write a single
101 	     * line per strip rather than giving an error.
102 	     */
103 	    if (mss >= 0)
104 	        break;
105 	    code = gs_error_rangecheck;
106 	default:
107 	    ecode = code;
108 	    param_signal_error(plist, param_name, ecode);
109 	case 1:
110 	    break;
111     }
112 
113     /* Following TIFF spec, FillOrder is integer */
114     switch (code = param_read_int(plist, (param_name = "FillOrder"), &fill_order)) {
115         case 0:
116 	    if (fill_order == 1 || fill_order == 2)
117 	        break;
118 	    code = gs_error_rangecheck;
119 	default:
120 	    ecode = code;
121 	    param_signal_error(plist, param_name, ecode);
122 	case 1:
123 	    break;
124     }
125 
126     if (ecode < 0)
127 	return ecode;
128     code = gdev_fax_put_params(dev, plist);
129     if (code < 0)
130 	return code;
131 
132     tfdev->MaxStripSize = mss;
133     tfdev->FillOrder = fill_order;
134     return code;
135 }
136 
137 /* Send the page to the printer. */
138 /* Print a page with a specified width, which may differ from	*/
139 /* the width stored in the device. The TIFF file may have	*/
140 /* multiple strips of height 'rows'.				*/
141 private int
gdev_stream_print_page_strips(gx_device_printer * pdev,FILE * prn_stream,const stream_template * temp,stream_state * ss,int width,long rows_per_strip)142 gdev_stream_print_page_strips(gx_device_printer * pdev, FILE * prn_stream,
143 			      const stream_template * temp, stream_state * ss,
144 			      int width, long rows_per_strip)
145 {
146     gx_device_tfax *const tfdev = (gx_device_tfax *)pdev;
147     int row, row_next;
148     int code = 0;
149 
150     for (row = 0; row < pdev->height; row = row_next) {
151 	row_next = min(row + rows_per_strip, pdev->height);
152 	code = gdev_fax_print_strip(pdev, prn_stream, temp, ss, width,
153 				    row, row_next);
154 	if (code < 0)
155 	    break;
156 	gdev_tiff_end_strip(&tfdev->tiff, prn_stream);
157 
158     }
159     return code;
160 }
161 
162 /* Print a page with a specified width, which may differ from the */
163 /* width stored in the device. */
164 private int
gdev_stream_print_page_width(gx_device_printer * pdev,FILE * prn_stream,const stream_template * temp,stream_state * ss,int width)165 gdev_stream_print_page_width(gx_device_printer * pdev, FILE * prn_stream,
166 			     const stream_template * temp, stream_state * ss,
167 			     int width)
168 {
169     return gdev_stream_print_page_strips(pdev, prn_stream, temp, ss,
170 					 width, pdev->height);
171 }
172 
173 private int
gdev_stream_print_page(gx_device_printer * pdev,FILE * prn_stream,const stream_template * temp,stream_state * ss)174 gdev_stream_print_page(gx_device_printer * pdev, FILE * prn_stream,
175 		       const stream_template * temp, stream_state * ss)
176 {
177     return gdev_stream_print_page_width(pdev, prn_stream, temp, ss,
178 					pdev->width);
179 }
180 
181 /* Print a fax page.  Other fax drivers use this. */
182 int
gdev_fax_print_page_stripped(gx_device_printer * pdev,FILE * prn_stream,stream_CFE_state * ss,long rows)183 gdev_fax_print_page_stripped(gx_device_printer * pdev, FILE * prn_stream,
184 		    stream_CFE_state * ss, long rows)
185 {
186     return gdev_stream_print_page_strips(pdev, prn_stream, &s_CFE_template,
187 					 (stream_state *)ss, ss->Columns,
188 					 rows);
189 }
190 
191 /* ---------------- Other TIFF output ---------------- */
192 
193 #include "slzwx.h"
194 #include "srlx.h"
195 
196 /* Device descriptors for TIFF formats other than fax. */
197 private dev_proc_print_page(tifflzw_print_page);
198 private dev_proc_print_page(tiffpack_print_page);
199 
200 const gx_device_tfax gs_tifflzw_device = {
201     prn_device_std_body(gx_device_tfax, prn_std_procs, "tifflzw",
202 			DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
203 			X_DPI, Y_DPI,
204 			0, 0, 0, 0,	/* margins */
205 			1, tifflzw_print_page)
206 };
207 
208 const gx_device_tfax gs_tiffpack_device = {
209     prn_device_std_body(gx_device_tfax, prn_std_procs, "tiffpack",
210 			DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
211 			X_DPI, Y_DPI,
212 			0, 0, 0, 0,	/* margins */
213 			1, tiffpack_print_page)
214 };
215 
216 /* Define the TIFF directory we use, beyond the standard entries. */
217 /* NB: this array is sorted by tag number (assumed below) */
218 typedef struct tiff_mono_directory_s {
219     TIFF_dir_entry BitsPerSample;
220     TIFF_dir_entry Compression;
221     TIFF_dir_entry Photometric;
222     TIFF_dir_entry FillOrder;
223     TIFF_dir_entry SamplesPerPixel;
224     TIFF_dir_entry T4T6Options;
225     /* Don't use CleanFaxData. */
226     /*  TIFF_dir_entry  CleanFaxData;   */
227 } tiff_mono_directory;
228 private const tiff_mono_directory dir_mono_template =
229 {
230     {TIFFTAG_BitsPerSample, TIFF_SHORT, 1, 1},
231     {TIFFTAG_Compression, TIFF_SHORT, 1, Compression_CCITT_T4},
232     {TIFFTAG_Photometric, TIFF_SHORT, 1, Photometric_min_is_white},
233     {TIFFTAG_FillOrder, TIFF_SHORT, 1, FillOrder_MSB2LSB},
234     {TIFFTAG_SamplesPerPixel, TIFF_SHORT, 1, 1},
235     {TIFFTAG_T4Options, TIFF_LONG, 1, 0},
236 	/* { TIFFTAG_CleanFaxData,      TIFF_SHORT, 1, CleanFaxData_clean }, */
237 };
238 
239 /* Forward references */
240 private int tfax_begin_page(gx_device_tfax *, FILE *,
241 			    const tiff_mono_directory *, int);
242 
243 /* Print a fax-encoded page. */
244 private int
tifff_print_page(gx_device_printer * dev,FILE * prn_stream,stream_CFE_state * pstate,tiff_mono_directory * pdir)245 tifff_print_page(gx_device_printer * dev, FILE * prn_stream,
246 		 stream_CFE_state * pstate, tiff_mono_directory * pdir)
247 {
248     gx_device_tfax *const tfdev = (gx_device_tfax *)dev;
249     int code;
250 
251     pdir->FillOrder.value = tfdev->FillOrder;
252     tfax_begin_page(tfdev, prn_stream, pdir, pstate->Columns);
253     pstate->FirstBitLowOrder = tfdev->FillOrder == 2;
254     code = gdev_fax_print_page_stripped(dev, prn_stream, pstate, tfdev->tiff.rows);
255     gdev_tiff_end_page(&tfdev->tiff, prn_stream);
256     return code;
257 }
258 private int
tiffcrle_print_page(gx_device_printer * dev,FILE * prn_stream)259 tiffcrle_print_page(gx_device_printer * dev, FILE * prn_stream)
260 {
261     stream_CFE_state state;
262     tiff_mono_directory dir;
263 
264     gdev_fax_init_fax_state(&state, (gx_device_fax *)dev);
265     state.EndOfLine = false;
266     state.EncodedByteAlign = true;
267     dir = dir_mono_template;
268     dir.Compression.value = Compression_CCITT_RLE;
269     dir.T4T6Options.tag = TIFFTAG_T4Options;
270     dir.T4T6Options.value = T4Options_fill_bits;
271     return tifff_print_page(dev, prn_stream, &state, &dir);
272 }
273 private int
tiffg3_print_page(gx_device_printer * dev,FILE * prn_stream)274 tiffg3_print_page(gx_device_printer * dev, FILE * prn_stream)
275 {
276     stream_CFE_state state;
277     tiff_mono_directory dir;
278 
279     gdev_fax_init_fax_state(&state, (gx_device_fax *)dev);
280     state.EndOfLine = true;
281     state.EncodedByteAlign = true;
282     dir = dir_mono_template;
283     dir.Compression.value = Compression_CCITT_T4;
284     dir.T4T6Options.tag = TIFFTAG_T4Options;
285     dir.T4T6Options.value = T4Options_fill_bits;
286     return tifff_print_page(dev, prn_stream, &state, &dir);
287 }
288 private int
tiffg32d_print_page(gx_device_printer * dev,FILE * prn_stream)289 tiffg32d_print_page(gx_device_printer * dev, FILE * prn_stream)
290 {
291     stream_CFE_state state;
292     tiff_mono_directory dir;
293 
294     gdev_fax_init_state(&state, (gx_device_fax *)dev);
295     state.K = (dev->y_pixels_per_inch < 100 ? 2 : 4);
296     state.EndOfLine = true;
297     state.EncodedByteAlign = true;
298     dir = dir_mono_template;
299     dir.Compression.value = Compression_CCITT_T4;
300     dir.T4T6Options.tag = TIFFTAG_T4Options;
301     dir.T4T6Options.value = T4Options_2D_encoding | T4Options_fill_bits;
302     return tifff_print_page(dev, prn_stream, &state, &dir);
303 }
304 private int
tiffg4_print_page(gx_device_printer * dev,FILE * prn_stream)305 tiffg4_print_page(gx_device_printer * dev, FILE * prn_stream)
306 {
307     stream_CFE_state state;
308     tiff_mono_directory dir;
309 
310     gdev_fax_init_state(&state, (gx_device_fax *)dev);
311     state.K = -1;
312     /*state.EncodedByteAlign = false; *//* no fill_bits option for T6 */
313     dir = dir_mono_template;
314     dir.Compression.value = Compression_CCITT_T6;
315     dir.T4T6Options.tag = TIFFTAG_T6Options;
316     return tifff_print_page(dev, prn_stream, &state, &dir);
317 }
318 
319 /* Print an LZW page. */
320 private int
tifflzw_print_page(gx_device_printer * dev,FILE * prn_stream)321 tifflzw_print_page(gx_device_printer * dev, FILE * prn_stream)
322 {
323     gx_device_tfax *const tfdev = (gx_device_tfax *)dev;
324     tiff_mono_directory dir;
325     stream_LZW_state state;
326     int code;
327 
328     dir = dir_mono_template;
329     dir.Compression.value = Compression_LZW;
330     dir.FillOrder.value = FillOrder_MSB2LSB;
331     tfax_begin_page(tfdev, prn_stream, &dir, dev->width);
332     state.InitialCodeLength = 8;
333     state.FirstBitLowOrder = false;
334     state.BlockData = false;
335     state.EarlyChange = 1;	/* PLRM is sort of confusing, but this is correct */
336     code = gdev_stream_print_page(dev, prn_stream, &s_LZWE_template,
337 				  (stream_state *) & state);
338     gdev_tiff_end_page(&tfdev->tiff, prn_stream);
339     return code;
340 }
341 
342 /* Print a PackBits page. */
343 private int
tiffpack_print_page(gx_device_printer * dev,FILE * prn_stream)344 tiffpack_print_page(gx_device_printer * dev, FILE * prn_stream)
345 {
346     gx_device_tfax *const tfdev = (gx_device_tfax *)dev;
347     tiff_mono_directory dir;
348     stream_RLE_state state;
349     int code;
350 
351     dir = dir_mono_template;
352     dir.Compression.value = Compression_PackBits;
353     dir.FillOrder.value = FillOrder_MSB2LSB;
354     tfax_begin_page(tfdev, prn_stream, &dir, dev->width);
355     state.EndOfData = false;
356     state.record_size = gdev_mem_bytes_per_scan_line((gx_device *) dev);
357     code = gdev_stream_print_page(dev, prn_stream, &s_RLE_template,
358 				  (stream_state *) & state);
359     gdev_tiff_end_page(&tfdev->tiff, prn_stream);
360     return code;
361 }
362 
363 /* Begin a TIFF fax page. */
364 private int
tfax_begin_page(gx_device_tfax * tfdev,FILE * fp,const tiff_mono_directory * pdir,int width)365 tfax_begin_page(gx_device_tfax * tfdev, FILE * fp,
366 		const tiff_mono_directory * pdir, int width)
367 {
368     /* Patch the width to reflect fax page width adjustment. */
369     int save_width = tfdev->width;
370     int code;
371 
372     tfdev->width = width;
373     code = gdev_tiff_begin_page((gx_device_printer *) tfdev,
374 				&tfdev->tiff, fp,
375 				(const TIFF_dir_entry *)pdir,
376 				sizeof(*pdir) / sizeof(TIFF_dir_entry),
377 				NULL, 0, tfdev->MaxStripSize);
378     tfdev->width = save_width;
379     return code;
380 }
381