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