1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied, modified
8 or distributed except as expressly authorized under the terms of that
9 license. Refer to licensing information at http://www.artifex.com/
10 or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11 San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
12 */
13
14 /* $Id: gdevtsep.c 10710 2010-02-04 17:47:57Z larsu $ */
15 /* tiffgray device: 8-bit Gray uncompressed TIFF device */
16 /* tiff32nc device: 32-bit CMYK uncompressed TIFF device */
17 /* tiffsep device: Generate individual TIFF gray files for each separation */
18 /* as well as a 'composite' 32-bit CMYK for the page. */
19 /* tiffsep1 device: Generate individual TIFF 1-bit files for each separation. */
20
21 #include "gdevtifs.h"
22 #include "gdevprn.h"
23 #include "gdevdevn.h"
24 #include "gsequivc.h"
25 #include "gxdht.h"
26 #include "gxiodev.h"
27 #include "stdio_.h"
28 #include "ctype_.h"
29
30 /*
31 * Some of the code in this module is based upon the gdevtfnx.c module.
32 * gdevtfnx.c has the following message:
33 * Thanks to Alan Barclay <alan@escribe.co.uk> for donating the original
34 * version of this code to Ghostscript.
35 */
36
37 /* ------ The device descriptors ------ */
38
39 /* Default X and Y resolution */
40 #define X_DPI 72
41 #define Y_DPI 72
42
43 /* ------ The tiffgray device ------ */
44
45 static dev_proc_print_page(tiffgray_print_page);
46
47 static const gx_device_procs tiffgray_procs =
48 prn_color_params_procs(tiff_open, tiff_output_page, tiff_close,
49 gx_default_gray_map_rgb_color, gx_default_gray_map_color_rgb,
50 tiff_get_params, tiff_put_params);
51
52 const gx_device_tiff gs_tiffgray_device = {
53 prn_device_body(gx_device_tiff, tiffgray_procs, "tiffgray",
54 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
55 X_DPI, Y_DPI,
56 0, 0, 0, 0, /* Margins */
57 1, 8, 255, 0, 256, 0, tiffgray_print_page),
58 arch_is_big_endian /* default to native endian (i.e. use big endian iff the platform is so*/,
59 COMPRESSION_NONE,
60 TIFF_DEFAULT_STRIP_SIZE
61 };
62
63
64 /* ------ Private functions ------ */
65
66 static void
tiff_set_gray_fields(gx_device_printer * pdev,TIFF * tif,unsigned short bits_per_sample,int compression,long max_strip_size)67 tiff_set_gray_fields(gx_device_printer *pdev, TIFF *tif,
68 unsigned short bits_per_sample,
69 int compression,
70 long max_strip_size)
71 {
72 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
73 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
74 TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
75 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
76
77 tiff_set_compression(pdev, tif, compression, max_strip_size);
78 }
79
80 static int
tiffgray_print_page(gx_device_printer * pdev,FILE * file)81 tiffgray_print_page(gx_device_printer * pdev, FILE * file)
82 {
83 gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
84 int code;
85
86 if (pdev->height > (max_long - ftell(file))/(pdev->width)) /* note width is never 0 in print_page */
87 return_error(gs_error_rangecheck); /* this will overflow max_long */
88
89 code = gdev_tiff_begin_page(tfdev, file);
90 if (code < 0)
91 return code;
92
93 tiff_set_gray_fields(pdev, tfdev->tif, 8, tfdev->Compression, tfdev->MaxStripSize);
94
95 return tiff_print_page(pdev, tfdev->tif);
96 }
97
98 /* ------ The cmyk devices ------ */
99
100 static dev_proc_print_page(tiffcmyk_print_page);
101
102 #define cmyk_procs(p_map_color_rgb, p_map_cmyk_color)\
103 tiff_open, NULL, NULL, tiff_output_page, tiff_close,\
104 NULL, p_map_color_rgb, NULL, NULL, NULL, NULL, NULL, NULL,\
105 tiff_get_params, tiff_put_params,\
106 p_map_cmyk_color, NULL, NULL, NULL, gx_page_device_get_page_device
107
108 /* 8-bit-per-plane separated CMYK color. */
109
110 static const gx_device_procs tiffcmyk_procs = {
111 cmyk_procs(cmyk_8bit_map_color_cmyk, cmyk_8bit_map_cmyk_color)
112 };
113
114 const gx_device_tiff gs_tiff32nc_device = {
115 prn_device_body(gx_device_tiff, tiffcmyk_procs, "tiff32nc",
116 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
117 X_DPI, Y_DPI,
118 0, 0, 0, 0, /* Margins */
119 4, 32, 255, 255, 256, 256, tiffcmyk_print_page),
120 arch_is_big_endian /* default to native endian (i.e. use big endian iff the platform is so*/,
121 COMPRESSION_NONE,
122 TIFF_DEFAULT_STRIP_SIZE
123 };
124
125 /* 16-bit-per-plane separated CMYK color. */
126
127 static const gx_device_procs tiff64nc_procs = {
128 cmyk_procs(cmyk_16bit_map_color_cmyk, cmyk_16bit_map_cmyk_color)
129 };
130
131 const gx_device_tiff gs_tiff64nc_device = {
132 prn_device_body(gx_device_tiff, tiff64nc_procs, "tiff64nc",
133 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
134 X_DPI, Y_DPI,
135 0, 0, 0, 0, /* Margins */
136 4, 64, 255, 255, 256, 256, tiffcmyk_print_page),
137 arch_is_big_endian /* default to native endian (i.e. use big endian iff the platform is so*/,
138 COMPRESSION_NONE,
139 TIFF_DEFAULT_STRIP_SIZE
140 };
141
142 /* ------ Private functions ------ */
143
144 static void
tiff_set_cmyk_fields(gx_device_printer * pdev,TIFF * tif,short bits_per_sample,uint16 compression,long max_strip_size)145 tiff_set_cmyk_fields(gx_device_printer *pdev, TIFF *tif,
146 short bits_per_sample,
147 uint16 compression,
148 long max_strip_size)
149 {
150 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
151 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED);
152 TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
153 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 4);
154
155 tiff_set_compression(pdev, tif, compression, max_strip_size);
156 }
157
158 static int
tiffcmyk_print_page(gx_device_printer * pdev,FILE * file)159 tiffcmyk_print_page(gx_device_printer * pdev, FILE * file)
160 {
161 gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
162 int code;
163
164 if (pdev->height > (max_long - ftell(file))/(pdev->width)) /* note width is never 0 in print_page */
165 return_error(gs_error_rangecheck); /* this will overflow max_long */
166
167 code = gdev_tiff_begin_page(tfdev, file);
168 if (code < 0)
169 return code;
170
171 tiff_set_cmyk_fields(pdev,
172 tfdev->tif,
173 pdev->color_info.depth / pdev->color_info.num_components,
174 tfdev->Compression,
175 tfdev->MaxStripSize);
176
177 return tiff_print_page(pdev, tfdev->tif);
178 }
179
180 /* ---------- The tiffsep device ------------ */
181
182 #define NUM_CMYK_COMPONENTS 4
183 #define MAX_FILE_NAME_SIZE gp_file_name_sizeof
184 #define MAX_COLOR_VALUE 255 /* We are using 8 bits per colorant */
185
186 /* The device descriptor */
187 static dev_proc_open_device(tiffsep_prn_open);
188 static dev_proc_close_device(tiffsep_prn_close);
189 static dev_proc_get_params(tiffsep_get_params);
190 static dev_proc_put_params(tiffsep_put_params);
191 static dev_proc_print_page(tiffsep_print_page);
192 static dev_proc_get_color_mapping_procs(tiffsep_get_color_mapping_procs);
193 static dev_proc_get_color_comp_index(tiffsep_get_color_comp_index);
194 static dev_proc_encode_color(tiffsep_encode_color);
195 static dev_proc_decode_color(tiffsep_decode_color);
196 static dev_proc_encode_color(tiffsep_encode_compressed_color);
197 static dev_proc_decode_color(tiffsep_decode_compressed_color);
198 static dev_proc_update_spot_equivalent_colors(tiffsep_update_spot_equivalent_colors);
199 static dev_proc_ret_devn_params(tiffsep_ret_devn_params);
200 static dev_proc_open_device(tiffsep1_prn_open);
201 static dev_proc_close_device(tiffsep1_prn_close);
202 static dev_proc_put_params(tiffsep1_put_params);
203 static dev_proc_print_page(tiffsep1_print_page);
204 static dev_proc_fill_path(sep1_fill_path);
205
206 #define tiffsep_devices_common\
207 gx_device_common;\
208 gx_prn_device_common;\
209 /* tiff state for separation files */\
210 FILE *sep_file[GX_DEVICE_COLOR_MAX_COMPONENTS];\
211 TIFF *tiff[GX_DEVICE_COLOR_MAX_COMPONENTS]; \
212 bool BigEndian; /* true = big endian; false = little endian */\
213 uint16 Compression; /* for the separation files, same values as
214 TIFFTAG_COMPRESSION */\
215 long MaxStripSize;\
216 gs_devn_params devn_params; /* DeviceN generated parameters */\
217 equivalent_cmyk_color_params equiv_cmyk_colors
218
219 /*
220 * A structure definition for a DeviceN type device
221 */
222 typedef struct tiffsep_device_s {
223 tiffsep_devices_common;
224 TIFF *tiff_comp; /* tiff file for comp file */
225 } tiffsep_device;
226
227 /* threshold array structure */
228 typedef struct threshold_array_s {
229 int dheight, dwidth;
230 byte *dstart;
231 } threshold_array_t;
232
233 typedef struct tiffsep1_device_s {
234 tiffsep_devices_common;
235 threshold_array_t thresholds[GX_DEVICE_COLOR_MAX_COMPONENTS + 1]; /* one extra for Default */
236 dev_t_proc_fill_path((*fill_path), gx_device); /* we forward to here */
237 } tiffsep1_device;
238
239 /* GC procedures */
240 static
ENUM_PTRS_WITH(tiffsep_device_enum_ptrs,tiffsep_device * pdev)241 ENUM_PTRS_WITH(tiffsep_device_enum_ptrs, tiffsep_device *pdev)
242 {
243 if (index == 0)
244 ENUM_RETURN(pdev->devn_params.compressed_color_list);
245 index--;
246 if (index < pdev->devn_params.separations.num_separations)
247 ENUM_RETURN(pdev->devn_params.separations.names[index].data);
248 ENUM_PREFIX(st_device_printer,
249 pdev->devn_params.separations.num_separations);
250 return 0;
251 }
252 ENUM_PTRS_END
253
RELOC_PTRS_WITH(tiffsep_device_reloc_ptrs,tiffsep_device * pdev)254 static RELOC_PTRS_WITH(tiffsep_device_reloc_ptrs, tiffsep_device *pdev)
255 {
256 RELOC_PREFIX(st_device_printer);
257 {
258 int i;
259
260 for (i = 0; i < pdev->devn_params.separations.num_separations; ++i) {
261 RELOC_PTR(tiffsep_device, devn_params.separations.names[i].data);
262 }
263 }
264 RELOC_PTR(tiffsep_device, devn_params.compressed_color_list);
265 }
266 RELOC_PTRS_END
267
268 /* Even though tiffsep_device_finalize is the same as gx_device_finalize, */
269 /* we need to implement it separately because st_composite_final */
270 /* declares all 3 procedures as private. */
271 static void
tiffsep_device_finalize(void * vpdev)272 tiffsep_device_finalize(void *vpdev)
273 {
274 gx_device_finalize(vpdev);
275 }
276
277 gs_private_st_composite_final(st_tiffsep_device, tiffsep_device,
278 "tiffsep_device", tiffsep_device_enum_ptrs, tiffsep_device_reloc_ptrs,
279 tiffsep_device_finalize);
280
281 /*
282 * Macro definition for tiffsep device procedures
283 */
284 #define sep_device_procs(open, close, encode_color, decode_color, update_spot_colors,put_params, fill_path) \
285 { open,\
286 gx_default_get_initial_matrix,\
287 NULL, /* sync_output */\
288 gdev_prn_output_page, /* output_page */\
289 close, /* close */\
290 NULL, /* map_rgb_color - not used */\
291 tiffsep_decode_color, /* map_color_rgb */\
292 NULL, /* fill_rectangle */\
293 NULL, /* tile_rectangle */\
294 NULL, /* copy_mono */\
295 NULL, /* copy_color */\
296 NULL, /* draw_line */\
297 NULL, /* get_bits */\
298 tiffsep_get_params, /* get_params */\
299 put_params, /* put_params */\
300 NULL, /* map_cmyk_color - not used */\
301 NULL, /* get_xfont_procs */\
302 NULL, /* get_xfont_device */\
303 NULL, /* map_rgb_alpha_color */\
304 gx_page_device_get_page_device, /* get_page_device */\
305 NULL, /* get_alpha_bits */\
306 NULL, /* copy_alpha */\
307 NULL, /* get_band */\
308 NULL, /* copy_rop */\
309 fill_path, /* fill_path */\
310 NULL, /* stroke_path */\
311 NULL, /* fill_mask */\
312 NULL, /* fill_trapezoid */\
313 NULL, /* fill_parallelogram */\
314 NULL, /* fill_triangle */\
315 NULL, /* draw_thin_line */\
316 NULL, /* begin_image */\
317 NULL, /* image_data */\
318 NULL, /* end_image */\
319 NULL, /* strip_tile_rectangle */\
320 NULL, /* strip_copy_rop */\
321 NULL, /* get_clipping_box */\
322 NULL, /* begin_typed_image */\
323 NULL, /* get_bits_rectangle */\
324 NULL, /* map_color_rgb_alpha */\
325 NULL, /* create_compositor */\
326 NULL, /* get_hardware_params */\
327 NULL, /* text_begin */\
328 NULL, /* finish_copydevice */\
329 NULL, /* begin_transparency_group */\
330 NULL, /* end_transparency_group */\
331 NULL, /* begin_transparency_mask */\
332 NULL, /* end_transparency_mask */\
333 NULL, /* discard_transparency_layer */\
334 tiffsep_get_color_mapping_procs,/* get_color_mapping_procs */\
335 tiffsep_get_color_comp_index, /* get_color_comp_index */\
336 encode_color, /* encode_color */\
337 decode_color, /* decode_color */\
338 NULL, /* pattern_manage */\
339 NULL, /* fill_rectangle_hl_color */\
340 NULL, /* include_color_space */\
341 NULL, /* fill_linear_color_scanline */\
342 NULL, /* fill_linear_color_trapezoid */\
343 NULL, /* fill_linear_color_triangle */\
344 update_spot_colors, /* update_spot_equivalent_colors */\
345 tiffsep_ret_devn_params /* ret_devn_params */\
346 }
347
348
349 #define tiffsep_devices_body(dtype, procs, dname, ncomp, pol, depth, mg, mc, sl, cn, print_page, compr)\
350 std_device_full_body_type_extended(dtype, &procs, dname,\
351 &st_tiffsep_device,\
352 (int)((long)(DEFAULT_WIDTH_10THS) * (X_DPI) / 10),\
353 (int)((long)(DEFAULT_HEIGHT_10THS) * (Y_DPI) / 10),\
354 X_DPI, Y_DPI,\
355 ncomp, /* MaxComponents */\
356 ncomp, /* NumComp */\
357 pol, /* Polarity */\
358 depth, 0, /* Depth, GrayIndex */\
359 mg, mc, /* MaxGray, MaxColor */\
360 mg + 1, mc + 1, /* DitherGray, DitherColor */\
361 sl, /* Linear & Separable? */\
362 cn, /* Process color model name */\
363 0, 0, /* offsets */\
364 0, 0, 0, 0 /* margins */\
365 ),\
366 prn_device_body_rest_(print_page),\
367 { 0 }, /* tiff state for separation files */\
368 { 0 }, /* separation files */\
369 arch_is_big_endian /* true = big endian; false = little endian */,\
370 compr /* COMPRESSION_* */,\
371 TIFF_DEFAULT_STRIP_SIZE /* MaxStripSize */
372
373 /*
374 * Select the default number of components based upon the number of bits
375 * that we have in a gx_color_index. If we have 64 bits then we can compress
376 * the colorant data. This allows us to handle more colorants. However the
377 * compressed encoding is not separable. If we do not have 64 bits then we
378 * use a simple non-compressable encoding.
379 */
380 #if USE_COMPRESSED_ENCODING
381 # define NC GX_DEVICE_COLOR_MAX_COMPONENTS
382 # define SL GX_CINFO_SEP_LIN_NONE
383 # define ENCODE_COLOR tiffsep_encode_compressed_color
384 # define DECODE_COLOR tiffsep_decode_compressed_color
385 #else
386 # define NC ARCH_SIZEOF_GX_COLOR_INDEX
387 # define SL GX_CINFO_SEP_LIN
388 # define ENCODE_COLOR tiffsep_encode_color
389 # define DECODE_COLOR tiffsep_decode_color
390 #endif
391 #define GCIB (ARCH_SIZEOF_GX_COLOR_INDEX * 8)
392
393 /*
394 * TIFF devices with CMYK process color model and spot color support.
395 */
396 static const gx_device_procs spot_cmyk_procs =
397 sep_device_procs(tiffsep_prn_open, tiffsep_prn_close, ENCODE_COLOR, DECODE_COLOR,
398 tiffsep_update_spot_equivalent_colors, tiffsep_put_params, NULL);
399
400 static const gx_device_procs spot1_cmyk_procs =
401 sep_device_procs(tiffsep1_prn_open, tiffsep1_prn_close, ENCODE_COLOR, DECODE_COLOR,
402 tiffsep_update_spot_equivalent_colors, tiffsep1_put_params, sep1_fill_path);
403
404 const tiffsep_device gs_tiffsep_device =
405 {
406 tiffsep_devices_body(tiffsep_device, spot_cmyk_procs, "tiffsep", NC, GX_CINFO_POLARITY_SUBTRACTIVE, GCIB, MAX_COLOR_VALUE, MAX_COLOR_VALUE, SL, "DeviceCMYK", tiffsep_print_page, COMPRESSION_LZW),
407 /* devn_params specific parameters */
408 { 8, /* Not used - Bits per color */
409 DeviceCMYKComponents, /* Names of color model colorants */
410 4, /* Number colorants for CMYK */
411 0, /* MaxSeparations has not been specified */
412 -1, /* PageSpotColors has not been specified */
413 {0}, /* SeparationNames */
414 0, /* SeparationOrder names */
415 {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
416 },
417 { true }, /* equivalent CMYK colors for spot colors */
418 };
419
420 const tiffsep1_device gs_tiffsep1_device =
421 {
422 tiffsep_devices_body(tiffsep1_device, spot1_cmyk_procs, "tiffsep1", NC, GX_CINFO_POLARITY_SUBTRACTIVE, GCIB, MAX_COLOR_VALUE, MAX_COLOR_VALUE, SL, "DeviceCMYK", tiffsep1_print_page, COMPRESSION_CCITTFAX4),
423 /* devn_params specific parameters */
424 { 1, /* Not used - Bits per color */
425 DeviceCMYKComponents, /* Names of color model colorants */
426 4, /* Number colorants for CMYK */
427 0, /* MaxSeparations has not been specified */
428 -1, /* PageSpotColors has not been specified */
429 {0}, /* SeparationNames */
430 0, /* SeparationOrder names */
431 {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
432 },
433 { true }, /* equivalent CMYK colors for spot colors */
434 { {0} }, /* threshold arrays */
435 0, /* fill_path */
436 };
437
438 #undef NC
439 #undef SL
440 #undef ENCODE_COLOR
441 #undef DECODE_COLOR
442
443 static const uint32_t bit_order[32]={
444 #if arch_is_big_endian
445 0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000, 0x01000000,
446 0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000,
447 0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100,
448 0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001
449 #else
450 0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001,
451 0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100,
452 0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000,
453 0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000, 0x01000000
454 #endif
455 };
456
457 /*
458 * The following procedures are used to map the standard color spaces into
459 * the color components for the tiffsep device.
460 */
461 static void
tiffsep_gray_cs_to_cm(gx_device * dev,frac gray,frac out[])462 tiffsep_gray_cs_to_cm(gx_device * dev, frac gray, frac out[])
463 {
464 int * map = ((tiffsep_device *) dev)->devn_params.separation_order_map;
465
466 gray_cs_to_devn_cm(dev, map, gray, out);
467 }
468
469 static void
tiffsep_rgb_cs_to_cm(gx_device * dev,const gs_imager_state * pis,frac r,frac g,frac b,frac out[])470 tiffsep_rgb_cs_to_cm(gx_device * dev, const gs_imager_state *pis,
471 frac r, frac g, frac b, frac out[])
472 {
473 int * map = ((tiffsep_device *) dev)->devn_params.separation_order_map;
474
475 rgb_cs_to_devn_cm(dev, map, pis, r, g, b, out);
476 }
477
478 static void
tiffsep_cmyk_cs_to_cm(gx_device * dev,frac c,frac m,frac y,frac k,frac out[])479 tiffsep_cmyk_cs_to_cm(gx_device * dev,
480 frac c, frac m, frac y, frac k, frac out[])
481 {
482 int * map = ((tiffsep_device *) dev)->devn_params.separation_order_map;
483
484 cmyk_cs_to_devn_cm(dev, map, c, m, y, k, out);
485 }
486
487 static const gx_cm_color_map_procs tiffsep_cm_procs = {
488 tiffsep_gray_cs_to_cm,
489 tiffsep_rgb_cs_to_cm,
490 tiffsep_cmyk_cs_to_cm
491 };
492
493 /*
494 * These are the handlers for returning the list of color space
495 * to color model conversion routines.
496 */
497 static const gx_cm_color_map_procs *
tiffsep_get_color_mapping_procs(const gx_device * dev)498 tiffsep_get_color_mapping_procs(const gx_device * dev)
499 {
500 return &tiffsep_cm_procs;
501 }
502
503 /*
504 * Encode a list of colorant values into a gx_color_index_value.
505 * With 64 bit gx_color_index values, we compress the colorant values. This
506 * allows us to handle more than 8 colorants.
507 */
508 static gx_color_index
tiffsep_encode_compressed_color(gx_device * dev,const gx_color_value colors[])509 tiffsep_encode_compressed_color(gx_device *dev, const gx_color_value colors[])
510 {
511 return devn_encode_compressed_color(dev, colors, &(((tiffsep_device *)dev)->devn_params));
512 }
513
514 /*
515 * Decode a gx_color_index value back to a list of colorant values.
516 * With 64 bit gx_color_index values, we compress the colorant values. This
517 * allows us to handle more than 8 colorants.
518 */
519 static int
tiffsep_decode_compressed_color(gx_device * dev,gx_color_index color,gx_color_value * out)520 tiffsep_decode_compressed_color(gx_device * dev, gx_color_index color, gx_color_value * out)
521 {
522 return devn_decode_compressed_color(dev, color, out,
523 &(((tiffsep_device *)dev)->devn_params));
524 }
525
526 /*
527 * Encode a list of colorant values into a gx_color_index_value.
528 * With 32 bit gx_color_index values, we simply pack values.
529 */
530 static gx_color_index
tiffsep_encode_color(gx_device * dev,const gx_color_value colors[])531 tiffsep_encode_color(gx_device *dev, const gx_color_value colors[])
532 {
533 int bpc = ((tiffsep_device *)dev)->devn_params.bitspercomponent;
534 int drop = sizeof(gx_color_value) * 8 - bpc;
535 gx_color_index color = 0;
536 int i = 0;
537 int ncomp = dev->color_info.num_components;
538
539 for (; i < ncomp; i++) {
540 color <<= bpc;
541 color |= (colors[i] >> drop);
542 }
543 return (color == gx_no_color_index ? color ^ 1 : color);
544 }
545
546 /*
547 * Decode a gx_color_index value back to a list of colorant values.
548 * With 32 bit gx_color_index values, we simply pack values.
549 */
550 static int
tiffsep_decode_color(gx_device * dev,gx_color_index color,gx_color_value * out)551 tiffsep_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out)
552 {
553 int bpc = ((tiffsep_device *)dev)->devn_params.bitspercomponent;
554 int drop = sizeof(gx_color_value) * 8 - bpc;
555 int mask = (1 << bpc) - 1;
556 int i = 0;
557 int ncomp = dev->color_info.num_components;
558
559 for (; i < ncomp; i++) {
560 out[ncomp - i - 1] = (gx_color_value) ((color & mask) << drop);
561 color >>= bpc;
562 }
563 return 0;
564 }
565
566 /*
567 * Device proc for updating the equivalent CMYK color for spot colors.
568 */
569 static int
tiffsep_update_spot_equivalent_colors(gx_device * dev,const gs_state * pgs)570 tiffsep_update_spot_equivalent_colors(gx_device * dev, const gs_state * pgs)
571 {
572 tiffsep_device * pdev = (tiffsep_device *)dev;
573
574 update_spot_equivalent_cmyk_colors(dev, pgs,
575 &pdev->devn_params, &pdev->equiv_cmyk_colors);
576 return 0;
577 }
578
579 /*
580 * Device proc for returning a pointer to DeviceN parameter structure
581 */
582 static gs_devn_params *
tiffsep_ret_devn_params(gx_device * dev)583 tiffsep_ret_devn_params(gx_device * dev)
584 {
585 tiffsep_device * pdev = (tiffsep_device *)dev;
586
587 return &pdev->devn_params;
588 }
589
590 /* Get parameters. We provide a default CRD. */
591 static int
tiffsep_get_params(gx_device * pdev,gs_param_list * plist)592 tiffsep_get_params(gx_device * pdev, gs_param_list * plist)
593 {
594 tiffsep_device * const pdevn = (tiffsep_device *) pdev;
595 int code = gdev_prn_get_params(pdev, plist);
596 int ecode = code;
597 gs_param_string comprstr;
598
599 if (code < 0)
600 return code;
601
602 code = devn_get_params(pdev, plist,
603 &(((tiffsep_device *)pdev)->devn_params),
604 &(((tiffsep_device *)pdev)->equiv_cmyk_colors));
605 if (code < 0)
606 return code;
607
608 if ((code = param_write_bool(plist, "BigEndian", &pdevn->BigEndian)) < 0)
609 ecode = code;
610 if ((code = tiff_compression_param_string(&comprstr, pdevn->Compression)) < 0 ||
611 (code = param_write_string(plist, "Compression", &comprstr)) < 0)
612 ecode = code;
613 if ((code = param_write_long(plist, "MaxStripSize", &pdevn->MaxStripSize)) < 0)
614 ecode = code;
615
616 return ecode;
617 }
618
619 /* Set parameters. We allow setting the number of bits per component. */
620 static int
tiffsep_put_params(gx_device * pdev,gs_param_list * plist)621 tiffsep_put_params(gx_device * pdev, gs_param_list * plist)
622 {
623 tiffsep_device * const pdevn = (tiffsep_device *) pdev;
624 int code;
625 const char *param_name;
626 gs_param_string comprstr;
627
628 /* Read BigEndian option as bool */
629 switch (code = param_read_bool(plist, (param_name = "BigEndian"), &pdevn->BigEndian)) {
630 default:
631 param_signal_error(plist, param_name, code);
632 return code;
633 case 0:
634 case 1:
635 break;
636 }
637 /* Read Compression */
638 switch (code = param_read_string(plist, (param_name = "Compression"), &comprstr)) {
639 case 0:
640 if ((code = tiff_compression_id(&pdevn->Compression, &comprstr)) < 0 ||
641 !tiff_compression_allowed(pdevn->Compression,
642 pdevn->devn_params.bitspercomponent))
643 {
644 param_signal_error(plist, param_name, code);
645 return code;
646 }
647 break;
648 case 1:
649 break;
650 default:
651 param_signal_error(plist, param_name, code);
652 return code;
653 }
654 switch (code = param_read_long(plist, (param_name = "MaxStripSize"), &pdevn->MaxStripSize)) {
655 case 0:
656 /*
657 * Strip must be large enough to accommodate a raster line.
658 * If the max strip size is too small, we still write a single
659 * line per strip rather than giving an error.
660 */
661 if (pdevn->MaxStripSize >= 0)
662 break;
663 code = gs_error_rangecheck;
664 default:
665 param_signal_error(plist, param_name, code);
666 return code;
667 case 1:
668 break;
669 }
670
671 return devn_printer_put_params(pdev, plist,
672 &(pdevn->devn_params), &(pdevn->equiv_cmyk_colors));
673 }
674
675 static int
tiffsep1_put_params(gx_device * pdev,gs_param_list * plist)676 tiffsep1_put_params(gx_device * pdev, gs_param_list * plist)
677 {
678 tiffsep1_device * const tfdev = (tiffsep1_device *) pdev;
679 int code;
680
681 if ((code = tiffsep_put_params(pdev, plist)) < 0)
682 return code;
683
684 /* put_params may have changed the fill_path proc -- we need it set to ours */
685 if (pdev->procs.fill_path != sep1_fill_path) {
686 tfdev->fill_path = pdev->procs.fill_path;
687 pdev->procs.fill_path = sep1_fill_path;
688 }
689 return code;
690
691 }
692 static void build_comp_to_sep_map(tiffsep_device *, short *);
693 static int number_output_separations(int, int, int, int);
694 static int create_separation_file_name(tiffsep_device *, char *, uint, int, bool);
695 static byte * threshold_from_order( gx_ht_order *, int *, int *, gs_memory_t *);
696 static int sep1_ht_order_to_thresholds(gx_device *pdev, const gs_imager_state *pis);
697 static void sep1_free_thresholds(tiffsep1_device *);
698 dev_proc_fill_path(clist_fill_path);
699
700 /* Open the tiffsep device */
701 /* Save the fill_hl_color and fill_path procs around the gdev_prn_open */
702 int
tiffsep1_prn_open(gx_device * pdev)703 tiffsep1_prn_open(gx_device * pdev)
704 {
705 tiffsep1_device * const tfdev = (tiffsep1_device *)pdev;
706 int code = gdev_prn_open(pdev);
707
708 #if !USE_COMPRESSED_ENCODING
709 /*
710 * If we are using the compressed encoding scheme, then set the separable
711 * and linear info.
712 */
713 set_linear_color_bits_mask_shift(pdev);
714 pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
715 #endif
716 /* gdev_prn_open may have changed the fill_path proc -- we need it set to ours */
717 if (pdev->procs.fill_path != sep1_fill_path) {
718 tfdev->fill_path = pdev->procs.fill_path;
719 pdev->procs.fill_path = sep1_fill_path;
720 }
721 return code;
722 }
723
724 /* Close the tiffsep device */
725 int
tiffsep1_prn_close(gx_device * pdev)726 tiffsep1_prn_close(gx_device * pdev)
727 {
728 tiffsep1_device * const tfdev = (tiffsep1_device *) pdev;
729 int num_dev_comp = tfdev->color_info.num_components;
730 int num_std_colorants = tfdev->devn_params.num_std_colorant_names;
731 int num_order = tfdev->devn_params.num_separation_order_names;
732 int num_spot = tfdev->devn_params.separations.num_separations;
733 char name[MAX_FILE_NAME_SIZE];
734 int code = gdev_prn_close(pdev);
735 short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
736 int comp_num;
737 int num_comp = number_output_separations(num_dev_comp, num_std_colorants,
738 num_order, num_spot);
739 const char *fmt;
740 gs_parsed_file_name_t parsed;
741
742 if (code < 0)
743 return code;
744 code = gx_parse_output_file_name(&parsed, &fmt,
745 tfdev->fname, strlen(tfdev->fname));
746 if (code < 0)
747 return code;
748
749 /* If we are doing separate pages, delete the old default file */
750 if (parsed.iodev == iodev_default) { /* filename includes "%nnd" */
751 if (fmt) {
752 char compname[MAX_FILE_NAME_SIZE];
753 long count1 = pdev->PageCount;
754
755 while (*fmt != 'l' && *fmt != '%')
756 --fmt;
757 if (*fmt == 'l')
758 sprintf(compname, parsed.fname, count1);
759 else
760 sprintf(compname, parsed.fname, (int)count1);
761 parsed.iodev->procs.delete_file(parsed.iodev, compname);
762 } else {
763 parsed.iodev->procs.delete_file(parsed.iodev, tfdev->fname);
764 }
765
766 }
767
768 build_comp_to_sep_map((tiffsep_device *)tfdev, map_comp_to_sep);
769 /* Close the separation files */
770 for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
771 if (tfdev->sep_file[comp_num] != NULL) {
772 int sep_num = map_comp_to_sep[comp_num];
773
774 code = create_separation_file_name((tiffsep_device *)tfdev, name,
775 MAX_FILE_NAME_SIZE, sep_num, true);
776 if (code < 0)
777 return code;
778 code = gx_device_close_output_file(pdev, name, tfdev->sep_file[comp_num]);
779 if (code < 0)
780 return code;
781 tfdev->sep_file[comp_num] = NULL;
782 }
783 if (tfdev->tiff[comp_num]) {
784 TIFFCleanup(tfdev->tiff[comp_num]);
785 tfdev->tiff[comp_num] = NULL;
786 }
787 }
788 /* If we have thresholds, free them and clear the pointers */
789 if( tfdev->thresholds[0].dstart != NULL) {
790 sep1_free_thresholds(tfdev);
791 }
792 return 0;
793 }
794
795
796 static int
sep1_fill_path(gx_device * pdev,const gs_imager_state * pis,gx_path * ppath,const gx_fill_params * params,const gx_device_color * pdevc,const gx_clip_path * pcpath)797 sep1_fill_path(gx_device * pdev, const gs_imager_state * pis,
798 gx_path * ppath, const gx_fill_params * params,
799 const gx_device_color * pdevc, const gx_clip_path * pcpath)
800 {
801 tiffsep1_device * const tfdev = (tiffsep1_device *)pdev;
802
803 /* If we haven't already converted the ht into thresholds, do it now */
804 if( tfdev->thresholds[0].dstart == NULL) {
805 int code = sep1_ht_order_to_thresholds(pdev, pis);
806
807 if (code < 0)
808 return code;
809 }
810 return (tfdev->fill_path)( pdev, pis, ppath, params, pdevc, pcpath);
811 }
812
813 /*
814 * This routine will check to see if the color component name match those
815 * that are available amoung the current device's color components.
816 *
817 * Parameters:
818 * dev - pointer to device data structure.
819 * pname - pointer to name (zero termination not required)
820 * nlength - length of the name
821 *
822 * This routine returns a positive value (0 to n) which is the device colorant
823 * number if the name is found. It returns GX_DEVICE_COLOR_MAX_COMPONENTS if
824 * the colorant is not being used due to a SeparationOrder device parameter.
825 * It returns a negative value if not found.
826 */
827 static int
tiffsep_get_color_comp_index(gx_device * dev,const char * pname,int name_size,int component_type)828 tiffsep_get_color_comp_index(gx_device * dev, const char * pname,
829 int name_size, int component_type)
830 {
831 tiffsep_device * pdev = (tiffsep_device *) dev;
832
833 /*
834 * We allow more spot colors than we can image. This allows the user
835 * to obtain separations for more than our max of 8 by doing multiple
836 * passes.
837 */
838 return devn_get_color_comp_index(dev,
839 &(pdev->devn_params), &(pdev->equiv_cmyk_colors),
840 pname, name_size, component_type, ALLOW_EXTRA_SPOT_COLORS);
841 }
842
843 /*
844 * There can be a conflict if a separation name is used as part of the file
845 * name for a separation output file. PostScript and PDF do not restrict
846 * the characters inside separation names. However most operating systems
847 * have some sort of restrictions. For instance: /, \, and : have special
848 * meaning under Windows. This implies that there should be some sort of
849 * escape sequence for special characters. This routine exists as a place
850 * to put the handling of that escaping. However it is not actually
851 * implemented. Instead we just map them to '_'.
852 */
853 static void
copy_separation_name(tiffsep_device * pdev,char * buffer,int max_size,int sep_num)854 copy_separation_name(tiffsep_device * pdev,
855 char * buffer, int max_size, int sep_num)
856 {
857 int sep_size = pdev->devn_params.separations.names[sep_num].size;
858 int i;
859 int restricted_chars[] = { '/', '\\', ':', 0 };
860
861 /* If name is too long then clip it. */
862 if (sep_size > max_size - 1)
863 sep_size = max_size - 1;
864 memcpy(buffer, pdev->devn_params.separations.names[sep_num].data,
865 sep_size);
866 /* Change some of the commonly known restricted characters to '_' */
867 for (i=0; restricted_chars[i] != 0; i++) {
868 char *p = buffer;
869
870 while ((p=memchr(p, restricted_chars[i], sep_size - (p - buffer))) != NULL)
871 *p = '_';
872 }
873 buffer[sep_size] = 0; /* Terminate string */
874 }
875
876 /*
877 * Determine the length of the base file name. If the file name includes
878 * the extension '.tif', then we remove it from the length of the file
879 * name.
880 */
881 static int
length_base_file_name(tiffsep_device * pdev)882 length_base_file_name(tiffsep_device * pdev)
883 {
884 int base_filename_length = strlen(pdev->fname);
885
886 #define REMOVE_TIF_FROM_BASENAME 1
887 #if REMOVE_TIF_FROM_BASENAME
888 if (base_filename_length > 4 &&
889 pdev->fname[base_filename_length - 4] == '.' &&
890 toupper(pdev->fname[base_filename_length - 3]) == 'T' &&
891 toupper(pdev->fname[base_filename_length - 2]) == 'I' &&
892 toupper(pdev->fname[base_filename_length - 1]) == 'F')
893 base_filename_length -= 4;
894 #endif
895 #undef REMOVE_TIF_FROM_BASENAME
896
897 return base_filename_length;
898 }
899
900 /*
901 * Create a name for a separation file.
902 */
903 static int
create_separation_file_name(tiffsep_device * pdev,char * buffer,uint max_size,int sep_num,bool use_sep_name)904 create_separation_file_name(tiffsep_device * pdev, char * buffer,
905 uint max_size, int sep_num, bool use_sep_name)
906 {
907 uint base_filename_length = length_base_file_name(pdev);
908
909 /*
910 * In most cases it is more convenient if we append '.tif' to the end
911 * of the file name.
912 */
913 #define APPEND_TIF_TO_NAME 1
914 #define SUFFIX_SIZE (4 * APPEND_TIF_TO_NAME)
915
916 memcpy(buffer, pdev->fname, base_filename_length);
917 buffer[base_filename_length++] = use_sep_name ? '(' : '.';
918 buffer[base_filename_length] = 0; /* terminate the string */
919
920 if (sep_num < pdev->devn_params.num_std_colorant_names) {
921 if (max_size < strlen(pdev->devn_params.std_colorant_names[sep_num]))
922 return_error(gs_error_rangecheck);
923 strcat(buffer, pdev->devn_params.std_colorant_names[sep_num]);
924 }
925 else {
926 sep_num -= pdev->devn_params.num_std_colorant_names;
927 if (use_sep_name) {
928 copy_separation_name(pdev, buffer + base_filename_length,
929 max_size - SUFFIX_SIZE - 2, sep_num);
930 } else {
931 /* Max of 10 chars in %d format */
932 if (max_size < base_filename_length + 11)
933 return_error(gs_error_rangecheck);
934 sprintf(buffer + base_filename_length, "s%d", sep_num);
935 }
936 }
937 if (use_sep_name)
938 strcat(buffer, ")");
939
940 #if APPEND_TIF_TO_NAME
941 if (max_size < strlen(buffer) + SUFFIX_SIZE)
942 return_error(gs_error_rangecheck);
943 strcat(buffer, ".tif");
944 #endif
945 return 0;
946 }
947
948 /*
949 * Determine the number of output separations for the tiffsep device.
950 *
951 * There are several factors which affect the number of output separations
952 * for the tiffsep device.
953 *
954 * Due to limitations on the size of a gx_color_index, we are limited to a
955 * maximum of 8 colors per pass. Thus the tiffsep device is set to 8
956 * components. However this is not usually the number of actual separation
957 * files to be created.
958 *
959 * If the SeparationOrder parameter has been specified, then we use it to
960 * select the number and which separation files are created.
961 *
962 * If the SeparationOrder parameter has not been specified, then we use the
963 * nuber of process colors (CMYK) and the number of spot colors unless we
964 * exceed the 8 component maximum for the device.
965 *
966 * Note: Unlike most other devices, the tiffsep device will accept more than
967 * four spot colors. However the extra spot colors will not be imaged
968 * unless they are selected by the SeparationOrder parameter. (This does
969 * allow the user to create more than 8 separations by a making multiple
970 * passes and using the SeparationOrder parameter.)
971 */
972 static int
number_output_separations(int num_dev_comp,int num_std_colorants,int num_order,int num_spot)973 number_output_separations(int num_dev_comp, int num_std_colorants,
974 int num_order, int num_spot)
975 {
976 int num_comp = num_std_colorants + num_spot;
977
978 if (num_comp > num_dev_comp)
979 num_comp = num_dev_comp;
980 if (num_order)
981 num_comp = num_order;
982 return num_comp;
983 }
984
985 /*
986 * This routine creates a list to map the component number to a separation number.
987 * Values less than 4 refer to the CMYK colorants. Higher values refer to a
988 * separation number.
989 *
990 * This is the inverse of the separation_order_map.
991 */
992 static void
build_comp_to_sep_map(tiffsep_device * pdev,short * map_comp_to_sep)993 build_comp_to_sep_map(tiffsep_device * pdev, short * map_comp_to_sep)
994 {
995 int num_sep = pdev->devn_params.separations.num_separations;
996 int num_std_colorants = pdev->devn_params.num_std_colorant_names;
997 int sep_num;
998 int num_channels;
999
1000 /* since both proc colors and spot colors are packed in same encoded value we
1001 need to have this limit */
1002
1003 num_channels =
1004 ( (num_std_colorants + num_sep) < (GX_DEVICE_COLOR_MAX_COMPONENTS) ? (num_std_colorants + num_sep) : (GX_DEVICE_COLOR_MAX_COMPONENTS) );
1005
1006 for (sep_num = 0; sep_num < num_channels; sep_num++) {
1007 int comp_num = pdev->devn_params.separation_order_map[sep_num];
1008
1009 if (comp_num >= 0 && comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS)
1010 map_comp_to_sep[comp_num] = sep_num;
1011 }
1012 }
1013
1014 /* Open the tiffsep device */
1015 int
tiffsep_prn_open(gx_device * pdev)1016 tiffsep_prn_open(gx_device * pdev)
1017 {
1018 int code = gdev_prn_open(pdev);
1019
1020 #if !USE_COMPRESSED_ENCODING
1021 /*
1022 * If we are using the compressed encoding scheme, then set the separable
1023 * and linear info.
1024 */
1025 set_linear_color_bits_mask_shift(pdev);
1026 pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
1027 #endif
1028 return code;
1029 }
1030
1031 static int
tiffsep_close_sep_file(tiffsep_device * tfdev,const char * fn,int comp_num)1032 tiffsep_close_sep_file(tiffsep_device *tfdev, const char *fn, int comp_num)
1033 {
1034 int code;
1035
1036 if (tfdev->tiff[comp_num]) {
1037 TIFFCleanup(tfdev->tiff[comp_num]);
1038 tfdev->tiff[comp_num] = NULL;
1039 }
1040
1041 code = gx_device_close_output_file((gx_device *)tfdev,
1042 fn,
1043 tfdev->sep_file[comp_num]);
1044 tfdev->sep_file[comp_num] = NULL;
1045 tfdev->tiff[comp_num] = NULL;
1046
1047 return code;
1048 }
1049
1050 /* Close the tiffsep device */
1051 int
tiffsep_prn_close(gx_device * pdev)1052 tiffsep_prn_close(gx_device * pdev)
1053 {
1054 tiffsep_device * const pdevn = (tiffsep_device *) pdev;
1055 int num_dev_comp = pdevn->color_info.num_components;
1056 int num_std_colorants = pdevn->devn_params.num_std_colorant_names;
1057 int num_order = pdevn->devn_params.num_separation_order_names;
1058 int num_spot = pdevn->devn_params.separations.num_separations;
1059 char name[MAX_FILE_NAME_SIZE];
1060 int code;
1061 short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
1062 int comp_num;
1063 int num_comp = number_output_separations(num_dev_comp, num_std_colorants,
1064 num_order, num_spot);
1065
1066 if (pdevn->tiff_comp) {
1067 TIFFCleanup(pdevn->tiff_comp);
1068 pdevn->tiff_comp = NULL;
1069 }
1070 code = gdev_prn_close(pdev);
1071 if (code < 0)
1072 return code;
1073
1074 build_comp_to_sep_map(pdevn, map_comp_to_sep);
1075 /* Close the separation files */
1076 for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
1077 if (pdevn->sep_file[comp_num] != NULL) {
1078 int sep_num = map_comp_to_sep[comp_num];
1079
1080 code = create_separation_file_name(pdevn, name,
1081 MAX_FILE_NAME_SIZE, sep_num, false);
1082 if (code < 0)
1083 return code;
1084 code = tiffsep_close_sep_file(pdevn, name, comp_num);
1085 if (code < 0)
1086 return code;
1087 }
1088 }
1089
1090 return 0;
1091 }
1092
1093 /*
1094 * Element for a map to convert colorants to a CMYK color.
1095 */
1096 typedef struct cmyk_composite_map_s {
1097 frac c, m, y, k;
1098 } cmyk_composite_map;
1099
1100 /*
1101 * Build the map to be used to create a CMYK equivalent to the current
1102 * device components.
1103 */
1104 static void
build_cmyk_map(tiffsep_device * pdev,int num_comp,short * map_comp_to_sep,cmyk_composite_map * cmyk_map)1105 build_cmyk_map(tiffsep_device * pdev, int num_comp,
1106 short *map_comp_to_sep, cmyk_composite_map * cmyk_map)
1107 {
1108 int comp_num;
1109
1110 for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
1111 int sep_num = map_comp_to_sep[comp_num];
1112
1113 cmyk_map[comp_num].c = cmyk_map[comp_num].m =
1114 cmyk_map[comp_num].y = cmyk_map[comp_num].k = frac_0;
1115 /* The tiffsep device has 4 standard colors: CMYK */
1116 if (sep_num < pdev->devn_params.num_std_colorant_names) {
1117 switch (sep_num) {
1118 case 0: cmyk_map[comp_num].c = frac_1; break;
1119 case 1: cmyk_map[comp_num].m = frac_1; break;
1120 case 2: cmyk_map[comp_num].y = frac_1; break;
1121 case 3: cmyk_map[comp_num].k = frac_1; break;
1122 }
1123 }
1124 else {
1125 sep_num -= pdev->devn_params.num_std_colorant_names;
1126 if (pdev->equiv_cmyk_colors.color[sep_num].color_info_valid) {
1127 cmyk_map[comp_num].c = pdev->equiv_cmyk_colors.color[sep_num].c;
1128 cmyk_map[comp_num].m = pdev->equiv_cmyk_colors.color[sep_num].m;
1129 cmyk_map[comp_num].y = pdev->equiv_cmyk_colors.color[sep_num].y;
1130 cmyk_map[comp_num].k = pdev->equiv_cmyk_colors.color[sep_num].k;
1131 }
1132 }
1133 }
1134 }
1135
1136 /*
1137 * Build a CMYK equivalent to a raster line.
1138 */
1139 static void
build_cmyk_raster_line(byte * src,byte * dest,int width,int num_comp,cmyk_composite_map * cmyk_map)1140 build_cmyk_raster_line(byte * src, byte * dest, int width,
1141 int num_comp, cmyk_composite_map * cmyk_map)
1142 {
1143 int pixel, comp_num;
1144 uint temp, cyan, magenta, yellow, black;
1145 cmyk_composite_map * cmyk_map_entry;
1146
1147 for (pixel = 0; pixel < width; pixel++) {
1148 cmyk_map_entry = cmyk_map;
1149 temp = *src++;
1150 cyan = cmyk_map_entry->c * temp;
1151 magenta = cmyk_map_entry->m * temp;
1152 yellow = cmyk_map_entry->y * temp;
1153 black = cmyk_map_entry->k * temp;
1154 cmyk_map_entry++;
1155 for (comp_num = 1; comp_num < num_comp; comp_num++) {
1156 temp = *src++;
1157 cyan += cmyk_map_entry->c * temp;
1158 magenta += cmyk_map_entry->m * temp;
1159 yellow += cmyk_map_entry->y * temp;
1160 black += cmyk_map_entry->k * temp;
1161 cmyk_map_entry++;
1162 }
1163 cyan /= frac_1;
1164 magenta /= frac_1;
1165 yellow /= frac_1;
1166 black /= frac_1;
1167 if (cyan > MAX_COLOR_VALUE)
1168 cyan = MAX_COLOR_VALUE;
1169 if (magenta > MAX_COLOR_VALUE)
1170 magenta = MAX_COLOR_VALUE;
1171 if (yellow > MAX_COLOR_VALUE)
1172 yellow = MAX_COLOR_VALUE;
1173 if (black > MAX_COLOR_VALUE)
1174 black = MAX_COLOR_VALUE;
1175 *dest++ = cyan;
1176 *dest++ = magenta;
1177 *dest++ = yellow;
1178 *dest++ = black;
1179 }
1180 }
1181
1182 static int
sep1_ht_order_to_thresholds(gx_device * pdev,const gs_imager_state * pis)1183 sep1_ht_order_to_thresholds(gx_device *pdev, const gs_imager_state *pis)
1184 {
1185 tiffsep1_device * const tfdev = (tiffsep1_device *)pdev;
1186 gs_memory_t *mem = pdev->memory;
1187
1188 /* If we have thresholds, free them and clear the pointers */
1189 if( tfdev->thresholds[0].dstart != NULL) {
1190 sep1_free_thresholds(tfdev);
1191 } else {
1192 int nc, j;
1193 gx_ht_order *d_order;
1194 threshold_array_t *dptr;
1195
1196 if (pis->dev_ht == NULL) {
1197 eprintf("sep1_order_to_thresholds: no dev_ht available\n");
1198 return_error(gs_error_rangecheck); /* error condition */
1199 }
1200 nc = pis->dev_ht->num_comp;
1201 for( j=0; j<nc; j++ ) {
1202 d_order = &(pis->dev_ht->components[j].corder);
1203 dptr = &(tfdev->thresholds[j]);
1204 dptr->dstart = threshold_from_order( d_order, &(dptr->dwidth), &(dptr->dheight), mem);
1205 if( dptr->dstart == NULL ) {
1206 eprintf("sep1_order_to_thresholds: conversion to thresholds failed.\n");
1207 return_error(gs_error_rangecheck); /* error condition */
1208 }
1209 }
1210 }
1211 return 0;
1212 }
1213
1214 static void
sep1_free_thresholds(tiffsep1_device * tfdev)1215 sep1_free_thresholds(tiffsep1_device *tfdev)
1216 {
1217 int i;
1218
1219 for (i=0; i < GX_DEVICE_COLOR_MAX_COMPONENTS + 1; i++) {
1220 threshold_array_t *dptr = &(tfdev->thresholds[i]);
1221
1222 if (dptr->dstart != NULL) {
1223 gs_free(tfdev->memory, dptr->dstart, dptr->dwidth * dptr->dheight, 1,
1224 "tiffsep1_threshold_array");
1225 dptr->dstart = NULL;
1226 }
1227 }
1228 }
1229
1230 /************************************************************************/
1231 /* This routine generates a threshold matrix for use in */
1232 /* the color dithering routine from the "order" info in */
1233 /* the current graphics state. */
1234 /* */
1235 /************************************************************************/
1236
1237 static byte*
threshold_from_order(gx_ht_order * d_order,int * Width,int * Height,gs_memory_t * memory)1238 threshold_from_order( gx_ht_order *d_order, int *Width, int *Height, gs_memory_t *memory)
1239 {
1240 int i, j, l, prev_l;
1241 unsigned char *thresh;
1242 gx_ht_bit *bits = (gx_ht_bit *)d_order->bit_data;
1243
1244 #ifdef DEBUG
1245 if ( gs_debug_c('h') ) {
1246 dprintf2(" width=%d, height=%d,",
1247 d_order->width, d_order->height );
1248 dprintf2(" num_levels=%d, raster=%d\n",
1249 d_order->num_levels, d_order->raster );
1250 }
1251 #endif
1252
1253 thresh = (byte *)gs_malloc(memory, d_order->num_bits, 1,
1254 "tiffsep1_threshold_array");
1255 if( thresh == NULL ) {
1256 #ifdef DEBUG
1257 eprintf("threshold_from_order, malloc failed\n");
1258 eprintf2(" width=%d, height=%d,",
1259 d_order->width, d_order->height );
1260 eprintf2(" num_levels=%d, raster=%d\n",
1261 d_order->num_levels, d_order->raster );
1262 #endif
1263 return thresh ; /* error if allocation failed */
1264 }
1265 for( i=0; i<d_order->num_bits; i++ )
1266 thresh[i] = 1;
1267
1268 *Width = d_order->width;
1269 *Height = d_order->height;
1270
1271 prev_l = 0;
1272 l = 1;
1273 while( l < d_order->num_levels ) {
1274 if( d_order->levels[l] > d_order->levels[prev_l] ) {
1275 int t_level = (256*l)/d_order->num_levels;
1276 int row, col;
1277 #ifdef DEBUG
1278 if ( gs_debug_c('h') )
1279 dprintf2(" level[%3d]=%3d\n", l, d_order->levels[l]);
1280 #endif
1281 for( j=d_order->levels[prev_l]; j<d_order->levels[l]; j++) {
1282 #ifdef DEBUG
1283 if ( gs_debug_c('h') )
1284 dprintf2(" bits.offset=%3d, bits.mask=%8x ",
1285 bits[j].offset, bits[j].mask);
1286 #endif
1287 row = bits[j].offset / d_order->raster;
1288 for( col=0; col < (8*sizeof(ht_mask_t)); col++ ) {
1289 if( bits[j].mask & bit_order[col] )
1290 break;
1291 }
1292 col += 8 * ( bits[j].offset - (row * d_order->raster) );
1293 #ifdef DEBUG
1294 if ( gs_debug_c('h') )
1295 dprintf3("row=%2d, col=%2d, t_level=%3d\n",
1296 row, col, t_level);
1297 #endif
1298 if( col < (int)d_order->width )
1299 *(thresh+col+(row * d_order->width)) = t_level;
1300 }
1301 prev_l = l;
1302 }
1303 l++;
1304 }
1305
1306 #ifdef DEBUG
1307 if ( gs_debug_c('h') ) {
1308 for( i=0; i<(int)d_order->height; i++ ) {
1309 dprintf1("threshold array row %3d= ", i);
1310 for( j=(int)d_order->width-1; j>=0; j-- )
1311 dprintf1("%3d ", *(thresh+j+(i*d_order->width)) );
1312 dprintf("\n");
1313 }
1314 }
1315 #endif
1316
1317 return thresh;
1318 }
1319
1320 /*
1321 * Output the image data for the tiff separation (tiffsep) device. The data
1322 * for the tiffsep device is written in separate planes to separate files.
1323 *
1324 * The DeviceN parameters (SeparationOrder, SeparationColorNames, and
1325 * MaxSeparations) are applied to the tiffsep device.
1326 */
1327 static int
tiffsep_print_page(gx_device_printer * pdev,FILE * file)1328 tiffsep_print_page(gx_device_printer * pdev, FILE * file)
1329 {
1330 tiffsep_device * const tfdev = (tiffsep_device *)pdev;
1331 int num_std_colorants = tfdev->devn_params.num_std_colorant_names;
1332 int num_order = tfdev->devn_params.num_separation_order_names;
1333 int num_spot = tfdev->devn_params.separations.num_separations;
1334 int num_comp, comp_num, sep_num, code = 0;
1335 short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
1336 cmyk_composite_map cmyk_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
1337 char name[MAX_FILE_NAME_SIZE];
1338 int base_filename_length = length_base_file_name(tfdev);
1339 int save_depth = pdev->color_info.depth;
1340 const char *fmt;
1341 gs_parsed_file_name_t parsed;
1342 int non_encodable_count = 0;
1343
1344 build_comp_to_sep_map(tfdev, map_comp_to_sep);
1345
1346 /* Print the names of the spot colors */
1347 for (sep_num = 0; sep_num < num_spot; sep_num++) {
1348 copy_separation_name(tfdev, name,
1349 MAX_FILE_NAME_SIZE - base_filename_length - SUFFIX_SIZE, sep_num);
1350 dlprintf1("%%%%SeparationName: %s\n", name);
1351 }
1352
1353 /*
1354 * Check if the file name has a numeric format. If so then we want to
1355 * create individual separation files for each page of the input.
1356 */
1357 code = gx_parse_output_file_name(&parsed, &fmt,
1358 tfdev->fname, strlen(tfdev->fname));
1359
1360 /* Write the page directory for the CMYK equivalent file. */
1361 pdev->color_info.depth = 32; /* Create directory for 32 bit cmyk */
1362 if (pdev->height > (max_long - ftell(file))/(pdev->width*4)) /* note width is never 0 in print_page */
1363 return_error(gs_error_rangecheck); /* this will overflow max_long */
1364
1365 if (gdev_prn_file_is_new(pdev)) {
1366 tfdev->tiff_comp = tiff_from_filep(pdev->dname, file, tfdev->BigEndian);
1367 if (!tfdev->tiff_comp)
1368 return_error(gs_error_invalidfileaccess);
1369 }
1370 code = tiff_set_fields_for_printer(pdev, tfdev->tiff_comp);
1371 tiff_set_cmyk_fields(pdev, tfdev->tiff_comp, 8, COMPRESSION_NONE, tfdev->MaxStripSize);
1372 pdev->color_info.depth = save_depth;
1373 if (code < 0)
1374 return code;
1375
1376 /* Set up the separation output files */
1377 num_comp = number_output_separations( tfdev->color_info.num_components,
1378 num_std_colorants, num_order, num_spot);
1379 for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
1380 int sep_num = map_comp_to_sep[comp_num];
1381
1382 code = create_separation_file_name(tfdev, name, MAX_FILE_NAME_SIZE,
1383 sep_num, false);
1384 if (code < 0)
1385 return code;
1386 /*
1387 * Close the old separation file if we are creating individual files
1388 * for each page.
1389 */
1390 if (tfdev->sep_file[comp_num] != NULL && fmt != NULL) {
1391 code = tiffsep_close_sep_file(tfdev, name, comp_num);
1392 if (code < 0)
1393 return code;
1394 }
1395 /* Open the separation file, if not already open */
1396 if (tfdev->sep_file[comp_num] == NULL) {
1397 code = gx_device_open_output_file((gx_device *)pdev, name,
1398 true, false, &(tfdev->sep_file[comp_num]));
1399 if (code < 0)
1400 return code;
1401 tfdev->tiff[comp_num] = tiff_from_filep(name,
1402 tfdev->sep_file[comp_num],
1403 tfdev->BigEndian);
1404 if (!tfdev->tiff[comp_num])
1405 return_error(gs_error_ioerror);
1406 }
1407
1408 pdev->color_info.depth = 8; /* Create files for 8 bit gray */
1409 if (pdev->height > (max_long - ftell(file))/(pdev->width)) /* note width is never 0 in print_page */
1410 return_error(gs_error_rangecheck); /* this will overflow max_long */
1411
1412 code = tiff_set_fields_for_printer(pdev, tfdev->tiff[comp_num]);
1413 tiff_set_gray_fields(pdev, tfdev->tiff[comp_num], 8, tfdev->Compression, tfdev->MaxStripSize);
1414 pdev->color_info.depth = save_depth;
1415 if (code < 0)
1416 return code;
1417 }
1418
1419 build_cmyk_map(tfdev, num_comp, map_comp_to_sep, cmyk_map);
1420
1421 {
1422 int raster = gdev_prn_raster(pdev);
1423 int width = tfdev->width;
1424 int cmyk_raster = width * NUM_CMYK_COMPONENTS;
1425 int pixel, y;
1426 byte * line = gs_alloc_bytes(pdev->memory, raster, "tiffsep_print_page");
1427 byte * unpacked = gs_alloc_bytes(pdev->memory, width * num_comp,
1428 "tiffsep_print_page");
1429 byte * sep_line;
1430 byte * row;
1431
1432 if (line == NULL || unpacked == NULL)
1433 return_error(gs_error_VMerror);
1434 sep_line =
1435 gs_alloc_bytes(pdev->memory, cmyk_raster, "tiffsep_print_page");
1436 if (sep_line == NULL) {
1437 gs_free_object(pdev->memory, line, "tiffsep_print_page");
1438 return_error(gs_error_VMerror);
1439 }
1440
1441 /* Write the page data. */
1442 for (y = 0; y < pdev->height; ++y) {
1443 code = gdev_prn_get_bits(pdev, y, line, &row);
1444 if (code < 0)
1445 break;
1446 /* Unpack the encoded color info */
1447 non_encodable_count += devn_unpack_row((gx_device *)pdev, num_comp,
1448 &(tfdev->devn_params), width, row, unpacked);
1449 /* Write separation data (tiffgray format) */
1450 for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
1451 byte * src = unpacked + comp_num;
1452 byte * dest = sep_line;
1453
1454 for (pixel = 0; pixel < width; pixel++, dest++, src += num_comp)
1455 *dest = MAX_COLOR_VALUE - *src; /* Gray is additive */
1456 TIFFWriteScanline(tfdev->tiff[comp_num], (tdata_t)sep_line, y, 0);
1457 }
1458 /* Write CMYK equivalent data (tiff32nc format) */
1459 build_cmyk_raster_line(unpacked, sep_line,
1460 width, num_comp, cmyk_map);
1461 TIFFWriteScanline(tfdev->tiff_comp, (tdata_t)sep_line, y, 0);
1462 }
1463 for (comp_num = 0; comp_num < num_comp; comp_num++ )
1464 TIFFWriteDirectory(tfdev->tiff[comp_num]);
1465 TIFFWriteDirectory(tfdev->tiff_comp);
1466
1467 gs_free_object(pdev->memory, line, "tiffsep_print_page");
1468 gs_free_object(pdev->memory, sep_line, "tiffsep_print_page");
1469 }
1470
1471 #if defined(DEBUG) && 0
1472 print_compressed_color_list(tfdev->devn_params.compressed_color_list,
1473 max(16, num_comp));
1474 #endif
1475
1476 /*
1477 * If we have any non encodable pixels then signal an error.
1478 */
1479 if (non_encodable_count) {
1480 dlprintf1("WARNING: Non encodable pixels = %d\n", non_encodable_count);
1481 return_error(gs_error_rangecheck);
1482 }
1483
1484 return code;
1485 }
1486
1487 /*
1488 * Output the image data for the tiff separation (tiffsep1) device. The data
1489 * for the tiffsep1 device is written in separate planes to separate files.
1490 *
1491 * The DeviceN parameters (SeparationOrder, SeparationColorNames, and
1492 * MaxSeparations) are applied to the tiffsep device.
1493 */
1494 static int
tiffsep1_print_page(gx_device_printer * pdev,FILE * file)1495 tiffsep1_print_page(gx_device_printer * pdev, FILE * file)
1496 {
1497 tiffsep1_device * const tfdev = (tiffsep1_device *)pdev;
1498 int num_std_colorants = tfdev->devn_params.num_std_colorant_names;
1499 int num_order = tfdev->devn_params.num_separation_order_names;
1500 int num_spot = tfdev->devn_params.separations.num_separations;
1501 int num_comp, comp_num, code = 0;
1502 short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
1503 char name[MAX_FILE_NAME_SIZE];
1504 int save_depth = pdev->color_info.depth;
1505 const char *fmt;
1506 gs_parsed_file_name_t parsed;
1507 int non_encodable_count = 0;
1508
1509 if (tfdev->thresholds[0].dstart == NULL)
1510 return_error(gs_error_rangecheck);
1511
1512 build_comp_to_sep_map((tiffsep_device *)tfdev, map_comp_to_sep);
1513
1514 /*
1515 * Check if the file name has a numeric format. If so then we want to
1516 * create individual separation files for each page of the input.
1517 */
1518 code = gx_parse_output_file_name(&parsed, &fmt,
1519 pdev->fname, strlen(pdev->fname));
1520
1521 /* If the output file is on disk and the name contains a page #, */
1522 /* then delete the previous file. */
1523 if (pdev->file != NULL && parsed.iodev == iodev_default && fmt) {
1524 char compname[MAX_FILE_NAME_SIZE];
1525 long count1 = pdev->PageCount;
1526
1527 gx_device_close_output_file((gx_device *)pdev, pdev->fname, pdev->file);
1528 pdev->file = NULL;
1529
1530 while (*fmt != 'l' && *fmt != '%')
1531 --fmt;
1532 if (*fmt == 'l')
1533 sprintf(compname, parsed.fname, count1);
1534 else
1535 sprintf(compname, parsed.fname, (int)count1);
1536 parsed.iodev->procs.delete_file(parsed.iodev, compname);
1537 /* we always need an open printer (it will get deleted in tiffsep1_prn_close */
1538 if ((code = gdev_prn_open_printer((gx_device *)pdev, 1)) < 0)
1539 return code;
1540 }
1541
1542 /* Set up the separation output files */
1543 num_comp = number_output_separations( tfdev->color_info.num_components,
1544 num_std_colorants, num_order, num_spot);
1545 for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
1546 int sep_num = map_comp_to_sep[comp_num];
1547
1548 code = create_separation_file_name((tiffsep_device *)tfdev, name,
1549 MAX_FILE_NAME_SIZE, sep_num, true);
1550 if (code < 0)
1551 return code;
1552 /*
1553 * Close the old separation file if we are creating individual files
1554 * for each page.
1555 */
1556 if (tfdev->sep_file[comp_num] != NULL && fmt != NULL) {
1557 code = gx_device_close_output_file((const gx_device *)tfdev, name,
1558 tfdev->sep_file[comp_num]);
1559 if (code < 0)
1560 return code;
1561 tfdev->sep_file[comp_num] = NULL;
1562 if (tfdev->tiff[comp_num]) {
1563 TIFFCleanup(tfdev->tiff[comp_num]);
1564 tfdev->tiff[comp_num] = NULL;
1565 }
1566 }
1567 /* Open the separation file, if not already open */
1568 if (tfdev->sep_file[comp_num] == NULL) {
1569 code = gx_device_open_output_file((gx_device *)pdev, name,
1570 true, false, &(tfdev->sep_file[comp_num]));
1571 if (code < 0)
1572 return code;
1573 tfdev->tiff[comp_num] = tiff_from_filep(name,
1574 tfdev->sep_file[comp_num],
1575 tfdev->BigEndian);
1576 if (!tfdev->tiff[comp_num])
1577 return_error(gs_error_ioerror);
1578 }
1579
1580 pdev->color_info.depth = 8; /* Create files for 8 bit gray */
1581 code = tiff_set_fields_for_printer(pdev, tfdev->tiff[comp_num]);
1582 tiff_set_gray_fields(pdev, tfdev->tiff[comp_num], 1, tfdev->Compression, tfdev->MaxStripSize);
1583 pdev->color_info.depth = save_depth;
1584 if (code < 0)
1585 return code;
1586
1587 } /* end initialization of separation files */
1588
1589
1590 { /* Get the expanded contone line, halftone and write out the dithered separations */
1591 int raster = gdev_prn_raster(pdev);
1592 int width = tfdev->width;
1593 int dithered_raster = ((7 + width) / 8) + ARCH_SIZEOF_LONG;
1594 int pixel, y;
1595 byte *line = gs_alloc_bytes(pdev->memory, raster, "tiffsep1_print_page");
1596 byte *unpacked = gs_alloc_bytes(pdev->memory, width * num_comp,
1597 "tiffsep1_print_page");
1598 /* the dithered_line is assumed to be 32-bit aligned by the alloc */
1599 uint32_t *dithered_line = (uint32_t *)gs_alloc_bytes(pdev->memory, dithered_raster,
1600 "tiffsep1_print_page");
1601 byte *row;
1602
1603 if (line == NULL || unpacked == NULL || dithered_line == NULL)
1604 return_error(gs_error_VMerror);
1605
1606 /* Loop for the lines */
1607 for (y = 0; y < pdev->height; ++y) {
1608 code = gdev_prn_get_bits(pdev, y, line, &row);
1609 if (code < 0)
1610 break;
1611 /* Unpack the encoded color info */
1612 non_encodable_count += devn_unpack_row((gx_device *)pdev, num_comp,
1613 &(tfdev->devn_params), width, row, unpacked);
1614 /* Dither the separation and write it out (tiffpack format) */
1615 for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
1616
1617 /***** #define SKIP_HALFTONING_FOR_TIMING *****/ /* uncomment for timing test */
1618 #ifndef SKIP_HALFTONING_FOR_TIMING
1619
1620 /*
1621 * Define 32-bit writes by default. Testing shows that while this is more
1622 * complex code, it runs measurably and consistently faster than the more
1623 * obvious 8-bit code. The 8-bit code is kept to help future optimization
1624 * efforts determine what affects tight loop optimization. Subtracting the
1625 * time when halftoning is skipped shows that the 32-bit halftoning is
1626 * 27% faster.
1627 *
1628 * The compressed color encoding has a much more significant impact on
1629 * the performance. On a 33 file test suite with spot colors, uncompressed
1630 * encoding (which is limited to CMYK + 4 spot colors) ran almost twice
1631 * the speed of compressed color encoding.
1632 */
1633 #define USE_32_BIT_WRITES
1634 byte *thresh_line_base = tfdev->thresholds[comp_num].dstart +
1635 ((y % tfdev->thresholds[comp_num].dheight) *
1636 tfdev->thresholds[comp_num].dwidth) ;
1637 byte *thresh_ptr = thresh_line_base;
1638 byte *thresh_limit = thresh_ptr + tfdev->thresholds[comp_num].dwidth;
1639 byte *src = unpacked + comp_num;
1640 #ifdef USE_32_BIT_WRITES
1641 uint32_t *dest = dithered_line;
1642 uint32_t val = 0;
1643 uint32_t *mask = &bit_order[0];
1644 #else /* example 8-bit code */
1645 byte *dest = dithered_line;
1646 byte val = 0;
1647 byte mask = 0x80;
1648 #endif /* USE_32_BIT_WRITES */
1649
1650 for (pixel = 0; pixel < width; pixel++, src += num_comp) {
1651 #ifdef USE_32_BIT_WRITES
1652 if (*src < *thresh_ptr++)
1653 val |= *mask;
1654 if (++mask == &(bit_order[32])) {
1655 *dest++ = val;
1656 val = 0;
1657 mask = &bit_order[0];
1658 }
1659 #else /* example 8-bit code */
1660 if (*src < *thresh_ptr++)
1661 val |= mask;
1662 mask >>= 1;
1663 if (mask == 0) {
1664 *dest++ = val;
1665 val = 0;
1666 mask = 0x80;
1667 }
1668 #endif /* USE_32_BIT_WRITES */
1669 if (thresh_ptr >= thresh_limit)
1670 thresh_ptr = thresh_line_base;
1671 } /* end src pixel loop - collect last bits if any */
1672 /* the following relies on their being enough 'pad' in dithered_line */
1673 #ifdef USE_32_BIT_WRITES
1674 if (mask != &bit_order[0]) {
1675 *dest = val;
1676 }
1677 #else /* example 8-bit code */
1678 if (mask != 0x80) {
1679 *dest = val;
1680 }
1681 #endif /* USE_32_BIT_WRITES */
1682 #endif /* SKIP_HALFTONING_FOR_TIMING */
1683 TIFFWriteScanline(tfdev->tiff[comp_num], (tdata_t)dithered_line, y, 0);
1684 } /* end component loop */
1685 }
1686 /* Update the strip data */
1687 for (comp_num = 0; comp_num < num_comp; comp_num++ )
1688 TIFFWriteDirectory(tfdev->tiff[comp_num]);
1689 gs_free_object(pdev->memory, line, "tiffsep1_print_page");
1690 gs_free_object(pdev->memory, dithered_line, "tiffsep1_print_page");
1691 }
1692
1693 /*
1694 * If we have any non encodable pixels then signal an error.
1695 */
1696 if (non_encodable_count) {
1697 dlprintf1("WARNING: Non encodable pixels = %d\n", non_encodable_count);
1698 return_error(gs_error_rangecheck);
1699 }
1700
1701 return code;
1702 }
1703